大家好,我是小悟
时间过得真快,转眼就到了国庆节尾巴,小伙伴们吃好喝好玩好了么。
关于微信开放平台第三方代小程序开发的两个事件接收推送通知,是开放平台代小程序实现业务的重要功能。
授权事件推送,事件类型以InfoType的值判断,消息与事件推送,事件类型以Event的值判断。
授权事件推送通知
授权事件推送包括:验证票据、授权成功、取消授权、授权更新、快速注册企业小程序、快速注册个人小程序、注册试用小程序、试用小程序快速认证、发起小程序管理员人脸核身、申请小程序备案。微信服务器会向第三方平台方的授权事件接收 URL 以 POST 的方式推送相关通知。
值得注意的是,关于发起小程序管理员人脸核身和申请小程序备案,官方文档归类的是消息与事件推送,数据格式是JSON。实测应该是授权事件推送,数据格式仍然是XML。
验证票据:在第三方平台创建审核通过后,微信服务器会向其“授权事件接收URL” 每隔10分钟以 POST 的方式推送票据。
InfoType的值为component_verify_ticket
<xml>
<AppId>some_appid</AppId>
<CreateTime>1413192605</CreateTime>
<InfoType>component_verify_ticket</InfoType>
<ComponentVerifyTicket>some_verify_ticket</ComponentVerifyTicket>
</xml>
授权成功:InfoType的值为authorized
<xml>
<AppId>第三方平台appid</AppId>
<CreateTime>1413192760</CreateTime>
<InfoType>authorized</InfoType>
<AuthorizerAppid>公众号appid</AuthorizerAppid>
<AuthorizationCode>授权码</AuthorizationCode>
<AuthorizationCodeExpiredTime>过期时间</AuthorizationCodeExpiredTime>
<PreAuthCode>预授权码</PreAuthCode>
<xml>
取消授权:InfoType的值为unauthorized
<xml>
<AppId>第三方平台appid</AppId>
<CreateTime>1413192760</CreateTime>
<InfoType>unauthorized</InfoType>
<AuthorizerAppid>公众号appid</AuthorizerAppid>
</xml>
授权更新:InfoType的值为updateauthorized
<xml>
<AppId>第三方平台appid</AppId>
<CreateTime>1413192760</CreateTime>
<InfoType>updateauthorized</InfoType>
<AuthorizerAppid>公众号appid</AuthorizerAppid>
<AuthorizationCode>授权码</AuthorizationCode>
<AuthorizationCodeExpiredTime>过期时间</AuthorizationCodeExpiredTime>
<PreAuthCode>预授权码</PreAuthCode>
<xml>
快速注册企业小程序:InfoType的值为notify_third_fasteregister
<xml>
<AppId><![CDATA[第三方平台appid]]></AppId>
<CreateTime>1535442403</CreateTime>
<InfoType><![CDATA[notify_third_fasteregister]]></InfoType>
<appid>创建小程序appid</appid>
<status>0</status>
<auth_code>xxxxx第三方授权码</auth_code>
<msg>OK</msg>
<info>
<name><![CDATA[企业名称]]></name>
<code><![CDATA[企业代码]]></code>
<code_type>1</code_type>
<legal_persona_wechat><![CDATA[法人微信号]]></legal_persona_wechat>
<legal_persona_name><![CDATA[法人姓名]]></legal_persona_name>
<component_phone><![CDATA[第三方联系电话]]></component_phone>
</info>
</xml>
快速注册个人小程序:InfoType的值为notify_third_fasteregister
<xml>
<AppId><![CDATA[第三方平台appid]]></AppId>
<CreateTime>1535442403</CreateTime>
<InfoType><![CDATA[notify_third_fasteregister]]></InfoType>
<appid>创建小程序appid</appid>
<status>0</status>
<auth_code>xxxxx第三方授权码</auth_code>
<msg>OK</msg>
<info>
<taskid><![CDATA[任务id]]></taskid> 实测只有返回这个
<wxuser><![CDATA[用户微信号]]></wxuser> 实测没有返回这个
<idname><![CDATA[用户姓名]]></wxidnnn> 实测没有返回这个
<component_phone><![CDATA[第三方联系电话]]></component_phone> 实测没有返回这个
</info>
</xml>
注册试用小程序:InfoType的值为notify_third_fastregisterbetaapp
<xml>
<AppId><![CDATA[第三方平台appid]]></AppId>
<CreateTime>1535442403</CreateTime>
<InfoType><![CDATA[notify_third_fastregisterbetaapp]]></InfoType>
<appid>创建小程序appid<appid>
<status>0</status>
<msg>OK</msg>
<info>
<unique_id><![CDATA[unique_id]]></unique_id>
<name><![CDATA[小程序名称]]></name>
</info>
</xml>
试用小程序快速认证:InfoType的值为notify_third_fastverifybetaapp
<xml>
<AppId><![CDATA[第三方平台appid]]></AppId>
<CreateTime>1535442403</CreateTime>
<InfoType><![CDATA[notify_third_fastverifybetaapp]]></InfoType>
<appid>小程序appid<appid>
<status>0</status>
<msg>OK</msg>
<info>
<name><![CDATA[企业名称]]></name>
<code><![CDATA[企业代码]]></code>
<code_type>1</code_type>
<legal_persona_wechat><![CDATA[法人微信号]]></legal_persona_wechat>
<legal_persona_name><![CDATA[法人姓名]]></legal_persona_name>
<component_phone><![CDATA[第三方联系电话]]></component_phone>
</info>
</xml>
发起小程序管理员人脸核身:InfoType的值为notify_icpfiling_verify_result
<xml>
<AppId><![CDATA[第三方平台appid]]></AppId>
<CreateTime>1689839779</CreateTime>
<InfoType><![CDATA[notify_icpfiling_verify_result]]></InfoType>
<task_id>人脸核验任务id<task_id>
<verify_appid>小程序唯一id</verify_appid>
<result>人脸核验结果:2-核验失败;3-核验成功</result>
</xml>
申请小程序备案:InfoType的值为notify_apply_icpfiling_result
<xml>
<AppId><![CDATA[第三方平台appid]]></AppId>
<CreateTime>1689839779</CreateTime>
<InfoType><![CDATA[notify_apply_icpfiling_result]]></InfoType>
<authorizer_appid>小程序唯一id<authorizer_appid>
<beian_status>备案状态</beian_status>
</xml>
接收 POST 请求后,只需直接返回字符串 success。为了加强安全性,postdata 中的 xml 将使用服务申请时的加解密 key 来进行加密,在收到推送后需进行解密。
@PostMapping(value = "saveTicket")
public void saveTicket(HttpServletRequest request, HttpServletResponse response) throws IOException {
String msgSignature = request.getParameter("msg_signature");
String timeStamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(),"UTF-8"));
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
sb = sb.append(line);
}
String postData = sb.toString();
try {
logger.warn("推送component_verify_ticket协议---->获得数据为msgSignature={},timeStamp={}, nonce={},postData={}",
msgSignature, timeStamp, nonce, postData);
ComponentVerifyTicket obj = DecryptMsgKey.loadComponentVerifyTicket(nonce, timeStamp, msgSignature,postData);
String infoType = obj.getInfoType();
logger.warn("infoType:{}", infoType);
if (StringUtils.equals("component_verify_ticket", infoType)) {
RedisService<ComponentVerifyTicket> redisService = RedisService.load();
redisService.save(obj, ComponentVerifyTicket.class);
logger.warn("推送component_verify_ticket协议---->成功,保存到缓存中的值为:" + obj);
} else if (StringUtils.equals("authorized", infoType)) {
logger.warn("授权成功");
} else if (StringUtils.equals("unauthorized", infoType)) {
logger.warn("取消授权");
} else if (StringUtils.equals("updateauthorized", infoType)) {
logger.warn("授权更新");
} else if (StringUtils.equals("notify_third_fasteregister", infoType)) {
logger.warn("快速注册小程序");
} else if (StringUtils.equals("notify_third_fastregisterbetaapp", infoType)) {
logger.warn("注册试用小程序");
} else if (StringUtils.equals("notify_third_fastverifybetaapp", infoType)) {
logger.warn("试用小程序快速认证");
} else if (StringUtils.equals("notify_icpfiling_verify_result", infoType)) {
logger.warn("发起小程序管理员人脸核身");
} else if (StringUtils.equals("notify_apply_icpfiling_result", infoType)) {
logger.warn("申请小程序备案");
}
} catch (Exception e) {
logger.error("系统异常", e);
} finally {
// 响应消息
PrintWriter out = response.getWriter();
out.print("success");
}
}
消息与事件推送通知
消息与事件推送包括:设置小程序名称、添加类目、提交代码审核。审核结果会向消息与事件接收 URL 进行事件推送。
设置小程序名称:Event的值为wxa_nickname_audit
<xml>
<ToUserName><![CDATA[gh_fxxxxxxxa4b2]]></ToUserName>
<FromUserName><![CDATA[odxxxxM-xxxxxxxx-trm4a7apsU8]]></FromUserName>
<CreateTime>1488800000</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[wxa_nickname_audit]]></Event>
<ret>2</ret>
<nickname>昵称</nickname>
<reason>驳回原因</reason>
</xml>
添加类目:Event的值为wxa_category_audit
<xml>
<ToUserName><![CDATA[gh_fxxxxxxxa4b2]]></ToUserName>
<FromUserName><![CDATA[odxxxxM-xxxxxxxx-trm4a7apsU8]]></FromUserName>
<CreateTime>1488800000</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[wxa_category_audit]]></Event>
<ret>2</ret>
<first>一级类目id</nickname>
<second>二级类目id</reason>
<reason>驳回原因</reason>
</xml>
提交代码审核:包括三种结果,审核通过、审核不通过、审核延后。
审核通过:Event的值为weapp_audit_success
<xml>
<ToUserName><![CDATA[gh_fb9688c2a4b2]]></ToUserName>
<FromUserName><![CDATA[od1P50M-fNQI5Gcq-trm4a7apsU8]]></FromUserName>
<CreateTime>1488856741</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[weapp_audit_success]]></Event>
<SuccTime>1488856741</SuccTime>
</xml>
审核不通过:Event的值为weapp_audit_fail
<xml>
<ToUserName><![CDATA[gh_fb9688c2a4b2]]></ToUserName>
<FromUserName><![CDATA[od1P50M-fNQI5Gcq-trm4a7apsU8]]></FromUserName>
<CreateTime>1488856591</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[weapp_audit_fail]]></Event>
<Reason><![CDATA[1:账号信息不符合规范:<br>(1):包含不适合因素<br>2:服务类目"金融业-保险_"与你提交代码审核时设置的功能页面内容不一致:<br>(1):功能页面设置的部分标签不属于所选的服务类目范围。<br>(2):功能页面设置的部分标签与该页面内容不相关。<br>]]></Reason>
<FailTime>1488856591</FailTime>
<ScreenShot>xxx|yyy|zzz</ScreenShot>
</xml>
审核延后:Event的值为weapp_audit_delay
<xml>
<ToUserName><![CDATA[gh_fb9688c2a4b2]]></ToUserName>
<FromUserName><![CDATA[od1P50M-fNQI5Gcq-trm4a7apsU8]]></FromUserName>
<CreateTime>1488856591</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[weapp_audit_delay]]></Event>
<Reason><![CDATA[为了更好的服务小程序,您的服务商正在进行提审系统的优化,可能会导致审核时效的增长,请耐心等待]]></Reason>
<DelayTime>1488856591</DelayTime>
</xml>
接收 POST 请求后,只需直接返回字符串 success。为了加强安全性,postdata 中的 xml 将使用服务申请时的加解密 key 来进行加密,在收到推送后需进行解密。
@PostMapping(value = "/notify/{appId}/callback")
public void callback(@PathVariable("appId") String appId, HttpServletRequest request, HttpServletResponse response) throws IOException {
logger.info("消息与事件通知appId:{}", appId);
String msgSignature = request.getParameter("msg_signature");
String timeStamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(),"UTF-8"));
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
sb = sb.append(line);
}
String postData = sb.toString();
logger.info("消息与事件通知postData:{}", postData);
try {
PushCallbackEvent pushCallbackEvent = DecryptMsgKey.loadPushCallbackEvent(nonce, timeStamp, msgSignature, postData);
String event = pushCallbackEvent.getEvent();
if (StringUtils.equals("wxa_nickname_audit", event)) {
logger.warn("设置小程序名称");
} else if (StringUtils.equals("wxa_category_audit", event)) {
logger.warn("添加类目");
} else if (StringUtils.equals("weapp_audit_success", event)) {
logger.warn("提交代码审核通过");
} else if (StringUtils.equals("weapp_audit_fail", event)) {
logger.warn("提交代码审核不通过");
} else if (StringUtils.equals("weapp_audit_delay", event)) {
logger.warn("提交代码审核延后");
}
} catch (Exception e) {
logger.error("系统异常", e);
} finally {
// 响应消息
PrintWriter out = response.getWriter();
out.print("success");
}
}
您的一键三连,是我更新的最大动力,谢谢
山水有相逢,来日皆可期,谢谢阅读,我们再会
我手中的金箍棒,上能通天,下能探海