微信-Native支付(扫二维码支付)工具类 2023最新保姆教程

news2024/11/25 0:25:07
0、照着微信开发文档 取到证书、秘钥等  好几个key

1、获取商户号merchantId
账户中心->商户信息->微信支付商户号

3、获取商户证书序列号merchantSerialNumber
账户中心->API安全->API证书管理

5、获取appID
产品中心->AppID账号管理

1、这个链接教你获取各种key   

Java接入微信支付APIV3(Native)_java native微信支付-CSDN博客

 2、导入依赖
<!--微信支付依赖-->
        <dependency>
            <groupId>com.github.wechatpay-apiv3</groupId>
            <artifactId>wechatpay-java</artifactId>
            <version>0.2.5</version>
        </dependency>
        <!-- hutool -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.16</version>
        </dependency>
3、工具类直接复制 配置好各种key  就可以直接调用了

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 javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;

/**
 * Native 支付工具类  获取支付地址、解析支付数据
 */
@Slf4j
public class PayUtils {
    //商户号
    public static String merchantId = "16***";
    //商户API私钥路径 服务器里的路径 
    public static String privateKeyPath = "/home/jx****rvice/apiclient_key.pem";
    //商户证书序列号
    public static String merchantSerialNumber = "*******";
    //商户APIV3密钥
    public static String apiV3key = "iK8fl7*3";
    public static String appId = "wx0*****7e";

    // 使用自动更新平台证书的RSA配置
    public static Config config = new RSAAutoCertificateConfig.Builder()
            .merchantId(merchantId) // 商户号
            .privateKeyFromPath(privateKeyPath)  // API证书地址(此处的路径自己调试一下,能找到就行)
            .merchantSerialNumber(merchantSerialNumber) // API证书序列号
            .apiV3Key(apiV3key) // API密匙
            .build();
    // 初始化 解析器 NotificationParser
    public static NotificationParser parser = new NotificationParser((NotificationConfig) config);
    /**
     * 获取支付地址 设置回调路径
     *
     * @param total     【总金额】 订单总金额,单位为分
     * @param desc      商品描述
     * @param notifyUrl 回调地址(必须是http)   如:"http://*7.*2.***.2**:8081/pay/notifyNative"
     * @return
     * @Param orderNo 自己后端的唯一订单号
     */
    public static String nativePayAddr(Integer total, String desc, String notifyUrl, String orderNo, String attach) {
        // 构建service
        NativePayService service = new NativePayService.Builder().config(config).build();
        // request.setXxx(val)设置所需参数,具体参数可见Request定义
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        amount.setTotal(total); // 【总金额】 订单总金额,单位为分。
        request.setAmount(amount);
        request.setAppid(appId); // 应用ID
        request.setMchid(merchantId);  // 商户号
        request.setDescription(desc);  // 商品描述
        request.setNotifyUrl(notifyUrl);  // 支付成功的回调地址
        request.setAttach(attach);
        // 生成模拟系统内部订单号(yyyyMMddHHmmssSSS)
        request.setOutTradeNo(orderNo);  // 自己后端的唯一订单号,此处使用时间模拟
        // 调用下单方法,得到应答
        try {
            // 发送请求
            PrepayResponse response = service.prepay(request);
            // 使用微信扫描 code_url 对应的二维码,即可体验Native支付
            System.out.println(response.getCodeUrl());
            // 将支付地址返回
            return response.getCodeUrl();
        } catch (Exception e) {
            System.out.println("获取支付的url失败:" + e.getMessage());
            return e.getMessage();
        }
    }



    /**
     * 解析器 解密微信给的数据
     *
     * @param request
     * @return
     */
    public Transaction parser(HttpServletRequest request) {
        try {
            // 获取请求体原内容(此时获取的数据是加密的)
            BufferedReader reader = request.getReader();
            StringBuilder requestBody = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                requestBody.append(line);
            }
            // 获取请求携带的数据,构造参数
            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(requestBody.toString()) // 请求体内容(原始内容,不要解析)
                    .build();
            // 解析为Transaction对象(解密数据)
            Transaction transaction = parser.parse(requestParam, Transaction.class);
            //解密完成后的数据
            return transaction;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}
4、具体调用  复制直接用 

swagger-ui 、ipUtil工具类 、@Slf4j  哪里报红删哪里 

实体类、支付记录表 自己设计吧 记得把支付日志表给我一份 




import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jxn.mapper.PayLogMapper;
import com.jxn.pojo.PayLog;
import com.jxn.utils.IpUtils;
import com.jxn.utils.PayUtils;
import com.jxn.utils.Result;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.partnerpayments.nativepay.model.Transaction;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.DynamicParameter;
import io.swagger.annotations.DynamicParameters;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

/**
 * @author szl
 * @date 2023/11/2 0002 10:30
 */
@Slf4j
@Api(tags = "支付")
@RestController
@CrossOrigin
@RequestMapping("/pay")
public class WechatPayController {

