APP预签约
更新时间:2025.09.19App预签约
接口说明
支持商户:【普通服务商】
请求方式:【POST】/v3/credit-repayment/partner/contracts/app-presign
请求域名:【主域名】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 包体参数
appid 必填 string(32)
【商户AppID】 商户在微信申请的公众号或移动应用AppID,与服务商商户号绑定。可参考服务商模式开发必要参数说明
plan_id 必填 string(64)
【模板ID】 信贷还款代扣模板ID; 在服务商平台上成功申请模板后系统自动分配的
out_contract_code 必填 string(64)
【服务商签约协议号】 服务商的签约协议号。服务商需保证唯一性。只能是数字、大小写字母的组合
display_name 必填 string(64)
【用户展示名称】 签约用户的名称,用于签约页面展示;需使用用户姓名掩码。掩码规则:只保留最后一个字符,除最后一个字符外全部字符(包括“.”等符号)均使用“*”替代;如姓名长度大于4个字符,统一用3个“*”+1位明文展示,如***G
contract_notify_url 必填 string(256)
【签约结果通知地址】 接收微信支付异步通知回调地址,通知URL必须为HTTPS且可直接可访问的URL,不能携带参数。参考回调通知注意事项
repayment_day 选填 integer
【还款日】 每月还款的日期
repayment_amount_limit 必填 string
【还款金额上限】 每次最多还款金额;单位:分
sub_merchant_code 选填 string(32)
【子商户号】 微信支付分配的商户号,服务商商户号与子商户号存在父子关系
sub_appid 选填 string(32)
【子商户AppID】 与子商户号绑定的AppID。可参考服务商模式开发必要参数说明
real_identity 选填 object
【用户实名信息】 商家可选择指定用户实名信息。指定用户实名信息后,微信支付系统会校验商户指定的用户实名信息跟用户在微信支付侧的实名信息是否一致。信息一致时才可进行签约;若信息不一致,不能进行本次签约。注:因实名信息不一致导致无法进行签约,微信支付将不会通知签约结果,也不会产生协议或订单信息。
| 属性 | |
identity_type 必填 string 【实名验证类型】 实名验证类型 可选取值
identity_id 必填 string(512) 【加密后的自然人证件号码】 经过加密后的自然人证件号码信息 real_name 必填 string(512) 【加密后的自然人姓名】 经过加密后的自然人姓名信息 |
请求示例
POST
1curl -X POST \ 2 https://api.mch.weixin.qq.com/v3/credit-repayment/partner/contracts/app-presign \ 3 -H "Authorization: WECHATPAY2-SHA256-RSA2048 mchid=\"1900000001\",..." \ 4 -H "Accept: application/json" \ 5 -H "Wechatpay-Serial: 5157F09EFDC096DE15EBE81A47057A7232F1B8E1" \ 6 -H "Content-Type: application/json" \ 7 -d '{ 8 "appid" : "wxd678efh567hg6787", 9 "plan_id" : "WxCreditRepaymentPlan12345678", 10 "out_contract_code" : "WxCreditRepayment20200910100000", 11 "display_name" : "*明", 12 "contract_notify_url" : "https://yourapp.com/notify", 13 "repayment_day" : 1, 14 "repayment_amount_limit" : "10000", 15 "sub_merchant_code" : "1000000109", 16 "sub_appid" : "wxcbda96de0b165489", 17 "real_identity" : { 18 "identity_type" : "REAL_IDENTITY_TYPE_ID_CARD", 19 "identity_id" : "1axtI9EZUr0343c89xQznxau+cRWPKP4YhVAoj/mEoNSgJh0nvuqQJ1cdXZHGUzyBjOtuLeVq+OLOaWGUScSM8+QLBk+kOK8QyR1TUo44YrmIl5KkjWLa3dpNJt+nIkpN1e7yr2mxO9LGqJdeQXDCHvOiUTK6lnAVxWY0ZrF4OQFmHqOCvqTaF3VxD5a8AT3gxyayF04IJSfPV0NheZvWFBHIUeRPf1/WQmJ/wXu2MfAuESB0dLBglT85i0Rws2GopaTUNiBuJBHdg01bR+YZvSYv8EJPyxuyYVh5bg/wSotNTYnVp13OUzMBKu25yOW5+RnunesXwq9ogPnSj7EDA==", 20 "real_name" : "OEimkKuua8igpd+0YDgqF2Z61leeGD7x87j3PhzsBhAK+/lltXENEOf6ThgV7niChzIpDujIpefE2JFZCJFurf6IV5rxNWBbjFeHYyUGAbf8zDx2Wbi7y7BGjApltIhsxAk+LhQ648Kcw4FMidL/79Gh3nHUfSGX+nEl3gtNi24Ilt8Vu0MMXhA1suDzlpbNDDrYnAhb1eeMziSu8jW7lDouwJXjGh9zgFPUuTxfOpteJIZSy8HWR+QPugdXBNouEezDPN8kojKbJHRtjaBJY3n3agkXShI5yvnc+DCYM+4VgNWZpTx9D0w3KAylJPKAAluYMzj4VXzZurjpruDg2A==" 21 } 22 }' 23
需配合微信支付工具库 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 * App预签约 24 */ 25public class PartnerPresignContractByApp { 26 private static String HOST = "https://api.mch.weixin.qq.com"; 27 private static String METHOD = "POST"; 28 private static String PATH = "/v3/credit-repayment/partner/contracts/app-presign"; 29 30 public static void main(String[] args) { 31 // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340 32 PartnerPresignContractByApp client = new PartnerPresignContractByApp( 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 PresignContractByAppRequest request = new PresignContractByAppRequest(); 41 request.appid = "wxd678efh567hg6787"; 42 request.planId = "WxCreditRepaymentPlan12345678"; 43 request.outContractCode = "WxCreditRepayment20200910100000"; 44 request.displayName = "*明"; 45 request.contractNotifyUrl = "https://yourapp.com/notify"; 46 request.repaymentDay = 1L; 47 request.repaymentAmountLimit = "10000"; 48 request.subMerchantCode = "1000000109"; 49 request.subAppid = "wxcbda96de0b165489"; 50 request.realIdentity = new RealIdentity(); 51 request.realIdentity.identityType = RealIdentityType.REAL_IDENTITY_TYPE_ID_CARD; 52 request.realIdentity.identityId = client.encrypt("identity_id"); 53 request.realIdentity.realName = client.encrypt("real_name"); 54 try { 55 PresignContractByAppResponse response = client.run(request); 56 // TODO: 请求成功,继续业务逻辑 57 System.out.println(response); 58 } catch (WXPayUtility.ApiException e) { 59 // TODO: 请求失败,根据状态码执行不同的逻辑 60 e.printStackTrace(); 61 } 62 } 63 64 public PresignContractByAppResponse run(PresignContractByAppRequest request) { 65 String uri = PATH; 66 String reqBody = WXPayUtility.toJson(request); 67 68 Request.Builder reqBuilder = new Request.Builder().url(HOST + uri); 69 reqBuilder.addHeader("Accept", "application/json"); 70 reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId); 71 reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo,privateKey, METHOD, uri, reqBody)); 72 reqBuilder.addHeader("Content-Type", "application/json"); 73 RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody); 74 reqBuilder.method(METHOD, requestBody); 75 Request httpRequest = reqBuilder.build(); 76 77 // 发送HTTP请求 78 OkHttpClient client = new OkHttpClient.Builder().build(); 79 try (Response httpResponse = client.newCall(httpRequest).execute()) { 80 String respBody = WXPayUtility.extractBody(httpResponse); 81 if (httpResponse.code() >= 200 && httpResponse.code() < 300) { 82 // 2XX 成功,验证应答签名 83 WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey, 84 httpResponse.headers(), respBody); 85 86 // 从HTTP应答报文构建返回数据 87 return WXPayUtility.fromJson(respBody, PresignContractByAppResponse.class); 88 } else { 89 throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers()); 90 } 91 } catch (IOException e) { 92 throw new UncheckedIOException("Sending request to " + uri + " failed.", e); 93 } 94 } 95 96 private final String mchid; 97 private final String certificateSerialNo; 98 private final PrivateKey privateKey; 99 private final String wechatPayPublicKeyId; 100 private final PublicKey wechatPayPublicKey; 101 102 public PartnerPresignContractByApp(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) { 103 this.mchid = mchid; 104 this.certificateSerialNo = certificateSerialNo; 105 this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath); 106 this.wechatPayPublicKeyId = wechatPayPublicKeyId; 107 this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath); 108 } 109 110 public String encrypt(String plainText) { 111 return WXPayUtility.encrypt(this.wechatPayPublicKey, plainText); 112 } 113 114 public static class PresignContractByAppRequest { 115 @SerializedName("appid") 116 public String appid; 117 118 @SerializedName("plan_id") 119 public String planId; 120 121 @SerializedName("out_contract_code") 122 public String outContractCode; 123 124 @SerializedName("display_name") 125 public String displayName; 126 127 @SerializedName("contract_notify_url") 128 public String contractNotifyUrl; 129 130 @SerializedName("repayment_day") 131 public Long repaymentDay; 132 133 @SerializedName("repayment_amount_limit") 134 public String repaymentAmountLimit; 135 136 @SerializedName("sub_merchant_code") 137 public String subMerchantCode; 138 139 @SerializedName("sub_appid") 140 public String subAppid; 141 142 @SerializedName("real_identity") 143 public RealIdentity realIdentity; 144 } 145 146 public static class PresignContractByAppResponse { 147 @SerializedName("presign_token") 148 public String presignToken; 149 150 @SerializedName("redirect_service") 151 public String redirectService; 152 } 153 154 public static class RealIdentity { 155 @SerializedName("identity_type") 156 public RealIdentityType identityType; 157 158 @SerializedName("identity_id") 159 public String identityId; 160 161 @SerializedName("real_name") 162 public String realName; 163 } 164 165 public enum RealIdentityType { 166 @SerializedName("REAL_IDENTITY_TYPE_INVALID") 167 REAL_IDENTITY_TYPE_INVALID, 168 @SerializedName("REAL_IDENTITY_TYPE_ID_CARD") 169 REAL_IDENTITY_TYPE_ID_CARD 170 } 171 172} 173
需配合微信支付工具库 wxpay_utility 使用,请参考Go
1package main 2 3import ( 4 "bytes" 5 "demo/wxpay_utility" // 引用微信支付工具库,参考 https://pay.weixin.qq.com/doc/v3/partner/4015119446 6 "encoding/json" 7 "fmt" 8 "net/http" 9 "net/url" 10) 11 12func main() { 13 // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340 14 config, err := wxpay_utility.CreateMchConfig( 15 "19xxxxxxxx", // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/partner/4013080340 16 "1DDE55AD98Exxxxxxxxxx", // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013058924 17 "/path/to/apiclient_key.pem", // 商户API证书私钥文件路径,本地文件路径 18 "PUB_KEY_ID_xxxxxxxxxxxxx", // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013038589 19 "/path/to/wxp_pub.pem", // 微信支付公钥文件路径,本地文件路径 20 ) 21 if err != nil { 22 fmt.Println(err) 23 return 24 } 25 26 request := &PresignContractByAppRequest{ 27 Appid: wxpay_utility.String("wxd678efh567hg6787"), 28 PlanId: wxpay_utility.String("WxCreditRepaymentPlan12345678"), 29 OutContractCode: wxpay_utility.String("WxCreditRepayment20200910100000"), 30 DisplayName: wxpay_utility.String("*明"), 31 ContractNotifyUrl: wxpay_utility.String("https://yourapp.com/notify"), 32 RepaymentDay: wxpay_utility.Int64(1), 33 RepaymentAmountLimit: wxpay_utility.String("10000"), 34 SubMerchantCode: wxpay_utility.String("1000000109"), 35 SubAppid: wxpay_utility.String("wxcbda96de0b165489"), 36 RealIdentity: &RealIdentity{ 37 IdentityType: REALIDENTITYTYPE_REAL_IDENTITY_TYPE_ID_CARD.Ptr(), 38 IdentityId: wxpay_utility.String("1axtI9EZUr0343c89xQznxau+cRWPKP4YhVAoj/mEoNSgJh0nvuqQJ1cdXZHGUzyBjOtuLeVq+OLOaWGUScSM8+QLBk+kOK8QyR1TUo44YrmIl5KkjWLa3dpNJt+nIkpN1e7yr2mxO9LGqJdeQXDCHvOiUTK6lnAVxWY0ZrF4OQFmHqOCvqTaF3VxD5a8AT3gxyayF04IJSfPV0NheZvWFBHIUeRPf1/WQmJ/wXu2MfAuESB0dLBglT85i0Rws2GopaTUNiBuJBHdg01bR+YZvSYv8EJPyxuyYVh5bg/wSotNTYnVp13OUzMBKu25yOW5+RnunesXwq9ogPnSj7EDA=="), /*请传入wxpay_utility.EncryptOAEPWithPublicKey 加密结果*/ 39 RealName: wxpay_utility.String("OEimkKuua8igpd+0YDgqF2Z61leeGD7x87j3PhzsBhAK+/lltXENEOf6ThgV7niChzIpDujIpefE2JFZCJFurf6IV5rxNWBbjFeHYyUGAbf8zDx2Wbi7y7BGjApltIhsxAk+LhQ648Kcw4FMidL/79Gh3nHUfSGX+nEl3gtNi24Ilt8Vu0MMXhA1suDzlpbNDDrYnAhb1eeMziSu8jW7lDouwJXjGh9zgFPUuTxfOpteJIZSy8HWR+QPugdXBNouEezDPN8kojKbJHRtjaBJY3n3agkXShI5yvnc+DCYM+4VgNWZpTx9D0w3KAylJPKAAluYMzj4VXzZurjpruDg2A=="), /*请传入wxpay_utility.EncryptOAEPWithPublicKey 加密结果*/ 40 }, 41 } 42 43 response, err := PartnerPresignContractByApp(config, request) 44 if err != nil { 45 fmt.Printf("请求失败: %+v\n", err) 46 // TODO: 请求失败,根据状态码执行不同的处理 47 return 48 } 49 50 // TODO: 请求成功,继续业务逻辑 51 fmt.Printf("请求成功: %+v\n", response) 52} 53 54func PartnerPresignContractByApp(config *wxpay_utility.MchConfig, request *PresignContractByAppRequest) (response *PresignContractByAppResponse, err error) { 55 const ( 56 host = "https://api.mch.weixin.qq.com" 57 method = "POST" 58 path = "/v3/credit-repayment/partner/contracts/app-presign" 59 ) 60 61 reqUrl, err := url.Parse(fmt.Sprintf("%s%s", host, path)) 62 if err != nil { 63 return nil, err 64 } 65 reqBody, err := json.Marshal(request) 66 if err != nil { 67 return nil, err 68 } 69 httpRequest, err := http.NewRequest(method, reqUrl.String(), bytes.NewReader(reqBody)) 70 if err != nil { 71 return nil, err 72 } 73 httpRequest.Header.Set("Accept", "application/json") 74 httpRequest.Header.Set("Wechatpay-Serial", config.WechatPayPublicKeyId()) 75 httpRequest.Header.Set("Content-Type", "application/json") 76 authorization, err := wxpay_utility.BuildAuthorization(config.MchId(), config.CertificateSerialNo(), config.PrivateKey(), method, reqUrl.RequestURI(), reqBody) 77 if err != nil { 78 return nil, err 79 } 80 httpRequest.Header.Set("Authorization", authorization) 81 82 client := &http.Client{} 83 httpResponse, err := client.Do(httpRequest) 84 if err != nil { 85 return nil, err 86 } 87 respBody, err := wxpay_utility.ExtractResponseBody(httpResponse) 88 if err != nil { 89 return nil, err 90 } 91 if httpResponse.StatusCode >= 200 && httpResponse.StatusCode < 300 { 92 // 2XX 成功,验证应答签名 93 err = wxpay_utility.ValidateResponse( 94 config.WechatPayPublicKeyId(), 95 config.WechatPayPublicKey(), 96 &httpResponse.Header, 97 respBody, 98 ) 99 if err != nil { 100 return nil, err 101 } 102 response := &PresignContractByAppResponse{} 103 if err := json.Unmarshal(respBody, response); err != nil { 104 return nil, err 105 } 106 107 return response, nil 108 } else { 109 return nil, wxpay_utility.NewApiException( 110 httpResponse.StatusCode, 111 httpResponse.Header, 112 respBody, 113 ) 114 } 115} 116 117type PresignContractByAppRequest struct { 118 Appid *string `json:"appid,omitempty"` 119 PlanId *string `json:"plan_id,omitempty"` 120 OutContractCode *string `json:"out_contract_code,omitempty"` 121 DisplayName *string `json:"display_name,omitempty"` 122 ContractNotifyUrl *string `json:"contract_notify_url,omitempty"` 123 RepaymentDay *int64 `json:"repayment_day,omitempty"` 124 RepaymentAmountLimit *string `json:"repayment_amount_limit,omitempty"` 125 SubMerchantCode *string `json:"sub_merchant_code,omitempty"` 126 SubAppid *string `json:"sub_appid,omitempty"` 127 RealIdentity *RealIdentity `json:"real_identity,omitempty"` 128} 129 130type PresignContractByAppResponse struct { 131 PresignToken *string `json:"presign_token,omitempty"` 132 RedirectService *string `json:"redirect_service,omitempty"` 133} 134 135type RealIdentity struct { 136 IdentityType *RealIdentityType `json:"identity_type,omitempty"` 137 IdentityId *string `json:"identity_id,omitempty"` 138 RealName *string `json:"real_name,omitempty"` 139} 140 141type RealIdentityType string 142 143func (e RealIdentityType) Ptr() *RealIdentityType { 144 return &e 145} 146 147const ( 148 REALIDENTITYTYPE_REAL_IDENTITY_TYPE_INVALID RealIdentityType = "REAL_IDENTITY_TYPE_INVALID" 149 REALIDENTITYTYPE_REAL_IDENTITY_TYPE_ID_CARD RealIdentityType = "REAL_IDENTITY_TYPE_ID_CARD" 150) 151
应答参数
200 OK
presign_token 必填 string(128)
【预签约码】 预签约生成的预签约码,用于跳转签约页面;有效期10分钟
redirect_service 必填 string(64)
【跳转到的签约服务提供方】 跳转到的签约服务提供方,用于跳转签约页面
应答示例
200 OK
1{ 2 "presign_token" : "f55a992c06ade13c1e174149b9e18a63cc900b19165a7515a4c4699ffd73e4a8fc839bc5e9d1b919ae0859619c02226e", 3 "redirect_service" : "wxpayRedirectService" 4} 5
错误码
以下是本接口返回的错误码列表。详细错误码规则,请参考微信支付接口规则-错误码和错误提示
状态码 | 错误码 | 描述 | 解决方案 |
|---|---|---|---|
400 | PARAM_ERROR | 参数错误 | 请根据错误提示正确传入参数 |
400 | INVALID_REQUEST | HTTP 请求不符合微信支付 APIv3 接口规则 | 请参阅 接口规则 |
401 | SIGN_ERROR | 验证不通过 | 请参阅 签名常见问题 |
500 | SYSTEM_ERROR | 系统异常,请稍后重试 | 请稍后重试 |
400 | ALREADY_EXISTS | 预签约的协议已存在 | 确认服务商签约协议号是否重复 |
429 | RATELIMIT_EXCEEDED | 请求超过接口频率限制 | 降低频率,稍后重试 |

