java 百度小程序支付 对接

1.开度小程序后天开发配置

    1.1 使用rsa 密钥生成工具,生成公钥私钥,使用工具,推荐阿里的生成工具https://help.aliyun.com/document_detail/123151.html

   1.2.支付设置后台配置,公钥和回调调地址。

2.生成预支付订单


    /**
     * 拼装参数
     * @param transactionSN
     * @param tradeAmount
     * @return
     */
    private BaiduPayApplyRespDto getBaiduPayApplyRespDto(String transactionSN, String tradeAmount) {
        BaiduPayApplyRespDto result = new BaiduPayApplyRespDto();
        OrderInfo order = new OrderInfo();
        Map<String,Object> sign = new HashMap<>();
        Map<String,Object> bizInfo = new HashMap<>();
        order.setAppKey(appKey);
        order.setDealId(dealId);
        order.setDealTitle("支付订单");
        order.setTotalAmount(tradeAmount);
        order.setTpOrderId(transactionSN);
        order.setSignFieldsRange("1");
        //组装参数
        sign.put("appKey",appKey);
        sign.put("dealId",dealId);
        sign.put("totalAmount", tradeAmount);
        sign.put("tpOrderId", transactionSN);
        order.setBizInfo(bizInfo);
        try {
            log.info("【参数签名】:{}", JSONObject.toJSONString(sign));
            order.setRsaSign(RSASign.sign(sign,privateKey));
        } catch (Exception e) {
            log.error("【参数签名失败】:", e);
            return null;
        }
        result.setOrderInfo(order);
        return result;
    }

2.2 签名部分代码

/*
 * Copyright (C) 2020 Baidu, Inc. All Rights Reserved.
 */
package com.baidu.*;

import static org.springframework.util.Assert.isTrue;
import static org.springframework.util.Assert.notNull;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;

import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

/**
 * 百度交易中台双向RSA签名工具
 * JDK版本要求:1.8+
 */
public class RSASign {

    private static final String CHARSET = "UTF-8";
    private static final String SIGN_TYPE_RSA = "RSA";
    private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
    private static final String SIGN_KEY = "rsaSign";

    /**
     * 使用私钥生成签名字符串
     *
     * @param params     待签名参数集合
     * @param privateKey 私钥原始字符串
     *
     * @return 签名结果字符串
     *
     * @throws Exception
     */
    public static String sign(Map<String, Object> params, String privateKey) throws Exception {
        isTrue(!CollectionUtils.isEmpty(params), "params is required");
        notNull(privateKey, "privateKey is required");

        String signContent = signContent(params);

        Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
        signature.initSign(getPrivateKeyPKCS8(privateKey));
        signature.update(signContent.getBytes(CHARSET));
        byte[] signed = signature.sign();

        return new String(Base64.getEncoder().encode(signed));
    }

    /**
     * 使用公钥校验签名
     *
     * @param params    入参数据,签名属性名固定为rsaSign
     * @param publicKey 公钥原始字符串
     *
     * @return true 验签通过 | false 验签不通过
     *
     * @throws Exception
     */
    public static boolean checkSign(Map<String, Object> params, String publicKey) throws Exception {
        isTrue(!CollectionUtils.isEmpty(params), "params is required");
        notNull(publicKey, "publicKey is required");

        // sign & content
        String content = signContent(params);
        String rsaSign = params.get(SIGN_KEY).toString();

        // verify
        Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
        signature.initVerify(getPublicKeyX509(publicKey));
        signature.update(content.getBytes(CHARSET));

        return signature.verify(Base64.getDecoder().decode(rsaSign.getBytes(CHARSET)));
    }

    /**
     * 对输入参数进行key过滤排序和字符串拼接
     *
     * @param params 待签名参数集合
     *
     * @return 待签名内容
     *
     * @throws UnsupportedEncodingException
     */
    private static String signContent(Map<String, Object> params) throws UnsupportedEncodingException {
        Map<String, String> sortedParams = new TreeMap<>(Comparator.naturalOrder());
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            String key = entry.getKey();
            if (legalKey(key)) {
                sortedParams.put(key, entry.getValue().toString());
            }
        }

