SpringBoot整合weixin-java-pay实现微信小程序支付的示例代码

 更新时间:2024年05月31日 11:26:52   作者:Eden要努力搞钱  
微信小程序支付是常见的一种功能,本文主要介绍了SpringBoot整合weixin-java-pay实现微信小程序支付的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧

准备工作

依赖引入

<dependency>
  <groupId>com.github.binarywang</groupId>
  <artifactId>weinxin-java-pay</artifactId>
  <version>对应的版本号</version>
</dependency>

证书申请和下载

官方文档: 直达

在这里插入图片描述

撸起袖子使劲干

配置类

参数配置类

/**
 * @author: Eden4J
 * @Description: 微信支付商户信息配置类
 */
@Data
@Component
@RefreshScope
@ConfigurationProperties(prefix = "wechat.pay")
public class WeChatPayProperties {

    /**
     * 微信小程序或者微信公众号appId
     */
    private String appid;
    /**
     * 商户号
     */
    private String mchId;
    /**
     * 商户密钥
     */
    private String mchKey;
    /**
     * 商户证书序列号
     */
    private String serialNo;
    /**
     * apiV3Key
     */
    private String apiV3Key;
    /**
     * 证书
     */
    private String keyPath;
    /**
     * 商户私钥文件
     */
    private String privateKeyPath;

    /**
     * apiclient_cert.pem证书文件
     */
    private String privateCertPath;

    /**
     * 交易类型
     * JSAPI--公众号支付
     * NATIVE--原生扫码支付
     * APP--app支付
     */
    private String tradeType;
    /**
     * 支付结果异步通知回调地址
     */
    private String notifyUrl;
}

微信支付配置类

/**
 * @author: Eden4J
 * @Description: 微信支付配置类
 */
@Component
@ConditionalOnClass(WxPayService.class)
@RequiredArgsConstructor
public class WeChatPayConfig {
    private final WeChatPayProperties properties;

    @Bean
    @ConditionalOnMissingBean
    public WxPayConfig payConfig() {
        WxPayConfig payConfig = new WxPayConfig();
        payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppid()));
        payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
        payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
        payConfig.setCertSerialNo(StringUtils.trimToNull(this.properties.getSerialNo()));
        payConfig.setApiV3Key(StringUtils.trimToNull(this.properties.getApiV3Key()));
        payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));
        payConfig.setPrivateKeyPath(StringUtils.trimToNull(this.properties.getPrivateKeyPath()));
        payConfig.setPrivateCertPath(StringUtils.trimToNull(this.properties.getPrivateCertPath()));
        payConfig.setTradeType(StringUtils.trimToNull(this.properties.getTradeType()));
        return payConfig;
    }

    @Bean
    public WxPayService wxPayService(WxPayConfig payConfig) {
        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);
        return wxPayService;
    }
}

自定义的微信预支付返回信息类

@Data
public class WxPayInfoVO implements Serializable {
    private String appId;
    private String timeStamp;
    private String nonceStr;
    private String packageValue;
    private String signType;
    private String paySign;
}

工具类

/**
 * @author: Eden4J
 * @Description: 微信支付相关工具类
 */
public class WxPayUtil {

    public static String sign(String signStr, PrivateKey privateKey) {
        Sign sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA, privateKey.getEncoded(), null);
        return Base64.encode(sign.sign(signStr.getBytes()));
    }

    public static String buildMessage(String appId, String timeStamp, String nonceStr, String body) {
        return appId + "\n" + timeStamp + "\n" + nonceStr + "\n" + body + "\n";
    }

    public static AutoUpdateCertificatesVerifier getVerifier(WxPayConfig wxPayConfig) throws IOException {
        PrivateKey privateKey = PemUtils.loadPrivateKey(new ClassPathResource("apiclient_key.pem").getInputStream());
        AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
                new WxPayCredentials(wxPayConfig.getMchId(), new PrivateKeySigner(wxPayConfig.getCertSerialNo(), privateKey))
                , wxPayConfig.getApiV3Key().getBytes("utf-8")
        );
        return verifier;
    }

    /**
     * 验证签名
     *
     * @param certificate
     * @param message
     * @param signature
     * @return
     */
    public static boolean verify(AutoUpdateCertificatesVerifier certificate, byte[] message, String signature) {
        try {
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initVerify(certificate.getValidCertificate());
            sign.update(message);
            return sign.verify(java.util.Base64.getDecoder().decode(signature));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持SHA256withRSA", e);
        } catch (SignatureException e) {
            throw new RuntimeException("签名验证过程发生了错误", e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException("无效的证书", e);
        }
    }
}

接口层和服务处理层代码

重点注意:微信支付回调结果通知不要使用JSONObject去做接收

接口层

@RestController
@RequestMapping("/请求路径")
@RequiredArgsConstructor
public class AppCustomerUserRechargeOrderController {
    private final IAppCustomerUserRechargeOrderService rechargeOrderService;

    @PostMapping("/preOrder")
    public Result<WxPayInfoVO> preOrder(@RequestParam("goodId") String goodId) {
        return Result.success(rechargeOrderService.preOrder(goodId));
    }

    // 支付回调
    @PostMapping("/back")
    public Map<String,String> back(@RequestBody Map body,HttpServletRequest request) {
      return rechargeOrderService.formalOrder(body, request);
    }
}

