微信支付Native下单API接口正确调用姿势

news2024/11/17 11:01:10

        商户Native支付下单接口,微信后台系统返回链接参数code_url,商户后台系统将code_url值生成二维码图片,用户使用微信客户端扫码后发起支付。

文档地址:微信支付-开发者文档

目录

一、Native下单接口简介

二、如何正确调通接口

(1) 测试调用接口

(2)签名生成规则

三、下单支付JAVA核心代码

(1)获取接口签名方法

(2)获取私钥对象方法

(3)接口签名加密方法

(4)构建加密信息字符串

(5)构建下单支付请求报文

(6)调用下单支付接口

四、需要用到的部分依赖包


一、Native下单接口简介

请求URL:https://api.mch.weixin.qq.com/v3/pay/transactions/native

请求方式:POST

请求参数:


{
	"mchid": "1900006XXX",
	"out_trade_no": "native12177525012014070332333",
	"appid": "wxdace645e0bc2cXXX",
	"description": "Image形象店-深圳腾大-QQ公仔",
	"notify_url": "https://weixin.qq.com/",
	"amount": {
		"total": 1,
		"currency": "CNY"
	}
}

参数说明:

mchid 商户号  :在微信商户平台(微信支付 - 中国领先的第三方支付平台 | 微信支付提供安全快捷的支付方式)中获取

 out_trade_no 商户订单号:自己生成的业务订单编号(只能是数字、大小写字母,且在同一个商户号下唯一)

description:商品描述信息

notify_url:回调通知地址(通知URL必须为直接可访问的URL,不允许携带其他参数,要求必须为https地址,本地可以借助于内网穿透工具来完成测试。)

amount :订单金额信息,注意total单位是分,不是元,这个跟支付宝接口有点不同,支付宝接口的单位是元,微信支付接口的单位是分 ,currency在国内使用的话,直接默认值CNY就行。

appid:使用公众号APPID(微信公众号需要先进行实名认证缴费300元)

然后让公众号和商户进行关联

业务流程时序图

二、如何正确调通接口

(1) 测试调用接口

首先拿到接口地址和请求参数去postman中测试一下

 接口返回返回提示告诉我们:Http头Authorization值格式错误,请参考《微信支付商户REST API签名规则》,也就是说这个接口需要进行签名验证。

(2)签名生成规则

签名生成规则文档地址:签名生成-接口规则 | 微信支付商户平台文档中心

在进行签名过程中,会用到这几个参数

① 商户API证书

 证书获取流程:什么是商户API证书?如何获取商户API证书?

② 商户证书序列号

API证书添加成功之后,点击管理就能看到商户证书序列号。

三、下单支付JAVA核心代码

(1)获取接口签名方法

getToken方法的作用是获取接口签名,具体参数解释

method:GET/POST

url:接口url地址

body:获取请求中的请求报文主体,

请求方法为GET时,报文主体为空。

当请求方法为POST或PUT时,请使用真实发送的JSON报文

signatureType :签名类型字符串常量:WECHATPAY2-SHA256-RSA2048

nonceStr :随机字符串,可以固定值。

    public static String getToken(String method, HttpUrl url, String body) throws IOException, NoSuchAlgorithmException, SignatureException, InvalidKeyException {
        String nonceStr = "593BEC0C930BF1AFEB40B4A08C8FB242";
        long timestamp = System.currentTimeMillis() / 1000;
        String message = buildMessage(method, url, timestamp, nonceStr, body);
        String signature = sign(message.getBytes("utf-8"));

        return signatureType + " mchid=\"" + mchid + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + merchantSerialNumber + "\","
                + "signature=\"" + signature + "\"";
    }

(2)获取私钥对象方法

参数说明:private_key的值来源于证书文件apiclient_key.pem文件类的所有内容。

 /**
     * 获取私钥。
     *
     * @return 私钥对象
     */
    public static PrivateKey getPrivateKey() throws IOException {
        try {
            String privateKey = private_key.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");

            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }

(3)接口签名加密方法

  public static String sign(byte[] message) throws NoSuchAlgorithmException, IOException, InvalidKeyException, SignatureException {
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(getPrivateKey());
        sign.update(message);
        return Base64.getEncoder().encodeToString(sign.sign());
    }

(4)构建加密信息字符串

   public static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
        String canonicalUrl = url.encodedPath();
        if (url.encodedQuery() != null) {
            canonicalUrl += "?" + url.encodedQuery();
        }
        return method + "\n"
                + canonicalUrl + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }

(5)构建下单支付请求报文

   /**
     * 构建下单支付请求JSON字符串
     *
     * @return
     */
    public static String buildNativePayJson(Double total_amount, String out_trade_no) {

        JSONObject jsonObject = new JSONObject();
        // 应用ID
        jsonObject.put("appid", appid);
        // 商户号
        jsonObject.put("mchid", mchid);
        // 商户订单号
        jsonObject.put("out_trade_no", out_trade_no);
        // 商品描述
        jsonObject.put("description", "易微帮在线充值" + total_amount + "元");
        // 回调通知URL
        jsonObject.put("notify_url", notify_url);
        JSONObject amount = new JSONObject();
        // 单位:分
        amount.put("total", Convert.toInt(total_amount * 100));
        //货币类型
        amount.put("currency", "CNY");
        jsonObject.put("amount", amount);
        return jsonObject.toJSONString();
    }