    @Autowired
    PayLogMapper payLogMapper;

    /**
     * Native支付下单,获取支付地址
     *
     * @param
     * @return 支付地址,前端用于生成支付二维码
     */
    @ApiOperation(value = "预支付,获取支付地址", response = Result.class)
    @DynamicParameters(name = "data", properties = {
            @DynamicParameter(name = "total", value = "页码", example = "1", required = true),
            @DynamicParameter(name = "userId", value = "条数", example = "10", required = true),
    })
    @PostMapping("/getNativePayAddr")
    public String nativePayAddr(HttpServletRequest request, @RequestBody JSONObject data) {
        //String ipAddr = IpUtils.getIpAddr(request);
        Integer total = data.getInteger("total");
        String userId = data.getString("userId");
        JSONObject attach = new JSONObject();
        attach.put("userId", userId);
        //attach.put("ipAddr", ipAddr);
        String notifyUrl = "http://4*.*2.1*2.2**:8081/pay/notifyNative";
        String orderNo = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN);
        //调用支付工具类,获取支付的url(也就是二维码)
        String payAddr = PayUtils.nativePayAddr(total, "测试xxx商品简述", notifyUrl, orderNo, attach.toString());
        return payAddr;
    }

    @ApiOperation(value = "成功支付的回调", response = Result.class)
    @PostMapping("/notifyNative")
    public void notifyNative(HttpServletRequest request, HttpServletResponse response) throws IOException {
    
        //String ipAddr = IpUtils.getIpAddr(request);
        //log.info("ipaddr:" + ipAddr);
        String a = "{\"transaction_id\":\"1217752501201407033233368018\",\"amount\":{    \"payer_total\":100,    \"total\":100,    \"currency\":\"CNY\",    \"payer_currency\":\"CNY\"},\"mchid\":\"1230000109\",\"trade_state\":\"SUCCESS\",\"bank_type\":\"CMC\",\"promotion_detail\":[    {        \"amount\":100,        \"wechatpay_contribute\":0,        \"coupon_id\":\"109519\",        \"scope\":\"GLOBAL\",        \"merchant_contribute\":0,        \"name\":\"单品惠-6\",        \"other_contribute\":0,        \"currency\":\"CNY\",        \"stock_id\":\"931386\",        \"goods_detail\":[            {                \"goods_remark\":\"商品备注信息\",                \"quantity\":1,                \"discount_amount\":1,                \"goods_id\":\"M1006\",                \"unit_price\":100            },            {                \"goods_remark\":\"商品备注信息\",                \"quantity\":1,                \"discount_amount\":1,                \"goods_id\":\"M1006\",                \"unit_price\":100            }        ]    },    {        \"amount\":100,        \"wechatpay_contribute\":0,        \"coupon_id\":\"109519\",        \"scope\":\"GLOBAL\",        \"merchant_contribute\":0,        \"name\":\"单品惠-6\",        \"other_contribute\":0,        \"currency\":\"CNY\",        \"stock_id\":\"931386\",        \"goods_detail\":[            {                \"goods_remark\":\"商品备注信息\",                \"quantity\":1,                \"discount_amount\":1,                \"goods_id\":\"M1006\",                \"unit_price\":100            },            {                \"goods_remark\":\"商品备注信息\",                \"quantity\":1,                \"discount_amount\":1,                \"goods_id\":\"M1006\",                \"unit_price\":100            }        ]    }],\"success_time\":\"2018-06-08T10:34:56+08:00\",\"payer\":{    \"openid\":\"oUpF8uMuAJO_M2pxb1Q9zNjWeS6o\"},\"out_trade_no\":\"1217752501201407033233368018\",\"AppID\":\"wxd678efh567hg6787\",\"trade_state_desc\":\"支付成功\",\"trade_type\":\"MICROPAY\",\"attach\":\"自定义数据\",\"scene_info\":{    \"device_id\":\"013467007045764\"}\n}";
        Transaction transaction = JSON.parseObject(a, Transaction.class);
        //Transaction transaction = new PayUtils().parser(request);
        log.info("解析后的数据:" + transaction.toString());
        // 获取支付单号
        log.info("支付成功,回调信息:{}", transaction);
        // 打印其中的"微信支付单号"字段,可用于查单操作
        log.info("微信支付单号:{}", transaction.getTransactionId());
        //解密完成后的数据
        PayLog payLog = new PayLog();
        payLog.setPayStatus(transaction.getTradeStateDesc());
        payLog.setCreateTime(transaction.getSuccessTime());
        payLog.setTotal(transaction.getAmount().getTotal());
        payLog.setTransactionId(transaction.getTransactionId());//微信支付系统生成的订单号
        payLog.setOrderNo(transaction.getOutTradeNo());//自己系统的订单号
        payLog.setPayType(transaction.getTradeType().toString());//支付类型
        if ("SUCCESS".equals(transaction.getTradeState().toString())) {
            payLog.setPayStatus("1");//交易状态
        } else {
            payLog.setPayStatus("0");//交易状态
        }
        payLog.setOpenid(transaction.getPayer().getSubOpenid() + transaction.getPayer().getSpOpenid());//支付人信息 包含openid
        String goodsName = transaction.getPromotionDetail().get(0).getName();
        payLog.setReturnData(transaction.toString());
        log.info("插入支付日志:{}", payLog.toString());
        payLogMapper.insert(payLog);
    }
}

