package com.yeshi.fanli.util.push;
|
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.io.OutputStream;
|
import java.io.UnsupportedEncodingException;
|
import java.net.HttpURLConnection;
|
import java.net.URL;
|
import java.net.URLDecoder;
|
import java.net.URLEncoder;
|
import java.text.MessageFormat;
|
import java.util.List;
|
import java.util.Properties;
|
|
import javax.annotation.PostConstruct;
|
|
import org.apache.commons.io.IOUtils;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Component;
|
import org.yeshi.utils.annotation.MapUtil;
|
|
import com.alibaba.fastjson.JSONObject;
|
import com.yeshi.fanli.entity.config.push.HWPushConfig;
|
import com.yeshi.fanli.exception.push.PushException;
|
import com.yeshi.fanli.service.inter.config.BusinessSystemService;
|
import com.yeshi.fanli.util.Constant;
|
import com.yeshi.fanli.util.taobao.TaoBaoUtil;
|
|
import net.sf.json.JSONArray;
|
|
@Component
|
public class HWPushUtil {
|
|
private static HWPushUtil hWPushUtil;
|
|
@Autowired
|
private BusinessSystemService businessSystemService;
|
|
@PostConstruct
|
public void init() {
|
hWPushUtil = this;
|
hWPushUtil.businessSystemService = this.businessSystemService;
|
}
|
|
private static String appSecret = "";
|
private static String appId = "";// 用户在华为开发者联盟申请的appId和appSecret(会员中心->我的产品,点击产品对应的Push服务,点击“移动应用详情”获取)
|
private static String tokenUrl = "https://login.cloud.huawei.com/oauth2/v2/token"; // 获取认证Token的URL
|
private static String apiUrl = "https://api.push.hicloud.com/pushsend.do"; // 应用级消息下发API
|
private static String accessToken;// 下发通知消息的认证Token
|
private static long tokenExpiredTime; // accessToken的过期时间
|
|
static {
|
Properties ps = org.yeshi.utils.PropertiesUtil
|
.getProperties(TaoBaoUtil.class.getClassLoader().getResourceAsStream("push_hw.properties"));
|
HWPushConfig config = (HWPushConfig) MapUtil.parseMap(HWPushConfig.class, ps);
|
appId = config.getAppId();
|
appSecret = config.getAppSecret();
|
}
|
|
private static String getIntent(String type, String activity, String url, String webUrl, Long id) {
|
net.sf.json.JSONObject data = new net.sf.json.JSONObject();
|
if (type != null)
|
data.put("type", type);
|
if (activity != null)
|
data.put("activity", activity);
|
if (url != null)
|
data.put("url", url);
|
if (webUrl != null)
|
data.put("webUrl", webUrl);
|
if (id != null)
|
data.put("id", id);
|
|
try {
|
return String.format(
|
"intent://flq/hmpush?data=%s#Intent;scheme=banliapp;launchFlags=0x4000000;end",
|
URLDecoder.decode(data.toString(), "UTF-8"));
|
} catch (UnsupportedEncodingException e) {
|
e.printStackTrace();
|
}
|
return null;
|
}
|
|
/**
|
* 推送商品
|
*
|
* @param deviceTokens
|
* -最大值1000
|
* @param title
|
* @param content
|
* @param goodsType
|
* @param goodsId
|
* @throws PushException
|
*/
|
public static void pushGoods(List<String> deviceTokens, String title, String content, int goodsType, Long goodsId)
|
throws PushException {
|
if (deviceTokens != null && deviceTokens.size() > 100)
|
throw new PushException(1, "设备数不能超过100个");
|
|
String activity = Constant.systemCommonConfig.getAndroidBaseactivityName()
|
+ ".ui.recommend.GoodsBrowserActivity";
|
String intent = getIntent("goodsdetail", activity, null, null, goodsId);
|
|
try {
|
String result = sendPushHWMessageForIntent(deviceTokens, title, content, intent);
|
net.sf.json.JSONObject data = net.sf.json.JSONObject.fromObject(result);
|
if (!"success".equalsIgnoreCase(data.optString("msg")))
|
throw new PushException(2, result);
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
|
/**
|
* 网页推送
|
*
|
* @param deviceTokens
|
* 最大值1000
|
* @param title
|
* @param content
|
* @param url
|
* -网页链接
|
* @throws PushException
|
*/
|
public static void pushUrl(List<String> deviceTokens, String title, String content, String url)
|
throws PushException {
|
if (deviceTokens != null && deviceTokens.size() > 100)
|
throw new PushException(1, "设备数不能超过1000个");
|
|
String activity = Constant.systemCommonConfig.getAndroidBaseactivityName() + ".ui.invite.ShareBrowserActivity";
|
String intent = getIntent("url", activity, null, url, null);
|
try {
|
String result = sendPushHWMessageForIntent(deviceTokens, title, content, intent);
|
net.sf.json.JSONObject data = net.sf.json.JSONObject.fromObject(result);
|
if (!"success".equalsIgnoreCase(data.optString("msg")))
|
throw new PushException(2, result);
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
|
/**
|
* 站内信推送
|
*
|
* @param deviceTokens
|
* 最大值1000
|
* @param title
|
* @param content
|
* @param url
|
* -网页链接
|
* @throws PushException
|
*/
|
public static void pushZNX(List<String> deviceTokens, String title, String content) throws PushException {
|
if (deviceTokens != null && deviceTokens.size() > 100)
|
throw new PushException(1, "设备数不能超过100个");
|
String intent = getIntent("ZNX", null, null, null, null);
|
if (intent == null)
|
return;
|
|
try {
|
String result = sendPushHWMessageForIntent(deviceTokens, title, content, intent);
|
net.sf.json.JSONObject data = net.sf.json.JSONObject.fromObject(result);
|
if (!"success".equalsIgnoreCase(data.optString("msg")))
|
throw new PushException(2, result);
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
|
public static void pushWEEX(List<String> deviceTokens, String title, String content, String weexUrl)
|
throws PushException {
|
String activity = Constant.systemCommonConfig.getAndroidBaseactivityName() + ".ui.mine.weex.WeexApplicationActivity";
|
String intent = getIntent("weex", activity, weexUrl, weexUrl, null);
|
if (intent == null)
|
return;
|
|
try {
|
String result = sendPushHWMessageForIntent(deviceTokens, title, content, intent);
|
net.sf.json.JSONObject data = net.sf.json.JSONObject.fromObject(result);
|
if (!"success".equalsIgnoreCase(data.optString("msg")))
|
throw new PushException(2, result);
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
|
public static void pushBaiChuanUrl(List<String> deviceTokens, String title, String content, String url)
|
throws PushException {
|
String intent = getIntent("baichuan", null, url, null, null);
|
if (intent == null)
|
return;
|
|
try {
|
String result = sendPushHWMessageForIntent(deviceTokens, title, content, intent);
|
net.sf.json.JSONObject data = net.sf.json.JSONObject.fromObject(result);
|
if (!"success".equalsIgnoreCase(data.optString("msg")))
|
throw new PushException(2, result);
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
|
public static void pushWelfareCenter(List<String> deviceTokens, String title, String content) throws PushException {
|
String activity = Constant.systemCommonConfig.getAndroidBaseactivityName() + ".ui.mine.WelfareCenterActivity";
|
String intent = getIntent("welfare", activity, null, null, null);
|
if (intent == null)
|
return;
|
|
try {
|
String result = sendPushHWMessageForIntent(deviceTokens, title, content, intent);
|
net.sf.json.JSONObject data = net.sf.json.JSONObject.fromObject(result);
|
if (!"success".equalsIgnoreCase(data.optString("msg")))
|
throw new PushException(2, result);
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
|
|
public static void pushUserSignInNotification(List<String> deviceTokens, String title, String content) throws PushException {
|
String activity = Constant.systemCommonConfig.getAndroidBaseactivityName() + ".ui.goldtask.GoldTaskActivity";
|
String intent = getIntent("signin", activity, null, null, null);
|
if (intent == null)
|
return;
|
|
try {
|
String result = sendPushHWMessageForIntent(deviceTokens, title, content, intent);
|
net.sf.json.JSONObject data = net.sf.json.JSONObject.fromObject(result);
|
if (!"success".equalsIgnoreCase(data.optString("msg")))
|
throw new PushException(2, result);
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
|
/**
|
* 推送设备消息
|
*
|
* @param deviceTokens
|
* -最大1000条
|
* @param title
|
* -标题
|
* @param content
|
* -内容
|
* @param intent
|
* 如:intent:#Intent;component=com.yeshi.ec.rebate/.myapplication.
|
* ui.invite.ShareBrowserActivity;S.url="+URLEncoder.encode("http
|
* ://www.baidu.com")+";end
|
* @return
|
* @throws IOException
|
*/
|
private static String sendPushHWMessageForIntent(List<String> deviceTokens, String title, String content,
|
String intent) throws IOException {
|
if (tokenExpiredTime <= System.currentTimeMillis()) {
|
refreshToken();
|
}
|
|
/* PushManager.requestToken为客户端申请token的方法,可以调用多次以防止申请token失败 */
|
/* PushToken不支持手动编写,需使用客户端的onToken方法获取 */
|
JSONArray deviceTokenList = new JSONArray();// 目标设备Token
|
for (String deviceToken : deviceTokens) {
|
deviceTokenList.add(deviceToken);
|
}
|
|
// 仅通知栏消息需要设置标题和内容,透传消息key和value为用户自定义
|
JSONObject body = new JSONObject();
|
body.put("title", title);// 消息标题
|
body.put("content", content);// 消息内容体
|
|
// 定义需要打开的appPkgName
|
JSONObject param = new JSONObject();
|
// param.put("url", "http://www.baidu.com");
|
|
param.put("intent", intent);
|
// param.put("appPkgName", "com.yeshi.ec.rebate");
|
|
JSONObject action = new JSONObject();
|
action.put("type", 1);// (1 自定义行为:行为由参数intent定义;2 打开URL:URL地址由参数url定义;3
|
// 打开APP:默认值,打开App的首页)
|
action.put("param", param);// 消息点击动作参数
|
|
JSONObject msg = new JSONObject();
|
msg.put("type", 3);// 3: 通知栏消息,异步透传消息请根据接口文档设置
|
msg.put("action", action);// 消息点击动作
|
msg.put("body", body);// 通知栏消息body内容
|
|
// 扩展信息,含BI消息统计,特定展示风格,消息折叠。
|
JSONObject ext = new JSONObject();
|
|
// ext.put("icon",
|
// "http://pic.qiantucdn.com/58pic/12/38/18/13758PIC4GV.jpg");//
|
// 自定义推送消息在通知栏的图标,value为一个公网可以访问的URL
|
|
// 华为PUSH消息总结构体
|
JSONObject hps = new JSONObject();
|
hps.put("msg", msg);
|
hps.put("ext", ext);
|
|
JSONObject payload = new JSONObject();
|
payload.put("hps", hps);
|
|
System.out.println(payload.toJSONString());
|
|
String postBody = MessageFormat.format(
|
"access_token={0}&nsp_svc={1}&nsp_ts={2}&device_token_list={3}&payload={4}",
|
URLEncoder.encode(accessToken, "UTF-8"), URLEncoder.encode("openpush.message.api.send", "UTF-8"),
|
URLEncoder.encode(String.valueOf(System.currentTimeMillis() / 1000), "UTF-8"),
|
URLEncoder.encode(deviceTokenList.toString(), "UTF-8"), URLEncoder.encode(payload.toString(), "UTF-8"));
|
|
String postUrl = apiUrl + "?nsp_ctx="
|
+ URLEncoder.encode("{\"ver\":\"1\", \"appId\":\"" + appId + "\"}", "UTF-8");
|
String result = httpPost(postUrl, postBody, 5000, 5000);
|
|
return result;
|
}
|
|
/**
|
* 推送打开APP的消息
|
*
|
* @param deviceTokens
|
* @param title
|
* @param content
|
* @return
|
* @throws IOException
|
*/
|
private static String sendPushHWMessageForOpenApp(List<String> deviceTokens, String title, String content)
|
throws IOException {
|
if (tokenExpiredTime <= System.currentTimeMillis()) {
|
refreshToken();
|
}
|
|
/* PushManager.requestToken为客户端申请token的方法,可以调用多次以防止申请token失败 */
|
/* PushToken不支持手动编写,需使用客户端的onToken方法获取 */
|
JSONArray deviceTokenList = new JSONArray();// 目标设备Token
|
for (String deviceToken : deviceTokens) {
|
deviceTokenList.add(deviceToken);
|
}
|
|
// 仅通知栏消息需要设置标题和内容,透传消息key和value为用户自定义
|
JSONObject body = new JSONObject();
|
body.put("title", title);// 消息标题
|
body.put("content", content);// 消息内容体
|
|
// 定义需要打开的appPkgName
|
JSONObject param = new JSONObject();
|
|
JSONObject action = new JSONObject();
|
action.put("type", 3);// (1 自定义行为:行为由参数intent定义;2 打开URL:URL地址由参数url定义;3
|
// 打开APP:默认值,打开App的首页)
|
action.put("param", param);// 消息点击动作参数
|
|
JSONObject msg = new JSONObject();
|
msg.put("type", 3);// 3: 通知栏消息,异步透传消息请根据接口文档设置
|
msg.put("action", action);// 消息点击动作
|
msg.put("body", body);// 通知栏消息body内容
|
|
// 扩展信息,含BI消息统计,特定展示风格,消息折叠。
|
JSONObject ext = new JSONObject();
|
ext.put("biTag", "Trump");// 设置消息标签,如果带了这个标签,会在回执中推送给CP用于检测某种类型消息的到达率和状态
|
// ext.put("icon",
|
// "http://pic.qiantucdn.com/58pic/12/38/18/13758PIC4GV.jpg");//
|
// 自定义推送消息在通知栏的图标,value为一个公网可以访问的URL
|
|
// 华为PUSH消息总结构体
|
JSONObject hps = new JSONObject();
|
hps.put("msg", msg);
|
hps.put("ext", ext);
|
|
JSONObject payload = new JSONObject();
|
payload.put("hps", hps);
|
|
String postBody = MessageFormat.format(
|
"access_token={0}&nsp_svc={1}&nsp_ts={2}&device_token_list={3}&payload={4}",
|
URLEncoder.encode(accessToken, "UTF-8"), URLEncoder.encode("openpush.message.api.send", "UTF-8"),
|
URLEncoder.encode(String.valueOf(System.currentTimeMillis() / 1000), "UTF-8"),
|
URLEncoder.encode(deviceTokenList.toString(), "UTF-8"), URLEncoder.encode(payload.toString(), "UTF-8"));
|
|
String postUrl = apiUrl + "?nsp_ctx="
|
+ URLEncoder.encode("{\"ver\":\"1\", \"appId\":\"" + appId + "\"}", "UTF-8");
|
String result = httpPost(postUrl, postBody, 5000, 5000);
|
|
return result;
|
}
|
|
/**
|
*
|
* 方法说明: 获取下发通知消息的认证Token
|
*
|
* @author mawurui createTime 2018年5月14日 下午4:47:26
|
* @throws IOException
|
*/
|
private static void refreshToken() throws IOException {
|
String msgBody = MessageFormat.format("grant_type=client_credentials&client_secret={0}&client_id={1}",
|
URLEncoder.encode(appSecret, "UTF-8"), appId);
|
String response = httpPost(tokenUrl, msgBody, 5000, 5000);
|
JSONObject obj = JSONObject.parseObject(response);
|
accessToken = obj.getString("access_token");
|
tokenExpiredTime = System.currentTimeMillis() + obj.getLong("expires_in") * 1000 - 5 * 60 * 1000;
|
}
|
|
public static String httpPost(String httpUrl, String data, int connectTimeout, int readTimeout) throws IOException {
|
OutputStream outPut = null;
|
HttpURLConnection urlConnection = null;
|
InputStream in = null;
|
|
try {
|
URL url = new URL(httpUrl);
|
urlConnection = (HttpURLConnection) url.openConnection();
|
urlConnection.setRequestMethod("POST");
|
urlConnection.setDoOutput(true);
|
urlConnection.setDoInput(true);
|
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
|
urlConnection.setConnectTimeout(connectTimeout);
|
urlConnection.setReadTimeout(readTimeout);
|
urlConnection.connect();
|
|
// POST data
|
outPut = urlConnection.getOutputStream();
|
outPut.write(data.getBytes("UTF-8"));
|
outPut.flush();
|
|
if (urlConnection.getResponseCode() < 400) {
|
in = urlConnection.getInputStream();
|
} else {
|
in = urlConnection.getErrorStream();
|
}
|
|
List<String> lines = IOUtils.readLines(in, urlConnection.getContentEncoding());
|
StringBuffer strBuf = new StringBuffer();
|
for (String line : lines) {
|
strBuf.append(line);
|
}
|
System.out.println(strBuf.toString());
|
return strBuf.toString();
|
} finally {
|
IOUtils.closeQuietly(outPut);
|
IOUtils.closeQuietly(in);
|
if (urlConnection != null) {
|
urlConnection.disconnect();
|
}
|
}
|
}
|
}
|