关于微信支付的流程梳理(主要是校验)

最近做了一个微信支付的功能,整理下思路(主要是校验逻辑):

先上图微信H5支付的官方流程图:

关于微信支付的流程梳理(主要是校验)_第1张图片


自己梳理了下流程:

① 用户请求支付---->② 前端页面请求后台接口---->③ 后台处理订单逻辑(请求微信支付校验接口,成功后返回相应的校验数据)---->④ 后台将校验数据返回给前端页面---->⑤ 前端页面封装数据调用微信支付接口---->⑥ 微信将结果回调到前端请求中配置的回调接口---->⑦ 回调接口接收到数据进行再次校验并处理支付后的逻辑


        第③步 所校验的参数:

         // 随机字符串
        parameters.put("nonce_str", RandomUtil.generateRandomCharAndNumber(10));
        // 商品名称
        parameters.put("body", orderName);
        // 商户系统内部的订单号(自己生成的订单号)
        String out_trade_no = orderId;
        parameters.put("out_trade_no", out_trade_no);
        // 订单金额以分为单位,只能为整数
        parameters.put("total_fee", total);
        // 客户端本地ip
        parameters.put("spbill_create_ip", request.getRemoteAddr());
        // 支付通知异步回调地址
        parameters.put("notify_url", P_NOTIFY_URL);
        // 交易类型     source:H5和小程序 都是“JSAPI”,

        parameters.put("trade_type", source);

        //商家数据包attach(区分来源渠道)  该字段可带参数过去 回调的时候会原样返回 回调可通过该字段进行数据校验并且处理
        parameters.put("attach", attach);
        
        // MD5进行签名,必须为UTF-8编码,注意上面几个参数名称的大小写
        
        String sign = createSign("UTF-8", parameters , apikey);
        parameters.put("sign", sign);

         // 生成xml结构的数据,用于统一下单接口的请求
        String requestXML = getRequestXml(parameters);
        log.info("统一下单接口请求数据requestXML={}", requestXML);
        /** 开始请求统一下单接口,获取预支付prepay_id */
        String result = HttpUtil.doPost(UNI_URL, requestXML);                       

        第④步 将返回的参数进行拆分 返回给前端:

        // 解析微信返回的信息,以Map形式存储便于取值
            Map map = XMLUtil.doXMLParse(result);
            String prepayId = map.get("prepay_id");

   获取预支付prepay_id之后,需要再次进行签名,参数有:appId,partnerId,prepayId,nonceStr,timeStamp,

package

                SortedMap params = new TreeMap();
                // app支付时package的值格式为Sign=WXPay ,h5支付时格式为:prepay_id=统一下单接口返回的订单号
                              
                  params.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
                  params.put("nonceStr", map.get("nonce_str"));
                  params.put("appId", P_APPID);

                  params.put("package", "prepay_id=" + prepayId);

                params.put("signType", "MD5");

                 sign = createSign("UTF-8", params, apikey);

                  params.put("sign", sign); 

                   params.put("partnerid", ModuleConstants.P_MCH_ID);

                   params.put("prepayid", prepayId);

               将params 返回给前端  前端根据这个返回的参数 发起支付调用

        后面就是根据回调在回调接口里面接收 返回的数据进行内部业务逻辑处理之后的业务

        


  附上 生成签名sign方法:

      /**
     * 签名
     *
     * @param characterEncoding
     * @param parameters
     * @return
     */
    public static String createSign(String characterEncoding, SortedMap parameters,String apikey) {
        StringBuffer sb = new StringBuffer();
        Set> es = parameters.entrySet();
        Iterator> it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            Object v = entry.getValue();
            /** 如果参数为key或者sign,则不参与加密签名 */
            if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        /** 支付密钥必须参与加密,放在字符串最后面 */
        sb.append("key=" + apikey);
        log.info("签名原始字符串:{}", sb);
        /** 记得最后一定要转换为大写 */
        String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        log.info("签名后的字符串:{}", sign);
        return sign;
    }

               


    附加微信H5支付官网地址:

      https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_4


    看到一个说明的更详细的文章,在这里记录下:

                https://blog.csdn.net/wtdask/article/details/75646968


你可能感兴趣的:(java)