这是官方的地址 微信回调给到你的数据  解析后存到自己 的支付记录表   

支付通知 - Native支付 | 微信支付商户文档中心

5、最后

1、拿到支付的url,搜索在线生成二维码,粘贴url 生成二维码

2、扫码支付后,触发回调,解析Transaction,取有用的数据,存到日志表

回调时  Transaction transaction  取得是demo数据,记得注释掉

有问题评论 在线答复。记得 支付日志表设计完 给我一份

饭在锅里,钱在抽屉里,工具类在这里,具体使用在那里,配置类在开发者文档里,我出去办点事

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1170146.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1220*2440mm建筑模板木工板:桥梁工程中的覆膜板选择

在桥梁工程中&#xff0c;选择合适的建筑模板木工板至关重要。其中&#xff0c;1220*2440mm规格的建筑模板木工板作为一种常见的选择&#xff0c;特别适用于混凝土工程和桥梁建设。本文将重点介绍这种规格的木工板作为覆膜板在桥梁工程中的应用。 1220*2440mm建筑模板木工板是一…

RISC Zero zkVM架构

1. 引言 RISC Zero zkVM为&#xff1a; 基于 FRI PLONK 构建的采用Von Neumann架构的ZK Machine将RISC-V微控制器 具化为 某基于STARK的证明系统&#xff0c;的微架构和编码机制。 2. Row (Time) Structure 一个cycle对应1个memory transaction&#xff0c;对用户传入的程…

嵌入式Linux HID多指触控/触摸设备报表描述符

这里只做一下简单记录&#xff0c;更为详细的修改流程后续的文章再介绍。 报表描述符 0x05, 0x0D, // Usage Page (Digitizer) 0x09, 0x04, // Usage (Touch Screen) 0xA1, 0x01, // Collection (Application) 0x85, 0x01, // Report ID (1) 0…

jbase实现业务脚本化

经过晚上和早上的努力&#xff0c;终于补上框架最后一块了&#xff0c;业务脚本侦听变化后自动编译jar包和调用&#xff0c;实现维护成本低&#xff0c;开发效率高的框架的基本体系。 实现自动编译jar包的类 package appcode;import org.w3c.dom.Document; import org.w3c.do…

Android 数据恢复的顶级软件分享

人们经常向我们询问有关 Android 数据恢复软件的信息以及它们是否有用。而且&#xff0c;我们给他们讲了两个朋友的故事——凯伦和亚历克斯。他们都丢失了 Android 手机上的一些重要数据。 丢失数据确实是一个令人心碎的时刻&#xff0c;根据丢失的文件&#xff0c;可能会让您…

Linux高级命令(扩展)三

一、date命令 1、date命令的作用 date命令的主要作用&#xff1a;用于获取计算机操作系统的系统时间 2、获取计算机的系统时间 # date 3、定制时间格式 # date "%F %T %Y %m %d %H %M %S" %F : 2020-04-03 %T : 09:45:36 %Y : 年 %m : 月 %d : 日 %H : 小时 %M…

这个超实用的门禁技巧,让办公楼安全更简单高效!

门禁监控是现代社会中不可或缺的一部分&#xff0c;用于确保安全和管理进出某个区域的人员。随着科技的不断发展&#xff0c;门禁监控已经远离了传统的机械锁和钥匙&#xff0c;变得更加智能化和高效。 客户案例 企业办公大楼 无锡某大型企业在其办公大楼内部部署了泛地缘科技…

【机器学习 | PipeLine】机器学习通用管道最佳实践!!(无论什么问题都能套上,确定不来看看?)

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

任正非说:只有“有为”才会“有位”,任何组织只有在流程中创造价值,才可能获得成长的机会。

你好&#xff01;这是华研荟【任正非说】系列的第28篇文章&#xff0c;让我们聆听任正非先生的真知灼见&#xff0c;学习华为的管理思想和管理理念。 一、所有一切要符合未来的作战需要&#xff0c;组织是为了作战而存在的&#xff0c;而不是作战服从组织的。 来源于任正非先生…

