微信支付的服务商模式V3支付(可直接使用)

article/2025/7/13 22:04:58

 直连商户模式和服务商模式区别:

        直连商户:例如张三开了一个小程序,然后别人在这个小程序买东西,结账的时候,钱是直接打到张三的账号上的。

        服务商模式:例如张三开了一个小程序,然后这个小程序中有一个开分店的功能,然后别人在分店购买东西,在结账的时候,钱是直接打到分店的负责人的账号上的。
        本文章说的是服务商模式(直连模式看这篇文章:微信直连商户V3支付(可直接使用)_流连勿忘返的博客-CSDN博客

微信支付逻辑(重点):

44ce6b79061943038deae8091cf7e087.png


        前端点击支付按钮,在调起微信自带支付页面之前,要往后端发一个请求,后端先是负责调用微信的 "统一下单" 接口,在调用这个接口的时候,会把本地订单号也一起发过去,然后会得到一个 prepay_id ,然后再针对 prepay_id 和一些参数做一个算法,得到相对应的签名值,然后返回给前端,然后前端就可以根据这些返回值调用支付,就可以支付了

        如果支付成功,那就ok了,因为有把本地的订单号一起传过去给微信那边,所以就相当于这个本地的订单号跟微信那边的订单绑定了,所以只要支付了腾讯那边的订单,那就相当于完成了本地订单。



1.申请证书,设置V3秘钥(这一步是服务商账号操作的)

 

 2.设置APPid账号管理(这一步是服务商操作的)

服务商账号关联要支付的小程序

 3.新增子商户(这个子商户实际上就是分店的主负责人)

可以手动添加,也可以使用接口来添加

4.配置子商户

 点击这个,然后跳转到这里:

继续点击:配置 

 把要支付的小程序或者公众号id配置进去

5.maven地址

        <dependency><groupId>com.github.wechatpay-apiv3</groupId><artifactId>wechatpay-apache-httpclient</artifactId><version>0.4.7</version></dependency>

6.公共参数接口

package com.example.demo.zhifu;/*** @Description:* @Author sk* @Date: 2023/7/5 14:31*//*** 服务商模式*/
public interface ServiceProvider {String NOTIFY_URL = ""; //回调地址String sp_mchid = ""; //服务商的商户号String sub_mchid = "xxx"; // 子商户号,在这里写固定的,用于测试String MCH_SERIAL_NO = ""; // 服务商的商户证书序列号String API_3KEY = "";   // 服务商的V3的密钥String sp_appid = "";     // ApIdString privateKey = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDAgPXTRI0OFMEk" +"yf4+OSHs0K7wpDKfChB4xchJHJ39WwSS+A/fsyIEzC547D0NbUeiRby4ybAIfroa" +"zQCXRjRr0x6typGVY2ul9khWhSeC/CZHd0JrfcOCDHa3uJR01MElrGBIwgGSINrk" +"luW+jYveIVtc+uI1DSZrUOFxj8dg7//dvlhWluClwUbQiv9OG131Bi1j/fivUhI2" +"hiPy8zWADiCqTv5xzH3RBIbRJgNO/eIxUvfzGgyPECQ9C6XN4uxKxVWHOcg/vAD7" +"vQJHFO5sZ4/Z5pisHlUNr3aclTWVQg9n+ReOb8ztlmoqU4bvkh+3QveqsScDCqWl" +"A0CZ0Nr/AgMBAAECggEBALoMKQltaFIiluSiYBjtCK+ipGCooM/6Xx8KL98RTFQv" +"YkVUf6r4qrkuSP/PedX/NstLUPDa5EnhiKYcWSTa0hEfsrfOXlOeCc0VMKaF/EDo" +"x2oshcHzgz+uIhK/zqL3eFCbv1ayQehj3oosmJBIptQhMvay9mrFccsoGSqzBcPV" +"nwg04jlqZK";}

其中的 商户证书序列号对应的证书秘钥 在下载好的证书的这个地方:


bb485ad4bd2e4018a7e4eab0dddb767e.png

 

其中红色框起来的就是商户证书序列号对应的证书秘钥:


28fc165bfdcb4540895fa84db76897d2.png

7.下单工具类

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;/*** 服务商的下单工具类* @author liaozan8888@163.com*/
public class PayMerchantUtil {private CloseableHttpClient httpClient;private CertificatesManager certificatesManager;private Verifier verifier;/*** App下单  具体下单场景查看官方文档** @param total* @param description* @return* @throws Exception*/public String requestwxChatPay(String orderSn, int total, String description,String openid) throws Exception {PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(ServiceProvider.privateKey.getBytes("utf-8")));// 获取证书管理器实例certificatesManager = CertificatesManager.getInstance();// 向证书管理器增加需要自动更新平台证书的商户信息certificatesManager.putMerchant(ServiceProvider.sp_mchid, new WechatPay2Credentials(ServiceProvider.sp_mchid,new PrivateKeySigner(ServiceProvider.MCH_SERIAL_NO, merchantPrivateKey)),ServiceProvider.API_3KEY.getBytes(StandardCharsets.UTF_8));// 从证书管理器中获取verifierverifier = certificatesManager.getVerifier(ServiceProvider.sp_mchid);httpClient = WechatPayHttpClientBuilder.create().withMerchant(ServiceProvider.sp_mchid, ServiceProvider.MCH_SERIAL_NO, merchantPrivateKey).withValidator(new WechatPay2Validator(certificatesManager.getVerifier(ServiceProvider.sp_mchid))).build();HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi");httpPost.addHeader("Accept", "application/json");httpPost.addHeader("Content-type", "application/json; charset=utf-8");ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectMapper objectMapper = new ObjectMapper();//组合请求参数JSON格式ObjectNode rootNode = objectMapper.createObjectNode();rootNode.put("sp_appid", ServiceProvider.sp_appid).put("sp_mchid", ServiceProvider.sp_mchid).put("sub_mchid", ServiceProvider.sub_mchid)// 回调地址.put("notify_url", ServiceProvider.NOTIFY_URL + "returnNotify").put("description", description).put("out_trade_no", orderSn);rootNode.putObject("amount")// total:金额,以分为单位,假如是10块钱,那就要写 1000.put("total", total).put("currency", "CNY");rootNode.putObject("payer").put("sp_openid", openid);// openidtry {objectMapper.writeValue(bos, rootNode);httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));//获取预支付IDCloseableHttpResponse response = httpClient.execute(httpPost);String bodyAsString = EntityUtils.toString(response.getEntity());//微信成功响应int statusCode = response.getStatusLine().getStatusCode();if (statusCode == 200) {//时间戳String timestamp = System.currentTimeMillis() / 1000 + "";//随机字符串String nonce = RandomUtil.randomString(32);StringBuilder builder = new StringBuilder();// Appidbuilder.append(ServiceProvider.sp_appid).append("\n");// 时间戳builder.append(timestamp).append("\n");// 随机字符串builder.append(nonce).append("\n");JsonNode jsonNode = objectMapper.readTree(bodyAsString);// 预支付会话IDbuilder.append("prepay_id=").append(jsonNode.get("prepay_id").textValue()).append("\n");//获取签名String sign = this.sign(builder.toString().getBytes("utf-8"), merchantPrivateKey);JSONObject jsonMap = new JSONObject();jsonMap.put("noncestr", nonce);jsonMap.put("timestamp", timestamp);jsonMap.put("prepayid", jsonNode.get("prepay_id").textValue());jsonMap.put("sign", sign);jsonMap.put("appid", ServiceProvider.sp_appid);jsonMap.put("partnerid", ServiceProvider.sp_mchid);return jsonMap.toJSONString();//响应签名数据,前端拿着响应数据调起微信SDK}} catch (Exception e) {e.printStackTrace();}return null;}/*** 计算签名** @param message* @param yourPrivateKey* @return*/private String sign(byte[] message, PrivateKey yourPrivateKey) {try {Signature sign = Signature.getInstance("SHA256withRSA");sign.initSign(yourPrivateKey);sign.update(message);return Base64.getEncoder().encodeToString(sign.sign());} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {e.printStackTrace();}return "";}

8.回调签名工具类

package com.example.demo.zhifu;/*** @Description:* @Author sk* @Date: 2023/7/5 14:31*/import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;/*** 回调签名配置* @author liaozan8888@163.com*/
public class AesUtil {static final int KEY_LENGTH_BYTE = 32;static final int TAG_LENGTH_BIT = 128;private final byte[] aesKey;public AesUtil(byte[] key) {if (key.length != KEY_LENGTH_BYTE) {throw new IllegalArgumentException("无效的ApiV3Key,长度必须为32个字节");}this.aesKey = key;}public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext) throws GeneralSecurityException, IOException {try {Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");SecretKeySpec key = new SecretKeySpec(aesKey, "AES");GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);cipher.init(Cipher.DECRYPT_MODE, key, spec);cipher.updateAAD(associatedData);return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8");} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {throw new IllegalStateException(e);} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {throw new IllegalArgumentException(e);}}
}

9.下单的controller

package com.example.demo.zhifu;import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.springframework.web.bind.annotation.*;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;/*** @Description:* @Author sk* @Date: 2023/7/5 19:10*/
@RestController@RequestMapping(value = "/pay")
public class payController {/*** 预支付下单* @param orderSn 订单号* @param total 分* @param description 描述* @return*/@GetMapping(value = "/getPay")public String getPay(String orderSn,int total , String description){PayMerchantUtil payMerchantUtil = new PayMerchantUtil();try {return payMerchantUtil.requestwxChatPay(orderSn, total, description, "oYgFI91D00GpCwccdnKDR4KNxI4k");} catch (Exception e) {throw new RuntimeException(e);}}// 支付回调@PostMapping(value = "/returnNotify")public Map returnNotify(@RequestBody JSONObject jsonObject){// v3 私钥String key = "xxxxx";String json = jsonObject.toString();String associated_data = (String) JSONUtil.getByPath(JSONUtil.parse(json), "resource.associated_data");String ciphertext = (String) JSONUtil.getByPath(JSONUtil.parse(json), "resource.ciphertext");String nonce = (String) JSONUtil.getByPath(JSONUtil.parse(json), "resource.nonce");try {String decryptData = new AesUtil(key.getBytes(StandardCharsets.UTF_8)).decryptToString(associated_data.getBytes(StandardCharsets.UTF_8), nonce.getBytes(StandardCharsets.UTF_8), ciphertext);System.out.println("decryptData = " + decryptData);//TODO 业务校验} catch (Exception e) {e.printStackTrace();}HashMap<String, String> stringStringHashMap = new HashMap<>();stringStringHashMap.put("code","200");stringStringHashMap.put("message","返回成功");// 返回这个说明应答成功return stringStringHashMap;}}

10.官方文档:

产品能力概览 | 微信支付服务商平台文档中心


http://chatgpt.dhexx.cn/article/nx0depGp.shtml

相关文章

如何发布到NPM上(转)

简要:这篇文章介绍了如何讲自己的包发布到NPM上&#xff0c;马克一下&#xff0c;将来有用 。。。 npm包发布 发布npm包&#xff0c;更方便以后下载使用。 我们已经把插件代码上传到github上面了&#xff0c;那么我们是否可以也做成一个npm包发布到npm上呢&#xff1f;答案是肯…

微信支付APIv3

文章目录 微信支付之前我的密钥啥的都是放到配置文件里面以后可以再写一个文件基础支付APIv3介绍获取验签和HttpClientAPIv3证书与密钥使用说明 微信支付的SDK工具Native支付流程我们程序运行时的日志也可以使用log.debug在方法堆栈里面查看我们程序执行的方法调用顺序内网穿透…

你了解过区块链的最新模式都有哪些呢?

热门项目 ①USDT跑分系统: 项目热度:***** 项目亮点: 1.使用全球主流稳定的结果货币USDT。 2.通道永不被封,资金永不被冻。 3.个人与个人之间的C2C点对点分散式交易。 4.高效,5分钟内迅速到账。 项目玩法: 500个usdt以上即可开启接单(相当于押金),静态跑一轮可得…

vpay平台模式开发 15天交付系统

近期迅速走进大家视野的Vpay是什么究竟是什么&#xff0c;有人说vpay是一个APP&#xff0c;有人说&#xff0c;是一个支付手段&#xff0c;接近一点的会说是一个模式&#xff0c;那究竟是什么模式?拆分?还是虚拟币?其实严谨来讲Vpay是 重新构建了连接方式&#xff0c;连接方…

vpay软件系统开发

“创新性强、前瞻性高&#xff0c;需要先行先试&#xff0c;但切忌‘一刀切’&#xff08;陈琦&#xff1a;138-2848-7919可微&#xff09;当天&#xff0c;互联网医疗企业丁香园创始人、董事长李天天在接受央视《新闻11》采访时表达了这样的观点&#xff0c;近两年的互联网圈子…

vpay模式软件开发 vpay系统

vpan它一方面通过数学和算法实现了全网的共识与信任(协议属性)&#xff0c;另一方面通过代币保证了生态体系的价值激励(货币属性)。 区块链适合应用的领域是已经现存大量结构化数据&#xff0c;或者是容易形成结构化数据的领域。这点比较类似ai&#xff0c;只有数据线上化结构化…

V免签-PC监控端 Vpay监控 PC 4.3

V免签-PC监控端 介绍 V免签pc监控端更新界面 支持微信、支付宝双端监听 使用说明 下载软件配置域名、密钥 版本更新 持续更新中~~~ 下载地址&#xff1a;https://wwsl.lanzoul.com/iSSo30vzqm1g https://www.159e.cn/75.html Vpay监控 4.3 更新日志&#xff1a; 1.修复…

Vpay是什么?Vpay怎么玩?用Vpay有什么好处?Vpay系统开发

&#xff08;1&#xff09;Vpay是什么&#xff1f; Vpay是一个全面开放的完全去中心化的网络支付平台&#xff0c;跟支付宝和微信一样&#xff0c;不同的是&#xff0c;Vpay是基于区块链技术开发的&#xff0c;用户之间能顺利实现点对点交易&#xff0c;支付&#xff0c;跨境转…

web前端第二周学习

第二周学习 二十一、嵌套列表二十二、表格标签二十三、表格属性二十四、表单标签二十五、表单相关标签二十六、表格表单组合使用二十七、div与span二十八、CSS语法格式二十九、内联样式与内部样式三十、外部样式及两种写法三十一、CSS颜色表示法三十二、背景样式三十三、背景实…

小程序与云开发实战 36 讲

课程介绍 小程序依托微信超过 10 亿的海量用户&#xff0c;它无需安装即可使用的完美用户体验&#xff0c;已经成为商家竞相争夺的大蛋糕&#xff0c;同时&#xff0c;小程序开发快速、容易部署广受程序员的喜爱&#xff0c;作为程序员的我们&#xff0c;还有什么理由不学习小…

WEB3.0白皮书

I // Part1 新浪潮 // 那么 Web3.0 究竟是什么? TA 能给当今世界带来什么变化? TA 由哪 些技术组成? 如何实现 Web3.0? TA 能带来哪些机会? 我们能从中得到什么? Web3.0 是一个非常前沿的话题&#xff0c;充满了不确定性&#xff0c;也没有任何人能准确预测…

如何在 2021 年使用 WordPress 制作游戏网站

您想学习如何使用 WordPress 制作游戏网站吗&#xff1f; 游戏从未如此流行。拥有自己的游戏网站&#xff0c;您可以创建一个游戏社区&#xff0c;创建一个受欢迎的游戏博客&#xff0c;甚至赚取副业收入。 在本文中&#xff0c;我们将向您展示如何在没有任何技术技能的情况下…

第一批 00 后 Web3 创业者,和他们的「人间清醒」

当不少 80 后、90 后还在困惑&#xff0c;生怕赶不上这趟所谓的 Web3「革命快车」的时候&#xff0c;有一些 00 后早已「玩得飞起」。一位 00 后朋友说&#xff0c;「你们眼中的革命&#xff0c;是我生活的日常。」 然而&#xff0c;这个新赛道有的不止是「狂热」&#xff0c;…

小甲鱼零基础入门学习python笔记

小甲鱼老师零基础入门学习Python全套资料百度云(包括小甲鱼零基础入门学习Python全套视频全套源码全套PPT课件全套课后题及Python常用工具包链接、电子书籍等&#xff09;请往我的资源&#xff08;https://download.csdn.net/download/qq_32809093/13099592&#xff09;查看 目…

web前端学习1-45集

web前端1-45集 第一集 课程划分1.HTMLCSS系列教程1之拨云见日2.HTMLCSS系列教程2之溯本求源3.HTMLCSS系列教程3之风声水起4.HTMLCSS系列教程4之巧夺天工如何学好web前端 第二集 拨云见日1. 什么是HTML、CSS&#xff1a;2. 代码跟网站的关系&#xff1a;3.写到哪里&#xff1a;4…

应用服务器语言,web服务器 语言

C语言进行CGI程序设计 也就是CGI程序接受Web浏览器发送给Web服务器的信息,进行处理,将响应结果再回送给Web服务器及Web浏览器。CGI程序一般完成Web网页中表单(Form)数据的处理、数据库查询和实现与传统应用系统的集成等工作。CGI程序可以用... 文章 技术让梦想更伟大-李肖遥 20…

web前端从入门到精通

web前端从入门到精通 HTMLCSS系列一、拨云见日如何创建.html文件--网页1.安装插件2.编辑器基本使用3.Chrome浏览器 &#xff08;市场份额最大&#xff09;4.深入了解网站开发5.web三大核心技术6.HTML基础结构与属性7.HTML初始代码8.HTML注释9.HTML语义化10.标题(h)与段落(p )11…

html5游戏视频UI框架,推荐几个精致的web UI框架

Aliceui是支付宝的样式解决方案&#xff0c;是一套精选的基于 spm 生态圈的样式模块集合&#xff0c;是 Arale 的子集&#xff0c;也是一套模块化的样式命名和组织规范&#xff0c;是写 CSS 的更好方式。 2.Amazeui Amaze UI 是一个轻量级、 Mobile first 的前端框架, 基于开源…

【蓝桥杯Web】2022年第十三届蓝桥杯Web大学组省赛真题解析(完整版)

&#x1f9d1;‍&#x1f4bc; 个人简介&#xff1a;一个不甘平庸的平凡人&#x1f36c; &#x1f5a5;️ Nodejs专栏&#xff1a;Node.js从入门到精通 &#x1f5a5;️ TS知识总结&#xff1a;十万字TS知识点总结 &#x1f449; 你的一键三连是我更新的最大动力❤️&#xff0…

万字详述 Web3 彻底颠覆品牌行业的底层叙事

序言 尽管 Web3 品牌是一个被普遍看好的方向&#xff0c;但目前缺乏一个从底层逻辑上完全不同于 Web2 的叙事逻辑&#xff0c;Web3 品牌在当前现状更多以营销策略的方式进行尝试&#xff0c;但是由于缺乏一个根本性的叙事&#xff0c;无法支撑品牌方真正的认可并将其上升到战略…