appid and openid not match问题
最近,运营发现在我们公司A公众号下授权登录的用户在微信里访问我们的H5官网时,无法进行支付,主要原因是付款时是B公众号的账户。
问题描述:由于业务问题,往往一个电商平台可能会有多个公众号,这些公众号可能用的是同一个微信联合登录接口,但是在提交订单的时候微信支付是需要验证APPID与OPENID的关联性,也就是说微信授权登录的公众号与结算的微信公众号必须是同一个公众号。那么,如何将多个公众号进行统一向一个公众号支付呢?
解决方案:
1、当遇到appid and openid not match这种微信支付报错之后,你就可以通知前端API需要更新你提交的APPID了。
我们公司的代码实现是将微信联合登录得到的OPENID写到了cookie里,提交订单的时候讲这个OPENID带给订单接口,当遇到appid and openid not match时候,我在js里开始调另外一个接口,并将当前的URL带给服务器,然后再这个接口里通过对支付的公众号的APPID去微信获取相应的OPENID,而且这一步是可以静默加载的,也就是不需要用户的授权的,同时将当前访问的URL写入到COOKIE里,这样在微信回调我的接口的时候我知道在获取OPENID后该回调那个页面。
/**
* 静默加载openId
*/
@RequestMapping(value = "getOpenId")
public void getOpenId(HttpServletResponse response,String url) {
try {
StringBuffer sb = new StringBuffer();
addCookie(WechatUtils.WECHAT_PAY_RETURN_KEY,url);
String callBackUrl = "http://" + Constant.WX_ROOT_DOMAIN
+ "/wechat/reloadOpenId.action";
sb.append(WchatConstant.AUTH_ACCESS_CODE_URL + "?appid=" + Constant.APPID + "&");
try {
sb.append("redirect_uri=").append(
URLEncoder.encode(callBackUrl, "utf-8"));
} catch (UnsupportedEncodingException e) {
logger.error("BaseFilter encode exception:" + e);
}
//重点是scope=snsapi_base,这个是静默加载
sb.append("&response_type=code&scope=snsapi_base&state=STATE&#wechat_redirect");
response.sendRedirect(sb.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 微信回调重新写入wechat_payment_openid
*/
@RequestMapping("reloadOpenId")
public void reloadOpenId(){
Map<String, Object> map = new HashMap<String, Object>();
try {
String code = super.getRequest().getParameter("code");
String state = super.getRequest().getParameter("state");
if (null == code || code.equals("authdeny") || null == state
|| state.isEmpty()) {
logger.error("微信授权出错");
return;
}
Map<String, String> mapAccessToken = WchatHttpClientUtils.getAccessTokenAndUid(
code, Constant.APPID, Constant.APPSECRET);
if(mapAccessToken != null && mapAccessToken.get("openid") != null){
addCookie(WechatUtils.OPENID_COOKIE_KEY, mapAccessToken.get("openid"));
}
String url = getCookieValue(WechatUtils.WECHAT_PAY_RETURN_KEY);
if(StringUtil.isNullorBlank(url)){
url = "http://" + Constant.CONFIG_DOMAIN;
}
this.getResponse().sendRedirect(url);
}catch (Exception e) {
e.printStackTrace();
}
}
}
代码可能有点乱,当时也急着解决的这个问题,这些代码都是在原来微信联合登录的基础的复制过来直接改了的,没有好好地整理一番,不过这些足以解决问题了。js里还有一点代码我也就不粘上来了,都告诉你们怎么实现了,解决跨公众号支付查资料大概用了3个小时,开始不知道网上的方案是不是可以解决问题,最后觉得反正只是报错OPENID与APPID对不上,那么我就把它对的上不就可以了,最后采用这个方法。这个解决方案连上线应该只需要一天的时间,还是比较实在的。
2、因为同一个开放平台下的公众号其实授权得到的unionid其实是一样的,只是不同公众号授权的openid不一样,所以相信你们公司的不同公众号应该也是在同一个开放平台下的,所以在登录的时候记录一下unionid和对应的公众号的APPID,这样你就可以找到对应的支付公众号需要的OPENID,当然,这里也有局限性,就是如果用户没有授权联合登录过支付的那个公众号,那么,用户中心还是不知道的OPENID,不过此时也可以同时调微信的接口查一遍对应的OPENID就可以了。