java对接微信支付SDK接口

1.对接准备

需要的参数包括开发者ID(appid)、商户号、商户api私钥、商户证书序列号、商户APIV3密钥、回调地址。

在微信公众平台https://mp.weixin.qq.com/ 注册应用,类型只选择“公众号/小程序/企业微信”,注册完成后需完成”微信认证“(微信收取300元),在基础配置中拿到开发者ID(APPID)。

在微信支付商户平台https://pay.weixin.qq.com注册商户,在账户中心-api安全中设置APIv3密钥,微信支付 APIv3 使用由 证书授权机构(Certificate Authority,简称CA)签发的证书,商户申请证书时,证书工具会生成商户私钥,并保存在本地证书文件夹的件 apiclient_key.pem 中。开发和部署,需要区分环境,加载 apiclient_key.pem 文件。

在账户中心-商户信息中拿到微信支付商户号,即商户ID (收钱的商家ID);

在产品中心-appid账号管理中,将申请的下来的APPID绑定到商户号下。 

Certificate Downloader 是 Java 微信支付 APIv3 平台证书的命令行下载工具。该工具可从https://api.mch.weixin.qq.com/v3/certificates 接口获取商户可用证书

2.maven引入jar包

<!-- 微信支付SDK -->
<dependency>
    <groupId>com.github.wechatpay-apiv3</groupId>
    <artifactId>wechatpay-java</artifactId>
    <version>0.2.9</version>
</dependency>

3.yml文件配置微信参数,工具类读取

@Component
public class WechatPayConfig {

    /**
     * 应用ID
     */
    public static String appid;

    /**
     * 商户号
     */
    public static String merchantId;

    /**
     * 商户API私钥路径
     */
    public static String privateKeyPath;

    /**
     * 商户证书序列号
     */
    public static String merchantSerialNumber;

    /**
     * 商户APIV3密钥
     */
    public static String apiV3Key;

    /**
     * 通知地址(有效性:1. HTTPS;2. 不允许携带查询串。)
     */
    public static String notifyUrl;

    /**
     * 微信支付配置
     */
    public static Config config;

    /**
     * 订单支付超时时间/分钟
     */
    public static final Integer ORDER_PAY_TIME_OUT = 1440;


    private WechatPayConfig() {}

    @Value("${wechat.pay.appid}")
    public void setAppid(String appid) {
        WechatPayConfig.appid = appid;
    }

    @Value("${wechat.pay.merchantId}")
    public void setMerchantId(String merchantId) {
        WechatPayConfig.merchantId = merchantId;
    }

    @Value("${wechat.pay.privateKeyPath}")
    public void setPrivateKeyPath(String privateKeyPath) {
        String classPath = System.getProperty("java.class.path");
        // 是否运行在开发环境
        boolean isRunningFromIde = classPath.toLowerCase().contains("eclipse") || classPath.toLowerCase().contains("idea");
        // 开发环境与部署jar包环境 不同获取私钥路径
        if (isRunningFromIde){
            WechatPayConfig.privateKeyPath = getClass().getClassLoader().getResource("apiclient_key.pem").getPath();
        }else {
            WechatPayConfig.privateKeyPath = privateKeyPath;
        }
    }

    @Value("${wechat.pay.merchantSerialNumber}")
    public void setMerchantSerialNumber(String merchantSerialNumber) {
        WechatPayConfig.merchantSerialNumber = merchantSerialNumber;
    }

    @Value("${wechat.pay.apiV3Key}")
    public void setApiV3Key(String apiV3Key) {
        WechatPayConfig.apiV3Key = apiV3Key;
    }

    @Value("${wechat.pay.notifyUrl}")
    public void setNotifyUrl(String notifyUrl) {
        WechatPayConfig.notifyUrl = notifyUrl;
    }

    @PostConstruct
    public void initializeConfig() {
        // 初始化微信配置
        config = new RSAAutoCertificateConfig.Builder()
                .merchantId(merchantId)
                .privateKeyFromPath(privateKeyPath)
                .merchantSerialNumber(merchantSerialNumber)
                .apiV3Key(apiV3Key)
                .build();
    }

}

4.对接支付接口

    /**
     * 微信 Native 支付下单
     *
     * @param amt         金额
     * @param orderNumber 订单号
     * @param description 描述
     * @return 二维码链接
     */
    public static AjaxResult nativePay(BigDecimal amt, String orderNumber, String description) {
        // 当前时间
        Date currentDate = new Date();
        // 将金额转换为分
        int total = amt.multiply(new BigDecimal("100")).intValue();
        try {
            // 构建service
            NativePayService service = new NativePayService.Builder().config(WechatPayConfig.config).build();
            // 构建请求对象
            PrepayRequest request = new PrepayRequest();
            request.setAppid(WechatPayConfig.appid);
            request.setMchid(WechatPayConfig.merchantId);
            request.setNotifyUrl(WechatPayConfig.notifyUrl);
            // 设置金额
            Amount amount = new Amount();
            amount.setTotal(total);
            request.setAmount(amount);
            request.setDescription(description);
            request.setOutTradeNo(orderNumber);
            // 计算订单失效时间
            Calendar calendar = DateUtils.toCalendar(currentDate);
            calendar.add(Calendar.MINUTE, WechatPayConfig.ORDER_PAY_TIME_OUT);
            request.setTimeExpire(DateUtils.parseDateToStr("yyyy-MM-dd'T'HH:mm:ss+08:00", calendar.getTime()));
            return AjaxResult.success(service.prepay(request).getCodeUrl());
        } catch (Exception e){
            log.error(e.getMessage(),e);
            return AjaxResult.error("支付订单创建失败");
        }
    }

