springboot整合微信扫码支付(详细)

2023-10-30

微信扫码支付

以下主要是针对微信支付V3接口进行的整合,且为Native支付

前期准备工作

1️⃣:获取微信相关数据

#绑定支付的appid
#商户id
#商户支付秘钥wechatKey,这个需要V3的
#证书序列号
#私钥文件(.pem文件)
#下面给出了相应的链接

微信支付商户平台

⚠️:这里千万别用微信服务商去注册,原因见下图

image-20230429154001177

上面的参数都获取到后,就可以进行springboot的整合了

2️⃣:导入maven坐标

<!--微信支付-->
<dependency>
  <groupId>com.github.wechatpay-apiv3</groupId>
  <artifactId>wechatpay-java</artifactId>
  <version>0.2.6</version>
</dependency>
package com.test.test.api.wechat.pay;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.partnerpayments.nativepay.model.Transaction;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;


/**
 * @author xiaobo
 * @date 2023/3/8
 */
@Controller
@Slf4j
@RequestMapping("/wechat")
public class WechatPayApi extends BaseController {

    private static final String APP_ID = "";

    private static final String MERCHANT_ID = "";

    private static final String WECHAT_KEY = "";

    private static final String MERCHANT_SERIAL_NUMBER = "";

    private static final String NOTIFY_URL = "";


    public static NativePayService service;
    public static Config config = null;
  
    public static final String WECHAT_PAY_SIGNATURE = "Wechatpay-Signature";
  
    public static final String WECHAT_PAY_TIMESTAMP = "Wechatpay-Timestamp";
  
    public static final String WECHAT_PAY_SIGNATURE_TYPE = "Wechatpay-Signature-Type";
  
    public static final String WECHAT_PAY_SERIAL = "Wechatpay-Serial";
  
    public static final String WECHAT_PAY_NONCE = "Wechatpay-Nonce";

    /**
     * Native支付预下单
     */
    @RequestMapping("prepay")
    @ResponseBody
    public RespResult wechatPay(double total_amount) {
        PrepayRequest prepayRequest = new PrepayRequest();
        Amount amount = new Amount();
        // total为分
        amount.setTotal((int) (total_amount * 100));
        prepayRequest.setAmount(amount);
        prepayRequest.setMchid(MERCHANT_ID);
        prepayRequest.setAppid(APP_ID);
        prepayRequest.setNotifyUrl(NOTIFY_URL);
        prepayRequest.setDescription("账户充值");
      	// 这里的订单号要保证唯一,这种方法不推荐(因为并发高的情况下会出现订单号不唯一)
        prepayRequest.setOutTradeNo(new SimpleDateFormat("yyyyMMddhhmmss").format(new Date()) + RandomUtil.randomNumbers(4));
        PrepayResponse prepayResponse = service.prepay(prepayRequest);
        // TODO 数据库处理订单(这里应该相应的生成订单)
        // 返回成功,以及相应的二维码地址(前端需要进行转换为二维码)
        return RespResult.success(prepayResponse.getCodeUrl(), jsonObject);
        }
        return RespResult.fail("获取微信支付码失败!");
    }

    @ResponseBody
    @PostMapping("success")
    public RespResult success(HttpServletRequest request) throws IOException {
        // 读取请求头内容
        String serialNumber = request.getHeader(WECHAT_PAY_SERIAL);
        String nonce = request.getHeader(WECHAT_PAY_NONCE);
        String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
        String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
        String signType = request.getHeader(WECHAT_PAY_SIGNATURE_TYPE);
        log.error(serialNumber, nonce, signature, timestamp);
        // 获取请求体内容
        ServletInputStream servletInputStream = request.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(servletInputStream));
        StringBuffer stringBuffer = new StringBuffer();
        String s;
        while ((s = bufferedReader.readLine()) != null) {
            stringBuffer.append(s);
        }
        // 构造 RequestParam
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(serialNumber)
                .nonce(nonce)
                .signature(signature)
                .timestamp(timestamp)
                // 若未设置signType,默认值为 WECHATPAY2-SHA256-RSA2048
                .signType(signType)
                .body(stringBuffer.toString())
                .build();

        // 初始化 NotificationParser
        NotificationParser parser = new NotificationParser((NotificationConfig) config);

        // 验签并解密报文
        Transaction decryptObject = parser.parse(requestParam, Transaction.class);
        log.error(decryptObject.toString());
        Map params = new HashMap(3);
        Map resultMap = (Map) JSON.parse(stringBuffer.toString());
        // TODO 你的业务逻辑处理
        return RespResult.success("成功!");
        }
        return RespResult.success("失败!");
    }

    @PostConstruct
    public static NativePayService initializeWechatConfiguration() throws FileNotFoundException {
        // 初始化商户配置
        String privateKeyPath = Objects.requireNonNull(KuocaiCdnBootApplication.class.getResource("/apiclient_key.pem")).getPath();

        if (config == null) {
            config =
                    new RSAAutoCertificateConfig.Builder()
                            .merchantId(MERCHANT_ID)
                            // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
                            .privateKeyFromPath(privateKeyPath)
                            .merchantSerialNumber(MERCHANT_SERIAL_NUMBER)
                            .apiV3Key(WECHAT_KEY)
                            .build();
        }
        if (service == null) {
            service = new NativePayService.Builder().config(config).build();
        }
        log.info("初始化微信配置成功~~~~~~");
        // 初始化服务
        return service;
    }
}

注意:这里的回调接口一定是域名下的接口,且可以访问,后面没参数

相应的微信V3接口文档说明如下

微信V3接口文档

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

springboot整合微信扫码支付(详细) 的相关文章

