【实战】 对接微信支付分(前端小程序、后端java) 【一】

      话不多说,先介绍一下业务背景。我是一个小白,一条有梦想的创业者,我们创业的一大方向是智能零售,“悦逛宝盒”是我们的品牌,致力于打造智能零售综合服务平台。了解智能零售的人应该知道,这里面的形式有很多,例如:售货机、智能柜、智能货架、咖啡机、无人店等等,今天介绍的这个业务场景,就是微信专门为这个行业推出的一款产品--《微信支付分》,下面就完整介绍一下,我是怎么一步步摸石头过河的。

      先看一下官方给的对接流程图,通过这个流程图,我们能很清楚的了解对接流程,方便我们快速切入。常规的我就不介绍了,相信大家都能看得懂,这里我只介绍我遇到的坑点。

 

坑点一:微信接口规则,采用APIv3

1.所有API请求必须为HTTPS

2.微信支付API v3使用JSON作为消息体的数据交换格式。请求须设置HTTP头部:

Content-Type: application/json
Accept: application/json

3.【重点】APIv3要求所有请求必须加签名,且签名算法与API版本有区别,下面来详细列举

微信支付商户API v3要求请求通过HTTPAuthorization头来传递签名。Authorization认证类型签名信息两个部分组成。

Authorization: 认证类型 签名信息

认证类型:固定为  WECHATPAY2-SHA256-RSA2048

签名信息:

  • 发起请求的商户(包括直连商户、服务商或渠道商)的商户号mchid

  • 商户API证书序列号serial_no,用于声明所使用的证书

  • 请求随机串nonce_str

  • 时间戳timestamp

  • 签名值signature

注:以上五项签名信息,无顺序要求。

Authorization头的示例如下:

Authorization: WECHATPAY2-SHA256-RSA2048 mchid="1900009191",nonce_str="593BEC0C930BF1AFEB40B4A08C8FB242",signature="uOVRnA4qG/MNnYzdQxJanN+zU+lTgIcnU9BxGw5dKjK+VdEUz2FeIoC+D5sB/LN+nGzX3hfZg6r5wT1pl2ZobmIc6p0ldN7J6yDgUzbX8Uk3sD4a4eZVPTBvqNDoUqcYMlZ9uuDdCvNv4TM3c1WzsXUrExwVkI1XO5jCNbgDJ25nkT/c1gIFvqoogl7MdSFGc4W4xZsqCItnqbypR3RuGIlR9h9vlRsy7zJR9PBI83X8alLDIfR1ukt1P7tMnmogZ0cuDY8cZsd8ZlCgLadmvej58SLsIkVxFJ8XyUgx9FmutKSYTmYtWBZ0+tNvfGmbXU7cob8H/4nLBiCwIUFluw==",timestamp="1554208460",serial_no="1DDE55AD98ED71D6EDD4A4A16996DE7B47773A8C"

(1)私钥、APIv3密钥和证书

         在使用APIv3接口前,一定要在微信商户后台(https://pay.weixin.qq.com)【账户中心-》API安全】设置APIv3密钥,并查看证书是否是APIv3版证书,如果不是,根据提示升级。如下图:

(2)【重点】签名算法,篇幅问题,单独写一篇,

地址:https://blog.csdn.net/w1170384758/article/details/105393505

坑点二:APIv3中,业务数据的签名算法发生改变(sign字段)

官方说明地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=4_3

API版本采用MD5签名,APIv3采用HMAC-SHA256签名方式,篇幅问题,单独写一篇介绍java版实现代码,

地址:https://blog.csdn.net/w1170384758/article/details/105393913

步骤一:

1.【查询用户授权状态】

这一步比较简单,就是调用微信接口,GET请求,前面签名做好,没啥难度。先贴代码,然后和大家讨论一个业务场景。

        //请求方式:GET
        String url = "https://api.mch.weixin.qq.com/v3/payscore/user-service-state?service_id="+ param.getServiceId() +"&appid="+ param.getAppId() +"&openid=" + param.getOpenId();
        HttpUrl httpUrl = HttpUrl.parse(url);
        try {
            String token = WxAPIV3SignUtils.getToken("GET",httpUrl,"",param.getMchId(),param.getPrivateKey(),param.getSerialNo());
            logger.debug("token={}",token);
            //调用微信接口
            OkHttpClient okHttpClient = new OkHttpClient();
            final Request request = new Request.Builder()
                    .url(url)
                    .addHeader("Content-Type","application/json")
                    .addHeader("Accept","application/json")
                    .addHeader("Authorization",token)
                    .build();
            final Call call = okHttpClient.newCall(request);
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Response response = call.execute();
                        String resStr = response.body().string();
                        logger.debug("查询用户支付分授权状态API:{}",resStr);          
                       
                    }catch (IOException ex){
                        ex.printStackTrace();
                    }
                }
            });
            thread.start();
            thread.join();
        }catch (Exception ex){
            ex.printStackTrace();
        }

那么这样看下来,关于查询用户支付分授权状态就有两种方式,方式一,调用你们的接口来查询用户授权状态,方式二,将用户授权状态(开通或关闭授权回调用通知)存到我们平台,查询时从我们的库中查询,关于这两种方式,询问过微信官方,没有给出回复,个人建议,如果服务器性能可以,还是实时查询,数据库可以存储下来,作为备查资料。

