前言
不多说,官方文档写的乱七八糟,v3还用的v2的付款码,导致代码十分混乱,骂的话已经不想多说了。
结合微信v3的SDK和github上面的描述,对于官方sdk未实现的接口可以自己根据OkHttpClientAdapter 的实现类发送 HTTP 请求,会自动生成签名和验证签名。下面给出我自己实现的可用的代码和v3中支付必要的参数和坑点。
关于商户模式的付款码支付可用通过微信开放社区这个链接来查看,实现的话其实都是大差不差。
实现
官方出了新的v3付款码支付的v3服务商模式付款码支付链接,参考链接和SDK中其它的支付方式可知需要如下几步。
一、接口与流程概览
- 接口地址:
POST https://api.mch.weixin.qq.com/v3/pay/partner/transactions/codepay - 核心步骤:
- 组装请求参数(服务商/子商户信息、订单信息、金额、付款码等)
- 设置
HttpHeaders(Accept/Content-Type均为application/json) - 构建
Config(商户证书、私钥、序列号)并初始化DefaultHttpClientBuilder() httpClient.execute()发送请求 → 解析响应 JSON → 映射为业务对象 → 返回结果
<dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-java</artifactId> <version>0.2.17</version> </dependency>
二、核心代码(可直接落地)
下面方法实现了“服务商模式的v3付款码支付”。只需将 getAppId()、getPlatformMchId()、getSubMchId()、getVxOutId()、getPrivateKeyPath()、getMerchantSerialNumber() 等替换为自己的实际实现即可。
public PayResponse<PaymentResponse> payOrder(PaymentOrderDto paymentOrderDto) {
try {
final String url = "https://api.mch.weixin.qq.com/v3/pay/partner/transactions/codepay";
//组装请求体
Map<String, Object> req = new HashMap<>();
req.put("sp_appid", this.getAppId());
req.put("sp_mchid", this.getPlatformMchId());
req.put("sub_mchid", this.getSubMchId());
req.put("description", paymentOrderDto.getPaySubject());
req.put("out_trade_no", paymentOrderDto.getOrderNo());
Map<String, Object> amount = new HashMap<>();
amount.put("total", Long.valueOf(this.multiply100(paymentOrderDto.getRealAmount())));
req.put("amount", amount);
Map<String, Object> payer = new HashMap<>();
payer.put("auth_code", paymentOrderDto.getAuthCode());
req.put("payer", payer);
Map<String, Object> storeInfo = new HashMap<>();
storeInfo.put("id", this.getVxOutId());
Map<String, Object> sceneInfo = new HashMap<>();
sceneInfo.put("store_info", storeInfo);
req.put("scene_info", sceneInfo);
//设置请求头
com.wechat.pay.java.core.http.HttpHeaders headers = new com.wechat.pay.java.core.http.HttpHeaders();
headers.addHeader("Accept", com.wechat.pay.java.core.http.MediaType.APPLICATION_JSON.getValue());
headers.addHeader("Content-Type", com.wechat.pay.java.core.http.MediaType.APPLICATION_JSON.getValue());
//构建 HTTP 请求
com.wechat.pay.java.core.http.HttpRequest httpRequest =
new com.wechat.pay.java.core.http.HttpRequest.Builder()
.httpMethod(com.wechat.pay.java.core.http.HttpMethod.POST)
.url(url)
.headers(headers)
.body(new com.wechat.pay.java.core.http.JsonRequestBody.Builder()
.body(com.wechat.pay.java.core.util.GsonUtil.toJson(req))
.build())
.build();
// 初始化 HttpClient(签名/验签由 Config 负责)
com.wechat.pay.java.core.Config cfg =
getConfig(this.getPlatformMchId(), getPrivateKeyPath(), getMerchantSerialNumber());
com.wechat.pay.java.core.http.HttpClient httpClient =
new com.wechat.pay.java.core.http.DefaultHttpClientBuilder()
.config(cfg)
.build();
// 5) 发送请求 & 解析响应
com.wechat.pay.java.core.http.HttpResponse<com.wechat.pay.java.core.http.JsonResponseBody> resp =
httpClient.execute(httpRequest, com.wechat.pay.java.core.http.JsonResponseBody.class);
String resultJson = extractVxServicePayResBodyJson(resp.getBody());
WxV3TransactionLite tx = com.alibaba.fastjson.JSON.parseObject(resultJson, WxV3TransactionLite.class);
return this.handleResult(tx, this.buildPaymentResp(tx, paymentOrderDto));
} catch (Exception e) {
log.error("微信特约商户付款码支付异常:{}", e.getMessage(), e);
return PayResponse.fail(e.getMessage(), null);
}
}
小提示
- 如果你的工程不想引入
GsonUtil,用 FastJSON(JSON.parseObject)或 Jackson(ObjectMapper.readValue)皆可。DefaultHttpClientBuilder所需Config里应配置:商户私钥、证书序列号、商户号,以及公钥等
三、轻量响应对象 WxV3TransactionLite
微信应答字段较多,实际以官方文档为准。此处给出常用字段的简版 POJO,方便快速落地:
@Data
public class WxV3TransactionLite {
private String sp_mchid; // 服务商商户号
private String sub_mchid; // 子商户号
private String out_trade_no; // 商户订单号
private String transaction_id; // 微信支付订单号
private String trade_state; // 交易状态 (e.g. SUCCESS, USERPAYING, NOTPAY)
private String trade_state_desc; // 状态描述
private String bank_type; // 付款银行
private String success_time; // 支付完成时间(RFC3339 格式)
private Amount amount; // 金额信息
private Payer payer; // 付款人信息(如返回)
@Data
public static class Amount {
private Integer total; // 订单总金额(分)
private Integer payer_total; // 用户支付金额(分)
private String currency; // 币种,CNY
private String payer_currency; // 用户支付币种(如返回)
}
@Data
public static class Payer {
private String openid; // 用户标识(如返回)
}
}
四、Config 的关键点和参数说明
Config 决定了自动签名与回包验签是否可靠:
目前微信支持多种Config类型,这里选用了RSAPublicKeyConfig来作为本次的Config,需要的配置如下:
- 文档里的字段/名称:商户号
mchid(服务商模式下指“服务商商户号”)- 含义与说明:在微信支付商户平台的商户号。服务商模式下,该值是服务商的
mchid,而子商户的sub_mchid体现在具体接口请求里,不在全局 SDK 配置里。 - 依据:—
- 含义与说明:在微信支付商户平台的商户号。服务商模式下,该值是服务商的
- 文档里的字段/名称:服务商 API 证书(apiclient_key.pem)
- 含义与说明:申请“商户 API 证书”时生成并保存在本地的私钥文件,SDK 用它对请求进行签名;常见文件名为
apiclient_key.pem。 - 依据:—
- 含义与说明:申请“商户 API 证书”时生成并保存在本地的私钥文件,SDK 用它对请求进行签名;常见文件名为
- 文档里的字段/名称:商户 API 证书序列号
serial_no- 含义与说明:与你当前使用的“商户 API 证书”对应的证书序列号(商户平台可查看或从证书中读取),SDK 会放到请求头
Wechatpay-Serial中配合签名使用。 - 依据:—
- 含义与说明:与你当前使用的“商户 API 证书”对应的证书序列号(商户平台可查看或从证书中读取),SDK 会放到请求头
- 文档里的字段/名称:
sp_appid- 含义与说明:服务商在微信开放平台(移动应用)或公众平台(公众号/小程序)申请的唯一标识。需与服务商商户号
sp_mchid绑定,支付能力会校验该绑定关系。 - 依据:—
- 含义与说明:服务商在微信开放平台(移动应用)或公众平台(公众号/小程序)申请的唯一标识。需与服务商商户号
- 文档里的字段/名称:
sub_mchid- 含义与说明:子商户(特约商户)在服务商体系下的唯一身份标识,发起服务商模式支付时必须传入。
- 依据:—
- 文档里的字段/名称:APIv3 密钥
- 含义与说明:用于 v3 接口的加解密(例如回调通知、平台证书下载等)。你备注“v3 中付款码支付使用了 v2 版本、v2 需要此参数”,若采用 v2 兼容路径请按渠道文档配置;纯 v3 流程中该密钥仍常用于回调验签/解密。
- 依据:—
- 文档里的字段/名称:微信支付公钥
- 含义与说明:用于验签(结合平台证书体系);在 SDK 自动拉取平台证书场景下通常无需手动配置公钥文件。
- 依据:—
- 文档里的字段/名称:门店编号
- 含义与说明:
scene_info.store_info.id,用于标识门店/收银点,便于账务核对与风险控制。v3 付款码支付需要此参数。 - 依据:客服文档说明(https://kf.qq.com/faq/230817neeaem2308177ZFfqM.html)
- 含义与说明:
详细获取可以看开发必要参数说明_通用规则|微信支付合作伙伴文档中心来获取配置。






空空如也!