获取用户填写抬头信息
更新时间:2025.09.05商户调用本接口,检查用户是否已完成抬头填写,并获取用户填写的抬头信息。在微信支付场景下,若该笔订单在下单时指定在支付凭证上展示开票入口,则也可以调用本接口查询用户填写的抬头。
接口说明
支持商户:【普通服务商】
请求方式:【GET】/v3/new-tax-control-fapiao/user-title
请求域名:【主域名】https://api.mch.weixin.qq.com 使用该域名将访问就近的接入点
【备域名】https://api2.mch.weixin.qq.com 使用该域名将访问异地的接入点 ,指引点击查看
请求参数
Header HTTP头参数
Authorization 必填 string
请参考签名认证生成认证信息
Accept 必填 string
请设置为application/json
query 查询参数
sub_mchid 必填 string(32)
【子商户号】 微信支付分配的子商户号,具体请参考服务商模式开发必要参数说明
scene 必填 string
【开票场景】 开票场景
可选取值
WITH_WECHATPAY
: 微信支付场景WITHOUT_WECHATPAY
: 非微信支付场景
fapiao_apply_id 必填 string(32)
【发票申请单号】 发票申请单号,唯一标识一次开票行为。当开票场景为WITHOUT_WECHATPAY时,为调用【获取用户抬头填写链接】接口时指定的发票申请单号;当开票场景为WITH_WECHATPAY时,为与本次开票关联的微信支付订单号,且必须是属于相应商户的订单
请求示例
GET
1curl -X GET \ 2 https://api.mch.weixin.qq.com/v3/new-tax-control-fapiao/user-title?sub_mchid=1900000109&scene=WITH_WECHATPAY&fapiao_apply_id=4200000444201910177461284488 \ 3 -H "Authorization: WECHATPAY2-SHA256-RSA2048 mchid=\"1900000001\",..." \ 4 -H "Accept: application/json" 5
需配合微信支付工具库 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 GetUserTitle { 26 private static String HOST = "https://api.mch.weixin.qq.com"; 27 private static String METHOD = "GET"; 28 private static String PATH = "/v3/new-tax-control-fapiao/user-title"; 29 30 public static void main(String[] args) { 31 // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340 32 GetUserTitle client = new GetUserTitle( 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 GetUserTitleRequest request = new GetUserTitleRequest(); 41 request.subMchid = "1900000109"; 42 request.scene = Scene.WITH_WECHATPAY; 43 request.fapiaoApplyId = "4200000444201910177461284488"; 44 try { 45 UserTitleEntity response = client.run(request); 46 // TODO: 请求成功,继续业务逻辑 47 System.out.println(response); 48 } catch (WXPayUtility.ApiException e) { 49 // TODO: 请求失败,根据状态码执行不同的逻辑 50 e.printStackTrace(); 51 } 52 } 53 54 public UserTitleEntity run(GetUserTitleRequest request) { 55 String uri = PATH; 56 Map<String, Object> args = new HashMap<>(); 57 args.put("sub_mchid", request.subMchid); 58 args.put("scene", request.scene); 59 args.put("fapiao_apply_id", request.fapiaoApplyId); 60 String queryString = WXPayUtility.urlEncode(args); 61 if (!queryString.isEmpty()) { 62 uri = uri + "?" + queryString; 63 } 64 65 Request.Builder reqBuilder = new Request.Builder().url(HOST + uri); 66 reqBuilder.addHeader("Accept", "application/json"); 67 reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId); 68 reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo, privateKey, METHOD, uri, null)); 69 reqBuilder.method(METHOD, null); 70 Request httpRequest = reqBuilder.build(); 71 72 // 发送HTTP请求 73 OkHttpClient client = new OkHttpClient.Builder().build(); 74 try (Response httpResponse = client.newCall(httpRequest).execute()) { 75 String respBody = WXPayUtility.extractBody(httpResponse); 76 if (httpResponse.code() >= 200 && httpResponse.code() < 300) { 77 // 2XX 成功,验证应答签名 78 WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey, 79 httpResponse.headers(), respBody); 80 81 // 从HTTP应答报文构建返回数据 82 return WXPayUtility.fromJson(respBody, UserTitleEntity.class); 83 } else { 84 throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers()); 85 } 86 } catch (IOException e) { 87 throw new UncheckedIOException("Sending request to " + uri + " failed.", e); 88 } 89 } 90 91 private final String mchid; 92 private final String certificateSerialNo; 93 private final PrivateKey privateKey; 94 private final String wechatPayPublicKeyId; 95 private final PublicKey wechatPayPublicKey; 96 97 public GetUserTitle(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) { 98 this.mchid = mchid; 99 this.certificateSerialNo = certificateSerialNo; 100 this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath); 101 this.wechatPayPublicKeyId = wechatPayPublicKeyId; 102 this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath); 103 } 104 105 public static class GetUserTitleRequest { 106 @SerializedName("sub_mchid") 107 @Expose(serialize = false) 108 public String subMchid; 109 110 @SerializedName("fapiao_apply_id") 111 @Expose(serialize = false) 112 public String fapiaoApplyId; 113 114 @SerializedName("scene") 115 @Expose(serialize = false) 116 public Scene scene; 117 } 118 119 public static class UserTitleEntity { 120 @SerializedName("type") 121 public BuyerType type; 122 123 @SerializedName("name") 124 public String name; 125 126 @SerializedName("taxpayer_id") 127 public String taxpayerId; 128 129 @SerializedName("address") 130 public String address; 131 132 @SerializedName("telephone") 133 public String telephone; 134 135 @SerializedName("bank_name") 136 public String bankName; 137 138 @SerializedName("bank_account") 139 public String bankAccount; 140 141 @SerializedName("phone") 142 public String phone; 143 144 @SerializedName("email") 145 public String email; 146 147 @SerializedName("amount") 148 public Long amount; 149 150 @SerializedName("out_trade_no") 151 public String outTradeNo; 152 153 @SerializedName("fapiao_bill_type") 154 public FapiaoBillType fapiaoBillType; 155 156 @SerializedName("user_apply_message") 157 public String userApplyMessage; 158 } 159 160 public enum Scene { 161 @SerializedName("WITH_WECHATPAY") 162 WITH_WECHATPAY, 163 @SerializedName("WITHOUT_WECHATPAY") 164 WITHOUT_WECHATPAY 165 } 166 167 public enum BuyerType { 168 @SerializedName("INDIVIDUAL") 169 INDIVIDUAL, 170 @SerializedName("ORGANIZATION") 171 ORGANIZATION 172 } 173 174 public enum FapiaoBillType { 175 @SerializedName("COMM_FAPIAO") 176 COMM_FAPIAO, 177 @SerializedName("VAT_FAPIAO") 178 VAT_FAPIAO 179 } 180 181} 182
需配合微信支付工具库 wxpay_utility 使用,请参考 Go
1package main 2 3import ( 4 "demo/wxpay_utility" // 引用微信支付工具库,参考 https://pay.weixin.qq.com/doc/v3/partner/4015119446 5 "encoding/json" 6 "fmt" 7 "net/http" 8 "net/url" 9) 10 11func main() { 12 // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340 13 config, err := wxpay_utility.CreateMchConfig( 14 "19xxxxxxxx", // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/partner/4013080340 15 "1DDE55AD98Exxxxxxxxxx", // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013058924 16 "/path/to/apiclient_key.pem", // 商户API证书私钥文件路径,本地文件路径 17 "PUB_KEY_ID_xxxxxxxxxxxxx", // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013038589 18 "/path/to/wxp_pub.pem", // 微信支付公钥文件路径,本地文件路径 19 ) 20 if err != nil { 21 fmt.Println(err) 22 return 23 } 24 25 request := &GetUserTitleRequest{ 26 SubMchid: wxpay_utility.String("1900000109"), 27 Scene: SCENE_WITH_WECHATPAY.Ptr(), 28 FapiaoApplyId: wxpay_utility.String("4200000444201910177461284488"), 29 } 30 31 response, err := GetUserTitle(config, request) 32 if err != nil { 33 fmt.Printf("请求失败: %+v\n", err) 34 // TODO: 请求失败,根据状态码执行不同的处理 35 return 36 } 37 38 // TODO: 请求成功,继续业务逻辑 39 fmt.Printf("请求成功: %+v\n", response) 40} 41 42func GetUserTitle(config *wxpay_utility.MchConfig, request *GetUserTitleRequest) (response *UserTitleEntity, err error) { 43 const ( 44 host = "https://api.mch.weixin.qq.com" 45 method = "GET" 46 path = "/v3/new-tax-control-fapiao/user-title" 47 ) 48 49 reqUrl, err := url.Parse(fmt.Sprintf("%s%s", host, path)) 50 if err != nil { 51 return nil, err 52 } 53 query := reqUrl.Query() 54 if request.SubMchid != nil { 55 query.Add("sub_mchid", *request.SubMchid) 56 } 57 if request.Scene != nil { 58 query.Add("scene", fmt.Sprintf("%v", *request.Scene)) 59 } 60 if request.FapiaoApplyId != nil { 61 query.Add("fapiao_apply_id", *request.FapiaoApplyId) 62 } 63 reqUrl.RawQuery = query.Encode() 64 httpRequest, err := http.NewRequest(method, reqUrl.String(), nil) 65 if err != nil { 66 return nil, err 67 } 68 httpRequest.Header.Set("Accept", "application/json") 69 httpRequest.Header.Set("Wechatpay-Serial", config.WechatPayPublicKeyId()) 70 authorization, err := wxpay_utility.BuildAuthorization(config.MchId(), config.CertificateSerialNo(), config.PrivateKey(), method, reqUrl.RequestURI(), nil) 71 if err != nil { 72 return nil, err 73 } 74 httpRequest.Header.Set("Authorization", authorization) 75 76 client := &http.Client{} 77 httpResponse, err := client.Do(httpRequest) 78 if err != nil { 79 return nil, err 80 } 81 respBody, err := wxpay_utility.ExtractResponseBody(httpResponse) 82 if err != nil { 83 return nil, err 84 } 85 if httpResponse.StatusCode >= 200 && httpResponse.StatusCode < 300 { 86 // 2XX 成功,验证应答签名 87 err = wxpay_utility.ValidateResponse( 88 config.WechatPayPublicKeyId(), 89 config.WechatPayPublicKey(), 90 &httpResponse.Header, 91 respBody, 92 ) 93 if err != nil { 94 return nil, err 95 } 96 response := &UserTitleEntity{} 97 if err := json.Unmarshal(respBody, response); err != nil { 98 return nil, err 99 } 100 101 return response, nil 102 } else { 103 return nil, wxpay_utility.NewApiException( 104 httpResponse.StatusCode, 105 httpResponse.Header, 106 respBody, 107 ) 108 } 109} 110 111type GetUserTitleRequest struct { 112 SubMchid *string `json:"sub_mchid,omitempty"` 113 FapiaoApplyId *string `json:"fapiao_apply_id,omitempty"` 114 Scene *Scene `json:"scene,omitempty"` 115} 116 117func (o *GetUserTitleRequest) MarshalJSON() ([]byte, error) { 118 type Alias GetUserTitleRequest 119 a := &struct { 120 SubMchid *string `json:"sub_mchid,omitempty"` 121 FapiaoApplyId *string `json:"fapiao_apply_id,omitempty"` 122 Scene *Scene `json:"scene,omitempty"` 123 *Alias 124 }{ 125 // 序列化时移除非 Body 字段 126 SubMchid: nil, 127 FapiaoApplyId: nil, 128 Scene: nil, 129 Alias: (*Alias)(o), 130 } 131 return json.Marshal(a) 132} 133 134type UserTitleEntity struct { 135 Type *BuyerType `json:"type,omitempty"` 136 Name *string `json:"name,omitempty"` 137 TaxpayerId *string `json:"taxpayer_id,omitempty"` 138 Address *string `json:"address,omitempty"` 139 Telephone *string `json:"telephone,omitempty"` 140 BankName *string `json:"bank_name,omitempty"` 141 BankAccount *string `json:"bank_account,omitempty"` 142 Phone *string `json:"phone,omitempty"` 143 Email *string `json:"email,omitempty"` 144 Amount *int64 `json:"amount,omitempty"` 145 OutTradeNo *string `json:"out_trade_no,omitempty"` 146 FapiaoBillType *FapiaoBillType `json:"fapiao_bill_type,omitempty"` 147 UserApplyMessage *string `json:"user_apply_message,omitempty"` 148} 149 150type Scene string 151 152func (e Scene) Ptr() *Scene { 153 return &e 154} 155 156const ( 157 SCENE_WITH_WECHATPAY Scene = "WITH_WECHATPAY" 158 SCENE_WITHOUT_WECHATPAY Scene = "WITHOUT_WECHATPAY" 159) 160 161type BuyerType string 162 163func (e BuyerType) Ptr() *BuyerType { 164 return &e 165} 166 167const ( 168 BUYERTYPE_INDIVIDUAL BuyerType = "INDIVIDUAL" 169 BUYERTYPE_ORGANIZATION BuyerType = "ORGANIZATION" 170) 171 172type FapiaoBillType string 173 174func (e FapiaoBillType) Ptr() *FapiaoBillType { 175 return &e 176} 177 178const ( 179 FAPIAOBILLTYPE_COMM_FAPIAO FapiaoBillType = "COMM_FAPIAO" 180 FAPIAOBILLTYPE_VAT_FAPIAO FapiaoBillType = "VAT_FAPIAO" 181) 182
应答参数
200 OK
type 必填 string
【购买方类型】 购买方类型
可选取值
INDIVIDUAL
: 个人、其他ORGANIZATION
: 单位
name 必填 string(256)
【名称】 购买方名称
taxpayer_id 选填 string(32)
【纳税人识别号】 购买方纳税人识别号,购买方类型为ORGANIZATION时必填
address 选填 string(128)
【地址】 购买方地址
telephone 选填 string(32)
【电话】 购买方电话
bank_name 选填 string(128)
【开户银行名称】 购买方开户银行名称
bank_account 选填 string(32)
【银行账号】 购买方银行账号
phone 选填 string
【手机号】 用户手机号。注意:该字段为密文字段,作为请求字段需加密,使用微信支付公钥加密(推荐),参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引;也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引;作为响应字段需解密,参考如何使用API证书解密敏感字段
email 选填 string
【邮箱地址】 用户邮箱地址。注意:该字段为密文字段,作为请求字段需加密,使用微信支付公钥加密(推荐),参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引;也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引;作为响应字段需解密,参考如何使用API证书解密敏感字段
amount 选填 integer
【订单金额】 微信支付订单金额,仅在微信支付场景下有效,单位:分
out_trade_no 选填 string(32)
【商户订单号】 商户订单号,仅在微信支付场景下有效
fapiao_bill_type 选填 string
【开具的发票类型】 用户选择提交开具发票的类型
可选取值
COMM_FAPIAO
: 增值税普通发票VAT_FAPIAO
: 增值税专用发票
user_apply_message 选填 string(100)
【留言信息】 用户申请开票时提交的留言信息
应答示例
200 OK
1{ 2 "type" : "INDIVIDUAL", 3 "name" : "深圳市南山区测试企业", 4 "taxpayer_id" : "202003261233701778", 5 "address" : "深圳市南山区深南大道10000号", 6 "telephone" : "075512345678", 7 "bank_name" : "测试银行", 8 "bank_account" : "62001234567890", 9 "phone" : "mI7HGEJ4Q2B91IGjHrl7FNN9QuFPDfzeXoaJM4B8ZghZPzXK+vNotEZu/Gthm87Szv0MK2AoC0/3ZMDgltMtdoY6O0qZ4F1iXiwCuqkkBe+9M4ggvdzpPGM+fyed2QU1seUGbii5RVVVB9s+zLEQ8nv74vsgl77MZx14nd5obtCcfAvPfDJob3oG7FqlThmYKJqjiOwBvvQse7p9R8onj/POzSrbM8re8ZYGp4LcehXopTLdk2ZVWRv8bnJgKZWArAcqMdahq4jY2UVYeY4vpMmq4xuRTYk6xNXvowBBKK2SX8SqM+jm1USyoBIazLu4oaNFNdBO3fip1a1rFW0vRw==", 10 "email" : "NzJy3r0Z2u2Vs5l+WSH0A3CZ1oGlCZ66aa2wUlMXNmACbd4wU8LqqYCuTG4cYWxrVUSmviV59/Uy9vLdIwuHZVrMalYAZGtb8inWGhDj3wUqQnPkmBKBVGIWG5Y6XJmMvpXW6rIKsdzxs8NwWj30cRNfjanLxiWc0aIgl8Knwo0JcxlcYLo38T9ntsrRkQZMQEWHaMYnzjp7ysLbp6yW83OZb/NwEufERBdPnIbDbVE7DUd5MGhvO+tlr2YC1b4VCsrDmjryuTD5nvYYCGHyfXW2CM23hZdBm9tPc+mU18Z9d4XkasnfsecGWd2ISkpPmnk3DtapnD64Nw8JyLtkgw==", 11 "amount" : 1000, 12 "out_trade_no" : "order_20200701_123456", 13 "fapiao_bill_type" : "COMM_FAPIAO", 14 "user_apply_message" : "用户留言" 15} 16
错误码
公共错误码
状态码 | 错误码 | 描述 | 解决方案 |
---|---|---|---|
400 | PARAM_ERROR | 参数错误 | 请根据错误提示正确传入参数 |
400 | INVALID_REQUEST | HTTP 请求不符合微信支付 APIv3 接口规则 | 请参阅 接口规则 |
401 | SIGN_ERROR | 验证不通过 | 请参阅 签名常见问题 |
500 | SYSTEM_ERROR | 系统异常,请稍后重试 | 请稍后重试 |
业务错误码
状态码 | 错误码 | 描述 | 解决方案 |
---|---|---|---|
400 | INVALID_REQUEST | 请求参数符合参数格式,但不符合业务规则 | 请使用正确的参数重新调用 |
403 | NO_AUTH | 商户无权限 | 请检查是否已经开通电子发票产品相关功能权限,并检查子商户是否接受了服务商的邀请 |
404 | RESOURCE_NOT_EXISTS | 用户尚未完成发票抬头的填写 | 请在接收到微信支付侧的【用户已申请开票】通知后重新调用,或者等待一段时间后重新调用 |
429 | FREQUENCY_LIMITED | 频率超限 | 请降低请求接口频率 |