美文网首页程序微信小程序微信小程序开发者
玩转小程序支付之支付结果通知

玩转小程序支付之支付结果通知

作者: 就叫小木木呀 | 来源:发表于2019-05-28 16:16 被阅读1次

上一篇讲了小程序支付的过程,接下来就是支付结果通知

官方文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7

注意: 

支付通知的url 是通过【统一下单API】中提交的参数notify_url设置,如果链接无法访问,商户将无法接收到微信通知。

通知url必须为直接可访问的url,不能携带参数。示例:notify_url:“https://pay.weixin.qq.com/wxpay/pay.action”

在前面的支付的参数中设置了支付结果的URL——baseUrl+"/notify"

支付时传的回调地址

所以支付通知会发到我自己服务器下的这个路径下,会接收到类似如下的xml字符串(如果正常的话,即result_code 和return_code都为SUCCESS)

微信支付通知内容

解析这个xml,可以得到transaction_id,out_trade_no等关键信息。

为了保证返回信息是否正确,我们可以去验证其正确性。

方法是对参数进行加密获取的签名,然后比对返回的签名和我们生成的签名是否一致,若不一致就表明返回的支付通知被修改,不过一般不会出现这种情况。

注意:

 可能是微信方面觉得一次不一定能通知到,所以支付通知可能会发多次,所以我们在收到正确的通知之后,需要给小程序官方返回一段xml,表示收到,之后就不会再收到啦。

返回给微信支付的确认内容

整个支付通知的处理的代码如下

/**

     * 支付完成通知

     * @param request

     * @param response

     * @return

     * @throws Exception

     */

    @RequestMapping(value = "/notify",method = RequestMethod.POST)

    public String notify(HttpServletRequest request, HttpServletResponse response) throws Exception {

        BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));

        String line = null;

        StringBuilder sb = new StringBuilder();

        while((line = br.readLine())!=null){

            sb.append(line);

        }

        //解析并给微信发回收到通知确认

        Map map =  PayUtils.doXMLParse(sb.toString());

        String returnCode = map.get("return_code").toString();

        if(returnCode.equals("SUCCESS")){

            String resultCode = map.get("result_code").toString();

            if(resultCode.equals("SUCCESS")){

                SortedMap packageParams = new TreeMap<String, String>();

                packageParams.put("appid", map.get("appid").toString());

                packageParams.put("attach", map.get("attach").toString());

                packageParams.put("bank_type", map.get("bank_type").toString());

                packageParams.put("cash_fee", map.get("cash_fee").toString());

                packageParams.put("fee_type", map.get("fee_type").toString());

                packageParams.put("is_subscribe", map.get("is_subscribe").toString());

                packageParams.put("mch_id", map.get("mch_id").toString());

                packageParams.put("nonce_str", map.get("nonce_str").toString());

                packageParams.put("openid", map.get("openid").toString());

                packageParams.put("out_trade_no", map.get("out_trade_no").toString());

                packageParams.put("result_code", map.get("result_code").toString());

                packageParams.put("return_code", map.get("return_code").toString());

                packageParams.put("time_end", map.get("time_end").toString());

                packageParams.put("total_fee", map.get("total_fee").toString());

                packageParams.put("trade_type", map.get("trade_type").toString());

                packageParams.put("transaction_id", map.get("transaction_id").toString());

                String sign = PayUtils.createSign(packageParams,key);

                String originSign = map.get("sign").toString();

                if(sign.equals(originSign)){

                    //签名一致,保存支付流水

                    String xml="<xml>"

                              +"<return_code>SUCCESS</return_code>"

                              +"<return_msg>OK</return_msg>"

                              +"</xml>";

                    ProfPayLog payLog = new ProfPayLog();

                    payLog.setCreatedAt(new Date());

                    payLog.setSource(Source.WeiXin);

                    DecimalFormat df = new DecimalFormat("######0.00");

                    payLog.setTotalFee(String.valueOf(df.format((Double.valueOf(map.get("total_fee").toString())/100))));

                    payLog.setTradeNo(map.get("out_trade_no").toString());

                    payLog.setTransactionId(map.get("transaction_id").toString());

                    String attach = map.get("attach").toString();//userId+"#wx#"+activityId

                    payLog.setUserId(attach.split("#wx#")[0]);

                    payLog.setType(ProfPayLog.Type.Pay);

                    WxappUser user = wxappUserService.find(Long.valueOf(attach.split("#wx#")[0]));

                    WxappActivity activity = wxappActivityService.find(Long.valueOf(attach.split("#wx#")[1]));

                    WxappActivityApply activityApply = wxappActivityApplyService.findActivityApplyByUserAndActivity(user, activity);

                    if(activityApply.getPayLogId() != null){

                        System.out.println("=========已经完成了存储支付流水=========");

                        return xml;

                    }else{

                        System.out.println("=========完成第一次保存支付流水=========");

                        payLog = wxappPayService.save(payLog);

                        //在活动申请表中关联上支付流水的id

                        activityApply.setPayLogId(String.valueOf(payLog.getId()));

                        wxappActivityApplyService.save(activityApply);

                        return xml;

                    }

                }else{

                    String xml="<xml>"

                              +"<return_code>FAIL</return_code>"

                              +"<return_msg>签名不一致</return_msg>"

                              +"</xml>";

                    return xml;

                }

            }else{

                String xml="<xml>"

                          +"<return_code>FAIL</return_code>"

                          +"<return_msg>支付通知失败</return_msg>"

                          +"</xml>";

                        return xml;

            }

        } else {

            String xml="<xml>"

                  +"<return_code>FAIL</return_code>"

                  +"<return_msg>支付通知失败</return_msg>"

                  +"</xml>";

                return xml;

        }

    }

码字不易,如果觉得有帮助,一定要给我点赞哟~~

不然信不信我砸了你家灯,半夜偷亲你 ( ̄ε  ̄) !!!

相关文章

网友评论

    本文标题:玩转小程序支付之支付结果通知

    本文链接:https://www.haomeiwen.com/subject/ttvdtctx.html