首先是需要定义两个请求接口: 一个是get请求用于微信小店后台绑定服务器对应的路由 一个是post请求用于接受微信小店不同的事件回调
微信小店的话回调数据主要是相关json数据回传过来 相比于之前接入的企微回调的相关内容是xml类型,需要避免xss拦截,以及对应官网工具类转一层;
消息推送:developers.weixin.qq.com/doc/store/s…
相关代码内容示例:
@Autowired
WechatStoreConfig wechatStoreConfig;
//get请求用于微信小店后台绑定路由验证
@GetMapping("/callback")
public void callback(HttpServletRequest request, HttpServletResponse response) throws IOException {
String msgSignature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String echostr = request.getParameter("echostr").trim();
echostr = echostr.replace(" ", "+");
log.info("微信小店收到回调消息: msgSignature={}, timestamp={}, nonce={},echostr={}", msgSignature, timestamp, nonce,echostr);
String token = wechatStoreConfig.getWechatStoreToken();
// 将 token、timestamp、nonce 进行字典序排序
List<String> params = Arrays.asList(nonce, timestamp, token);
// 将排序后的参数字符串拼接成一个字符串
Collections.sort(params);
StringBuilder paramStr = new StringBuilder();
for (String param : params) {
paramStr.append(param);
}
String calculatedSignature = sha1(paramStr.toString());
String result =null;
if (msgSignature.equals(calculatedSignature)) {
// 相等说明请求来自微信服务器,合法,回包消息体内容为 echostr
result = echostr;
}
log.info("密文: calculatedSignature={}", calculatedSignature);
response.getWriter().print(result);
response.getWriter().close();
}
//post请求接受订阅:
@PostMapping(value = "/callback")
public String callBack() {
String result = "success";
String token = wechatStoreConfig.getWechatStoreToken();
String storeId = wechatStoreConfig.getWechatStoreId();
String appSecret = wechatStoreConfig.getWechatStoreAppSecret();
String wechatStoreEncodingAesKey = wechatStoreConfig.getWechatStoreEncodingAesKey();
ServletRequestAttributes servletRequestAttributes = null;
try {
if (RequestContextHolder.getRequestAttributes() != null) {
servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (servletRequestAttributes != null) {
HttpServletRequest request = servletRequestAttributes.getRequest();
String sMsgSignature = request.getParameter("msg_signature");
// 时间戳
String sTimestamp = request.getParameter("timestamp");
// 随机数
String sNonce = request.getParameter("nonce");
log.info("微信小店收到回调消息: msg_signature={}, timestamp={}, sNonce={}", sMsgSignature, sTimestamp, sNonce);
InputStream inputStream = request.getInputStream();
String sPostData = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
org.json.JSONObject json = new org.json.JSONObject(sPostData);
String encrypt = json.getString("Encrypt");
//验证是否微信请求:
// 将 token、timestamp、nonce 进行字典序排序
List<String> params = Arrays.asList(token, sTimestamp, sNonce,encrypt);
// 将排序后的参数字符串拼接成一个字符串
Collections.sort(params);
StringBuilder paramStr = new StringBuilder();
for (String param : params) {
paramStr.append(param);
}
//sha1--官方引入https://wximg.gtimg.com/shake_tv/mpwiki/cryptoDemo.zip
String calculatedSignature = sha1(paramStr.toString());
if (!sMsgSignature.equals(calculatedSignature)) {
log.warn("微信小店请求不合法: sMsgSignature={}, calculatedSignature={}", sMsgSignature, calculatedSignature);
// 相等说明请求来自微信服务器,合法,回包消息体内容为 echostr
return result;
}
//WXBizMsgCrypt--官方引入https://wximg.gtimg.com/shake_tv/mpwiki/cryptoDemo.zip
WXBizMsgCrypt wxBizMsgCrypt = new WXBizMsgCrypt(token, wechatStoreEncodingAesKey, storeId);
String sMsg = wxBizMsgCrypt.decrypt(encrypt);
log.info("微信小店,解析后的消息体信息:\n{}",sMsg);
ObjectMapper objectMapper = new ObjectMapper();
WecahtStoreMsg wechatMessage = objectMapper.readValue(sMsg, WecahtStoreMsg.class);
// 打印解析后的消息体
String event = wechatMessage.getEvent();
log.info("微信小店,序列化后的消息体:\n{},event{}", wechatMessage,event);
//event类型区分不同的事件:
//成功支付:channels_ec_order_pay
//退款同意:channels_ec_order_cancel cancel_type=3
//同时上述事件过来基本都有product_order_status_update事件回调
}
}
}catch (Exception e){
log.error("微信小店:回调异常",e);
}
return result;
}
//accessToken获取:常用:https://developers.weixin.qq.com/doc/store/shop/API/basics/getaccesstoken.html
1. 常用的事件:
成功支付事件:channels_ec_order_pay
退款事件相关事件:
1:channels_ec_order_cancel 对应的cancel_type为3,全部售后事件已完成,比如说用户买了两件,然后这两件都退掉:
WecahtStoreMsg(toUserName=XXX,fromUserName=XXX,createTime=1747221305,msgType=event,event=channels_ec_order_cancel,productOrderStatusUpdate=null,orderInfo=WecahtStoreMsg.OrderInfo(orderId=3728110005492004096,cancelType=3,payTime=0,finishDelivery=0),finderShopAftersaleStatusUpdate=null),eventchannels_ec_order_cancel
2:如果说用户一次性买了三件,然后只退了一件则会有对应的channels_ec_aftersale_update事件推送:
{"ToUserName":"XXX","FromUserName":"XXX","CreateTime":1747221304,"MsgType":"event","Event":"channels_ec_aftersale_update","finder_shop_aftersale_status_update":{"after_sale_order_id":"XXX","status":"MERCHANT_REFUND_SUCCESS","order_id":"XXX"}}
3:小店后台的话同意,拒绝退款,还有有协商退款,协商相关金额,具体退款金额可以根据after_sale_order_id 查询售后单,查询相关退款详情金额amount数据api:
developers.weixin.qq.com/doc/store/s…
4:可以同时买多笔订单,需要批处理下
5:虚拟商品相关信息:订单详情的:RechargeInfo中
2. 后台相关配置:
相关api配置:
点击服务市场经营工具,右上角的自研,配置相关消息推送的路由
2:微信小店后台可以配置自定义商品id进行关联起来:
3:一些api:
获取订单详情:developers.weixin.qq.com/doc/store/s… developers.weixin.qq.com/doc/store/s…