今天要说的是微信推送消息的详细流程,配合微信开发手册一起使用哦,虽然说开发手册有坑,但是毕竟我们需要使用他开发
我们登陆 微信公众平台在「微信公众平台 - 设置 - 开发设置」页 配置服务器的URL,填写 Token令牌 消息加密密钥 加密方式和数据格式这些基本的信息,数据格式我这里使用的是JSON格式
这里配置完成一会微信需要验证下你输入的URL,也就是说你需要按照微信的验证规则写一个接口,以下是JAVA片段
public void receiveMsg(){
String echostr = getPara("echostr");// 随机字符串
//判断是否为认证
if(StringUtils.isBlank(echostr)){
//否则接收客户发送消息
responseMsg();
}else {
//如果认证去验证
checkSignature();
}
}
这里就是你在微信配置的URL,根据echostr判断是 验证 还是 发图文消息
private void checkSignature() {
String echostr = getPara("echostr");// 随机字符串
String signature = getPara("signature");// 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
String timestamp = getPara("timestamp");// 时间戳
String nonce = getPara("nonce");// 随机数
PrintWriter out = null;
try {
out = getResponse().getWriter();
// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,否则接入失败
if (loveHomeSerivce.checkSignature(signature, timestamp, nonce)) {
out.print(echostr);
out.flush();//这个地方必须画重点,消息推送配置Token令牌错误校验失败,搞了我很久,必须要刷新!!!!!!!
}
} catch (IOException e) {
e.printStackTrace();
logger.error("获取Response错误");
} finally {
out.close();
}
}
public static boolean checkSignature(String signature, String timestamp, String nonce) {
//与token 比较
String[] arr = new String[] {TOKEN, timestamp, nonce };
// 将token、timestamp、nonce三个参数进行字典排序
Arrays.sort(arr);
StringBuilder content = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
content.append(arr[i]);
}
MessageDigest md = null;
String tmpStr = null;
try {
md = MessageDigest.getInstance("SHA-1");
// 将三个参数字符串拼接成一个字符串进行sha1加密
byte[] digest = md.digest(content.toString().getBytes());
tmpStr = StrUtil.byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
content = null;
// 将sha1加密后的字符串可与signature对比
return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
}
/**
* 将字节数组转换为十六进制字符串
*
* @param byteArray
* @return
*/
public static String byteToStr(byte[] byteArray) {
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
}
开发者通过检验 signature 对请求进行校验(下面有校验方式)。若确认此次 GET 请求来自微信服务器,请原样返回 echostr 参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验流程如下:
验证成功后以后访问你在微信配置的URL就是发送图文消息,以上验证只是验证你配置的URL是否正常,下面是发送图文消息的代码
public void responseMsg(){
PrintWriter out = null;//输入返回内容
try {
out = getResponse().getWriter();
//处理Post请求中的body
Map mapResult = HttpRequestUtil.getPostRequestBody(getRequest());
String openid = mapResult.get("FromUserName");//发送者的openid
String title = mapResult.get("Title");//标题
String pagePath = mapResult.get("PagePath");//小程序页面路径
String thumbUrl = mapResult.get("ThumbUrl");//封面图片的临时cdn链接
if(StringUtils.isBlank(openid) || StringUtils.isBlank(title) || StringUtils.isBlank(pagePath) || StringUtils.isBlank(thumbUrl)){
return;
}
JSONObject jsonObject = loveHomeSerivce.sendImgLink(openid, title, pagePath, thumbUrl);
if(jsonObject == null){
logger.error("发送客服消息接口返回失败!");
return;
}
logger.error("微信返回请求:errcode="+jsonObject.getIntValue("errcode")+",errmsg="+jsonObject.getString("errmsg"));
} catch (Exception e) {
e.printStackTrace();
logger.error("发送客服消息接口失败!");
}
out.print("success");
out.flush();
这里注意 本人这里测试直接return"success" 是不行的,自己可以尝试下,这就是所谓的微信开发文档的坑吧
public JSONObject sendImgLink(String openid, String title, String pagePath, String thumbUrl) throws IOException {
//获取接口凭证url
String getAccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET";
//获取接口凭证
String accessToken = getAccessToken(getAccessTokenUrl,appId,secret);
//发送微信请求
JSONObject PostJson = sendXIRequest(openid, title, pagePath, thumbUrl, accessToken);
return PostJson;
}
/**
1. 获取接口凭证
*/
private String getAccessToken(String url, String appId, String secret) throws IOException {
HttpClient oHttpClient = new HttpClient();
//设置传入参数
url = url.replace("APPID", appId);
url = url.replace("SECRET", secret);
//发送获取接口凭证接口
GetMethod oMethod = new GetMethod(url);
String sResponsePost = "";//获取接口凭证的结果
String accessToken = null;//获取接口凭证
oHttpClient.executeMethod(oMethod);
//获取访问结果
sResponsePost = new String(oMethod.getResponseBody(), "UTF-8");
JSONObject GetJsonResult = JSONObject.parseObject(sResponsePost);
Map mapResult = JSONObject.toJavaObject(GetJsonResult, Map.class);
accessToken = mapResult.get("access_token");
if(accessToken == null){
g_logger.error("发送客服消息接口失败!");
}
return accessToken;
}
获取接口凭证是需要传入三个参数:
/**
* @Description //TODO 发送微信请求
**/
private JSONObject sendXIRequest(String openid, String title, String pagePath, String thumbUrl, String accessToken) {
//发送请求接口
Map linkMap = getSignUpInfo(title,pagePath,thumbUrl);
JSONObject wxPar = new JSONObject();
wxPar.put("touser", openid);
wxPar.put("msgtype", "link");
wxPar.put("link", linkMap);
String requestUrl="https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN";
requestUrl=requestUrl.replace("ACCESS_TOKEN", accessToken);
wxPar = WeixinUtil.httpRequest(requestUrl,"POST",wxPar.toString());
return wxPar;
}
发送图文消息时传入的参数:
public Map getSignUpInfo(String title, String pagePath, String imgUrl){
Map map = new HashMap();
if (pagePath != null && pagePath.length() > 1){
map.put("title", title);
map.put("description", "打开页面,点击右上角【......】分享");
Map parser = UrlAnalysis.parser(pagePath);
StringBuffer signUpUrl = new StringBuffer();
signUpUrl.append(URL);
map.put("url", signUpUrl.toString());
map.put("thumb_url", imgUrl);
}
return map;
}
link的拼接参数:
好了这样就可以了,各位大佬,有何不对请指教!