查询合作关系列表
更新时间:2024.11.18为商户提供合作关系列表的查询能力。
接口说明
支持商户:【普通服务商】 【渠道商】
请求方式:【GET】/v3/marketing/partnerships
请求域名:【主域名】https://api.mch.weixin.qq.com 使用该域名将访问就近的接入点
【备域名】https://api2.mch.weixin.qq.com 使用该域名将访问异地的接入点 ,指引点击查看
请求参数
Header HTTP头参数
Authorization 必填 string
请参考签名认证生成认证信息
Accept 必填 string
请设置为application/json
query 查询参数
limit 选填 integer
【分页大小】分页大小,最大50。 不传默认为20
offset 选填 integer
【分页页码】分页页码,页码从0开始
partner 选填 object
【合作方信息】合作方信息
属性 | |
type 必填 string 【合作方类别】合作方类别,枚举值见文档 可选取值:
appid 选填 string(32) 【合作方Appid】合作方Appid,合作方类别为APPID时必填 merchant_id 选填 string(15) 【合作方商户ID】合作方商户ID,合作方类别为MERCHANT时必填 |
authorized_data 必填 object
【被授权数据】被授权数据
属性 | |
business_type 必填 string 【授权业务类别】授权业务类别,枚举值见文档 可选取值:
stock_id 选填 string(20) 【授权批次ID】授权批次ID,授权业务类别为券批次时必填 |
请求示例
GET
1curl -X GET \ 2 https://api.mch.weixin.qq.com/v3/marketing/partnerships?limit=5&offset=10&authorized_data=%7B%22business_type%22%3A%22FAVOR_STOCK%22%2C%22stock_id%22%3A%222433405%22%7D&partner=%7B%22type%22%3A%22APPID%22%2C%22appid%22%3A%22wx4e1916a585d1f4e9%22%2C%22merchant_id%22%3A%222480029552%22%7D \ 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 ListPartnerships { 26 private static String HOST = "https://api.mch.weixin.qq.com"; 27 private static String METHOD = "GET"; 28 private static String PATH = "/v3/marketing/partnerships"; 29 30 public static void main(String[] args) { 31 // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340 32 ListPartnerships client = new ListPartnerships( 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 ListPartnershipsRequest request = new ListPartnershipsRequest(); 41 request.limit = 1L; 42 request.offset = 1L; 43 request.partner = new PartnerInfo(); 44request.partner.type = PartnerType.APPID; 45request.partner.appid = "wx4e1916a585d1f4e9"; 46request.partner.merchantId = "2480029552"; 47 request.authorizedData = new AuthorizedDataFilter(); 48request.authorizedData.businessType = AuthBusinessType.FAVOR_STOCK; 49request.authorizedData.stockId = "2433405"; 50 try { 51 ListPartnershipsResponse response = client.run(request); 52 // TODO: 请求成功,继续业务逻辑 53 System.out.println(response); 54 } catch (WXPayUtility.ApiException e) { 55 // TODO: 请求失败,根据状态码执行不同的逻辑 56 e.printStackTrace(); 57 } 58 } 59 60 public ListPartnershipsResponse run(ListPartnershipsRequest request) { 61 String uri = PATH; 62 Map<String, Object> args = new HashMap<>(); 63 args.put("limit", request.limit); 64 args.put("offset", request.offset); 65 args.put("partner", request.partner); 66 args.put("authorized_data", request.authorizedData); 67 String queryString = WXPayUtility.urlEncode(args); 68 if (!queryString.isEmpty()) { 69 uri = uri + "?" + queryString; 70 } 71 72 Request.Builder reqBuilder = new Request.Builder().url(HOST + uri); 73 reqBuilder.addHeader("Accept", "application/json"); 74 reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId); 75 reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo, privateKey, METHOD, uri, null)); 76 reqBuilder.method(METHOD, null); 77 Request httpRequest = reqBuilder.build(); 78 79 // 发送HTTP请求 80 OkHttpClient client = new OkHttpClient.Builder().build(); 81 try (Response httpResponse = client.newCall(httpRequest).execute()) { 82 String respBody = WXPayUtility.extractBody(httpResponse); 83 if (httpResponse.code() >= 200 && httpResponse.code() < 300) { 84 // 2XX 成功,验证应答签名 85 WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey, 86 httpResponse.headers(), respBody); 87 88 // 从HTTP应答报文构建返回数据 89 return WXPayUtility.fromJson(respBody, ListPartnershipsResponse.class); 90 } else { 91 throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers()); 92 } 93 } catch (IOException e) { 94 throw new UncheckedIOException("Sending request to " + uri + " failed.", e); 95 } 96 } 97 98 private final String mchid; 99 private final String certificateSerialNo; 100 private final PrivateKey privateKey; 101 private final String wechatPayPublicKeyId; 102 private final PublicKey wechatPayPublicKey; 103 104 public ListPartnerships(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) { 105 this.mchid = mchid; 106 this.certificateSerialNo = certificateSerialNo; 107 this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath); 108 this.wechatPayPublicKeyId = wechatPayPublicKeyId; 109 this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath); 110 } 111 112 public static class ListPartnershipsRequest { 113 @SerializedName("limit") 114 @Expose(serialize = false) 115 public Long limit; 116 117 @SerializedName("offset") 118 @Expose(serialize = false) 119 public Long offset; 120 121 @SerializedName("partner") 122 @Expose(serialize = false) 123 public PartnerInfo partner; 124 125 @SerializedName("authorized_data") 126 @Expose(serialize = false) 127 public AuthorizedDataFilter authorizedData; 128 } 129 130 public static class ListPartnershipsResponse { 131 @SerializedName("data") 132 public List<PartnershipsEntity> data; 133 134 @SerializedName("offset") 135 public Long offset; 136 137 @SerializedName("limit") 138 public Long limit; 139 140 @SerializedName("total_count") 141 public Long totalCount; 142 } 143 144 public static class PartnerInfo { 145 @SerializedName("type") 146 public PartnerType type; 147 148 @SerializedName("appid") 149 public String appid; 150 151 @SerializedName("merchant_id") 152 public String merchantId; 153 } 154 155 public static class AuthorizedDataFilter { 156 @SerializedName("business_type") 157 public AuthBusinessType businessType; 158 159 @SerializedName("stock_id") 160 public String stockId; 161 } 162 163 public static class PartnershipsEntity { 164 @SerializedName("partner") 165 public PartnerInfo partner; 166 167 @SerializedName("authorized_data") 168 public AuthorizedData authorizedData; 169 170 @SerializedName("build_time") 171 public String buildTime; 172 173 @SerializedName("terminate_time") 174 public String terminateTime; 175 176 @SerializedName("create_time") 177 public String createTime; 178 179 @SerializedName("update_time") 180 public String updateTime; 181 } 182 183 public enum PartnerType { 184 @SerializedName("APPID") 185 APPID, 186 @SerializedName("MERCHANT") 187 MERCHANT 188 } 189 190 public enum AuthBusinessType { 191 @SerializedName("FAVOR_STOCK") 192 FAVOR_STOCK, 193 @SerializedName("BUSIFAVOR_STOCK") 194 BUSIFAVOR_STOCK 195 } 196 197 public static class AuthorizedData { 198 @SerializedName("business_type") 199 public AuthBusinessType businessType; 200 201 @SerializedName("stock_id") 202 public String stockId; 203 } 204 205} 206
需配合微信支付工具库 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 := &ListPartnershipsRequest{ 26 Limit: wxpay_utility.Int64(5), 27 Offset: wxpay_utility.Int64(10), 28 AuthorizedData: &AuthorizedDataFilter{ 29 BusinessType: AUTHBUSINESSTYPE_FAVOR_STOCK.Ptr(), 30 StockId: wxpay_utility.String("2433405"), 31 }, 32 Partner: &PartnerInfo{ 33 Type: PARTNERTYPE_APPID.Ptr(), 34 Appid: wxpay_utility.String("wx4e1916a585d1f4e9"), 35 MerchantId: wxpay_utility.String("2480029552"), 36 }, 37 } 38 39 response, err := ListPartnerships(config, request) 40 if err != nil { 41 fmt.Printf("请求失败: %+v\n", err) 42 // TODO: 请求失败,根据状态码执行不同的处理 43 return 44 } 45 46 // TODO: 请求成功,继续业务逻辑 47 fmt.Printf("请求成功: %+v\n", response) 48} 49 50func ListPartnerships(config *wxpay_utility.MchConfig, request *ListPartnershipsRequest) (response *ListPartnershipsResponse, err error) { 51 const ( 52 host = "https://api.mch.weixin.qq.com" 53 method = "GET" 54 path = "/v3/marketing/partnerships" 55 ) 56 57 reqUrl, err := url.Parse(fmt.Sprintf("%s%s", host, path)) 58 if err != nil { 59 return nil, err 60 } 61 query := reqUrl.Query() 62 if request.Limit != nil { 63 query.Add("limit", fmt.Sprintf("%v", *request.Limit)) 64 } 65 if request.Offset != nil { 66 query.Add("offset", fmt.Sprintf("%v", *request.Offset)) 67 } 68 if request.Partner != nil { 69 jsonStr, err := json.Marshal(*request.Partner) 70 if err != nil { 71 return nil, fmt.Errorf("failed to marshal partner: %v", err) 72 } 73 query.Add("partner", string(jsonStr)) 74 } 75 if request.AuthorizedData != nil { 76 jsonStr, err := json.Marshal(*request.AuthorizedData) 77 if err != nil { 78 return nil, fmt.Errorf("failed to marshal authorized_data: %v", err) 79 } 80 query.Add("authorized_data", string(jsonStr)) 81 } 82 reqUrl.RawQuery = query.Encode() 83 httpRequest, err := http.NewRequest(method, reqUrl.String(), nil) 84 if err != nil { 85 return nil, err 86 } 87 httpRequest.Header.Set("Accept", "application/json") 88 httpRequest.Header.Set("Wechatpay-Serial", config.WechatPayPublicKeyId()) 89 authorization, err := wxpay_utility.BuildAuthorization(config.MchId(), config.CertificateSerialNo(), config.PrivateKey(), method, reqUrl.RequestURI(), nil) 90 if err != nil { 91 return nil, err 92 } 93 httpRequest.Header.Set("Authorization", authorization) 94 95 client := &http.Client{} 96 httpResponse, err := client.Do(httpRequest) 97 if err != nil { 98 return nil, err 99 } 100 respBody, err := wxpay_utility.ExtractResponseBody(httpResponse) 101 if err != nil { 102 return nil, err 103 } 104 if httpResponse.StatusCode >= 200 && httpResponse.StatusCode < 300 { 105 // 2XX 成功,验证应答签名 106 err = wxpay_utility.ValidateResponse( 107 config.WechatPayPublicKeyId(), 108 config.WechatPayPublicKey(), 109 &httpResponse.Header, 110 respBody, 111 ) 112 if err != nil { 113 return nil, err 114 } 115 response := &ListPartnershipsResponse{} 116 if err := json.Unmarshal(respBody, response); err != nil { 117 return nil, err 118 } 119 120 return response, nil 121 } else { 122 return nil, wxpay_utility.NewApiException( 123 httpResponse.StatusCode, 124 httpResponse.Header, 125 respBody, 126 ) 127 } 128} 129 130type ListPartnershipsRequest struct { 131 Limit *int64 `json:"limit,omitempty"` 132 Offset *int64 `json:"offset,omitempty"` 133 Partner *PartnerInfo `json:"partner,omitempty"` 134 AuthorizedData *AuthorizedDataFilter `json:"authorized_data,omitempty"` 135} 136 137func (o *ListPartnershipsRequest) MarshalJSON() ([]byte, error) { 138 type Alias ListPartnershipsRequest 139 a := &struct { 140 Limit *int64 `json:"limit,omitempty"` 141 Offset *int64 `json:"offset,omitempty"` 142 Partner *PartnerInfo `json:"partner,omitempty"` 143 AuthorizedData *AuthorizedDataFilter `json:"authorized_data,omitempty"` 144 *Alias 145 }{ 146 // 序列化时移除非 Body 字段 147 Limit: nil, 148 Offset: nil, 149 Partner: nil, 150 AuthorizedData: nil, 151 Alias: (*Alias)(o), 152 } 153 return json.Marshal(a) 154} 155 156type ListPartnershipsResponse struct { 157 Data []PartnershipsEntity `json:"data,omitempty"` 158 Offset *int64 `json:"offset,omitempty"` 159 Limit *int64 `json:"limit,omitempty"` 160 TotalCount *int64 `json:"total_count,omitempty"` 161} 162 163type PartnerInfo struct { 164 Type *PartnerType `json:"type,omitempty"` 165 Appid *string `json:"appid,omitempty"` 166 MerchantId *string `json:"merchant_id,omitempty"` 167} 168 169type AuthorizedDataFilter struct { 170 BusinessType *AuthBusinessType `json:"business_type,omitempty"` 171 StockId *string `json:"stock_id,omitempty"` 172} 173 174type PartnershipsEntity struct { 175 Partner *PartnerInfo `json:"partner,omitempty"` 176 AuthorizedData *AuthorizedData `json:"authorized_data,omitempty"` 177 BuildTime *string `json:"build_time,omitempty"` 178 TerminateTime *string `json:"terminate_time,omitempty"` 179 CreateTime *string `json:"create_time,omitempty"` 180 UpdateTime *string `json:"update_time,omitempty"` 181} 182 183type PartnerType string 184 185func (e PartnerType) Ptr() *PartnerType { 186 return &e 187} 188 189const ( 190 PARTNERTYPE_APPID PartnerType = "APPID" 191 PARTNERTYPE_MERCHANT PartnerType = "MERCHANT" 192) 193 194type AuthBusinessType string 195 196func (e AuthBusinessType) Ptr() *AuthBusinessType { 197 return &e 198} 199 200const ( 201 AUTHBUSINESSTYPE_FAVOR_STOCK AuthBusinessType = "FAVOR_STOCK" 202 AUTHBUSINESSTYPE_BUSIFAVOR_STOCK AuthBusinessType = "BUSIFAVOR_STOCK" 203) 204 205type AuthorizedData struct { 206 BusinessType *AuthBusinessType `json:"business_type,omitempty"` 207 StockId *string `json:"stock_id,omitempty"` 208} 209
应答参数
|
data 选填 array[object]
【合作关系结果集】合作关系查询结果集。如查询结果为0,将在控制流返回错误
属性 | |||||||||
partner 必填 object 【合作方信息】合作方信息
authorized_data 必填 object 【被授权数据】被授权数据
build_time 必填 string(32) 【建立合作关系时间】建立合作关系时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示,北京时间2015年5月20日 13点29分35秒。 terminate_time 选填 string(32) 【终止合作关系时间】终止合作关系时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示,北京时间2015年5月20日 13点29分35秒。 create_time 必填 string(32) 【创建时间】创建时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示,北京时间2015年5月20日 13点29分35秒。 update_time 必填 string(32) 【更新时间】更新时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示,北京时间2015年5月20日 13点29分35秒。 |
offset 必填 integer
【分页页码】分页页码
limit 必填 integer
【分页大小】分页大小
total_count 选填 integer
【总数量】总数量,当offset=0或者当前查询为空时返回
应答示例
200 OK
1{ 2 "data" : [ 3 { 4 "partner" : { 5 "type" : "APPID", 6 "appid" : "wx4e1916a585d1f4e9", 7 "merchant_id" : "2480029552" 8 }, 9 "authorized_data" : { 10 "business_type" : "FAVOR_STOCK", 11 "stock_id" : "2433405" 12 }, 13 "build_time" : "2015-05-20T13:29:35.120+08:00", 14 "terminate_time" : "2015-05-20T13:29:35.120+08:00", 15 "create_time" : "2015-05-20T13:29:35.120+08:00", 16 "update_time" : "2015-05-20T13:29:35.120+08:00" 17 } 18 ], 19 "offset" : 10, 20 "limit" : 5, 21 "total_count" : 1234 22} 23
错误码
公共错误码
状态码 | 错误码 | 描述 | 解决方案 |
---|---|---|---|
400 | PARAM_ERROR | 参数错误 | 请根据错误提示正确传入参数 |
400 | INVALID_REQUEST | HTTP 请求不符合微信支付 APIv3 接口规则 | 请参阅 接口规则 |
401 | SIGN_ERROR | 验证不通过 | 请参阅 签名常见问题 |
500 | SYSTEM_ERROR | 系统异常,请稍后重试 | 请稍后重试 |
业务错误码
状态码 | 错误码 | 描述 | 解决方案 |
---|---|---|---|
400 | APPID_MCHID_NOT_MATCH | appid与mchid不匹配 | 请确认appid是否正确填写 |
400 | INVALID_REQUEST | 请求参数符合参数格式,但不符合业务规则 | 根据错误提示,传入符合业务规则的参数 |
400 | INVALID_REQUEST | 委托营销合作关系不存在 | 请确认合作方信息是否正确 |
400 | MCH_NOT_EXISTS | 商户号不存在 | 请确认发券商户号信息是否有误 |
403 | NO_AUTH | 商户未被授权 | 登录商户平台核对,传入正确信息 |
404 | RESOURCE_NOT_EXISTS | 资源不存在或无可用 | 请确认资源均存在且可用 |
429 | FREQUENCY_LIMITED | 频率超限 | 请求量不要超过接口调用频率限制 |