RK-3399pro 萤火虫firefly 官方unbuntu 固件系统安装搜狗中文输入法

RK-3399pro 萤火虫firefly 官方unbuntu 固件系统安装搜狗输入法&#xff08;适用于所有基于Ubuntu的UI桌面系统&#xff09; 一、添加中文语言支持输入法平台fcitx 1.安装fcitx sudo apt-get install fcitx 2.然后设置fcitx为开机自启动 sudo cp /usr/share/applications/fc…

Python进阶之推导式与生成器

文章目录 一、推导式1.列表推导式2.字典推导式3.集合推导式4.元组推导式&#xff08;生成器推导式&#xff09; 二、生成器1.生成器表达式2.生成器函数3.send函数 结束语 &#x1f482; 个人主页:风间琉璃&#x1f91f; 版权: 本文由【风间琉璃】原创、在CSDN首发、需要转载请联…

【数智化人物展】华院计算董事长、创始人宣晓华:通用大模型只是起点,尚需结合专业知识方能解决行业核心问题...

宣晓华 本文由华院计算董事长、创始人宣晓华投递并参与《2023中国企业数智化转型升级先锋人物》榜单/奖项评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 大模型的出现&#xff0c;正在开启着国内新一轮AI热潮。 某种程度上&#xff0c;真正在当下决定企业成败的&#…

22款奔驰S400L升级原厂 360全景影像 高清环绕的视野

您是否经历过这种场面呢&#xff1f; 停车位&#xff0c;狭窄障碍停车困难 避免盲区&#xff0c;倒车盲区危及生命安全 狭窄路段&#xff0c;无法判断是否安全通过 视角盲区&#xff0c;小孩站在视野盲区看不到 360度无缝3D全车可见&#xff0c;解决各个视角盲区&#xff…

开发一款直播弹幕游戏需要多少钱?

开发一款直播弹幕游戏需要多少钱&#xff1f;有好多朋友在咨询过弹幕游戏的开发价格后&#xff0c;都会比较吃惊&#xff0c;一款体量这么小的游戏为什么动辄就要几万块甚至十几万&#xff1f; 我来给你们说分析一下原因&#xff0c;这种游戏如果脱离开直播间&#xff0c;可以…

算法通关村第五关-黄金挑战LRU问题

大家好我是苏麟 , 今天聊聊LRU问题 , 相信学过操作系统的小伙伴并不陌生 . LRU问题 LRU的含义 LRU是Least Recently Used的缩写&#xff0c;即最近最少使用&#xff0c;是一种常用的页面置换算法&#xff0c;选择最近最久未使用的页面予以淘汰。 图解 : 如果再有其他元素就依…

ST表与RMQ(倍增表)

【概述】 RMQ : Range Maximum/minimum Query 这就是指区间最大或最小值&#xff08;区间最值&#xff09; ST表&#xff1a;Spars Table&#xff0c;一种可以解决 RMQ 的&#xff0c;基于倍增的数据结构&#xff0c;利用 ST 算法预处理打出的表&#xff0c;称为 ST 表。 …

EMC Unity存储系统如何查看SSD的使用寿命

为什么要写这个博客&#xff1f; 客户对老的EMC unity的存储系统要扩容&#xff0c;如何确定SSD磁盘是全新的还是拆机二手的&#xff1f;很多时候客户还有一个奇葩的要求&#xff0c;就是要和5年前的磁盘PN一致&#xff0c;甚至要求固件版本一致&#xff0c;最关键的还要求是全…

【LeetCode】每日一题 2023_11_4 数组中两个数的最大异或值

文章目录 刷题前唠嗑题目&#xff1a;数组中两个数的最大异或值题目描述代码与解题思路 结语 刷题前唠嗑 LeetCode? 启动&#xff01;&#xff01;&#xff01; 题目&#xff1a;数组中两个数的最大异或值 题目链接&#xff1a;421. 数组中两个数的最大异或值 题目描述 代…

分享去视频/图片水印的工具(完结篇)

简介 视频去水印是在数字时代日益重要和频繁的需求之一。水印是一种保护版权和确认身份的常见手段&#xff0c;但在某些情况下&#xff0c;水印可能会对视频内容产生负面影响&#xff0c;因此需要去除。 首先&#xff0c;视频去水印可以改善视频观看体验。有些视频平台或个人会…

非常有用的工具箱IT-Tools

什么是 IT-Tools &#xff1f; IT-Tools 汇集了 70 多种对开发人员和 IT 工作人员有用的工具。这个令人惊叹的工具的酷炫之处在于它不需要设置&#xff0c;不需要持久卷&#xff0c;您可以立即开始使用它。它包含大量工具&#xff0c;可生成密码、编辑 CSS 和 HTML 代码、文件格…