发起转账

更新时间:2025.07.29

服务商商户可通过此接口申请创建转账单

  • 接口返回的HTTP状态码及错误码,仅代表本次请求的结果,不能代表订单状态。

  • 接口返回的HTTP状态码为200,且赔付状态为ACCEPT时,可认为发起商家转账成功。

  • 接口返回的HTTP状态码不为200时,请商户务必不要立即更换商户订单单号重试。可根据错误码列表中的描述和接口返回的信息进行处理,并在查询原订单结果为失败或者联系客服确认情况后,再更换商户订单号进行重试。否则会有重复转账的资金风险。

注:单个商户的接口频率限制为100次/s

接口说明

支持商户:【普通服务商】

请求方式:【POST】/v3/fund-app/mch-transfer/partner/transfer-bills

请求域名:【主域名】https://api.mch.weixin.qq.com 使用该域名将访问就近的接入点

     【备域名】https://api2.mch.weixin.qq.com 使用该域名将访问异地的接入点 ,指引点击查看

请求参数

Header  HTTP头参数

 Authorization  必填 string

请参考签名认证生成认证信息


 Accept  必填 string

请设置为application/json


 Content-Type  必填 string

请设置为application/json


 Wechatpay-Serial  必填 string

【微信支付公钥ID】或【微信支付平台证书序列号】  请求参数中的敏感字段,需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引;也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号平台证书加密敏感信息指引


body  包体参数

 sub_mchid  必填   string(32)

【子商户号】 微信支付分配的商户号,出资商户号


 appid  必填   string(32)

【商户AppID】 申请商户号的AppID或商户号绑定的AppID(企业号corpid即为此AppID)


 out_bill_no  必填   string(32)

【商户单号】 商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一


 transfer_scene_id  必填   string(36)

【转账场景ID】 该笔转账使用的转账场景,可前往“商户平台-产品中心-商家转账”中申请。如:1001-现金营销


 openid  必填   string(64)

【收款用户OpenID】 商户AppID下,某用户的OpenID 获取openid的链接


 user_name  选填   string

【收款用户姓名】 收款方真实姓名。需要加密传入,支持标准RSA算法和国密算法,公钥由微信侧提供。
转账金额 >= 2,000元时,该笔明细必须填写
若商户传入收款用户姓名,微信支付会校验收款用户与输入姓名是否一致,并提供电子回单


 transfer_amount  必填   integer

【转账金额】 转账金额单位为“分”。


 transfer_remark  必填   string(32)

【转账备注】 转账备注,用户收款时可见该备注信息,UTF8编码,最多允许32个字符


 notify_url  选填   string(256)

【通知地址】 异步接收微信支付结果通知的回调地址,通知url必须为公网可访问的URL,必须为HTTPS,不能携带参数。


 user_recv_perception  选填   string(10)

【用户收款感知】 用户收款时感知到的收款原因将根据转账场景自动展示默认内容。如有其他展示需求,可在本字段传入。各场景展示的默认内容和支持传入的内容,可查看产品文档了解。


 transfer_scene_report_infos  选填   array[object]

【转账场景报备信息】 各转账场景下需报备的内容,可通过产品文档了解。

属性

请求示例

Java
Go
curl

需配合微信支付工具库 WXPayUtility 使用,请参考 Java 

