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

### Spring Boot 实现微信码登录 #### 一、引入依赖 为了简化开发过程,可以使用 `wxlogin-spring-boot-starter` 这个第三方库来快速集成微信码登录功能。仅需在项目的 `pom.xml` 文件中添加如下 Maven 依赖即可完成环境搭建[^2]。 ```xml <dependency> <groupId>com.tofries</groupId> <artifactId>wxlogin-spring-boot-starter</artifactId> <version>1.0.0</version> </dependency> ``` #### 二、配置文件设置 接着,在 `application.yml` 或者 `application.properties` 中加入必要的参数配置,比如 AppID 和 AppSecret 等基本信息,这些信息可以从微信公众平台获取到。以下是 YAML 配置样例: ```yaml wx: login: appId: wxxxxxxxxxxxxxxx # 替换成自己的AppID appSecret: xxxxxxxxxxxxxx # 替换成自己的AppSecret ``` #### 三、控制器编写 创建一个新的 Controller 类用于处理前端请求并返回相应的视图页面或 JSON 数据给客户端展示二维码等内容。下面是一个简单的 Java 控制器实例: ```java import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class WxLoginController { @GetMapping("/qrCode") public String getQrCodeUrl() { // 调用微信接口生成带参二维码链接逻辑... return "https://example.com/qrcode?param=value"; } } ``` 此段代码展示了如何定义一个 RESTful API 来响应来自浏览器或其他 HTTP 客户端对于获取二维码 URL 的 GET 请求,并假设已经实现了调用微信服务端API的方法以构建有效的二维码地址字符串[^1]。 #### 四、回调处理器 当用户二维码后会触发一次由微信服务器发起至开发者设定好的重定向 URI 上的 POST 请求携带授权code作为参数传递过来;此时就需要在这个路径下建立对应的 Handler 方法来进行后续操作如交换 access_token 及 openid 并验证身份合法性等步骤。 ```java @GetMapping("/callback") public ResponseEntity<?> handleCallback(@RequestParam("code") String code) { // 使用code换取access_token和openid的过程省略... Map<String, Object> userInfo = new HashMap<>(); // 将获取到的信息放入map中以便向前端传输 return ResponseEntity.ok(userInfo); } ``` 上述方法接收到了从微信跳转回来附带的临时票据(code),之后就可以利用它去向官方申请用户的唯一标识符 OpenID 以及其他公开资料了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值