SpringMVC微信公众号服务器验证不通过

Easter79
• 阅读 470

最近开始搞搞开放平台,先是TaoBaoSDK,挺好用的基本每碰到什么问题,就是各种没权限。。。

后来搞微信的,第一步卡了我一天。。。年纪大了,反应迟钝啊。。。

首先按照公众号平台里把信息配置好,这里我就不截图了

服务端刚开始调用的是Demo里WXBizMsgCrypt.verifyUrl(msgSignature,timeStamp,nonce,echoStr)

不要问我为什么,因为懒。。。

就是验不通过,经过核对参数、设置编码等等最后发现这个方法不是用来响应服务端验证的,而且Demo里似乎也没有现成的方法。。。。

于是动手开始改了(同学们要相信自己啊):

签名方法:考虑到Demo里那个方法是四个参数的,所以写了一个兼容多个参数的

/**
 * 签名数据
 * @param args 签名数据列表 arg[0]必须为appId
 * @return 签名结果
 */
public String sign(String... args){
    /*** 不用看 begin,就是把第一个参数由appId换成token,因为我这个多账号,否则写死 ****/
    String appId = args[0];
    AppConf conf = getAppConf(appId);
    args[0]=conf.getToken();
    /*** 不用看 end  *****/

    // 字典序排序,如果有null的这里会报错
    Arrays.sort(args);
    // 字符串拼接
    StringBuffer buffer = new StringBuffer();
    for(String str:args){
        if(str!=null){
            buffer.append(str);
        }
    }
    try{
        // SHA1签名生成
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        md.update(buffer.toString().getBytes());
        byte[] digest = md.digest();

        StringBuffer hexstr = new StringBuffer();
        String shaHex = "";
        for (int i = 0; i < digest.length; i++) {
            shaHex = Integer.toHexString(digest[i] & 0xFF);
            if (shaHex.length() < 2) {
                hexstr.append(0);
            }
            hexstr.append(shaHex);
        }
        return hexstr.toString();
    }catch(Exception ex){
        throw new BaseRuntimeException(WXServerError.sign(appId,args));
    }
    
}

调用的地方

   - 签名返回报文,4个参数(不知道是不是这个,反正签了):

String sign =wxMsgCryptService.sign(info.getAppId(),timestamp,nonce,encrypt);

   - 响应服务端验证,3个参数(这个是正主)

if(signature!=null){
    String sign = wxMsgCryptService.sign(appId,timestamp,nonce);
    
    if(sign.equals(signature)){
        if(body==null){
            return echostr;
        }
    }else{
        throw new BaseRuntimeException(WXServerError.verify(appId,timestamp,nonce,signature));
    }
}

返回部分:返回是我很费解的地方,可以是字符串、可以是xml、没有异常报文不是200的一律失败,不过好像也没什么不对。

// 返回的直接是Http Body了
@ResponseBody
/** 我习惯了用扩展名来区分响应,微信那边配的是server/{appId}.xml
 *  这样返回的就是xml了,那天支持json了换json吧
 */
@RequestMapping("server/{appId}.*")
public Object service(
    @PathVariable("appId") String appId,
    @RequestParam(value="signature",required=false)String signature,
    @RequestParam(value="timestamp",required=false)String timestamp,
    @RequestParam(value="nonce",required=false)String nonce,
    @RequestParam(value="echostr",required=false)String echostr,
    @RequestBody(required=false) String body){

    logger.info("accept -> signature:{},timestamp:{},nonce:{},echostr:{}",new Object[]{
            signature,timestamp,nonce,echostr
    });
    // 配置的时候有三个选项:明文的时候就不验签了,估计不会有人这么配置吧
    // 接受明文消息时,不进行验签
    if(signature!=null){
        String sign = wxMsgCryptService.sign(appId,timestamp,nonce);
        
        if(sign.equals(signature)){
            if(body==null){
                // 响应验证到这里就结束了,返回echostr,微信那边就验证通过了
                return echostr;
            }
        }else{
            throw new BaseRuntimeException(WXServerError.verify(appId,timestamp,nonce,signature));
        }
    }
    
    logger.info("receive->{}",body);
    
     
    // 以下接受到消息的处理,属于增值包 😜
    
    MsgCryptInfo info = new MsgCryptInfo();
    info.setAppId(appId);
    info.setNonce(nonce);
    info.setSignature(signature);
    info.setTimeStamp(timestamp);
    // 里面判断要不要解密消息,不要直接返回了
    WXMessage message = wxMessageService.getMessage(info,body);
    // 去找对应的消息处理器生成返回消息
    message = wxMessageService.reply(message);
    // 无返回消息时
    if(message==null){
        // 官方说返回"success"字串也是成功,我是不会让它走到这个分支的,邪恶啊
        return DEFAULT_REPLY;
    }
    // 接受明文消息时,不进行验签
    if(signature!=null){
        // 消息加密部分,官方的Demo抄下来就好了
        message = wxMessageService.encryptMessage(info, message);
    }
    
    return message;
}

