电商收付通系列⑧,合单下单之支付通知

举报
悟空码字 发表于 2023/06/11 10:02:42 2023/06/11
【摘要】 用户支付完成后,微信会把相关支付结果和用户信息发送给清算机构,清算机构需要接收处理后返回应答成功,然后继续给异步通知到下游从业机构。

大家好,我是小悟

1、介绍

用户支付完成后,微信会把相关支付结果和用户信息发送给清算机构,清算机构需要接收处理后返回应答成功,然后继续给异步通知到下游从业机构。

对后台通知交互时,如果微信收到应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。

2、对通知数据进行解密

系统对于开启结果通知的内容一定要做签名验证,并校验通知的信息是否与我们的信息一致,防止数据泄露导致出现“假通知”,造成资金损失。

支付通知和获取微信支付平台证书一样,需要对获取到的内容进行解密,解密规则一样,AesUtils这个解密工具类参考官方文档给的demo。


String result = new String(outSteam.toByteArray(), StandardCharsets.UTF_8);

System.out.println("微信支付回调返回参数result:=====" + result);

JSONObject json = JSONObject.parseObject(result);

System.out.println("微信支付回调返回参数json:=====" + json);

JSONObject resourceRes = json.getJSONObject("resource");

System.out.println("微信支付回调返回参数resourceRes:=====" + resourceRes);

AesUtils aesUtil = new AesUtils("APIv3密钥".getBytes(StandardCharsets.UTF_8));

String resourceStr = aesUtil.decryptToString(resourceRes.getString("associated_data").getBytes(StandardCharsets.UTF_8),
        resourceRes.getString("nonce").getBytes(StandardCharsets.UTF_8),
        resourceRes.getString("ciphertext"));
JSONObject resourceJson = JSONObject.parseObject(resourceStr);

System.out.println("微信支付回调返回参数resourceJson明文:=====" + resourceJson);

3、避免重复下发通知

同样的通知可能会多次发送给我们自身系统,所以我们需要做好正确处理重复通知的逻辑。当自身系统收到通知进行处理时,先检查对应业务数据的状态,并判断该通知是否已经处理。如果未处理,则再进行处理,如果已处理,则直接返回结果成功。

为尽可能提高通知的成功率,微信侧会重复发起通知,为了避免这样的结果影响到处理业务逻辑,我们需要返回一定格式的响应数据给微信,如下,亲测有效。

Map<String,Object> res = new HashMap<String, Object> ();
res.put("code","SUCCESS");
res.put("message","OK");

res.put("code","ERROR_NAME");
res.put("message",e.getMessage());

4、支付通知接口

在合单支付的notify_url参数字段传入"https://xxx/combineNotify"即可

@RequestMapping(value = "/combineNotify", method = {RequestMethod.POST})
public Map<String,Object> combineNotify(HttpServletRequest request) {
    Map<String,Object> res = new HashMap<String, Object> ();
    try {
        // 创建支付应答对象
        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        outSteam.close();
        inStream.close();

        String result = new String(outSteam.toByteArray(), StandardCharsets.UTF_8);

        System.out.println("微信支付回调返回参数result:=====" + result);

        JSONObject json = JSONObject.parseObject(result);

        System.out.println("微信支付回调返回参数json:=====" + json);

        JSONObject resourceRes = json.getJSONObject("resource");

        System.out.println("微信支付回调返回参数resourceRes:=====" + resourceRes);

        AesUtils aesUtil = new AesUtils("APIv3密钥".getBytes(StandardCharsets.UTF_8));

        String resourceStr = aesUtil.decryptToString(resourceRes.getString("associated_data").getBytes(StandardCharsets.UTF_8),
                resourceRes.getString("nonce").getBytes(StandardCharsets.UTF_8),
                resourceRes.getString("ciphertext"));

        JSONObject resourceJson = JSONObject.parseObject(resourceStr);

        System.out.println("微信支付回调返回参数resourceJson明文:=====" + resourceJson);

        //验证微信支付返回签名
        String Wtimestamp = request.getHeader("Wechatpay-Timestamp");
        String Wnonce = request.getHeader("Wechatpay-Nonce");
        String Wsign = request.getHeader("Wechatpay-Signature");

        System.out.println("Wtimestamp:"+Wtimestamp+",Wnonce:"+Wnonce+",Wsign:"+Wsign);
        //拼装待签名串
        StringBuffer ss =new StringBuffer();
        ss.append(Wtimestamp).append("\n");
        ss.append(Wnonce).append("\n");
        ss.append(result).append("\n");

        //验证签名
        if(SignUtils.v3VerifyRSA(ss.toString(), Base64.decodeBase64(Wsign.getBytes()), "/data/tomcat/webapps/ROOT/wechat_pay_platform_4927801AFE1D0A15A2E4491C9C13E6414B17AFCC.pem")) {
            System.out.println("微信支付回调签名验证成功");
        }else {
            System.out.println("微信支付回调签名验证失败");
        }
        res.put("code","SUCCESS");
        res.put("message","OK");
    } catch (GeneralSecurityException e) {
        e.printStackTrace();
        res.put("code","ERROR_NAME");
        res.put("message",e.getMessage());
    } catch (IOException e) {
        e.printStackTrace();
        res.put("code","ERROR_NAME");
        res.put("message",e.getMessage());
    } catch (Exception e) {
        e.printStackTrace();
        res.put("code","ERROR_NAME");
        res.put("message",e.getMessage());
    }
    return res;
}