(6)调用下单支付接口

        //商户订单号
        String out_trade_no = PayUtil.getOrderNum();
        String body = WxPayUtil.buildNativePayJson(amount, out_trade_no);
        String url = "https://api.mch.weixin.qq.com/v3/pay/transactions/native";
        HttpUrl httpurl = HttpUrl.parse(url);
        String sign = WxPayUtil.getToken("POST", httpurl, body);

        String response = HttpUtil.createPost(url)
                .header("Authorization", sign)
                .body(body)
                .execute().body();

下单支付接口调用成功之后,response字符串的格式如下。

{
	"code_url": "weixin://wxpay/bizpayurl?pr=p4lpSuKzz"
}

后续使用,将code_url的值生成二维码,展现给用户扫码即可。 

可以来我的个人网站参考一下应用场景。

页面地址:易微帮-专业IT技术协助平台

四、需要用到的部分依赖包


        <!--微信支付v3接口-->
        <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.12</version>
        </dependency>

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

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

相关文章

5. AOP

一、如何定义一个MethodHandler? 1.Controller注解修饰的类 1.注册成Spring Bean 2.表示它是一个SpringMVC下的Controller 2.在这个类下的方法中&#xff0c;只要被RequestMapping修饰&&方法的形参符合规定&#xff08;需要看文档&#xff09; 方法的返回值符合规定…

VK0256/B/C玩具、冷气机等段码液晶驱动芯片(IC)(32EGx8COM)技术资料选表

K PP 2543型号&#xff1a;VK0256/B/C封装形式&#xff1a;QFP64/LQFP64/LQFP52 VK0256/B/C是一个点阵式存储映射的LCD驱动器&#xff0c;可支持最大256点&#xff08;32EGx8COM&#xff09;的LCD屏。单片机可通过3/4线串行接口配置显示参数和发送显示数据&#xff0c;也可通过…

与ChatGpt聊天,学习golang标签的反射机制

与ChatGpt聊天&#xff0c;学习golang标签的反射机制引ChatGPT火了以后&#xff0c;本拐先是恐惧&#xff0c;之后是拥抱。最近很多编程知识的学习&#xff0c;都是通过 chatgpt来搞定。众所周知&#xff0c;本拐就是一个啥技术都半斤八两的程序员&#xff0c;这次&#xff0c;…

05服务发现:引入etcd服务注册中心

在分布式微服务架构中,服务注册发现组件(通常称为服务注册中心)往往有着举足轻重的作用,它的性能与稳定可能会直接影响到整个服务的状态,比如Spring Cloud中的Eureka、Dubbo中的Zookeeper等等,接下来我们就gRPC微服务中最常见的服务注册中心etcd,来讲述下两者在具体是怎…

Mr. Cappuccino的第41杯咖啡——Kubernetes之Pod调度策略

Kubernetes之Pod调度策略Pod的4种调度策略定向调度nodeNamenodeSelector亲和性调度node亲和性硬限制软限制关系运算符pod亲和性pod反亲和性污点和容忍污点&#xff08;taints&#xff09;容忍&#xff08;tolerations&#xff09;默认情况下&#xff0c;Scheduler计算出一个Pod…

conda 搭建tensorflow-GPU和pycharm以及VS2022 软件环境配置

conda 搭建tensorflow-GPU和pycharm以及VS2022 软件环境配置一、TensorFlow 环境配置安装1. Anaconda下载安装2.conda创建tensorflow环境二、pycharm以及VS2022 环境配置2.1 pycharm 软件安装以及环境配置2.2.1 pycharm 软件安装2.2.2 pycharm 软件conda环境配置2.2 Visual Stu…

注意!华为折叠屏手机的原厂膜不能自己撕!

对于用惯了直板手机的朋友来说&#xff0c;新机开箱撕膜是一件十分有“仪式感”的事情&#xff0c;但是对于折叠屏手机来说&#xff0c;这样的操作万万不可。华为折叠屏手机在使用的过程中也有着和传统智能手机不一样的注意事项&#xff0c;下面这几点大家在入手折叠屏手机之后…

如何利用Power Virtual Agents机器人进行设备维修登记

今天我们来介绍如何利用PVA聊天机器人进行设备维修登记。设计思路是在PVA聊天机器人的对话框中输入“设备维修”触发短语后进行设备维修登记&#xff0c;然后通过自动化流程将维修信息存入到Lists中并通过邮件的形式发送给负责设备维修的人员。 首先&#xff0c;在PVA聊天机器人…

【yolov5】将标注好的数据集进行划分(附完整可运行python代码)

