我正在参加「掘金·启航计划」
首先上的是微信官方文档:developers.weixin.qq.com/minigame/de…
由于微信支付具有一定的限制性,所以我们在特定的场景下,用户可以跳转到公众号,然后发送对应的url后拉起支付。那么这种场景是怎么实现的呢。就是通过消息推送实现的。 我们可以看下下面的一个使用场景,小程序无法支付的情况下,用户跳转到微信公众号完成付费。
- url:服务的地址一般服务器地址+接口名称
- token令牌+消息加密秘钥:可以自定义
- 消息加密方式+数据格式:建议明文+XML方面
回调测试代码,主要是为了让微信服务器调用。能够将正确的报文返回给微信。
@RequestMapping(value = "/checkWeixinValid", method = RequestMethod.GET)
public String checkWeixinValid(@RequestParam(name = "signature") String signature,
@RequestParam(name = "timestamp") String timestamp,
@RequestParam(name = "nonce") String nonce,
@RequestParam(name = "echostr") String echostr) {
// .......
return echostr;
}
真实案例:
- 本次是用了xml的方式解析。所以会有一步是将xml解析成map。
- 解析完成,看参数的组成,然后根据自定义的规则去过滤组装参数。
- 给微信发送消息。
最后附上代码(代码仅供参考,如果需要交流可以关注私信我):
@RequestMapping(value = "/checkWeixinValid", method = RequestMethod.POST)
public void replyMessage(HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String, String> map = null;
//从工具类中获取XML解析之后的map
try {
map = readWechatXml(request);
} catch (IOException e) {
log.error("获取输入流失败", e);
} catch (DocumentException e) {
log.error("读取XML失败", e);
}
assert map != null;
replyMessage(map,response);
log.info("自动回复的消息内容为:{}", JSON.toJSONString(map));
}
@SuppressWarnings("unchecked")
public static Map<String, String> readWechatXml(HttpServletRequest request) throws IOException, DocumentException {
Map<String, String> map = new HashMap<String, String>(16);
//获取输入流
InputStream input = request.getInputStream();
//使用dom4j的SAXReader读取(org.dom4j.io.SAXReader;)
SAXReader sax = new SAXReader();
Document doc = sax.read(input);
//获取XML数据包根元素
Element root = doc.getRootElement();
//得到根元素的所有子节点
List<Element> elementList = root.elements();
//遍历所有节点并将其放进map
for (Element e : elementList) {
map.put(e.getName(), e.getText());
}
//释放资源
input.close();
return map;
}
// 发送消息
public void replyMessage(Map<String, String> msg, HttpServletResponse response) throws Exception {
System.out.println("客服消息自动回复 ====> start");
String opendId = msg.get("FromUserName");
Map<String, String> contenMap = Maps.newHashMapWithExpectedSize(2);
// 若用户消息包含关键字则自动回复
try {
// 给用户发送的消息
contenMap.put("content", "请点击链接打开APP:" + "https://www.baidu.com");
} catch (Exception e) {
contenMap.put("content", e.getMessage());
}
sendMessage(opendId, "text", contenMap);
// 此处将消息转发至人工客服,不然人工客服窗会没有消息
Map<String, Object> tranMap = Maps.newHashMapWithExpectedSize(4);
tranMap.put("ToUserName", msg.get("FromUserName"));
tranMap.put("FromUserName", msg.get("ToUserName"));
tranMap.put("CreateTime", msg.get("CreateTime"));
tranMap.put("MsgType", "transfer_customer_service");
printData(JSONObject.toJSONString(tranMap), response);
}
// 发送消息
private void sendMessage(String opendId, String msgType, Map<String, String> contentMap) throws
UnsupportedEncodingException {
Map<String, Object> replyMessageMap = Maps.newHashMapWithExpectedSize(4);
replyMessageMap.put("touser", opendId);
replyMessageMap.put("msgtype", msgType);
replyMessageMap.put(msgType, contentMap);
String messageJson = JSONObject.toJSONString(replyMessageMap);
messageJson = new String(messageJson.getBytes(), "UTF-8");
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"
.replace("APPID", "appId")
.replace("APPSECRET", "secret");
String response = HttpUtil.get(url);
if (response == null) {
return;
}
WxAccessTokenRes wxAccessTokenRes = JSONUtil.toBean(response, WxAccessTokenRes.class);
String geturl = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token="
+ wxAccessTokenRes.getAccess_token();
// 发送结果
HttpUtil.post(geturl, messageJson);
}
private void printData(String data, HttpServletResponse resp) {
PrintWriter out;
try {
resp.reset();
resp.getOutputStream().print("success");
out = resp.getWriter();
out.print(data);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}