处理层

 @Override
    public WxPayInfoVO preRecharge(String goodId) {
        try {
            //看看是否有其他的业务逻辑
            // 调用微信的统一下单接口获取预支付单返回前端 createOrderV3(TradeTypeEnum tradeType, WxPayUnifiedOrderV3Request request)
            WxPayUnifiedOrderV3Request payRequest = new WxPayUnifiedOrderV3Request();
            payRequest.setOutTradeNo(rechargeNo);//系统充值订单号
            payRequest.setDescription(goodsPackage.getPackageName());
            //订单失效时间
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
            payRequest.setTimeExpire(dateFormat.format(DateUtil.offset(new Date(), DateField.HOUR_OF_DAY, 1)));
            WxPayUnifiedOrderV3Request.Payer payer = new WxPayUnifiedOrderV3Request.Payer();
            payer.setOpenid(userAccount.getOpenId());
            payRequest.setPayer(payer);
            WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
            amount.setTotal(rechargeOrder.getTotalAmount().multiply(BigDecimal.valueOf(100)).intValue());
            amount.setCurrency("CNY");
            payRequest.setAmount(amount);
            payRequest.setNotifyUrl(weChatPayProperties.getNotifyUrl());
            WxPayUnifiedOrderV3Result.JsapiResult jsapiResult = wxPayService.createOrderV3(TradeTypeEnum.JSAPI, payRequest);
            String encode = WxPayUtil.sign(WxPayUtil.buildMessage(weChatPayProperties.getAppid(), jsapiResult.getTimeStamp(), jsapiResult.getNonceStr(), jsapiResult.getPackageValue())
                    , PemUtils.loadPrivateKey(new ClassPathResource("apiclient_key.pem").getInputStream()));
            WxPayInfoVO payInfoVO = PojoUtil.exchangePojo(jsapiResult, WxPayInfoVO.class);
            payInfoVO.setPaySign(encode);
            return payInfoVO;
        } catch (WxPayException e) {
            e.printStackTrace();
            throw new BizException("微信支付失败", e);
        } catch (IOException e) {
            e.printStackTrace();
            throw new BizException("微信支付失败", e);
        }
    }

    @Override
    public Map<String, String> createFormalOrder(Map body, HttpServletRequest request) {
        try {
            Map<String, String> resultMap = new HashMap<>();
            resultMap.put("code", "FAIL");
            ObjectMapper objectMapper = new ObjectMapper();
            try {
            	//官方文档中有说明切记不要改变原始报文主体,如果使用JSONObject接收的话,不能使用JSON转换出来的字符串,会出现验签错误的情况,请注意
                String data = objectMapper.writeValueAsString(body);
                SignatureHeader header = new SignatureHeader();
                header.setTimeStamp(request.getHeader("Wechatpay-Timestamp"));
                header.setNonce(request.getHeader("Wechatpay-Nonce"));
                header.setSignature(request.getHeader("Wechatpay-Signature"));
                header.setSerial(request.getHeader("Wechatpay-Serial"));
                WxPayNotifyV3Result notifyV3Result =wxPayService.parseOrderNotifyV3Result(data, header);
                WxPayNotifyV3Result.DecryptNotifyResult decryptNotifyResult = notifyV3Result.getResult();//解密后的数据
                    if ("SUCCESS".equalsIgnoreCase(decryptNotifyResult.getTradeState())) {
                        resultMap.put("code", "SUCCESS");
                    }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("微信支付成功回调失败", e);
        }
    }

到此这篇关于SpringBoot整合weixin-java-pay实现微信小程序支付的示例代码的文章就介绍到这了,更多相关SpringBoot weixin-java-pay微信小程序支付内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中的FileInputStream是否需要close问题

    Java中的FileInputStream是否需要close问题

    这篇文章主要介绍了Java中的FileInputStream是否需要close问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • 基于Java编写第一个区块链项目

    基于Java编写第一个区块链项目

    区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式,下面这篇文章主要给大家介绍了基于Java实现区块链的相关资料,需要的朋友可以参考下
    2021-08-08
  • CompletableFuture 异步编排示例详解

    CompletableFuture 异步编排示例详解

    这篇文章主要为大家介绍了CompletableFuture 异步编排示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • 通过Java计算文件的MD5值实现方式

    通过Java计算文件的MD5值实现方式

    本文将详细介绍如何使用Java语言来计算文件的MD5值,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • shade解决mybatis包冲突问题及项目引用的方法

    shade解决mybatis包冲突问题及项目引用的方法

    这篇文章主要介绍了shade解决mybatis包冲突问题及项目引用的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • redis深入浅出分布式锁实现上篇

    redis深入浅出分布式锁实现上篇

    在单体应用中,如果我们对共享数据不进行加锁操作,会出现数据一致性问题,我们的解决办法通常是加锁。下面我们一起聊聊使用redis来实现分布式锁
    2022-08-08
  • SpringBoot整合RocketMq实现分布式事务

    SpringBoot整合RocketMq实现分布式事务

    这篇文章主要为大家详细介绍了SpringBoot整合RocketMq实现分布式事务的相关知识,文中的示例代码讲解详细,有需要的小伙伴可以参考一下
    2024-11-11
  • java的json解析类库使用示例

    java的json解析类库使用示例

    这篇文章主要介绍了java的json解析类库使用方法,这里使用Zson解析json,这是一个开源的json处理类库
    2014-03-03
  • SpringBoot+React实现计算个人所得税

    SpringBoot+React实现计算个人所得税

    本文将以个人所得税的计算为例,使用React+SpringBoot+GcExcel来实现这一功能,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解下
    2023-09-09
  • Java实现ThreadLocal数据在线程池间传递的解决方案

    Java实现ThreadLocal数据在线程池间传递的解决方案

    随着业务的发展,系统新增了一个需求:需要根据接口请求头中的特定信息动态选择数据库实例进行查询,这个上下文信息在请求进入后被存储在ThreadLocal中,本文给大家介绍了Java实现ThreadLocal数据在线程池间传递的解决方案,需要的朋友可以参考下
    2025-07-07

最新评论