PS:当时我用verifyURL跑不过验证的时候,我内心时崩溃的,在想难道未认证的订阅号连这个都不让干了。所以我终究还是低估了微信对于个人开发者的友好

点赞
收藏
评论区
推荐文章
微标题信公众号文章,阅读数,点赞数历史文章抓取
微标题信公众号文章,阅读数,点赞数历史文章抓取需求最近在做舆情与微信文章相关的数据抓取,发现微信公众号有些难点很难克服。市面上流行的数据抓取思路要么被腾讯封杀,要么操作难度大。解决方案搜狗微信无法采集历史,而且搜索也不按时间排序。获取的数据的价值不高,仅仅可以通过他获取公众号的biz。微信公众平台微信公
Jacquelyn38 Jacquelyn38
3年前
手写一个仿微信登录的nodejs程序
前言首先,我们看一下微信开放文档中的一张图:上面的一幅图中清楚地介绍了微信登录整个过程,下面对图上所示进行总结:一、二维码的获得1.用户打开登录网页后,登录网页后台根据微信OAuth2.0协议向微信开发平台请求授权登录,并传递事先在微信开发平台中审核通过的AppID和AppSecrect等参数;2.微信开发平台对AppID等参数进行验证,并向
刘望舒 刘望舒
3年前
Android深入四大组件(一)应用程序启动过程(后篇)
Android框架层Android深入四大组件categories:Android框架层本文首发于微信公众号「刘望舒」1.ActivityManageService到ApplicationThread的调用流程AMS的startActivity方法中return了startActivityAsUser方法:<!moreframeworks/base/s
Wesley13 Wesley13
3年前
1小时搭建微信小程序后端
CoNami小程序Demo端到端开发指南1\.注册登录微信公众平台登录https://mp.weixin.qq.com,里面有详细的指引,这里就不赘述了。这里注册最后得到的比较重要的东西包括两个(https://www.oschina.net/action/GoToLink
Wesley13 Wesley13
3年前
2020微信运动一键刷步数,让你重回排行榜第一
微信运动很久之前就有了,不过我是最近才开始玩的,你的微信运动排行榜里是不总有人长期霸占第一,他应该不是每天都在运动,很可能是使用了工具刷的,今天就分享下。在线刷微信运动步数首先在应用商店下载一个乐心健康app ,使用手机号注册,并且设置一个登陆密码,然后在数据共享里开启第三方同步(包含微信运动,支付宝运动,阿里体育,需要关注他们的公
Wesley13 Wesley13
3年前
JAVA获取微信小程序openid和获取公众号openid,以及通过openid获取用户信息
一,首先说明下这个微信的openid  为了识别用户,每个用户针对每个公众号会产生一个安全的OpenID,如果需要在多公众号、移动应用之间做用户共通,则需前往微信开放平台,将这些公众号和应用绑定到一个开放平台账号下,绑定后,一个用户虽然对多个公众号和应用有多个不同的OpenID,但他对所有这些同一开放平台账号下的公众
Wesley13 Wesley13
3年前
PHP微信小程序支付——签名错误
!(https://static.oschina.net/uploads/space/2018/0509/141657_Tqix_3477605.png)先分清几个概念:微信公众平台、微信开放平台、微信商户平台1.微信公众平台、微信开放平台、微信商户平台是三个不同的平台2.微信公众平台:用于公众号、小程序等等的设置平台,包括APPID、APP
Wesley13 Wesley13
3年前
h5 接入微信支付
我们公司,现在用ping做h5接入,用的是h5"壹收款"准备:如果公司,现在还没有公众号的话,支付宝。可以把这些工作,给ping来做这些事情 1.注册微信公众号,开通支付功能。2.注册ping (如果是自己开开通的微信支付,要填写相关信息)3.微信设置网页授权获取用户基本信
Easter79 Easter79
3年前
SpringMVC基础配置
按:最近公众号文章主要是整理一些老文章,主要是个人CSDN上的博客,也会穿插一些新的技术点。SpringMVC是什么,有多火,我这里就不再啰嗦了,SpringMVC比Struts2好用太多,我在学校的时候私下里两种都接触过,对比之后果断选择了SpringMVC,后来在做Android应用开发的时候,偶尔需要搭建一个后台服务,都是毫不
Stella981 Stella981
3年前
JFinal极速开发微信公众号
10分钟搭建属于自己的ngork服务器,实现内网穿透(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Fzyw_java%2Farticle%2Fdetails%2F70341106)Android微信、支付App支付SDK(http
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k