java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java对接微信支付SDK接口

java对接微信支付SDK接口简单图文教程

作者:子木凝烟

在微信支付接口对接过程中,开发者需准备多项关键参数,如开发者ID(appid)、商户号等,并完成相关注册与认证流程,文中通过图文介绍的非常详细,需要的朋友可以参考下

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对接微信支付SDK接口的文章就介绍到这了,更多相关java对接微信支付SDK接口内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文