当前位置:首页 » 《随便一记》 » 正文

java对接微信支付SDK接口

14 人参与  2024年11月15日 15:21  分类 : 《随便一记》  评论

点击全文阅读


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文件配置微信参数,工具类读取

@Componentpublic 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);        }    }


 


点击全文阅读


本文链接:http://zhangshiyu.com/post/186622.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1