5、结果

微信支付回调返回参数json:====={"summary":"支付成功","event_type":"TRANSACTION.SUCCESS","create_time":"2020-03-24T18:07:42+08:00","resource":{"associated_data":"transaction","ciphertext":"6XMaa17DRH9uKYuRJneC3wy6ihGiPquKGaCsCScBtxxMY5PLHEeLPl3kBgH/Yes+FOrLh92zsbQa85OIAtnc7eqlLpWb1uiP3jJhglmjzul35WK+naUsxzKLDgUFnUcyfV1PTM287QEFRIC+jvbwHK82lpELOEUCnBx0/ompQM3fzxWQczlw3CvPWTciSgy8XUqui5owvXxkbrKwruIEfigY/LOByXW0w26jX7hEKLjAghdD1NvIgFhkKf3MkbGduNiDsTn1V5z9hzoWR2MwJI/NZFRpsdr9QmxkSiGwf0FzqnOhCLsjntXAKru89CsdWyfznl2BRdbBYF+4ZRqRgbMr+sROQ9TNXVMYjNFeeyXdnpM0BNAdOIKCMI7eBkHsyARgKkXVVlAUkInatbkO/IyIUyJ4PaUJJAYkbxsgIrh1XXpDMfmR8lVpDT8FfumNebL4cILpcOCTfJ+4mn8Es8xKdOiGgEH6ZVqYrjWVkUwBwAHel4xGdat8i80wlIUh2q1z9IN0QggIHp4lCbnSeyeqiTh3WwFiM6Yv/1pHaYde/JSRo0fmdIhFrPGR383GXWqCkQK7yoUydu8e5Dq4qY1GPI9VcaAkMG68sVl762w3Us5/VvO41+nX1BlhFWNsg0VqDLHRvWL+I/gsbXHffub34Je2UF1e0mL7ghmFEXT6k6fQ4FYvSEPQ8CI3KaxMW1RJfUBRqpzKfrzkfi6EgVDAKXQvJc4HvwSmdix8UkRXysger/yfzugVAqwUV2SC6qm+m29MOHGgb37fCaL5fJOnXkvBeb7suYsT2RbyIvoA","original_type":"transaction","nonce":"qyzVVgtmQ0fk","algorithm":"AEAD_AES_256_GCM"},"resource_type":"encrypt-resource","id":"7b3b0fa6-a627-59c1-0733-2606ec31153c"}
微信支付回调返回参数resourceJson明文:====={"combine_appid":"wxd352ef315ac365bd","sub_orders":[{"transaction_id":"4323220200001484847904033204","amount":{"payer_amount":1,"total_amount":1,"currency":"CNY","payer_currency":"CNY"},"mchid":"1915696108","trade_state":"SUCCESS","out_trade_no":"out_trade_no2_1585030201441","bank_type":"OTHERS","trade_type":"JSAPI","attach":"123&456&789","success_time":"2020-03-24T18:07:43+08:00","sub_mchid":"1564468071"}],"combine_payer_info":{"openid":"ofMy16jrqy7Z8pS23M5JI4SkKvwc"},"combine_out_trade_no":"out_trade_no1_1504430158999","combine_mchid":"1811569960","scene_info":{"device_id":"POS1:12"}}
Wtimestamp:1546844504,Wnonce:jXQ70fE0SepL62SNpUhduNCooXF2RseC,Wsign:m2QZupx0hp3fPmfAfYD35FoYK+o1DOzWQs8vkeGTiFY68JHkIlx1cx825sPbW/AHu5xsQ4nlOt4BZZ0Q4Z6szqYgxJUZe/JR0OXNtoG0yHq0m5teVLoFY5eEAuY3szAPC5RIsUOs0ByXP62KEiNNiw7sYbdVXDar4MkKLho7NY6sjaigRQZeSGvsV0q0TIy1HTQTR9otAJ5lnibwbheecXaCLvvkvHGr/kDPHkvnP1fIzVzeIM32VDTf9L4/k7vN4zdgd4R73Y/6hmk8vyTsB+VfciqUpDUQ0rC0SigGzaLukawRK+S3r4XBe1nNiM0jVTKIe5l7s8BO9THd+gwI6A==
微信支付回调签名验证成功


您的一键三连,是我更新的最大动力,谢谢

山水有相逢,来日皆可期,谢谢阅读,我们再会

我手中的金箍棒,上能通天,下能探海

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。