2.扫描生成的二维码,微信进行函数的回调

回调函数: 

        1.首先获取请求头的时间戳和随机数

        2.微信回调时,会把回调的参数body传递给该接口

        3. 获取平台对应的证书来核实签名

        4.进行回调的报文解密

        5.获取微信支付返回的信息

        6.如果支付成功,保存用户订单明细


    /**
     * 支付回调
     * @param body
     * @param request
     * @return
     */
    @PostMapping("/api/pay/callback")
    public Map orderPayCallback(@RequestBody Map body, HttpServletRequest request)
    {
        log.info("1----------->微信支付回调开始");
        Map<String, Object>  result = new HashMap();
        //1:获取微信支付回调的获取签名信息
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        //获取随机数
        String nonce = request.getHeader("Wechatpay-Nonce");
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            // 2: 开始解析报文体
            String data = objectMapper.writeValueAsString(body);
            String message = timestamp + "\n" + nonce + "\n" + data + "\n";
            //3:获取应答签名
            String sign = request.getHeader("Wechatpay-Signature");
            //4:获取平台对应的证书
            String serialNo = request.getHeader("Wechatpay-Serial");
            //如果yaml的证书公钥不包含微信传递过来的证书公钥,则获取平台证书
            if (!KsdStaticParameter.certificateMap.containsKey(serialNo))
            {
                KsdStaticParameter.certificateMap = WechatPayUtils.refreshCertificate();
            }
            X509Certificate x509Certificate = KsdStaticParameter.certificateMap.get(serialNo);
            //核实签名是否正确
            if (!WechatPayUtils.verify(x509Certificate, message.getBytes(), sign))
            {
                throw new IllegalArgumentException("微信支付签名验证失败:" + message);
            }
            log.info("签名验证成功");
            Map<String, String> resource = (Map) body.get("resource");
            // 5:回调报文解密
            AesUtil aesUtil = new AesUtil(KsdStaticParameter.v3Key.getBytes());
            //解密后json字符串
            String decryptToString = aesUtil.decryptToString(
                    resource.get("associated_data").getBytes(),
                    resource.get("nonce").getBytes(),
                    resource.get("ciphertext"));
            log.info("2------------->decryptToString====>{}", decryptToString);
            //6:获取微信支付返回的信息
            Map<String, Object> jsonData = objectMapper.readValue(decryptToString, Map.class);
            //7: 支付状态的判断 如果是success就代表支付成功
            if ("SUCCESS".equals(jsonData.get("trade_state")))
            {
                // 8:获取支付的交易单号,流水号,和附属参数
                String out_trade_no = jsonData.get("out_trade_no").toString();
                String transaction_id = jsonData.get("transaction_id").toString();
                // 附属参数
                String attach = jsonData.get("attach").toString();
                //TODO 根据订单号查询支付状态,如果未支付,更新支付状态 为已支付
                log.info("3----------->微信支付成功,支付流水号是:{},附属参数是:{}", out_trade_no, attach);
                log.info("4----------->微信支付成功,支付流水号是:{},{}", transaction_id);

                // 把附属参数转换成map
                HashMap<String,Object> hashMap = JsonUtil.string2Obj(attach, HashMap.class);
                // 保存用户订单明细
                KssUserPay userPay = new KssUserPay();
                userPay.setUserid(String.valueOf(hashMap.get("userid")));
                userPay.setNickname(String.valueOf(hashMap.get("nickname")));
                userPay.setCourseid(String.valueOf(hashMap.get("courseid")));
                userPay.setPrice(String.valueOf(hashMap.get("price")));
                userPay.setTradeno(transaction_id);
                userPay.setCreateTime(new Date());
                userPayService.saveOrUpdate(userPay);
            }
            result.put("code", "SUCCESS");
            result.put("message", "成功");
        } catch (Exception e) {
            result.put("code", "fail");
            result.put("message", "系统错误");
            e.printStackTrace();
        }
        return result;
    }

验证签名:

 /**
     * 验证签名
     * @param certificate
     * @param message
     * @param signature
     * @return
     */
    public static boolean verify(X509Certificate certificate, byte[] message, String signature) {
        try {
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initVerify(certificate);
            sign.update(message);
            return sign.verify(Base64.getDecoder().decode(signature));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持SHA256withRSA", e);
        } catch (SignatureException e) {
            throw new RuntimeException("签名验证过程发生了错误", e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException("无效的证书", e);
        }
    }
微信回调成功生成的明文信息:
package com.suqi.payment.utils;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * 微信回调成功生成的明文信息
 */
public class AesUtil
{

    static final int KEY_LENGTH_BYTE = 32;
    static final int TAG_LENGTH_BIT = 128;
    private final byte[] aesKey;

    public AesUtil(byte[] key) {
        if (key.length != KEY_LENGTH_BYTE) {
            throw new IllegalArgumentException("无效的ApiV3Key,长度必须为32个字节");
        }
        this.aesKey = key;
    }

    public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext)
            throws GeneralSecurityException, IOException {
        try {
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

            SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
            GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);

            cipher.init(Cipher.DECRYPT_MODE, key, spec);
            cipher.updateAAD(associatedData);

            return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8");
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            throw new IllegalStateException(e);
        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
            throw new IllegalArgumentException(e);
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值