Java整合微信支付V3版本APP支付

接入微信APP支付准备:

1:申请商户号(mchid),入驻微信商户平台

2:申请APPID,开通微信开放平台,创建移动应用(第三步)

3:绑定APPID和MCHID,开放平台应用关联商户平台。可关系多个,多对多关系     获取APPID和商户号

4:配置APIkey,微信商户平台,账号中心=》AIP安全    配置APIV3秘钥和申请API证书   申请API证书需下载证书工具(申请API证书步骤里有工具安装包)

5:没了,有了APPID、商户号 、商户证书序列号、V3Api密钥、商户私钥。就开始上手吧。

6:导入依赖 

<dependency>
    <groupId>com.github.wechatpay-apiv3</groupId>
    <artifactId>wechatpay-apache-httpclient</artifactId>
    <version>0.4.7</version>
</dependency>
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.3.10</version>
</dependency>

1.配置支付信息,工具类

/**
 * 微信支付回调body实体
 * @author liaozan8888@163.com
 */
@Data
public class SuccessCallBackObj {
    private String summary;
    private String event_type;
    private String create_time;
    private String resource_type;
    private String id;
    private Resource resource;
}
/**
 * 微信回调Resource 实体
 * @author liaozan8888@163.com
 */
@Data
public class Resource implements Serializable {
    private String original_type;
    private String algorithm;
    private String ciphertext;
    private String associated_data;
    private String nonce;
}
/**
 * 支付参数配置
 * @author liaozan8888@163.com
 */
public interface PayConstants {
    String NOTIFY_URL = "XXXX"; //回调地址
    String MCH_ID = "XXXX"; //商户号
    String MCH_SERIAL_NO = "XXXX"; //商户证书序列号
    String API_3KEY = "XXXX";   //Api密钥
    String APP_ID = "XXXX";     //ApId
    String PACKAGE = "Sign=WXPay";  //签名国定字符串
    String privateKey = "XXXX";//商户私钥
}
/**
 * 回调签名配置
 * @author liaozan8888@163.com
 */
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);
        }
    }
}
 

2.调起APP支付

/**
 * 下单工具类
 * @author liaozan8888@163.com
 */
public class PayUtil {
    private CloseableHttpClient httpClient;
    private CertificatesManager certificatesManager;
    private Verifier verifier;
    /**
     * App下单  具体下单场景查看官方文档
     *
     * @param total
     * @param description
     * @return
     * @throws Exception
     */
    public String requestwxChatPay(String orderSn, int total, String description) throws Exception {
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(PayConstants.privateKey.getBytes("utf-8")));
        // 获取证书管理器实例
        certificatesManager = CertificatesManager.getInstance();
        // 向证书管理器增加需要自动更新平台证书的商户信息
        certificatesManager.putMerchant(PayConstants.MCH_ID, new WechatPay2Credentials(PayConstants.MCH_ID,
                        new PrivateKeySigner(PayConstants.MCH_SERIAL_NO, merchantPrivateKey)),
                PayConstants.API_3KEY.getBytes(StandardCharsets.UTF_8));
        // 从证书管理器中获取verifier
        verifier = certificatesManager.getVerifier(PayConstants.MCH_ID);
        httpClient = WechatPayHttpClientBuilder.create()
                .withMerchant(PayConstants.MCH_ID, PayConstants.MCH_SERIAL_NO, merchantPrivateKey)
                .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(PayConstants.MCH_ID)))
                .build();
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/app");
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type", "application/json; charset=utf-8");

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectMapper objectMapper = new ObjectMapper();
        //组合请求参数JSON格式
        ObjectNode rootNode = objectMapper.createObjectNode();
        rootNode.put("mchid", PayConstants.MCH_ID)
                .put("appid", PayConstants.APP_ID)
                .put("notify_url", PayConstants.NOTIFY_URL + "notify")
                .put("description", description)
                .put("out_trade_no", orderSn);
        rootNode.putObject("amount")
                .put("total", total)
                .put("currency", "CNY");
        try {
            objectMapper.writeValue(bos, rootNode);
            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
            //获取预支付ID
            CloseableHttpResponse response = httpClient.execute(httpPost);
            String bodyAsString = EntityUtils.toString(response.getEntity());
            //微信成功响应
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                //时间戳
                String timestamp = System.currentTimeMillis() / 1000 + "";
                //随机字符串
                String nonce = RandomUtil.randomString(32);
                StringBuilder builder = new StringBuilder();
                // Appid
                builder.append(PayConstants.APP_ID).append("\n");
                // 时间戳
                builder.append(timestamp).append("\n");
                // 随机字符串
                builder.append(nonce).append("\n");
                JsonNode jsonNode = objectMapper.readTree(bodyAsString);
                // 预支付会话ID
                builder.append(jsonNode.get("prepay_id").textValue()).append("\n");
                //获取签名
                String sign = this.sign(builder.toString().getBytes("utf-8"), merchantPrivateKey);
                JSONObject jsonMap = new JSONObject();
                jsonMap.put("noncestr", nonce);
                jsonMap.put("timestamp", timestamp);
                jsonMap.put("prepayid", jsonNode.get("prepay_id").textValue());
                jsonMap.put("sign", sign);
                jsonMap.put("package", PayConstants.PACKAGE);
                jsonMap.put("appid", PayConstants.APP_ID);
                jsonMap.put("partnerid", PayConstants.MCH_ID);
                return jsonMap.toJSONString();//响应签名数据,前端拿着响应数据调起微信SDK
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 计算签名
     *
     * @param message
     * @param yourPrivateKey
     * @return
     */
    private String sign(byte[] message, PrivateKey yourPrivateKey) {
        try {
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initSign(yourPrivateKey);
            sign.update(message);
            return Base64.getEncoder().encodeToString(sign.sign());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (java.security.InvalidKeyException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 回调验证签名
     *
     * @param serial
     * @param message
     * @param signatrue
     * @return
     */
    public static boolean signVerify(String serial, String message, String signatrue) {
        CertificatesManager certificatesManager = null;

        Verifier verifier = null;
        try {
            PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(PayConstants.privateKey.getBytes("utf-8")));
            // 获取证书管理器实例
            certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(PayConstants.MCH_ID, new WechatPay2Credentials(PayConstants.MCH_ID,
                            new PrivateKeySigner(PayConstants.MCH_SERIAL_NO, merchantPrivateKey)),
                    PayConstants.API_3KEY.getBytes(StandardCharsets.UTF_8));

            return verifier.verify(serial, message.getBytes("utf-8"), signatrue);
        } catch (Exception e) {

        }
        return false;
    }

    /**
     * 回调通知解密
     *
     * @param successCallBackObj
     * @return
     */
    public static String decryptToString(SuccessCallBackObj successCallBackObj) {
        if (successCallBackObj.getResource().getAssociated_data() == null) {
            return null;
        }
        //附加数据
        String associated_data = successCallBackObj.getResource().getAssociated_data();
        //随机串
        String nonce = successCallBackObj.getResource().getNonce();
        //数据密文
        String ciphertext = successCallBackObj.getResource().getCiphertext();
        //解密Resource
        AesUtil aesUtil = new AesUtil(PayConstants.API_3KEY.getBytes());
        try {
            return aesUtil.decryptToString(associated_data.getBytes(), nonce.getBytes(), ciphertext);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不秃头不是好技术员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值