5.回调地址

    /**
     * 微信支付回调
     *
     * @return 回调结果
     */
    @PostMapping("/wechat")
    public ResponseEntity.BodyBuilder wechat(@RequestBody String body, HttpServletRequest request) {
        try {
            // 构造 RequestParam
            RequestParam requestParam = new RequestParam.Builder()
                    // 序列号
                    .serialNumber(request.getHeader("Wechatpay-Serial"))
                    // 随机数
                    .nonce(request.getHeader("Wechatpay-Nonce"))
                    // 签名
                    .signature(request.getHeader("Wechatpay-Signature"))
                    // 时间戳
                    .timestamp(request.getHeader("Wechatpay-Timestamp"))
                    .body(body)
                    .build();
            // 初始化解析器
            NotificationParser parser = new NotificationParser((NotificationConfig) WechatPayConfig.config);
            // 验签、解密并转换成 Transaction
            Transaction transaction = parser.parse(requestParam, Transaction.class);
            // 校验交易状态
            if (Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())) {
                // 支付成功,根据订单编号查询订单信息
                // 1.查询订单信息
                Order orderOld = orderService.selectForUpdateByOrderNumber(transaction.getOutTradeNo());
                // 校验金额
                if (orderOld != null && orderOld.getPayAmount().equals(transaction.getAmount().getTotal())) {
                    // 金额相等 完成支付 更新订单状态
                    WechatPayUtil.success(orderOld,transaction);
                } else {
                    // 金额异常 执行退款
                    WechatPayUtil.refunded(new WechatPayRedis(transaction.getOutTradeNo(), transaction.getAmount().getTotal(), null));
                }
            }
        } catch (ValidationException e) {
            // 签名验证失败,返回 401 UNAUTHORIZED 状态码
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED);
        }

        // 处理成功,返回 200 OK 状态码
        return ResponseEntity.status(HttpStatus.OK);
    }

    /**
     * 支付成功
     */
    public static void success( Order orderOld,Transaction transaction) {
        try {
            // 支付完成时间
            Date payTime = DateUtils.parseDate(transaction.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ss+08:00");
            // 校验订单信息 & 支付结果 & 订单有效期止日期
            if (orderOld != null && orderOld.getPayResult() == 0 && payTime.compareTo(orderOld.getExpirationDate()) < 1) {
                // 构建修改对象
                Order updateOrder = new Order();
                updateOrder.setId(orderOld.getId());
                updateOrder.setPayMethod(PayMethodEnum.W.name());
                updateOrder.setPayChannel(PayChannelEnum.P.name());
                updateOrder.setPayDate(payTime);
                updateOrder.setPayResult(PayResultEnum.PAID.getCode());
                updateOrder.setPayType(PayTypeEnum.U.name());
                updateOrder.setSerialNumber(transaction.getTransactionId());
                if (orderService.editPayResult(updateOrder,orderOld) == 1) {
                    // 删除Redis订单支付信息
                    SpringUtils.getBean(RedisCache.class).deleteObject(WechatPayConfig.ORDER_PAY_REDIS_PREFIX + transaction.getOutTradeNo());
                }
            } else {
                // 订单信息不存在 执行退款
                WechatPayUtil.refunded(new WechatPayRedis(transaction.getOutTradeNo(), transaction.getAmount().getTotal(), null));
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 执行退款
     */
    public static void refunded(WechatPayRedis wechatPay) {
        try {
            // 构建退款Service
            RefundService service = new RefundService.Builder().config(WechatPayConfig.config).build();
            // 构建请求对象
            CreateRequest request = new CreateRequest();
            request.setOutTradeNo(wechatPay.getOrderNumber());
            request.setOutRefundNo(wechatPay.getOrderNumber());
            // 支付总金额(分)
            long total = wechatPay.getTotal();
            // 设置退款金额
            AmountReq amount = new AmountReq();
            amount.setRefund(total);
            amount.setTotal(total);
            amount.setCurrency("CNY");
            request.setAmount(amount);
            // 请求API申请退款
            Refund refund = service.create(request);
            // 校验退款结果
            if (refund != null && Status.SUCCESS.equals(refund.getStatus())) {
                // 退款成功
                log.info("微信退款成功:{}", wechatPay);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }


 

Java小程序可以使用微信支付接口实现支付功能。对接微信支付接口的步骤如下: 1. 获取微信支付接口的开发者账号,并进行账号绑定和认证。 2. 在Java小程序的后端代码中,引入微信支付SDK,可以使用第三方的开源SDK,如微信官方提供的java-sdk或者其他优秀的支付SDK。 3. 在小程序中,创建一个支付请求页面,用户选择商品并点击支付按钮。将用户购买的商品信息传递到后台。 4. 后台接收到支付请求后,调用微信支付接口,传递必要的支付参数,包括商户号、商户订单号、支付金额、支付方式等。 5. 微信支付接口会返回一个预支付交易会话标识prepay_id,后台将该值返回给前端,前端将该值存储到小程序的支付参数中。 6. 前端根据prepay_id、商户号、商户订单号等参数,调用微信支付的API,通过微信支付页面生成支付订单。 7. 用户在小程序中看到生成的支付订单,选择支付方式(如微信支付或其他支付方式),输入支付密码等信息完成支付。 8. 支付成功后,微信支付接口会向后台发送支付结果通知,后台需要对接收到的结果进行验证,包括验证订单是否支付成功、验证订单金额是否一致等。 9. 后台验证通过后,向前端返回支付成功的信息,前端展示支付成功页面,并修改相关订单状态。 10. 后台同时需要记录支付相关的信息,如支付时间、支付方式等,供后续的订单查询和统计使用。 以上就是Java小程序对接微信支付接口的一般步骤,具体实现过程还需要根据具体的业务需求进行调整和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值