2.未授权时,引导用户授权服务,这里先给出前端(小程序)代码

   var extraData = res.data.data;//后台接口组装的签约信息
        wx.openBusinessView({
          businessType: 'wxpayScoreEnable',
          extraData: extraData,
          success(res) {
            // 成功跳转到签约小程序
            console.log("签约支付分成功:",JSON.stringify(res))
        
          },
          fail(res) {
            // 未成功跳转到签约小程序 
            console.log("签约支付分失败",JSON.stringify(res));
                   //做二次校验,查询用户签约情况
                   var jsonData = JSON.stringify({
             
                  });
                  console.log("【二次确认】校验支付分签约信息接口入参:" + data)
                  wx.request({
                    url: '',
                    method: "POST",
                    data: {
                      data: jsonData
                    },
                    header: {
                      'content-type': 'application/x-www-form-urlencoded;charset=utf-8'
                    },
                    success: function (res) {
                      //打印日志
                      console.log("校验支付分签约信息接口调用成功");
                      console.log("返回参数:" + JSON.stringify(res))
                      var isSign = res.data.data.isSign;
              
                      if (isSign == 1) { //用户已签约    
                        console.log("确认用户已签约微信支付分")
                       
                      }
                      if (isSign == 0) { //用户未签约,给出提示
                        console.log("确认用户未签约微信支付分")
                        wx.showModal({
                          title: '温馨提示',
                          showCancel:false,
                          content: '开通微信支付分,享受便捷购物,请重新扫码开通',
                          confirmText: '是',
                          success(res) {
                            console.log("弹框展示成功:",JSON.stringify(res))
                            that.data.allowScan = 1;
                            wx.switchTab({
                              url: '../index/index',
                            })
                
                          },
                          fail(res) {
                            console.log("弹框展示失败:",JSON.stringify(res))
                          }
                        })
                          
                      }
                    },
                    fail: function (res) {
                      console.log("调用获取用户免密签约信息接口出错:" + JSON.stringify(res));

                    }
                  })
          },
        })

这里需要注意的点是,在签约成功界面,点击返回键(安卓手机)或左上角后退键时,触发的是wx.openBusinessView的fail方法,所以个人建议,在fail方法中加个二次check逻辑。

下面给出java后台组装支付分业务数据(extraData)的代码段,签名算法前面已经给出。

        out.setOut_request_no(SerialnoUtils.buildUUID());
        long currentTimeMillis = System.currentTimeMillis();//生成时间戳
        long second = currentTimeMillis / 1000L;//转换成秒
        String seconds = String.valueOf(second).substring(0, 10);//截取前10位
        out.setTimestamp(seconds);//时间戳string(10)
        out.setNonce_str(WxAPIV3SignUtils.generateNonceStr());
        out.setSign_type(WxAPIV3SignUtils.sign_type);

        //生成签名
        String sign = MapUtils.getObjectHMACSHA256Sign(out,StringUtils.isNotBlank(mch_key) ? mch_key : SystemConst.WX_KEY);
        out.setSign(sign);

步骤二:【创建支付分订单】https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore/chapter3_1.shtml

POST请求,代码实现上没啥难度,直接上核心代码

    public static final MediaType MediaType_JSON = MediaType.parse("application/json; charset=utf-8");


            //生成签名
            String url = "https://api.mch.weixin.qq.com/v3/payscore/serviceorder";
            HttpUrl httpUrl = HttpUrl.parse(url);
            String token = WxAPIV3SignUtils.getToken("POST",httpUrl,JSON.toJSONString(wxApplyPayScoreIn),payScoreConfig.getMchId(),payScoreConfig.getPrivateKey(),payScoreConfig.getSerialNo());

            OkHttpClient okHttpClient = new OkHttpClient();
            RequestBody requestBody = RequestBody.create(MediaType_JSON,JSON.toJSONString(wxApplyPayScoreIn));
            Request request = new Request.Builder()
                    .url(url)
                    .addHeader("Content-Type","application/json")
                    .addHeader("Accept","application/json")
                    .addHeader("Authorization",token)
                    .post(requestBody)
                    .build();

            Response response = okHttpClient.newCall(request).execute();
            logger.debug("【创建支付分订单API】接口返回:{},code={},message={},body={}",JSON.toJSONString(response),response.code(),response.message(),response.body().string());
            if (response.isSuccessful()){//请求成功
            }else{
            }

POST调用本身没啥难度,这里重点介绍一个,组装请求参数时容易遇到的坑

(1)

这里的appid指的是你实际发起的客户端appid,不一定是公众号,如,我使用的是小程序,那么这个参数传递的是小程序appid

(2)

 金额,对接过微信支付的都知道,微信默认的金额都是分,所以注意与商户的业务数据做好对应。

(3)

 关于时间传递这块,我认为也是一个坑。大家仔细看好官方说明。

篇幅原因,这篇先写到这,后续订单完结、支付回调、退款等在下一篇介绍,地址:

新人发帖,如有疑问或错误,欢迎大家订正。

发布了4 篇原创文章 · 获赞 10 · 访问量 172

猜你喜欢

转载自blog.csdn.net/w1170384758/article/details/105314041
今日推荐