随机推荐

  • react调用model层的接口(dispatch)在组件中获取接口返回状态

    我们调用model层的接口 然后在组件中获取接口返回的数据 逻辑通常是 在model层写好了逻辑 去获取或者计算接口返回数据 然后组件再引入这个model层中的数据 在组件中dispatch这个接口就行 但是我现在在组件中调用这个接口后 我
  • python import模块方法

    python包含子目录中的模块方法比较简单 关键是能够在sys path里面找到通向模块文件的路径 下面将具体介绍几种常用情况 1 主程序与模块程序在同一目录下 如下面程序结构 src mod1 py test1 py 若在程序test1
  • egg jwt token生成以及验证拦截

    1 安装egg jwt npm install egg jwt save 2 配置 config plugin js jwt jwt插件启用 enable true package egg jwt config config default
  • Linux(基础IO、文件权限、Makefile)

    目录 1 man 手册 1 1 汉化 1 2 具体使用 2 文件权限 2 1 权限理解 2 2 文件详细信息查询 2 3 权限更改 3 常用函数接口 3 1 open 3 2 read 3 3 write 3 4 close 3 5 函数使
  • 二分查找总结——左闭右开区间和左闭右闭区间(C++语言)

    二分查找 1 左闭右开区间 如有相同元素返回查找到的第一个元素 PS 主循环判断条件都是一样的 left lt right 注意这里不能取等号 有相同元素时 如果要返回第一个查找到的元素 则区间包含相同元素时应该从右向左收缩 这时判断条件应
  • opencv两张图片叠加显示

    详细流程 一 线性混合操作 使用addWeighted 1 代码 2 说明 3 图片效果 二 使用roi和mask方式 1 代码 2 说明 3 图片效果 一 线性混合操作 使用addWeighted 1 代码 include
  • 在reportlab中,如果设置字符间距?

    在reportlab中 可以使用ParagraphStyle类来设置字符间距 可以在创建ParagraphStyle对象时 传入参数 wordWrap 来设置字符间距 示例代码如下 from reportlab lib styles imp
  • Java 多种文件读写方式

    前两天用到读写文件的操作 上网搜了一些这方面的资料 很有用的 java中多种方式读文件一 多种方式读文件内容 1 按字节读取文件内容2 按字符读取文件内容3 按行读取文件内容4 随机读取文件内容 import java io Buffere
  • 公司网络慢如何解决,怎样诊断网络卡的原因

    企业局域网由于网络环境复杂 终端数量 设备数量都比较多 经常会出现网络卡顿等故障 一旦网络变慢时 面对复杂的网络环境 网管技术人员需要迅速并且准确的诊断出问题所在 并且加以解决 本文中 我将尽量描述网络变卡变慢的常见原因以及诊断方法 大体来
  • JAVA后端部署项目三步走

    1 JAVA部署项目三步走 1 1 查看 运行的端口 lsof i 8804 8804 为端口 发现端口25111被监听 1 2 杀死进程 终止程序 pid 为进程号 kill 9 pid 1 3 后台运行jar包 nohup java j
  • 网上书城前端界面

    前言 1 用户登录注册界面编写 2 前台主界面编写 3 搜索书籍界面编写 4 购物车界面编写 接下来就上代码了 注册界面
  • pixel手机救砖教程

    Pixel救砖教程 所谓救砖 就是你手机开不了机了 故障了 俗称 砖 如果你舍不得仍了重换 那么就需要救砖 9008深刷我没用过 所以如果你需要用9008深刷 请去别处找教程 直接进入正题 救砖 准备工具 电脑一台 线一条 一部快废了的pi
  • 滤波电容的大小的选取

    印制板中有接触器 继电器 按钮等元件时 操作它们时均会产生较大火花放电 必须采用RC吸收电路来吸收放电电流 一般R取1 2k C取2 2 4 7 F 一般的10PF左右的电容用来滤除高频的干扰信号 0 1UF左右的用来滤除低频的纹波干扰 可
  • 【C++】基类析构函数报错 LNK2001 无法解析的外部符号

    bug 情况说明 在基类没有显式析构函数的时候 不会报错 添加了显式析构函数就会报错 LNK2001 无法解析的外部符号 记录下该 bug 的修改要点 基类 显示析构函数 声明需要用 虚函数 virtual BaseClass 基类 需要添
  • (android地图开发) 高德地图自定义标题栏

    截图效果 布局文件
  • Axios的二次,三次封装

    import axios from axios import showToast from vant 这里是引入的组价库 做提示用 import vant es toast style 组件库样式 import router from ro
  • -bash: nginx: command not found 解决方案

    楼主已经安装了Nginx在Linux下面 然后也把Nginx启动了 此时想重新加载一下Nginx 然后输入命令 居然发生了下面的错误 我的Linux系统是 centos 6 5 的 root zxc sbin nginx s reload
  • vue-axios的总结及项目中的常见封装方法。

    前言 我们知道 vue 2 0版本开始推荐使用 axios 来完成前端 ajax 请求 axios 是一个基于Promise 的 http 库 可以用在浏览器和 node js 中 axios 成为vue全家桶的一个重要部分 对前后端接口请
  • Unity 四元数、欧拉角、轴角 之间的互相转换

    using UnityEngine public class RotateTest MonoBehaviour public Transform a public Transform b public Transform c void St
  • springboot整合微信扫码支付(详细)

    微信扫码支付 以下主要是针对微信支付V3接口进行的整合 且为Native支付 前期准备工作 1 获取微信相关数据 绑定支付的appid 商户id 商户支付秘钥wechatKey 这个需要V3的 证书序列号 私钥文件 pem文件 下面给出了相