同步会员开通结果
更新时间:2025.06.22所有会员卡新开卡,我们回调给商家,商家还需要再同步给我们才算开卡成功(但是导入不用)
接口说明
支持商户:【普通服务商】
请求方式:【POST】/v3/brand/partner/card-member/user-cards/{user_card_code}/confirm
请求域名:【主域名】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说明以及微信支付公钥加密敏感信息指引;也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引
path 路径参数
user_card_code 必填 string(32)
【会员卡code】 会员在一个会员卡模版下的唯一标志,用户领取会员卡后获得的code
query 查询参数
card_id 必填 string(32)
【会员卡模板 ID】 商家创建微信会员卡模板成功后系统返回的会员卡模板ID
body 包体参数
brand_id 必填 string(32)
【品牌ID】 商家进驻微信支付品牌商家后获得的品牌ID(灰度期间联系微信支付运营获取),用于标记该会员卡的归属方
openid 必填 string(128)
【用户标识】 用户在品牌商家会员卡模板AppID下的唯一标识
card_color 选填 string(7)
【卡背景颜色】 用于卡片正面设计的RGB颜色编码,仅支持十六进制
card_picture_url 选填 string(256)
【卡图片】 商家自定义会员卡背景图。仅支持通过图片上传API接口获取的图片URL地址。支持JPG/JPEG/PNG格式,建议尺寸716px*320px,图片背景色需为透明,且图片小于1M。图片上传API指引
phone_number 选填 string(512)
【加密的手机号】 注册会员的手机号码。该字段需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引,也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引。
level 选填 string(10)
【等级】 用户会员等级,展示字段,商家可以自定义填写内容。
valid_date_information 选填 object
【会员卡有效期】 会员卡有效期
属性 | |
type 选填 string 【有效期类型】 1.该有效期为会员卡激活后的有效期 2.支持绝对有效期&相对有效期设置 3.绝对有效期:固定过期时间,需遵循 RFC3339 标准格式:yyyy-MM-DDTHH:mm:ss+TIMEZONE。yyyy-MM-DD 表示年月日;T 字符用于分隔日期和时间部分;HH:mm:ss 表示具体的时分秒;TIMEZONE 表示时区(例如,+08:00 对应东八区时间,即北京时间)。示例:2015-05-20T13:29:35+08:00 表示北京时间2015年5月20日13点29分35秒。 4.相对有效期:用户激活后x天后有效,x为天数。最多支持10,957天(30年) 5.永久有效 6.过期后卡状态变为“已过期” 7.过期后不再出现服务项,且无法给用户发送会员服务消息通知 可选取值
available_begin_time 选填 string(32) 【有效期开始时间】 type为FIX_TIME_RANGE时专用, 表示有效期开始时间。需需遵循 RFC3339 标准格式:yyyy-MM-DDTHH:mm:ss+TIMEZONE。yyyy-MM-DD 表示年月日;T 字符用于分隔日期和时间部分;HH:mm:ss 表示具体的时分秒;TIMEZONE 表示时区(例如,+08:00 对应东八区时间,即北京时间)。示例:2015-05-20T13:29:35+08:00 表示北京时间2015年5月20日13点29分35秒。 available_end_time 选填 string(32) 【有效期结束时间】 type为FIX_TERM_RANGE时专用,表示有效期结束时间。需需遵循 RFC3339 标准格式:yyyy-MM-DDTHH:mm:ss+TIMEZONE。yyyy-MM-DD 表示年月日;T 字符用于分隔日期和时间部分;HH:mm:ss 表示具体的时分秒;TIMEZONE 表示时区(例如,+08:00 对应东八区时间,即北京时间)。示例:2015-05-20T13:29:35+08:00 表示北京时间2015年5月20日13点29分35秒。 available_day_after_receive 选填 integer 【领取后N天内有效】 type为FIX_TERM时专用,表示领取后N个自然天内有效。最长不超过30年(10958 天) |
user_information 选填 object
【用户开卡时填写的个人信息】 用户开卡时填写的个人信息
属性 | |||||||||
common_field_list 选填 array[object] 【平台提供的通用开卡信息字段】 包含性别、手机、头像、昵称、姓名等基本信息字段
custom_field_list 选填 array[object] 【商家自定义的开卡信息字段】 商家自定义的开卡信息字段,当前最多只允许传入1项
|
attach 选填 string(256)
【商家数据包】 商家在创建用户会员卡时可传入自定义数据包,该数据对用户不可见,用于存储商家自定义信息,其总长度限制在256字符以内。查询用户会员卡详情时会将此字段返回给商家。
user_card_confirm_state 必填 string
【会员开卡状态】 商家需要同步会员开卡状态
可选取值
CREATE_CARD_SUCCESS
: 开卡成功CREATE_CARD_FAIL
: 开卡失败
请求示例
需配合微信支付工具库 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 ConfirmUserCard { 26 private static String HOST = "https://api.mch.weixin.qq.com"; 27 private static String METHOD = "POST"; 28 private static String PATH = "/v3/brand/partner/card-member/user-cards/{user_card_code}/confirm"; 29 30 public static void main(String[] args) { 31 // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340 32 ConfirmUserCard client = new ConfirmUserCard( 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 ConfirmUserCardRequest request = new ConfirmUserCardRequest(); 41 request.userCardCode = "478515832665"; 42 request.cardId = "pbLatjvWOibDc5-TBnbUk1pD12o0"; 43 request.brandId = "1004"; 44 request.openid = "obLatjnx9gnqzS4myYGmLZ7LgLBA"; 45 request.cardColor = "#FFFF00"; 46 request.cardPictureUrl = "https://wxpaylogo.qpic.cn/wxpaylogo/PiajxSqBRaEIPAeia7Imvtsn7sYGNcEj33YzVvJF88ECQ19LXId8ZL2Q/0"; 47 request.phoneNumber = client.encrypt("phone_number"); 48 request.level = "钻石会员"; 49 request.validDateInformation = new DateInfo(); 50 request.validDateInformation.type = DateType.PERMANENT; 51 request.validDateInformation.availableBeginTime = "2020-05-20T13:29:35.120+08:00"; 52 request.validDateInformation.availableEndTime = "2020-05-20T13:29:35.120+08:00"; 53 request.validDateInformation.availableDayAfterReceive = 30L; 54 request.userInformation = new UserInfo(); 55 request.userInformation.commonFieldList = new ArrayList<>(); 56 { 57 UserInfoCommonField commonFieldListItem = new UserInfoCommonField(); 58 commonFieldListItem.name = CommonFieldFlag.USER_FORM_FLAG_BIRTHDAY; 59 commonFieldListItem.value = client.encrypt("value"); 60 request.userInformation.commonFieldList.add(commonFieldListItem); 61 }; 62 request.userInformation.customFieldList = new ArrayList<>(); 63 { 64 UserInfoCustomField customFieldListItem = new UserInfoCustomField(); 65 customFieldListItem.name = "喜欢的运动"; 66 customFieldListItem.userChosenValues = new ArrayList<>(); 67 { 68 customFieldListItem.userChosenValues.add("vvysDQeEaH3I+wRh14St0abIkvQyFgh/fbWYSs2bLtG9tj+bdJn4WSCPzLhShNHgujZzseiL6sYmT7E65mv/eFeTa7yslYfrX0hrhHazSM/+tfvN/C3OZwiBbcrF9LTIIdBVhGOqhCx0gK5YAVZc8dbW/yJqC5i79PDfVYJtpQe3A4v/GiDa2Q+Mv03taxgnEkzqlSPjkXiCYBj9UaFJ4bqCTXiO2Kt6TpczvAaZW+9/blxiJwqEFXe78LbrIQvkDUmVdZbqBdPQ+QGQgc/2Ea4IbP/EEt1qSyXnFbzaaKSE2j4mAFON3kzNexb/SYkHZNJAuCittaW4wpGj7U+h9A=="); 69 }; 70 request.userInformation.customFieldList.add(customFieldListItem); 71 }; 72 request.attach = "自定义数据说明"; 73 request.userCardConfirmState = UserCardConfirmState.CREATE_CARD_SUCCESS; 74 try { 75 UserCard response = client.run(request); 76 77 // TODO: 请求成功,继续业务逻辑 78 System.out.println(response); 79 } catch (WXPayUtility.ApiException e) { 80 // TODO: 请求失败,根据状态码执行不同的逻辑 81 e.printStackTrace(); 82 } 83 } 84 85 public UserCard run(ConfirmUserCardRequest request) { 86 String uri = PATH; 87 uri = uri.replace("{user_card_code}", WXPayUtility.urlEncode(request.userCardCode)); 88 Map<String, Object> args = new HashMap<>(); 89 args.put("card_id", request.cardId); 90 uri = uri + "?" + WXPayUtility.urlEncode(args); 91 String reqBody = WXPayUtility.toJson(request); 92 93 Request.Builder reqBuilder = new Request.Builder().url(HOST + uri); 94 reqBuilder.addHeader("Accept", "application/json"); 95 reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId); 96 reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo,privateKey, METHOD, uri, reqBody)); 97 reqBuilder.addHeader("Content-Type", "application/json"); 98 RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody); 99 reqBuilder.method(METHOD, requestBody); 100 Request httpRequest = reqBuilder.build(); 101 102 // 发送HTTP请求 103 OkHttpClient client = new OkHttpClient.Builder().build(); 104 try (Response httpResponse = client.newCall(httpRequest).execute()) { 105 String respBody = WXPayUtility.extractBody(httpResponse); 106 if (httpResponse.code() >= 200 && httpResponse.code() < 300) { 107 // 2XX 成功,验证应答签名 108 WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey, 109 httpResponse.headers(), respBody); 110 111 // 从HTTP应答报文构建返回数据 112 return WXPayUtility.fromJson(respBody, UserCard.class); 113 } else { 114 throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers()); 115 } 116 } catch (IOException e) { 117 throw new UncheckedIOException("Sending request to " + uri + " failed.", e); 118 } 119 } 120 121 private final String mchid; 122 private final String certificateSerialNo; 123 private final PrivateKey privateKey; 124 private final String wechatPayPublicKeyId; 125 private final PublicKey wechatPayPublicKey; 126 127 public ConfirmUserCard(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) { 128 this.mchid = mchid; 129 this.certificateSerialNo = certificateSerialNo; 130 this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath); 131 this.wechatPayPublicKeyId = wechatPayPublicKeyId; 132 this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath); 133 } 134 135 public String encrypt(String plainText) { 136 return WXPayUtility.encrypt(this.wechatPayPublicKey, plainText); 137 } 138 139 public static class ConfirmUserCardRequest { 140 @SerializedName("brand_id") 141 public String brandId; 142 143 @SerializedName("user_card_code") 144 @Expose(serialize = false) 145 public String userCardCode; 146 147 @SerializedName("card_id") 148 @Expose(serialize = false) 149 public String cardId; 150 151 @SerializedName("openid") 152 public String openid; 153 154 @SerializedName("card_color") 155 public String cardColor; 156 157 @SerializedName("card_picture_url") 158 public String cardPictureUrl; 159 160 @SerializedName("phone_number") 161 public String phoneNumber; 162 163 @SerializedName("level") 164 public String level; 165 166 @SerializedName("valid_date_information") 167 public DateInfo validDateInformation; 168 169 @SerializedName("user_information") 170 public UserInfo userInformation; 171 172 @SerializedName("attach") 173 public String attach; 174 175 @SerializedName("user_card_confirm_state") 176 public UserCardConfirmState userCardConfirmState; 177 } 178 179 public static class UserCard { 180 @SerializedName("user_card_code") 181 public String userCardCode; 182 183 @SerializedName("card_id") 184 public String cardId; 185 186 @SerializedName("openid") 187 public String openid; 188 189 @SerializedName("card_color") 190 public String cardColor; 191 192 @SerializedName("card_picture_url") 193 public String cardPictureUrl; 194 195 @SerializedName("brand_id") 196 public String brandId; 197 198 @SerializedName("card_type") 199 public CardType cardType; 200 201 @SerializedName("phone_number") 202 public String phoneNumber; 203 204 @SerializedName("level") 205 public String level; 206 207 @SerializedName("valid_date_information") 208 public DateInfo validDateInformation; 209 210 @SerializedName("pickup_time") 211 public String pickupTime; 212 213 @SerializedName("user_information") 214 public UserInfo userInformation; 215 216 @SerializedName("attach") 217 public String attach; 218 219 @SerializedName("user_card_state") 220 public UserCardState userCardState; 221 222 @SerializedName("invalid_reason") 223 public String invalidReason; 224 225 @SerializedName("invalid_time") 226 public String invalidTime; 227 228 @SerializedName("create_time") 229 public String createTime; 230 231 @SerializedName("modify_time") 232 public String modifyTime; 233 } 234 235 public static class DateInfo { 236 @SerializedName("type") 237 public DateType type; 238 239 @SerializedName("available_begin_time") 240 public String availableBeginTime; 241 242 @SerializedName("available_end_time") 243 public String availableEndTime; 244 245 @SerializedName("available_day_after_receive") 246 public Long availableDayAfterReceive; 247 } 248 249 public static class UserInfo { 250 @SerializedName("common_field_list") 251 public List<UserInfoCommonField> commonFieldList; 252 253 @SerializedName("custom_field_list") 254 public List<UserInfoCustomField> customFieldList; 255 } 256 257 public enum UserCardConfirmState { 258 @SerializedName("CREATE_CARD_SUCCESS") 259 CREATE_CARD_SUCCESS, 260 @SerializedName("CREATE_CARD_FAIL") 261 CREATE_CARD_FAIL 262 } 263 264 public enum CardType { 265 @SerializedName("PURCHASE") 266 PURCHASE, 267 @SerializedName("NORMAL") 268 NORMAL, 269 @SerializedName("BALANCE") 270 BALANCE 271 } 272 273 public enum UserCardState { 274 @SerializedName("UNACTIVATED") 275 UNACTIVATED, 276 @SerializedName("EFFECTIVE") 277 EFFECTIVE, 278 @SerializedName("EXPIRED") 279 EXPIRED, 280 @SerializedName("INVALID") 281 INVALID 282 } 283 284 public enum DateType { 285 @SerializedName("FIX_TIME_RANGE") 286 FIX_TIME_RANGE, 287 @SerializedName("FIX_TERM") 288 FIX_TERM, 289 @SerializedName("PERMANENT") 290 PERMANENT 291 } 292 293 public static class UserInfoCommonField { 294 @SerializedName("name") 295 public CommonFieldFlag name; 296 297 @SerializedName("value") 298 public String value; 299 } 300 301 public static class UserInfoCustomField { 302 @SerializedName("name") 303 public String name; 304 305 @SerializedName("user_chosen_values") 306 public List<String> userChosenValues; 307 } 308 309 public enum CommonFieldFlag { 310 @SerializedName("USER_FORM_FLAG_SEX") 311 USER_FORM_FLAG_SEX, 312 @SerializedName("USER_FORM_FLAG_NAME") 313 USER_FORM_FLAG_NAME, 314 @SerializedName("USER_FORM_FLAG_BIRTHDAY") 315 USER_FORM_FLAG_BIRTHDAY, 316 @SerializedName("USER_FORM_FLAG_ADDRESS") 317 USER_FORM_FLAG_ADDRESS, 318 @SerializedName("USER_FORM_FLAG_EMAIL") 319 USER_FORM_FLAG_EMAIL, 320 @SerializedName("USER_FORM_FLAG_CITY") 321 USER_FORM_FLAG_CITY 322 } 323 324} 325
需配合微信支付工具库 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 "strings" 11) 12 13func main() { 14 // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340 15 config, err := wxpay_utility.CreateMchConfig( 16 "19xxxxxxxx", // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/partner/4013080340 17 "1DDE55AD98Exxxxxxxxxx", // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013058924 18 "/path/to/apiclient_key.pem", // 商户API证书私钥文件路径,本地文件路径 19 "PUB_KEY_ID_xxxxxxxxxxxxx", // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013038589 20 "/path/to/wxp_pub.pem", // 微信支付公钥文件路径,本地文件路径 21 ) 22 if err != nil { 23 fmt.Println(err) 24 return 25 } 26 27 request := &ConfirmUserCardRequest{ 28 UserCardCode: wxpay_utility.String("478515832665"), 29 CardId: wxpay_utility.String("pbLatjvWOibDc5-TBnbUk1pD12o0"), 30 BrandId: wxpay_utility.String("1004"), 31 Openid: wxpay_utility.String("obLatjnx9gnqzS4myYGmLZ7LgLBA"), 32 CardColor: wxpay_utility.String("#FFFF00"), 33 CardPictureUrl: wxpay_utility.String("https://wxpaylogo.qpic.cn/wxpaylogo/PiajxSqBRaEIPAeia7Imvtsn7sYGNcEj33YzVvJF88ECQ19LXId8ZL2Q/0"), 34 PhoneNumber: wxpay_utility.String("vvysDQeEaH3I+wRh14St0abIkvQyFgh/fbWYSs2bLtG9tj+bdJn4WSCPzLhShNHgujZzseiL6sYmT7E65mv/eFeTa7yslYfrX0hrhHazSM/+tfvN/C3OZwiBbcrF9LTIIdBVhGOqhCx0gK5YAVZc8dbW/yJqC5i79PDfVYJtpQe3A4v/GiDa2Q+Mv03taxgnEkzqlSPjkXiCYBj9UaFJ4bqCTXiO2Kt6TpczvAaZW+9/blxiJwqEFXe78LbrIQvkDUmVdZbqBdPQ+QGQgc/2Ea4IbP/EEt1qSyXnFbzaaKSE2j4mAFON3kzNexb/SYkHZNJAuCittaW4wpGj7U+h9A=="), /*请传入 wxpay_utility.EncryptOAEPWithPublicKey 加密结果*/ 35 Level: wxpay_utility.String("钻石会员"), 36 ValidDateInformation: &DateInfo{ 37 Type: DATETYPE_PERMANENT.Ptr(), 38 AvailableBeginTime: wxpay_utility.String("2020-05-20T13:29:35.120+08:00"), 39 AvailableEndTime: wxpay_utility.String("2020-05-20T13:29:35.120+08:00"), 40 AvailableDayAfterReceive: wxpay_utility.Int64(30), 41 }, 42 UserInformation: &UserInfo{ 43 CommonFieldList: []UserInfoCommonField{UserInfoCommonField{ 44 Name: COMMONFIELDFLAG_USER_FORM_FLAG_BIRTHDAY.Ptr(), 45 Value: wxpay_utility.String("vvysDQeEaH3I+wRh14St0abIkvQyFgh/fbWYSs2bLtG9tj+bdJn4WSCPzLhShNHgujZzseiL6sYmT7E65mv/eFeTa7yslYfrX0hrhHazSM/+tfvN/C3OZwiBbcrF9LTIIdBVhGOqhCx0gK5YAVZc8dbW/yJqC5i79PDfVYJtpQe3A4v/GiDa2Q+Mv03taxgnEkzqlSPjkXiCYBj9UaFJ4bqCTXiO2Kt6TpczvAaZW+9/blxiJwqEFXe78LbrIQvkDUmVdZbqBdPQ+QGQgc/2Ea4IbP/EEt1qSyXnFbzaaKSE2j4mAFON3kzNexb/SYkHZNJAuCittaW4wpGj7U+h9A=="), /*请传入 wxpay_utility.EncryptOAEPWithPublicKey 加密结果*/ 46 }}, 47 CustomFieldList: []UserInfoCustomField{UserInfoCustomField{ 48 Name: wxpay_utility.String("喜欢的运动"), 49 UserChosenValues: []string{"vvysDQeEaH3I+wRh14St0abIkvQyFgh/fbWYSs2bLtG9tj+bdJn4WSCPzLhShNHgujZzseiL6sYmT7E65mv/eFeTa7yslYfrX0hrhHazSM/+tfvN/C3OZwiBbcrF9LTIIdBVhGOqhCx0gK5YAVZc8dbW/yJqC5i79PDfVYJtpQe3A4v/GiDa2Q+Mv03taxgnEkzqlSPjkXiCYBj9UaFJ4bqCTXiO2Kt6TpczvAaZW+9/blxiJwqEFXe78LbrIQvkDUmVdZbqBdPQ+QGQgc/2Ea4IbP/EEt1qSyXnFbzaaKSE2j4mAFON3kzNexb/SYkHZNJAuCittaW4wpGj7U+h9A=="}, 50 }}, 51 }, 52 Attach: wxpay_utility.String("自定义数据说明"), 53 UserCardConfirmState: USERCARDCONFIRMSTATE_CREATE_CARD_SUCCESS.Ptr(), 54 } 55 56 response, err := ConfirmUserCard(config, request) 57 if err != nil { 58 fmt.Printf("请求失败: %+v\n", err) 59 // TODO: 请求失败,根据状态码执行不同的处理 60 return 61 } 62 63 // TODO: 请求成功,继续业务逻辑 64 fmt.Printf("请求成功: %+v\n", response) 65} 66 67func ConfirmUserCard(config *wxpay_utility.MchConfig, request *ConfirmUserCardRequest) (response *UserCard, err error) { 68 const ( 69 host = "https://api.mch.weixin.qq.com" 70 method = "POST" 71 path = "/v3/brand/partner/card-member/user-cards/{user_card_code}/confirm" 72 ) 73 74 reqUrl, err := url.Parse(fmt.Sprintf("%s%s", host, path)) 75 if err != nil { 76 return nil, err 77 } 78 reqUrl.Path = strings.Replace(reqUrl.Path, "{user_card_code}", url.PathEscape(*request.UserCardCode), -1) 79 query := reqUrl.Query() 80 query.Add("card_id", *request.CardId) 81 reqUrl.RawQuery = query.Encode() 82 reqBody, err := json.Marshal(request) 83 if err != nil { 84 return nil, err 85 } 86 httpRequest, err := http.NewRequest(method, reqUrl.String(), bytes.NewReader(reqBody)) 87 if err != nil { 88 return nil, err 89 } 90 httpRequest.Header.Set("Accept", "application/json") 91 httpRequest.Header.Set("Wechatpay-Serial", config.WechatPayPublicKeyId()) 92 httpRequest.Header.Set("Content-Type", "application/json") 93 authorization, err := wxpay_utility.BuildAuthorization(config.MchId(), config.CertificateSerialNo(), config.PrivateKey(), method, reqUrl.RequestURI(), reqBody) 94 if err != nil { 95 return nil, err 96 } 97 httpRequest.Header.Set("Authorization", authorization) 98 99 client := &http.Client{} 100 httpResponse, err := client.Do(httpRequest) 101 if err != nil { 102 return nil, err 103 } 104 105 respBody, err := wxpay_utility.ExtractResponseBody(httpResponse) 106 if err != nil { 107 return nil, err 108 } 109 110 if httpResponse.StatusCode >= 200 && httpResponse.StatusCode < 300 { 111 // 2XX 成功,验证应答签名 112 err = wxpay_utility.ValidateResponse( 113 config.WechatPayPublicKeyId(), 114 config.WechatPayPublicKey(), 115 &httpResponse.Header, 116 respBody, 117 ) 118 if err != nil { 119 return nil, err 120 } 121 122 if err := json.Unmarshal(respBody, response); err != nil { 123 return nil, err 124 } 125 126 return response, nil 127 } else { 128 return nil, wxpay_utility.NewApiException( 129 httpResponse.StatusCode, 130 httpResponse.Header, 131 respBody, 132 ) 133 } 134} 135 136type ConfirmUserCardRequest struct { 137 BrandId *string `json:"brand_id,omitempty"` 138 UserCardCode *string `json:"user_card_code,omitempty"` 139 CardId *string `json:"card_id,omitempty"` 140 Openid *string `json:"openid,omitempty"` 141 CardColor *string `json:"card_color,omitempty"` 142 CardPictureUrl *string `json:"card_picture_url,omitempty"` 143 PhoneNumber *string `json:"phone_number,omitempty"` 144 Level *string `json:"level,omitempty"` 145 ValidDateInformation *DateInfo `json:"valid_date_information,omitempty"` 146 UserInformation *UserInfo `json:"user_information,omitempty"` 147 Attach *string `json:"attach,omitempty"` 148 UserCardConfirmState *UserCardConfirmState `json:"user_card_confirm_state,omitempty"` 149} 150 151func (o *ConfirmUserCardRequest) MarshalJSON() ([]byte, error) { 152 type Alias ConfirmUserCardRequest 153 a := &struct { 154 UserCardCode *string `json:"user_card_code,omitempty"` 155 CardId *string `json:"card_id,omitempty"` 156 *Alias 157 }{ 158 // 序列化时移除非 Body 字段 159 UserCardCode: nil, 160 CardId: nil, 161 Alias: (*Alias)(o), 162 } 163 return json.Marshal(a) 164} 165 166type UserCard struct { 167 UserCardCode *string `json:"user_card_code,omitempty"` 168 CardId *string `json:"card_id,omitempty"` 169 Openid *string `json:"openid,omitempty"` 170 CardColor *string `json:"card_color,omitempty"` 171 CardPictureUrl *string `json:"card_picture_url,omitempty"` 172 BrandId *string `json:"brand_id,omitempty"` 173 CardType *CardType `json:"card_type,omitempty"` 174 PhoneNumber *string `json:"phone_number,omitempty"` 175 Level *string `json:"level,omitempty"` 176 ValidDateInformation *DateInfo `json:"valid_date_information,omitempty"` 177 PickupTime *string `json:"pickup_time,omitempty"` 178 UserInformation *UserInfo `json:"user_information,omitempty"` 179 Attach *string `json:"attach,omitempty"` 180 UserCardState *UserCardState `json:"user_card_state,omitempty"` 181 InvalidReason *string `json:"invalid_reason,omitempty"` 182 InvalidTime *string `json:"invalid_time,omitempty"` 183 CreateTime *string `json:"create_time,omitempty"` 184 ModifyTime *string `json:"modify_time,omitempty"` 185} 186 187type DateInfo struct { 188 Type *DateType `json:"type,omitempty"` 189 AvailableBeginTime *string `json:"available_begin_time,omitempty"` 190 AvailableEndTime *string `json:"available_end_time,omitempty"` 191 AvailableDayAfterReceive *int64 `json:"available_day_after_receive,omitempty"` 192} 193 194type UserInfo struct { 195 CommonFieldList []UserInfoCommonField `json:"common_field_list,omitempty"` 196 CustomFieldList []UserInfoCustomField `json:"custom_field_list,omitempty"` 197} 198 199type UserCardConfirmState string 200 201func (e UserCardConfirmState) Ptr() *UserCardConfirmState { 202 return &e 203} 204 205const ( 206 USERCARDCONFIRMSTATE_CREATE_CARD_SUCCESS UserCardConfirmState = "CREATE_CARD_SUCCESS" 207 USERCARDCONFIRMSTATE_CREATE_CARD_FAIL UserCardConfirmState = "CREATE_CARD_FAIL" 208) 209 210type CardType string 211 212func (e CardType) Ptr() *CardType { 213 return &e 214} 215 216const ( 217 CARDTYPE_PURCHASE CardType = "PURCHASE" 218 CARDTYPE_NORMAL CardType = "NORMAL" 219 CARDTYPE_BALANCE CardType = "BALANCE" 220) 221 222type UserCardState string 223 224func (e UserCardState) Ptr() *UserCardState { 225 return &e 226} 227 228const ( 229 USERCARDSTATE_UNACTIVATED UserCardState = "UNACTIVATED" 230 USERCARDSTATE_EFFECTIVE UserCardState = "EFFECTIVE" 231 USERCARDSTATE_EXPIRED UserCardState = "EXPIRED" 232 USERCARDSTATE_INVALID UserCardState = "INVALID" 233) 234 235type DateType string 236 237func (e DateType) Ptr() *DateType { 238 return &e 239} 240 241const ( 242 DATETYPE_FIX_TIME_RANGE DateType = "FIX_TIME_RANGE" 243 DATETYPE_FIX_TERM DateType = "FIX_TERM" 244 DATETYPE_PERMANENT DateType = "PERMANENT" 245) 246 247type UserInfoCommonField struct { 248 Name *CommonFieldFlag `json:"name,omitempty"` 249 Value *string `json:"value,omitempty"` 250} 251 252type UserInfoCustomField struct { 253 Name *string `json:"name,omitempty"` 254 UserChosenValues []string `json:"user_chosen_values,omitempty"` 255} 256 257type CommonFieldFlag string 258 259func (e CommonFieldFlag) Ptr() *CommonFieldFlag { 260 return &e 261} 262 263const ( 264 COMMONFIELDFLAG_USER_FORM_FLAG_SEX CommonFieldFlag = "USER_FORM_FLAG_SEX" 265 COMMONFIELDFLAG_USER_FORM_FLAG_NAME CommonFieldFlag = "USER_FORM_FLAG_NAME" 266 COMMONFIELDFLAG_USER_FORM_FLAG_BIRTHDAY CommonFieldFlag = "USER_FORM_FLAG_BIRTHDAY" 267 COMMONFIELDFLAG_USER_FORM_FLAG_ADDRESS CommonFieldFlag = "USER_FORM_FLAG_ADDRESS" 268 COMMONFIELDFLAG_USER_FORM_FLAG_EMAIL CommonFieldFlag = "USER_FORM_FLAG_EMAIL" 269 COMMONFIELDFLAG_USER_FORM_FLAG_CITY CommonFieldFlag = "USER_FORM_FLAG_CITY" 270) 271
POST
1curl -X POST \ 2 https://api.mch.weixin.qq.com/v3/brand/partner/card-member/user-cards/478515832665/confirm?card_id=pbLatjvWOibDc5-TBnbUk1pD12o0 \ 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 "brand_id" : "1004", 9 "openid" : "obLatjnx9gnqzS4myYGmLZ7LgLBA", 10 "card_color" : "#FFFF00", 11 "card_picture_url" : "https://wxpaylogo.qpic.cn/wxpaylogo/PiajxSqBRaEIPAeia7Imvtsn7sYGNcEj33YzVvJF88ECQ19LXId8ZL2Q/0", 12 "phone_number" : "vvysDQeEaH3I+wRh14St0abIkvQyFgh/fbWYSs2bLtG9tj+bdJn4WSCPzLhShNHgujZzseiL6sYmT7E65mv/eFeTa7yslYfrX0hrhHazSM/+tfvN/C3OZwiBbcrF9LTIIdBVhGOqhCx0gK5YAVZc8dbW/yJqC5i79PDfVYJtpQe3A4v/GiDa2Q+Mv03taxgnEkzqlSPjkXiCYBj9UaFJ4bqCTXiO2Kt6TpczvAaZW+9/blxiJwqEFXe78LbrIQvkDUmVdZbqBdPQ+QGQgc/2Ea4IbP/EEt1qSyXnFbzaaKSE2j4mAFON3kzNexb/SYkHZNJAuCittaW4wpGj7U+h9A==", 13 "level" : "钻石会员", 14 "valid_date_information" : { 15 "type" : "PERMANENT", 16 "available_begin_time" : "2020-05-20T13:29:35.120+08:00", 17 "available_end_time" : "2020-05-20T13:29:35.120+08:00", 18 "available_day_after_receive" : 30 19 }, 20 "user_information" : { 21 "common_field_list" : [ 22 { 23 "name" : "USER_FORM_FLAG_BIRTHDAY", 24 "value" : "vvysDQeEaH3I+wRh14St0abIkvQyFgh/fbWYSs2bLtG9tj+bdJn4WSCPzLhShNHgujZzseiL6sYmT7E65mv/eFeTa7yslYfrX0hrhHazSM/+tfvN/C3OZwiBbcrF9LTIIdBVhGOqhCx0gK5YAVZc8dbW/yJqC5i79PDfVYJtpQe3A4v/GiDa2Q+Mv03taxgnEkzqlSPjkXiCYBj9UaFJ4bqCTXiO2Kt6TpczvAaZW+9/blxiJwqEFXe78LbrIQvkDUmVdZbqBdPQ+QGQgc/2Ea4IbP/EEt1qSyXnFbzaaKSE2j4mAFON3kzNexb/SYkHZNJAuCittaW4wpGj7U+h9A==" 25 } 26 ], 27 "custom_field_list" : [ 28 { 29 "name" : "喜欢的运动", 30 "user_chosen_values" : [ 31 "vvysDQeEaH3I+wRh14St0abIkvQyFgh/fbWYSs2bLtG9tj+bdJn4WSCPzLhShNHgujZzseiL6sYmT7E65mv/eFeTa7yslYfrX0hrhHazSM/+tfvN/C3OZwiBbcrF9LTIIdBVhGOqhCx0gK5YAVZc8dbW/yJqC5i79PDfVYJtpQe3A4v/GiDa2Q+Mv03taxgnEkzqlSPjkXiCYBj9UaFJ4bqCTXiO2Kt6TpczvAaZW+9/blxiJwqEFXe78LbrIQvkDUmVdZbqBdPQ+QGQgc/2Ea4IbP/EEt1qSyXnFbzaaKSE2j4mAFON3kzNexb/SYkHZNJAuCittaW4wpGj7U+h9A==" 32 ] 33 } 34 ] 35 }, 36 "attach" : "自定义数据说明", 37 "user_card_confirm_state" : "CREATE_CARD_SUCCESS" 38 }' 39
应答参数
200 OK
user_card_code 必填 string(32)
【会员卡code】 会员在一个会员卡模版下的唯一标志,用户领取会员卡后获得的code
card_id 必填 string(32)
【会员卡模板 ID】 商家创建微信会员卡模板成功后系统返回的会员卡模板ID
openid 必填 string(128)
【用户标识】 用户在品牌商家会员卡模板AppID下的唯一标识
card_color 选填 string(7)
【卡背景颜色】 用于卡片正面设计的RGB颜色编码,仅支持十六进制
card_picture_url 选填 string(256)
【卡图片】 商家自定义会员卡背景图。仅支持通过图片上传API接口获取的图片URL地址。支持JPG/JPEG/PNG格式,建议尺寸716px*320px,图片背景色需为透明,且图片小于1M。
brand_id 必填 string(32)
【品牌ID】 商家进驻微信支付品牌商家后获得的品牌ID(灰度期间联系微信支付运营获取),用于标记该会员卡的归属方
card_type 必填 string
【会员卡类型】 支持付费、普通、储值 3 种类型。
可选取值
PURCHASE
: 付费NORMAL
: 普通BALANCE
: 储值
phone_number 选填 string(512)
【加密的手机号】 注册会员的手机号码,仅在用户授权手机号、商家通过 API 传入的情况下有值。解密请参考如何使用API证书解密敏感字段。
level 选填 string(10)
【等级】 用户会员等级,展示字段,商家可以自定义填写内容。
valid_date_information 必填 object
【会员卡有效期】 会员卡有效期
属性 | |
type 选填 string 【有效期类型】 1.该有效期为会员卡激活后的有效期 2.支持绝对有效期&相对有效期设置 3.绝对有效期:固定过期时间,需遵循 RFC3339 标准格式:yyyy-MM-DDTHH:mm:ss+TIMEZONE。yyyy-MM-DD 表示年月日;T 字符用于分隔日期和时间部分;HH:mm:ss 表示具体的时分秒;TIMEZONE 表示时区(例如,+08:00 对应东八区时间,即北京时间)。示例:2015-05-20T13:29:35+08:00 表示北京时间2015年5月20日13点29分35秒。 4.相对有效期:用户激活后x天后有效,x为天数。最多支持10,957天(30年) 5.永久有效 6.过期后卡状态变为“已过期” 7.过期后不再出现服务项,且无法给用户发送会员服务消息通知 可选取值
available_begin_time 选填 string(32) 【有效期开始时间】 type为FIX_TIME_RANGE时专用, 表示有效期开始时间。需需遵循 RFC3339 标准格式:yyyy-MM-DDTHH:mm:ss+TIMEZONE。yyyy-MM-DD 表示年月日;T 字符用于分隔日期和时间部分;HH:mm:ss 表示具体的时分秒;TIMEZONE 表示时区(例如,+08:00 对应东八区时间,即北京时间)。示例:2015-05-20T13:29:35+08:00 表示北京时间2015年5月20日13点29分35秒。 available_end_time 选填 string(32) 【有效期结束时间】 type为FIX_TERM_RANGE时专用,表示有效期结束时间。需需遵循 RFC3339 标准格式:yyyy-MM-DDTHH:mm:ss+TIMEZONE。yyyy-MM-DD 表示年月日;T 字符用于分隔日期和时间部分;HH:mm:ss 表示具体的时分秒;TIMEZONE 表示时区(例如,+08:00 对应东八区时间,即北京时间)。示例:2015-05-20T13:29:35+08:00 表示北京时间2015年5月20日13点29分35秒。 available_day_after_receive 选填 integer 【领取后N天内有效】 type为FIX_TERM时专用,表示领取后N个自然天内有效。最长不超过30年(10958 天) |
pickup_time 必填 string(32)
【领取时间】 用户领取会员卡的时间,需遵循 RFC3339 标准格式:yyyy-MM-DDTHH:mm:ss+TIMEZONE。yyyy-MM-DD 表示年月日;T 字符用于分隔日期和时间部分;HH:mm:ss 表示具体的时分秒;TIMEZONE 表示时区(例如,+08:00 对应东八区时间,即北京时间)。示例:2015-05-20T13:29:35+08:00 表示北京时间2015年5月20日13点29分35秒。
user_information 选填 object
【用户开卡时填写的个人信息】 用户开卡时填写的个人信息
属性 | |||||||||
common_field_list 选填 array[object] 【平台提供的通用开卡信息字段】 包含性别、手机、头像、昵称、姓名等基本信息字段
custom_field_list 选填 array[object] 【商家自定义的开卡信息字段】 商家自定义的开卡信息字段,当前最多只允许传入1项
|
attach 选填 string(256)
【商家数据包】 商家在创建用户会员卡时可传入自定义数据包,该数据对用户不可见,用于存储商家自定义信息,其总长度限制在256字符以内。查询用户会员卡详情时会将此字段返回给商家。
user_card_state 必填 string
【用户会员卡状态】 用户当前的卡状态
可选取值
UNACTIVATED
: 用户已领卡,但还未激活EFFECTIVE
: 用户的会员卡可正常使用EXPIRED
: 用户的会员卡已过期INVALID
: 用户的会员卡已失效
invalid_reason 选填 string(32)
【作废原因】 会员卡作废时传入的原因
invalid_time 选填 string(32)
【作废时间】 会员卡作废操作的时间,需遵循 RFC3339 标准格式:yyyy-MM-DDTHH:mm:ss+TIMEZONE。yyyy-MM-DD 表示年月日;T 字符用于分隔日期和时间部分;HH:mm:ss 表示具体的时分秒;TIMEZONE 表示时区(例如,+08:00 对应东八区时间,即北京时间)。示例:2015-05-20T13:29:35+08:00 表示北京时间2015年5月20日13点29分35秒。
create_time 必填 string(32)
【创建时间】 创建会员卡的时间,需遵循 RFC3339 标准格式:yyyy-MM-DDTHH:mm:ss+TIMEZONE。yyyy-MM-DD 表示年月日;T 字符用于分隔日期和时间部分;HH:mm:ss 表示具体的时分秒;TIMEZONE 表示时区(例如,+08:00 对应东八区时间,即北京时间)。示例:2015-05-20T13:29:35+08:00 表示北京时间2015年5月20日13点29分35秒。
modify_time 必填 string(32)
【更新时间】 更新会员卡的时间,需遵循 RFC3339 标准格式:yyyy-MM-DDTHH:mm:ss+TIMEZONE。yyyy-MM-DD 表示年月日;T 字符用于分隔日期和时间部分;HH:mm:ss 表示具体的时分秒;TIMEZONE 表示时区(例如,+08:00 对应东八区时间,即北京时间)。示例:2015-05-20T13:29:35+08:00 表示北京时间2015年5月20日13点29分35秒。
应答示例
200 OK
1{ 2 "user_card_code" : "478515832665", 3 "card_id" : "pbLatjvWOibDc5-TBnbUk1pD12o0", 4 "openid" : "obLatjnx9gnqzS4myYGmLZ7LgLBA", 5 "card_color" : "#FFFF00", 6 "card_picture_url" : "https://wxpaylogo.qpic.cn/wxpaylogo/PiajxSqBRaEIPAeia7Imvtsn7sYGNcEj33YzVvJF88ECQ19LXId8ZL2Q/0", 7 "brand_id" : "1001622624", 8 "card_type" : "NORMAL", 9 "phone_number" : "vvysDQeEaH3I+wRh14St0abIkvQyFgh/fbWYSs2bLtG9tj+bdJn4WSCPzLhShNHgujZzseiL6sYmT7E65mv/eFeTa7yslYfrX0hrhHazSM/+tfvN/C3OZwiBbcrF9LTIIdBVhGOqhCx0gK5YAVZc8dbW/yJqC5i79PDfVYJtpQe3A4v/GiDa2Q+Mv03taxgnEkzqlSPjkXiCYBj9UaFJ4bqCTXiO2Kt6TpczvAaZW+9/blxiJwqEFXe78LbrIQvkDUmVdZbqBdPQ+QGQgc/2Ea4IbP/EEt1qSyXnFbzaaKSE2j4mAFON3kzNexb/SYkHZNJAuCittaW4wpGj7U+h9A==", 10 "level" : "钻石会员", 11 "valid_date_information" : { 12 "type" : "PERMANENT", 13 "available_begin_time" : "2020-05-20T13:29:35.120+08:00", 14 "available_end_time" : "2020-05-20T13:29:35.120+08:00", 15 "available_day_after_receive" : 30 16 }, 17 "pickup_time" : "2020-05-20T13:29:35.120+08:00", 18 "user_information" : { 19 "common_field_list" : [ 20 { 21 "name" : "USER_FORM_FLAG_BIRTHDAY", 22 "value" : "vvysDQeEaH3I+wRh14St0abIkvQyFgh/fbWYSs2bLtG9tj+bdJn4WSCPzLhShNHgujZzseiL6sYmT7E65mv/eFeTa7yslYfrX0hrhHazSM/+tfvN/C3OZwiBbcrF9LTIIdBVhGOqhCx0gK5YAVZc8dbW/yJqC5i79PDfVYJtpQe3A4v/GiDa2Q+Mv03taxgnEkzqlSPjkXiCYBj9UaFJ4bqCTXiO2Kt6TpczvAaZW+9/blxiJwqEFXe78LbrIQvkDUmVdZbqBdPQ+QGQgc/2Ea4IbP/EEt1qSyXnFbzaaKSE2j4mAFON3kzNexb/SYkHZNJAuCittaW4wpGj7U+h9A==" 23 } 24 ], 25 "custom_field_list" : [ 26 { 27 "name" : "喜欢的运动", 28 "user_chosen_values" : [ 29 "vvysDQeEaH3I+wRh14St0abIkvQyFgh/fbWYSs2bLtG9tj+bdJn4WSCPzLhShNHgujZzseiL6sYmT7E65mv/eFeTa7yslYfrX0hrhHazSM/+tfvN/C3OZwiBbcrF9LTIIdBVhGOqhCx0gK5YAVZc8dbW/yJqC5i79PDfVYJtpQe3A4v/GiDa2Q+Mv03taxgnEkzqlSPjkXiCYBj9UaFJ4bqCTXiO2Kt6TpczvAaZW+9/blxiJwqEFXe78LbrIQvkDUmVdZbqBdPQ+QGQgc/2Ea4IbP/EEt1qSyXnFbzaaKSE2j4mAFON3kzNexb/SYkHZNJAuCittaW4wpGj7U+h9A==" 30 ] 31 } 32 ] 33 }, 34 "attach" : "自定义数据说明", 35 "user_card_state" : "EFFECTIVE", 36 "invalid_reason" : "传入的自定义作废原因", 37 "invalid_time" : "2020-05-20T13:29:35.120+08:00", 38 "create_time" : "2020-05-20T13:29:35.120+08:00", 39 "modify_time" : "2020-05-20T13:29:35.120+08:00" 40} 41
错误码
公共错误码
状态码 | 错误码 | 描述 | 解决方案 |
---|---|---|---|
400 | PARAM_ERROR | 参数错误 | 请根据错误提示正确传入参数 |
400 | INVALID_REQUEST | HTTP 请求不符合微信支付 APIv3 接口规则 | 请参阅 接口规则 |
401 | SIGN_ERROR | 验证不通过 | 请参阅 签名常见问题 |
500 | SYSTEM_ERROR | 系统异常,请稍后重试 | 请稍后重试 |
业务错误码
状态码 | 错误码 | 描述 | 解决方案 |
---|---|---|---|
400 | INVALID_REQUEST | 会员卡模版ID不属于该品牌 | 请确认品牌ID和会员卡模版ID是否正确 |