        StringBuilder builder = new StringBuilder();
        if (!CollectionUtils.isEmpty(sortedParams)) {
            for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
                builder.append(entry.getKey());
                builder.append("=");
                builder.append(entry.getValue());
                builder.append("&");
            }
            builder.deleteCharAt(builder.length() - 1);
        }
        return builder.toString();
    }

    /**
     * 将公钥字符串进行Base64 decode之后,生成X509标准公钥
     *
     * @param publicKey 公钥原始字符串
     *
     * @return X509标准公钥
     *
     * @throws InvalidKeySpecException
     * @throws NoSuchAlgorithmException
     */
    private static PublicKey getPublicKeyX509(String publicKey) throws InvalidKeySpecException,
            NoSuchAlgorithmException, UnsupportedEncodingException {
        if (StringUtils.isEmpty(publicKey)) {
            return null;
        }
        KeyFactory keyFactory = KeyFactory.getInstance(SIGN_TYPE_RSA);
        byte[] decodedKey = Base64.getDecoder().decode(publicKey.getBytes(CHARSET));
        return keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));
    }

    /**
     * 将私钥字符串进行Base64 decode之后,生成PKCS #8标准的私钥
     *
     * @param privateKey 私钥原始字符串
     *
     * @return PKCS #8标准的私钥
     *
     * @throws Exception
     */
    private static PrivateKey getPrivateKeyPKCS8(String privateKey) throws Exception {
        if (StringUtils.isEmpty(privateKey)) {
            return null;
        }
        KeyFactory keyFactory = KeyFactory.getInstance(SIGN_TYPE_RSA);
        byte[] decodedKey = Base64.getDecoder().decode(privateKey.getBytes(CHARSET));
        return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(decodedKey));
    }

    /**
     * 有效的待签名参数key值
     * 非空、且非签名字段
     *
     * @param key 待签名参数key值
     *
     * @return true | false
     */
    private static boolean legalKey(String key) {
        return StringUtils.hasText(key) && !SIGN_KEY.equalsIgnoreCase(key);
    }
}

3.小程序前端调起支付。

4.回调处理

4.1,回调部分java代码实现 ,这里唯一需要注意的就是验签的公钥,这里是百度小程序后台,支付设置里面的平台公钥,不是开发者公钥

@Data
public class BaiduPayReq implements Serializable {

    /**
     * 交易单号
     */
    private String tpOrderId;

    /**
     * 订单状态
     */
    private Integer status;

    /**
     * 百度交易号
     */
    private String orderId;

    /**
     * 订单实际支付金额
     */
    private Integer payMoney;

    /**
     * 支付时间
     */
    private Integer payTime;
    /**
     * 消息id
     */
    private String messageId;
    /**
     * 签名
     */
    private String rsaSign;
    /**
     *
     */
    private String dealId;
    /**
     *
     */
    private Long userId;

    private Integer unitPrice;

    private Integer count;

    private Integer totalMoney;

    private Integer promoMoney;

    private Integer hbMoney;

    private Integer hbBalanceMoney;

    private Integer giftCardMoney;

    private Object promoDetail;

    private Integer payType;

    private Object returnData;

    private Integer partnerId;

}
 /**
     * 百度支付回调地址
     *
     * @return
     */
    @RequestMapping(value = "/callback")
    public JSONObject notifyPay(BaiduPayReq req) {
        log.info("BaiduPayReq:{}", JSONObject.toJSONString(req));
        JSONObject resultObj = new JSONObject();
        //是百度小程序后台支付设置里面的平台公钥,不是开发者公钥,切记
        String baiduPayPublicKey="";
        try {
           
            //支付参数验签
            Map<String, Object> sign = JSON.parseObject(JSON.toJSONString(req), new TypeReference<Map<String, Object>>() {
            });
            sign.put("rsaSign", req.getRsaSign().replace(" ", ""));
            log.info("【百度支付验签入参】:{}", JSONObject.toJSONString(sign));
            boolean check = RSASign.checkSign(sign, baiduPayPublicKey);
            log.info("【百度支付验签结果】:{}", check);
            if (!check) {
                return resultObj;
            }
            //处理业务逻辑
        }catch (Exception e){
            log.error("【baiduPay notifyPay】 error:{}", e);
        }
        return resultObj;
    }
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值