问题描述 准备使用yolov5训练自己的模型&#xff0c;自己将下载的开源数据集按照自己的要求重新标注了一下&#xff0c;然后现在对其进行划分。 问题分析 划分数据集主要的步骤就是&#xff0c;首先要将数据集打乱顺序&#xff0c;然后按照一定的比例将其分为训练集&#xf…

【Blender】使用Blender渲染一段360度旋转的动画

目录一、前言二、方法描述三、渲染设置四、结果一、前言 本文主要讲述了如何使用Blender渲染一段物体360度旋转的动画。 渲染好的效果如下&#xff1a; 二、方法描述 第一步&#xff1a;shiftA&#xff0c;我们在Blender里新建一个平面 第二步&#xff1a;摁s键(scale)&…

(三十五)Vue之过渡与动画

文章目录概述单元素/组件的过渡CSS动画CSS过渡多元素/组件的过渡集成第三方动画Animate上一篇&#xff1a;&#xff08;三十四&#xff09;Vue之新生命周期钩子nextTick 概述 Vue 在插入、更新或者移除 DOM 时&#xff0c;提供多种不同方式的应用过渡效果。包括以下工具&…

PyTorch常用的损失函数(ChatGPT)

L1Loss nn.L1Loss 也称为平均绝对误差&#xff08;Mean Absolute Error&#xff0c;MAE&#xff09;。它计算预测值与真实值之间的差异&#xff08;即误差&#xff09;&#xff0c;然后取绝对值并求和&#xff0c;最后除以样本数量得到平均误差。具体来说&#xff0c;对于一批…

萌新应该如何开始学习走向自动化测试高薪岗位?

对于测试人员来说&#xff0c;不管进行功能测试还是自动化测试&#xff0c;还是性能测试&#xff0c;都是需要编写测试用例&#xff0c;所以我们必须先要了解清楚手工测试用例与自动化测试用例的一些特点&#xff0c;才能更好的开展自动化测试工作。1.1手工测试用例和自动化测试…

最新中文版Studio One6音乐制作DAW工具

你现在用的是什麽 DAW&#xff1f;大家常常在说的 DAW &#xff0c;就是指数位音乐工作站软件&#xff0c;像是常见的 Ableton、Logic、Protools、Cubase 等等&#xff0c;这些都算是 DAW。以上的例子&#xff0c;他们的完整版几乎都是需要花费购买的&#xff0c;当然也有一些免…

【Go基础】Socket和WebSocket编程

文章目录一、Socket编程1. 网络通信过程2. TCP CS架构2.1 网络通信模型2.2 TCP协议解读2.3 Go TCP编程3. UDP CS架构3.1 UDP协议解读3.2 Go UDP编程二、WebSocket编程1. WebSocket协议解读2. WebSocket CS架构实现3. 聊于室实现一、Socket编程 1. 网络通信过程 DMA&#xff1a…

Elasticsearch - Configuring security in Elasticsearch 开启用户名和密码访问

文章目录概述实操Step 1 验证当前版本是否支持安全功能Step 2 打开安全设置Step 3 配置节点间通讯传输的安全性创建证书颁发机构为Elasticsearch集群中的节点生成证书Step 4 修改 elasticsearch.yml配置设置 用户名和密码概述 ES版本&#xff1a; 7.6 官方指导手册&#xff1…

Spring MVC之WebApplicationContext 容器的初始化

简介因为 spring-mvc项目&#xff0c;是 spring-framework的子项目&#xff0c;所以需要拉取 spring-framework整个工程&#xff0c;包含 Spring 所有的子项目前期准备工作源码拉取从 Spring 的 Git 仓库 Fork 项目到自己的 Git 仓库&#xff0c;方便我们在阅读源码的过程中&am…

3年软件测试工作经验裸辞,有点后悔了...

2019年毕业&#xff0c;现在有3年的软件测试工作经验&#xff0c;刚毕业前半年在一家知名上市公司&#xff0c;后面则进入一家传统行业公司待到现在2年半。 由于看不到技术成长以及其他原因&#xff0c;上上周辞职了&#xff0c;目前交接中&#xff0c;下个月中旬就得离开了&a…

基于国产龙芯 CPU 的气井工业网关研究与设计(一)

当前&#xff0c;我国气田的自动化控制程度还未完全普及&#xff0c;并且与世界已普及的气井站的自 动化程度也存在一定的差距。而在天然气资源相对丰富的国家&#xff0c;开采过程中设备研发资 金投入较大&#xff0c;研发周期较长&#xff0c;更新了一代又一代的自动化开采系…

看过来,u盘删除的文件还能找回吗?两种方法,

u盘删除的文件还能找回吗&#xff1f;u盘&#xff0c;全称USB闪存驱动器&#xff0c;它不需物理驱动器&#xff0c;即插即用&#xff0c;且其存储容量远超过软盘&#xff0c;方便携带使用。u盘作为我们常用的存储设备&#xff0c;也是有自己不同功能和划分。以下例举了几种&…