1package com.java.demo;
2
3import com.java.utils.WXPayUtility; // 引用微信支付工具库,参考:https://pay.weixin.qq.com/doc/v3/partner/4014985777
4
5import com.google.gson.annotations.SerializedName;
6import com.google.gson.annotations.Expose;
7import okhttp3.MediaType;
8import okhttp3.OkHttpClient;
9import okhttp3.Request;
10import okhttp3.RequestBody;
11import okhttp3.Response;
12
13import java.io.IOException;
14import java.io.UncheckedIOException;
15import java.security.PrivateKey;
16import java.security.PublicKey;
17import java.util.ArrayList;
18import java.util.HashMap;
19import java.util.List;
20import java.util.Map;
21
22/**
23 * 发起转账
24 */
25public class TransferToUser {
26  private static String HOST = "https://api.mch.weixin.qq.com";
27  private static String METHOD = "POST";
28  private static String PATH = "/v3/fund-app/mch-transfer/partner/transfer-bills";
29
30  public static void main(String[] args) {
31    // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340
32    TransferToUser client = new TransferToUser(
33      "19xxxxxxxx",                    // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/partner/4013080340
34      "1DDE55AD98Exxxxxxxxxx",         // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013058924
35      "/path/to/apiclient_key.pem",    // 商户API证书私钥文件路径,本地文件路径
36      "PUB_KEY_ID_xxxxxxxxxxxxx",      // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013038589
37      "/path/to/wxp_pub.pem"           // 微信支付公钥文件路径,本地文件路径
38    );
39
40    TransferToUserRequest request = new TransferToUserRequest();
41    request.subMchid = "1900001121";
42    request.appid = "wxf636efh567hg4356";
43    request.outBillNo = "plfk2020042013";
44    request.transferSceneId = "1000";
45    request.openid = "o-MYE42l80oelYMDE34nYD456Xoy";
46    request.userName = client.encrypt("user_name");
47    request.transferAmount = 400000L;
48    request.transferRemark = "2020年4月报销";
49    request.notifyUrl = "https://www.weixin.qq.com/wxpay/pay.php";
50    request.userRecvPerception = "现金奖励";
51    request.transferSceneReportInfos = new ArrayList<>();
52    {
53      TransferSceneReportInfo transferSceneReportInfosItem = new TransferSceneReportInfo();
54      transferSceneReportInfosItem.infoType = "活动名称";
55      transferSceneReportInfosItem.infoContent = "新会员有礼";
56      request.transferSceneReportInfos.add(transferSceneReportInfosItem);
57    };
58    try {
59      TransferToUserResponse response = client.run(request);
60
61      // TODO: 请求成功,继续业务逻辑
62      System.out.println(response);
63    } catch (WXPayUtility.ApiException e) {
64      // TODO: 请求失败,根据状态码执行不同的逻辑
65      e.printStackTrace();
66    }
67  }
68
69  public TransferToUserResponse run(TransferToUserRequest request) {
70    String uri = PATH;
71    String reqBody = WXPayUtility.toJson(request);
72
73    Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
74    reqBuilder.addHeader("Accept", "application/json");
75    reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId);
76    reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo,privateKey, METHOD, uri, reqBody));
77    reqBuilder.addHeader("Content-Type", "application/json");
78    RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody);
79    reqBuilder.method(METHOD, requestBody);
80    Request httpRequest = reqBuilder.build();
81
82    // 发送HTTP请求
83    OkHttpClient client = new OkHttpClient.Builder().build();
84    try (Response httpResponse = client.newCall(httpRequest).execute()) {
85      String respBody = WXPayUtility.extractBody(httpResponse);
86      if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
87        // 2XX 成功,验证应答签名
88        WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey,
89            httpResponse.headers(), respBody);
90
91        // 从HTTP应答报文构建返回数据
92        return WXPayUtility.fromJson(respBody, TransferToUserResponse.class);
93      } else {
94        throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
95      }
96    } catch (IOException e) {
97      throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
98    }
99  }
100
101  private final String mchid;
102  private final String certificateSerialNo;
103  private final PrivateKey privateKey;
104  private final String wechatPayPublicKeyId;
105  private final PublicKey wechatPayPublicKey;
106
107  public TransferToUser(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) {
108    this.mchid = mchid;
109    this.certificateSerialNo = certificateSerialNo;
110    this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath);
111    this.wechatPayPublicKeyId = wechatPayPublicKeyId;
112    this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath);
113  }
114
115  public String encrypt(String plainText) {
116    return WXPayUtility.encrypt(this.wechatPayPublicKey, plainText);
117  }
118
119  public static class TransferToUserRequest {
120    @SerializedName("sub_mchid")
121    public String subMchid;
122  
123    @SerializedName("appid")
124    public String appid;
125  
126    @SerializedName("out_bill_no")
127    public String outBillNo;
128  
129    @SerializedName("transfer_scene_id")
130    public String transferSceneId;
131  
132    @SerializedName("openid")
133    public String openid;
134  
135    @SerializedName("user_name")
136    public String userName;
137  
138    @SerializedName("transfer_amount")
139    public Long transferAmount;
140  
141    @SerializedName("transfer_remark")
142    public String transferRemark;
143  
144    @SerializedName("notify_url")
145    public String notifyUrl;
146  
147    @SerializedName("user_recv_perception")
148    public String userRecvPerception;
149  
150    @SerializedName("transfer_scene_report_infos")
151    public List<TransferSceneReportInfo> transferSceneReportInfos;
152  }
153  
154  public static class TransferToUserResponse {
155    @SerializedName("sub_mchid")
156    public String subMchid;
157  
158    @SerializedName("out_bill_no")
159    public String outBillNo;
160  
161    @SerializedName("transfer_bill_no")
162    public String transferBillNo;
163  
164    @SerializedName("create_time")
165    public String createTime;
166  
167    @SerializedName("package_info")
168    public String packageInfo;
169  }
170  
171  public static class TransferSceneReportInfo {
172    @SerializedName("info_type")
173    public String infoType;
174  
175    @SerializedName("info_content")
176    public String infoContent;
177  }
178  
179}
180

