springboot集成实现微信扫码支付

背景

PC端项目需要实现微信扫码支付功能,申请微信商户号,获取如下参数appId,merchId,key和证书等信息

1. 引入sdk

 <dependency>
            <groupId>com.github.wxpay</groupId>
            <artifactId>wxpay-sdk</artifactId>
            <version>0.0.3</version>
        </dependency>

2. Yaml配置

wx-pay:
  appId: xxxxxxxxxxxxxxxxx
  #证书的位置
  certPath: classpath:apiclient_cert.p12
  key: xxxxxxxxxxxxxxxx
  mchId: xxxxxxxxxxxxxxxx
  

3. 将证书放在resource目录下,并yaml配置

4. 微信配置文件WxConfig,创建bean对象注入

@Configuration
public class WxPayConfig {
    @Value("${wx-pay.appId}")
    private String appId;

    @Value("${wx-pay.mchId}")
    private String mchId;

    @Value("${wx-pay.key}")
    private String key;

    @Value("${wx-pay.certPath}")
    private String certPath;

    @Bean
    public WXPay wxPay() throws Exception {
        
        WXPayConfig payConfig = new WXPayConfig() {
            @Override
            public String getAppID() {
                return appId;
            }

            @Override
            public String getMchID() {
                return mchId;
            }

            @Override
            public String getKey() {
                return key;
            }

            @Override
            public InputStream getCertStream() {
                try {
                    return resource.getInputStream();
                } catch (Exception e) {
                    throw new RuntimeException("Failed to load certificate", e);
                }
            }

            @Override
            public int getHttpConnectTimeoutMs() {
                return 0;
            }

            @Override
            public int getHttpReadTimeoutMs() {
                return 0;
            }

            // 根据需要实现其他方法,如设置超时等
        };

        // 创建WXPay实例,这里假设使用MD5签名
        return new WXPay(payConfig, WXPayConstants.SignType.MD5);
    }
}

5. 微信支付工具类

 public String pay(String title,String orderNo,BigDecimal amount,String notifyUrl) {
        try {
            //String orderNo= TouUtil.getOrderNo();
            Map<String, String> data = new HashMap<String, String>();
            data.put("body", title);
            data.put("out_trade_no", orderNo);
            data.put("fee_type", "CNY");
            data.put("total_fee", String.valueOf(NumberUtil.mul(amount,100)));
            data.put("spbill_create_ip", "127.0.0.1");
            data.put("notify_url", notifyUrl);
            data.put("trade_type", "NATIVE");
            data.put("product_id", UUID.randomUUID().toString());
            // 发起支付请求
            Map<String, String> resp = wxPay.unifiedOrder(data);
            if ("SUCCESS".equals(resp.get("return_code")) && "SUCCESS".equals(resp.get("result_code"))) {
                //插入记录
                return resp.get("code_url");
            } else {
                logger.info("微信支付错误{}",resp.toString());
                throw new RuntimeException("wxpay error");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

6. 支付回调

@RequestMapping("chargeBuyWx")
    public String chargeBuyWx(HttpServletRequest request) {
        try {
            // 解析微信支付回调请求参数
            Map<String, String> params = parseXml(request.getInputStream());
            boolean verifyResult = wxPay.isPayResultNotifySignatureValid(params);
            if (verifyResult) {
                String outTradeNo = params.get("out_trade_no");
                String tradeNo = params.get("trade_no");
                String totalAmount = params.get("total_fee");
                logger.info("会员充值回调 {}",outTradeNo);
                LambdaQueryWrapper<TnlMoneyDto>wrapper=new LambdaQueryWrapper<>();
                wrapper.eq(TnlMoneyDto::getOrderNo,outTradeNo);
                wrapper.eq(TnlMoneyDto::getStatus,0);
                TnlMoneyDto moneyDto=moneyMapper.selectOne(wrapper);
                if(ObjectUtil.isNotEmpty(moneyDto)){
                    moneyDto.setStatus(1);
                    moneyMapper.update(moneyDto,wrapper);
                    //等级处理
                    LambdaQueryWrapper<UserDto>queryWrapper=new LambdaQueryWrapper<>();
                    queryWrapper.eq(UserDto::getId,moneyDto.getUId());
                    UserDto userDto=userMapper.selectOne(queryWrapper);
                    BigDecimal money= NumberUtil.add(userDto.getScore(), Convert.toBigDecimal(totalAmount).divide(new BigDecimal(100)));
                    userDto.setScore(money);
                    logger.info("会员充值回调 {}",money);
                    userMapper.update(userDto,queryWrapper);
                }
                return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
            }else {
                return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名验证失败]]></return_msg></xml>";
            }
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

7. 解析微信回调工具

private Map<String, String> parseXml(InputStream inputStream) throws Exception {
        // 使用try-with-resources确保inputStream被关闭
        try (InputStream is = inputStream;
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
             byte[] buffer = new byte[1024];
             int length;
             while ((length = is.read(buffer)) != -1) {
                outputStream.write(buffer, 0, length);
             }
             String xml = outputStream.toString("utf-8");
             return WXPayUtil.xmlToMap(xml);
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值