获取邀请开通的商户信息
更新时间:2025.09.03通过时间范围,邀请的code等参数查询服务商邀请的商户信息,支持分页查询。
接口说明
支持商户:【普通服务商】
请求方式:【GET】/v3/new-tax-control-fapiao/fapiaomerchant/listspinvitemchinfo
请求域名:【主域名】https://api.mch.weixin.qq.com 使用该域名将访问就近的接入点
【备域名】https://api2.mch.weixin.qq.com 使用该域名将访问异地的接入点 ,指引点击查看
请求参数
Header HTTP头参数
Authorization 必填 string
请参考签名认证生成认证信息
Accept 必填 string
请设置为application/json
query 查询参数
query_time_start 必填 string
【查询时间起】 查询邀请商户的起始时间,遵循RFC3339标准格式:yyyy-MM-DDTHH:mm:ss+TIMEZONE
query_time_end 必填 string
【查询时间止】 查询商户邀请的结束时间,与query_time_start的间隔时间不能大于7天。遵循RFC3339标准格式:yyyy-MM-DDTHH:mm:ss+TIMEZONE
offset 必填 integer
【本次查询的起始位置】 当前查询的分页页数。从0开始计数,如offset=10,表示从第11条记录开始返回
limit 必填 integer
【本次查询的最大数量】 每页所查询的商户信息数量
invite_code 选填 string
【服务商邀请code】 邀请链接唯一标识
mch_invite_status 必填 string
【商户邀请状态】 商户邀请状态
可选取值
MCH_INVITE_SUCC
: 商户已接受邀请,通过【检查子商户开票功能状态】接口查询具体状态MCH_INVITE_FAILED
: 商户邀请开通失败,具体失败原因查看invite_failed_reason字段
请求示例
GET
1curl -X GET \ 2 https://api.mch.weixin.qq.com/v3/new-tax-control-fapiao/fapiaomerchant/listspinvitemchinfo?query_time_start=2020-07-01T12:00:00+08:00&query_time_end=2020-07-02T12:00:00+08:00&offset=10&limit=1&invite_code=code_20200101_123&mch_invite_status=MCH_INVITE_SUCC \ 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 ListSpInviteMchInfo { 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/fapiaomerchant/listspinvitemchinfo"; 29 30 public static void main(String[] args) { 31 // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340 32 ListSpInviteMchInfo client = new ListSpInviteMchInfo( 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 ListSpInviteMchInfoRequest request = new ListSpInviteMchInfoRequest(); 41 request.queryTimeStart = "2020-07-01T12:00:00+08:00"; 42 request.queryTimeEnd = "2020-07-02T12:00:00+08:00"; 43 request.offset = 10L; 44 request.limit = 1L; 45 request.inviteCode = "code_20200101_123"; 46 request.mchInviteStatus = MchInviteStatus.MCH_INVITE_SUCC; 47 try { 48 ListSpInviteMchInfoResp response = client.run(request); 49 // TODO: 请求成功,继续业务逻辑 50 System.out.println(response); 51 } catch (WXPayUtility.ApiException e) { 52 // TODO: 请求失败,根据状态码执行不同的逻辑 53 e.printStackTrace(); 54 } 55 } 56 57 public ListSpInviteMchInfoResp run(ListSpInviteMchInfoRequest request) { 58 String uri = PATH; 59 Map<String, Object> args = new HashMap<>(); 60 args.put("query_time_start", request.queryTimeStart); 61 args.put("query_time_end", request.queryTimeEnd); 62 args.put("offset", request.offset); 63 args.put("limit", request.limit); 64 args.put("invite_code", request.inviteCode); 65 args.put("mch_invite_status", request.mchInviteStatus); 66 String queryString = WXPayUtility.urlEncode(args); 67 if (!queryString.isEmpty()) { 68 uri = uri + "?" + queryString; 69 } 70 71 Request.Builder reqBuilder = new Request.Builder().url(HOST + uri); 72 reqBuilder.addHeader("Accept", "application/json"); 73 reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId); 74 reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo, privateKey, METHOD, uri, null)); 75 reqBuilder.method(METHOD, null); 76 Request httpRequest = reqBuilder.build(); 77 78 // 发送HTTP请求 79 OkHttpClient client = new OkHttpClient.Builder().build(); 80 try (Response httpResponse = client.newCall(httpRequest).execute()) { 81 String respBody = WXPayUtility.extractBody(httpResponse); 82 if (httpResponse.code() >= 200 && httpResponse.code() < 300) { 83 // 2XX 成功,验证应答签名 84 WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey, 85 httpResponse.headers(), respBody); 86 87 // 从HTTP应答报文构建返回数据 88 return WXPayUtility.fromJson(respBody, ListSpInviteMchInfoResp.class); 89 } else { 90 throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers()); 91 } 92 } catch (IOException e) { 93 throw new UncheckedIOException("Sending request to " + uri + " failed.", e); 94 } 95 } 96 97 private final String mchid; 98 private final String certificateSerialNo; 99 private final PrivateKey privateKey; 100 private final String wechatPayPublicKeyId; 101 private final PublicKey wechatPayPublicKey; 102 103 public ListSpInviteMchInfo(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) { 104 this.mchid = mchid; 105 this.certificateSerialNo = certificateSerialNo; 106 this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath); 107 this.wechatPayPublicKeyId = wechatPayPublicKeyId; 108 this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath); 109 } 110 111 public static class ListSpInviteMchInfoRequest { 112 @SerializedName("query_time_start") 113 @Expose(serialize = false) 114 public String queryTimeStart; 115 116 @SerializedName("query_time_end") 117 @Expose(serialize = false) 118 public String queryTimeEnd; 119 120 @SerializedName("offset") 121 @Expose(serialize = false) 122 public Long offset; 123 124 @SerializedName("limit") 125 @Expose(serialize = false) 126 public Long limit; 127 128 @SerializedName("invite_code") 129 @Expose(serialize = false) 130 public String inviteCode; 131 132 @SerializedName("mch_invite_status") 133 @Expose(serialize = false) 134 public MchInviteStatus mchInviteStatus; 135 } 136 137 public static class ListSpInviteMchInfoResp { 138 @SerializedName("total_count") 139 public Long totalCount; 140 141 @SerializedName("offset") 142 public Long offset; 143 144 @SerializedName("limit") 145 public Long limit; 146 147 @SerializedName("links") 148 public GetResponseLinks links; 149 150 @SerializedName("mch_invite_result_list") 151 public List<MchInviteResultInfo> mchInviteResultList; 152 } 153 154 public enum MchInviteStatus { 155 @SerializedName("MCH_INVITE_SUCC") 156 MCH_INVITE_SUCC, 157 @SerializedName("MCH_INVITE_FAILED") 158 MCH_INVITE_FAILED 159 } 160 161 public static class GetResponseLinks { 162 @SerializedName("next") 163 public String next; 164 165 @SerializedName("prev") 166 public String prev; 167 168 @SerializedName("self") 169 public String self; 170 } 171 172 public static class MchInviteResultInfo { 173 @SerializedName("sub_mchid") 174 public String subMchid; 175 176 @SerializedName("mch_invite_status") 177 public MchInviteStatus mchInviteStatus; 178 179 @SerializedName("ep_name") 180 public String epName; 181 182 @SerializedName("tax_id") 183 public String taxId; 184 185 @SerializedName("invite_code") 186 public String inviteCode; 187 188 @SerializedName("operate_time") 189 public String operateTime; 190 191 @SerializedName("invite_failed_code") 192 public DigitalTaxInviteFailedReason inviteFailedCode; 193 194 @SerializedName("invite_failed_reason") 195 public String inviteFailedReason; 196 } 197 198 public enum DigitalTaxInviteFailedReason { 199 @SerializedName("UNKNOWN_TAX_INFO") 200 UNKNOWN_TAX_INFO, 201 @SerializedName("INVALID_COMPANY_INFO") 202 INVALID_COMPANY_INFO, 203 @SerializedName("NOT_MEET_ACCESS_CONDITION") 204 NOT_MEET_ACCESS_CONDITION, 205 @SerializedName("NOT_IN_PILOT_SCOPE") 206 NOT_IN_PILOT_SCOPE, 207 @SerializedName("MISSING_TAX_AUTHORITY_CODE") 208 MISSING_TAX_AUTHORITY_CODE, 209 @SerializedName("MERCHANT_INFO_NOT_SET") 210 MERCHANT_INFO_NOT_SET, 211 @SerializedName("UNKNOWN_ERROR") 212 UNKNOWN_ERROR 213 } 214 215} 216
需配合微信支付工具库 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 := &ListSpInviteMchInfoRequest{ 26 QueryTimeStart: wxpay_utility.String("2020-07-01T12:00:00+08:00"), 27 QueryTimeEnd: wxpay_utility.String("2020-07-02T12:00:00+08:00"), 28 Offset: wxpay_utility.Int64(10), 29 Limit: wxpay_utility.Int64(1), 30 InviteCode: wxpay_utility.String("code_20200101_123"), 31 MchInviteStatus: MCHINVITESTATUS_MCH_INVITE_SUCC.Ptr(), 32 } 33 34 response, err := ListSpInviteMchInfo(config, request) 35 if err != nil { 36 fmt.Printf("请求失败: %+v\n", err) 37 // TODO: 请求失败,根据状态码执行不同的处理 38 return 39 } 40 41 // TODO: 请求成功,继续业务逻辑 42 fmt.Printf("请求成功: %+v\n", response) 43} 44 45func ListSpInviteMchInfo(config *wxpay_utility.MchConfig, request *ListSpInviteMchInfoRequest) (response *ListSpInviteMchInfoResp, err error) { 46 const ( 47 host = "https://api.mch.weixin.qq.com" 48 method = "GET" 49 path = "/v3/new-tax-control-fapiao/fapiaomerchant/listspinvitemchinfo" 50 ) 51 52 reqUrl, err := url.Parse(fmt.Sprintf("%s%s", host, path)) 53 if err != nil { 54 return nil, err 55 } 56 query := reqUrl.Query() 57 if request.QueryTimeStart != nil { 58 query.Add("query_time_start", *request.QueryTimeStart) 59 } 60 if request.QueryTimeEnd != nil { 61 query.Add("query_time_end", *request.QueryTimeEnd) 62 } 63 if request.Offset != nil { 64 query.Add("offset", fmt.Sprintf("%v", *request.Offset)) 65 } 66 if request.Limit != nil { 67 query.Add("limit", fmt.Sprintf("%v", *request.Limit)) 68 } 69 if request.InviteCode != nil { 70 query.Add("invite_code", *request.InviteCode) 71 } 72 if request.MchInviteStatus != nil { 73 query.Add("mch_invite_status", fmt.Sprintf("%v", *request.MchInviteStatus)) 74 } 75 reqUrl.RawQuery = query.Encode() 76 httpRequest, err := http.NewRequest(method, reqUrl.String(), nil) 77 if err != nil { 78 return nil, err 79 } 80 httpRequest.Header.Set("Accept", "application/json") 81 httpRequest.Header.Set("Wechatpay-Serial", config.WechatPayPublicKeyId()) 82 authorization, err := wxpay_utility.BuildAuthorization(config.MchId(), config.CertificateSerialNo(), config.PrivateKey(), method, reqUrl.RequestURI(), nil) 83 if err != nil { 84 return nil, err 85 } 86 httpRequest.Header.Set("Authorization", authorization) 87 88 client := &http.Client{} 89 httpResponse, err := client.Do(httpRequest) 90 if err != nil { 91 return nil, err 92 } 93 respBody, err := wxpay_utility.ExtractResponseBody(httpResponse) 94 if err != nil { 95 return nil, err 96 } 97 if httpResponse.StatusCode >= 200 && httpResponse.StatusCode < 300 { 98 // 2XX 成功,验证应答签名 99 err = wxpay_utility.ValidateResponse( 100 config.WechatPayPublicKeyId(), 101 config.WechatPayPublicKey(), 102 &httpResponse.Header, 103 respBody, 104 ) 105 if err != nil { 106 return nil, err 107 } 108 response := &ListSpInviteMchInfoResp{} 109 if err := json.Unmarshal(respBody, response); err != nil { 110 return nil, err 111 } 112 113 return response, nil 114 } else { 115 return nil, wxpay_utility.NewApiException( 116 httpResponse.StatusCode, 117 httpResponse.Header, 118 respBody, 119 ) 120 } 121} 122 123type ListSpInviteMchInfoRequest struct { 124 QueryTimeStart *string `json:"query_time_start,omitempty"` 125 QueryTimeEnd *string `json:"query_time_end,omitempty"` 126 Offset *int64 `json:"offset,omitempty"` 127 Limit *int64 `json:"limit,omitempty"` 128 InviteCode *string `json:"invite_code,omitempty"` 129 MchInviteStatus *MchInviteStatus `json:"mch_invite_status,omitempty"` 130} 131 132func (o *ListSpInviteMchInfoRequest) MarshalJSON() ([]byte, error) { 133 type Alias ListSpInviteMchInfoRequest 134 a := &struct { 135 QueryTimeStart *string `json:"query_time_start,omitempty"` 136 QueryTimeEnd *string `json:"query_time_end,omitempty"` 137 Offset *int64 `json:"offset,omitempty"` 138 Limit *int64 `json:"limit,omitempty"` 139 InviteCode *string `json:"invite_code,omitempty"` 140 MchInviteStatus *MchInviteStatus `json:"mch_invite_status,omitempty"` 141 *Alias 142 }{ 143 // 序列化时移除非 Body 字段 144 QueryTimeStart: nil, 145 QueryTimeEnd: nil, 146 Offset: nil, 147 Limit: nil, 148 InviteCode: nil, 149 MchInviteStatus: nil, 150 Alias: (*Alias)(o), 151 } 152 return json.Marshal(a) 153} 154 155type ListSpInviteMchInfoResp struct { 156 TotalCount *int64 `json:"total_count,omitempty"` 157 Offset *int64 `json:"offset,omitempty"` 158 Limit *int64 `json:"limit,omitempty"` 159 Links *GetResponseLinks `json:"links,omitempty"` 160 MchInviteResultList []MchInviteResultInfo `json:"mch_invite_result_list,omitempty"` 161} 162 163type MchInviteStatus string 164 165func (e MchInviteStatus) Ptr() *MchInviteStatus { 166 return &e 167} 168 169const ( 170 MCHINVITESTATUS_MCH_INVITE_SUCC MchInviteStatus = "MCH_INVITE_SUCC" 171 MCHINVITESTATUS_MCH_INVITE_FAILED MchInviteStatus = "MCH_INVITE_FAILED" 172) 173 174type GetResponseLinks struct { 175 Next *string `json:"next,omitempty"` 176 Prev *string `json:"prev,omitempty"` 177 Self *string `json:"self,omitempty"` 178} 179 180type MchInviteResultInfo struct { 181 SubMchid *string `json:"sub_mchid,omitempty"` 182 MchInviteStatus *MchInviteStatus `json:"mch_invite_status,omitempty"` 183 EpName *string `json:"ep_name,omitempty"` 184 TaxId *string `json:"tax_id,omitempty"` 185 InviteCode *string `json:"invite_code,omitempty"` 186 OperateTime *string `json:"operate_time,omitempty"` 187 InviteFailedCode *DigitalTaxInviteFailedReason `json:"invite_failed_code,omitempty"` 188 InviteFailedReason *string `json:"invite_failed_reason,omitempty"` 189} 190 191type DigitalTaxInviteFailedReason string 192 193func (e DigitalTaxInviteFailedReason) Ptr() *DigitalTaxInviteFailedReason { 194 return &e 195} 196 197const ( 198 DIGITALTAXINVITEFAILEDREASON_UNKNOWN_TAX_INFO DigitalTaxInviteFailedReason = "UNKNOWN_TAX_INFO" 199 DIGITALTAXINVITEFAILEDREASON_INVALID_COMPANY_INFO DigitalTaxInviteFailedReason = "INVALID_COMPANY_INFO" 200 DIGITALTAXINVITEFAILEDREASON_NOT_MEET_ACCESS_CONDITION DigitalTaxInviteFailedReason = "NOT_MEET_ACCESS_CONDITION" 201 DIGITALTAXINVITEFAILEDREASON_NOT_IN_PILOT_SCOPE DigitalTaxInviteFailedReason = "NOT_IN_PILOT_SCOPE" 202 DIGITALTAXINVITEFAILEDREASON_MISSING_TAX_AUTHORITY_CODE DigitalTaxInviteFailedReason = "MISSING_TAX_AUTHORITY_CODE" 203 DIGITALTAXINVITEFAILEDREASON_MERCHANT_INFO_NOT_SET DigitalTaxInviteFailedReason = "MERCHANT_INFO_NOT_SET" 204 DIGITALTAXINVITEFAILEDREASON_UNKNOWN_ERROR DigitalTaxInviteFailedReason = "UNKNOWN_ERROR" 205) 206
应答参数
200 OK
total_count 必填 integer
【总数】 满足查询条件的所有邀请商户总数
offset 必填 integer
【本次查询的起始位置】 本次查询的起始位置。从0开始计数,如offset=10,表示从第11条记录开始返回
limit 必填 integer
【本次查询的最大数量】 每页所查询的商户信息数量
links 选填 object
【相关链接】 相关链接
属性 | |
next 选填 string(1024) 【下一页链接】 使用同样的limit进行下一页查询时的请求链接。当前为最后一页时,返回为空 prev 选填 string(1024) 【上一页链接】 使用同样的limit进行上一页查询时的请求链接。如果为第一页时,返回为空 self 选填 string(1024) 【当前链接】 当前的请求链接 |
mch_invite_result_list 选填 array[object]
【邀请的商户结果】 服务商邀请的商户结果列表
属性 | |
sub_mchid 选填 string 【邀请的商户商户号】 服务商邀请的商户号,当邀请状态为MCH_INVITE_SUCC返回 mch_invite_status 必填 string 【邀请商户的状态】 邀请商户的具体状态 可选取值
ep_name 必填 string(1024) 【商户名称】 商户名称 tax_id 必填 string(32) 【商户税号】 商户税号 invite_code 必填 string 【服务商邀请商户code】 邀请链接唯一标识 operate_time 必填 string 【商户操作时间】 如果邀请状态为MCH_INVITE_SUCC,则是商户确认授权的时间;如果邀请状态为MCH_INVITE_FAILED,则是商户邀请失败的时间。遵循RFC3339标准格式:yyyy-MM-DDTHH:mm:ss+TIMEZONE invite_failed_code 选填 string 【商户邀请失败错误码】 邀请失败时返回 可选取值
invite_failed_reason 选填 string(1024) 【商户邀请失败的原因】 邀请失败时返回,描述商户邀请失败的具体原因 |
应答示例
200 OK
1{ 2 "total_count" : 50, 3 "offset" : 10, 4 "limit" : 1, 5 "links" : { 6 "next" : "/v3/new-tax-control-fapiao/xxx?offset=2&limit=5", 7 "prev" : "/v3/new-tax-control-fapiao/xxx?offset=0&limit=5", 8 "self" : "/v3/new-tax-control-fapiao/xxx?offset=1&limit=5" 9 }, 10 "mch_invite_result_list" : [ 11 { 12 "sub_mchid" : "1999192837", 13 "mch_invite_status" : "MCH_INVITE_SUCC", 14 "ep_name" : "示例(深圳)有限公司", 15 "tax_id" : "9144050071126766XG", 16 "invite_code" : "code_20200101_123", 17 "operate_time" : "2020-07-01T00:00:00", 18 "invite_failed_code" : "UNKNOWN_TAX_INFO", 19 "invite_failed_reason" : "示例失败原因" 20 } 21 ] 22} 23
错误码
公共错误码
状态码 | 错误码 | 描述 | 解决方案 |
---|---|---|---|
400 | PARAM_ERROR | 参数错误 | 请根据错误提示正确传入参数 |
400 | INVALID_REQUEST | HTTP 请求不符合微信支付 APIv3 接口规则 | 请参阅 接口规则 |
401 | SIGN_ERROR | 验证不通过 | 请参阅 签名常见问题 |
500 | SYSTEM_ERROR | 系统异常,请稍后重试 | 请稍后重试 |
业务错误码
状态码 | 错误码 | 描述 | 解决方案 |
---|---|---|---|
400 | INVALID_REQUEST | 请求参数符合参数格式,但不符合业务规则 | 请使用正确的参数重新调用 |
403 | NO_AUTH | 商户无权限 | 请检查是否已经开通电子发票产品相关功能权限,并检查子商户是否接受了服务商的邀请 |
429 | FREQUENCY_LIMITED | 频率超限 | 请降低请求接口频率 |