应答参数

200 OK

 sub_mchid  必填   string

【子商户号】 微信支付分配的商户号,出资商户


 out_bill_no  必填   string

【商户单号】 商户系统内部的商家单号,只能由数字、大小写字母组成,在商户系统内部唯一


 transfer_bill_no  必填   string

【微信支付转账单号】 微信支付转账单号,转账单的唯一标识


 create_time  必填   string

【受理时间】 受理成功时会返回,按照使用rfc3339所定义的格式,格式为yyyy-MM-DDThh:mm:ss+TIMEZONE


 package_info  必填   string

【跳转领取页面的package信息】 跳转微信支付收款页的package信息,APP调起用户确认收款 或者 JSAPI调起用户确认收款 时需要使用的参数。

单据创建后,用户24小时内不领取将过期关闭,建议拉起用户确认收款页面前,先查单据状态:如单据状态为待收款用户确认,可用之前的package信息拉起;单据到终态时需更换单号重新发起转账。

应答示例

200 OK

1{
2  "sub_mchid" : "1900001109",
3  "out_bill_no" : "plfk2020042013",
4  "transfer_bill_no" : "1330000071100999991182020050700019480001",
5  "create_time" : "2015-05-20T13:29:35+08:00",
6  "package_info" : "affffddafdfafddffda=="
7}
8

 

错误码

公共错误码

状态码

错误码

描述

解决方案

400

PARAM_ERROR

参数错误

请根据错误提示正确传入参数

400

INVALID_REQUEST

HTTP 请求不符合微信支付 APIv3 接口规则

请参阅 接口规则

401

SIGN_ERROR

验证不通过

请参阅 签名常见问题

500

SYSTEM_ERROR

系统异常,请稍后重试

请稍后重试

业务错误码

状态码

错误码

描述

解决方案

403

NOT_ENOUGH

资金不足

确认出资商户余额充足

429

FREQUENCY_LIMIT_EXCEED

请求接口频率过快

降低频率,稍后重试

400

INVALID_REQUEST

请求不符合业务规则

请参阅 产品介绍、开发指引 和 接口规则

403

NO_AUTH

没有相关权限

请参阅 产品介绍、开发指引

400

ALREADY_EXISTS

订单已存在

单据已经关闭或用户已经确认,无法发起转账,请通过查单接口确认转账结果

 

 

反馈
咨询
目录
置顶