创建代金券批次
更新时间:2024.10.31商户可以通过调用此接口创建微信支付代金券批次,包括预充值&免充值代金券;创建完成后将获得代金券批次id,将可用于各个营销场景的活动投放。
接口频率:单个商户号调用频率60/min,所有商户号调用频率为1000/min
接口耗时:500ms
接口说明
支持商户:【普通商户】
请求方式:【POST】/v3/marketing/favor/coupon-stocks
请求域名:【主域名】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
body 包体参数
stock_name 必填 string(20)
【批次名称】批次名称
校验规则:
1、批次名称最多9个中文汉字
2、批次名称最多20个字母
3、批次名称中不能包含不当内容和特殊字符 _ , ; |
comment 选填 string(60)
【批次备注】仅配置商户可见,用于自定义信息
belong_merchant 必填 string(20)
【归属商户号】批次归属商户号
本字段暂未开放生效,但入参时请设置为当前创建代金券商户号即不会报错,暂时不支持入参其他的商户号
available_begin_time 必填 string
【可用时间-开始时间】批次开始时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
校验规则:
1、开始时间不可早于当前时间
2、不能创建365天后开始的批次
3、批次可用时间范围最长为90天
available_end_time 必填 string
【可用时间-结束时间】批次结束时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
stock_use_rule 必填 object
【发放规则】批次使用规则
属性 | |
max_coupons 必填 integer 【发放总上限】最大发券数 max_amount 必填 integer 【总预算】最大发券预算,当营销经费no_cash选择预充值false时,激活批次时会从制券商户的余额中扣除预算,请保证账户金额充足,单位:分 max_amount_by_day 选填 integer 【单天预算发放上限】设置此字段,允许指定单天最大发券预算,单位:分。 max_coupons_per_user 必填 integer 【单个用户可领个数】活动期间每个用户可领个数,当开启了自然人限领时,多个微信号同属于一个身份证时,视为同一用户。 natural_person_limit 必填 boolean 【是否开启自然人限制】当开启了自然人限领时,多个微信号同属于一个身份证时,视为同一用户。 prevent_api_abuse 必填 boolean 【是否开启防刷拦截】若开启防刷拦截,当用户命中恶意、小号、机器、羊毛党、黑产等风险行为时,无法成功发放代金券。 |
pattern_info 选填 object
【代金券详情页】代金券详情页
属性 | |
description 必填 string(1000) 【使用说明】用于说明详细的活动规则,会展示在代金券详情页。 merchant_logo 选填 string(128) 【商户logo】商户logo ,仅支持通过《图片上传API》接口获取的图片URL地址。1、商户logo大小需为120像素*120像素。2、支持JPG/JPEG/PNG格式,且图片小于1M。3、最多128个UTF8字符* merchant_name 选填 string(12) 【品牌名称】品牌名称,展示在用户卡包 background_color 选填 string 【背景颜色】券的背景颜色,可设置14种颜色,色值请参考下方说明。颜色取值为颜色图中的颜色名称。可选枚举字段不用则不传,不可以传空值 可选取值:
coupon_image 选填 string(128) 【券详情图片】券详情图片,850像素*350像素,且图片大小不超过2M,支持JPG/PNG格式,仅支持通过《图片上传API》接口获取的图片URL地址。* jump_target 选填 string 【卡包跳转目标】枚举值:PAYMENT_CODE:跳转至微信支付付款码,点击“立即使用”跳转至微信支付付款码 MINI_PROGRAM:跳转至小程序,点击“立即使用”跳转至配置的商家小程序(需要指定小程序appid和path) DEFAULT_PAGE:跳转至默认页, 点击“立即使用”跳转至默认页面 如未传该参数,则默认跳转至默认页。 可选取值:
mini_program_appid 选填 string(128) 【小程序appid】跳转的小程序appid,跳转至小程序时必填。跳转的小程序appid需至少和一个可核销商户有绑定关系。 mini_program_path 选填 string(128) 【小程序path】跳转的小程序path,跳转至小程序时必填。 |
coupon_use_rule 必填 object
【核销规则】
属性 | |||||||||||||||||
coupon_available_time 选填 object 【券生效时间】允许指定券的特殊生效时间规则。
fixed_normal_coupon 选填 object 【固定面额满减券使用规则】stock_type为NORMAL时必填
goods_tag 选填 array[string(128)] 【订单优惠标记】订单优惠标记,按json格式。 trade_type 选填 array[string] 【指定支付模式】允许指定支付方式的交易才可核销/使用代金券,不填则默认“不限”。 可选取值:
combine_use 选填 boolean 【是否可叠加其他优惠】允许指定本优惠是否可以和本商户号创建的其他券同时使用,不填则默认为:“不允许同时使用”。枚举值:true:是false:否 available_items 选填 array[string(128)] 【可核销商品编码】包含指定SKU商品编码的交易才可核销/使用代金券:活动商户在交易下单时,需传入用户购买的所有SKU商品编码,当命中代金券中设置的商品编码时可享受优惠。 unavailable_items 选填 array[string(128)] 【不参与优惠商品编码】该字段暂未开放 available_merchants 必填 array[string(20)] 【可核销商户号】可用商户的交易才可核销/使用代金券。当营销经费no_cash=false时,可用商户允许填入任何类型的特约商户或普通商户 limit_card 选填 object 【指定银行卡BIN】指定银行卡bin付款的交易可核销/使用代金券,当批次限定了指定银行卡时方可生效
|
no_cash 必填 boolean
【营销经费】营销经费。
枚举值:
true:免充值
false:预充值
1、免充值:制券方无需提前充值资金,用户核销代金券时,直接从订单原价中扣除优惠减价金额,最终只将用户实际支付的金额结算给核销商户,商户实收少于订单原价。
2、预充值:制券方需将优惠预算提前充值到微信支付商户可用余额中,用户核销代金券时,系统从制券方商户可用余额中扣除优惠减价部分对应的资金,连同用户实际支付的资金,一并结算给核销商户,不影响实收。
stock_type 必填 string(16)
【批次类型】批次类型,仅支持:
NORMAL:固定面额满减券批次
out_request_no 必填 string(128)
【商户单据号】商户创建批次凭据号(格式:商户id+日期+流水号),可包含英文字母,数字,|,_,*,-等内容,不允许出现其他不合法符号,商户侧需保持商户单据号全局唯一。
ext_info 选填 string(128)
【扩展属性】扩展属性字段,按json格式,如无需要则不填写。
该字段暂未开放
请求示例
POST
1curl -X POST \ 2 https://api.mch.weixin.qq.com/v3/marketing/favor/coupon-stocks \ 3 -H "Authorization: WECHATPAY2-SHA256-RSA2048 mchid=\"1900000001\",..." \ 4 -H "Accept: application/json" \ 5 -H "Content-Type: application/json" \ 6 -d '{ 7 "stock_name" : "微信支付代金券批次", 8 "comment" : "零售批次", 9 "belong_merchant" : "98568865", 10 "available_begin_time" : "2015-05-20T13:29:35.120+08:00", 11 "available_end_time" : "2015-05-20T13:29:35.120+08:00", 12 "stock_use_rule" : { 13 "max_coupons" : 100, 14 "max_amount" : 5000, 15 "max_amount_by_day" : 400, 16 "max_coupons_per_user" : 3, 17 "natural_person_limit" : false, 18 "prevent_api_abuse" : false 19 }, 20 "pattern_info" : { 21 "description" : "微信支付营销代金券", 22 "merchant_logo" : "CDN地址", 23 "merchant_name" : "微信支付", 24 "background_color" : "COLOR010", 25 "coupon_image" : "https://qpic.cn/xxx", 26 "jump_target" : "PAYMENT_CODE", 27 "mini_program_appid" : "wx23232232323", 28 "mini_program_path" : "/path/index/index" 29 }, 30 "coupon_use_rule" : { 31 "coupon_available_time" : { 32 "fix_available_time" : { 33 "available_week_day" : [ 34 1 35 ], 36 "begin_time" : 0, 37 "end_time" : 3600 38 }, 39 "second_day_available" : false, 40 "available_time_after_receive" : 7 41 }, 42 "fixed_normal_coupon" : { 43 "coupon_amount" : 100, 44 "transaction_minimum" : 100 45 }, 46 "goods_tag" : [ 47 "123321" 48 ], 49 "trade_type" : [ 50 "MICROAPP" 51 ], 52 "combine_use" : false, 53 "available_items" : [ 54 "123321" 55 ], 56 "unavailable_items" : [ 57 "789987" 58 ], 59 "available_merchants" : [ 60 "9856000" 61 ], 62 "limit_card" : { 63 "name" : "精粹白金", 64 "bin" : [ 65 "62542688" 66 ] 67 } 68 }, 69 "no_cash" : false, 70 "stock_type" : "NORMAL", 71 "out_request_no" : "example_out_request_no", 72 "ext_info" : "{'exinfo1':'1234','exinfo2':'3456'}" 73 }' 74
需配合微信支付工具库 WXPayUtility 使用,请参考Java
1package com.java.demo; 2 3import com.java.utils.WXPayUtility; // 引用微信支付工具库,参考:https://pay.weixin.qq.com/doc/v3/merchant/4014931831 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 CreateCouponStock { 26 private static String HOST = "https://api.mch.weixin.qq.com"; 27 private static String METHOD = "POST"; 28 private static String PATH = "/v3/marketing/favor/coupon-stocks"; 29 30 public static void main(String[] args) { 31 // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/merchant/4013070756 32 CreateCouponStock client = new CreateCouponStock( 33 "19xxxxxxxx", // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756 34 "1DDE55AD98Exxxxxxxxxx", // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053 35 "/path/to/apiclient_key.pem", // 商户API证书私钥文件路径,本地文件路径 36 "PUB_KEY_ID_xxxxxxxxxxxxx", // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816 37 "/path/to/wxp_pub.pem" // 微信支付公钥文件路径,本地文件路径 38 ); 39 40 CreateCouponStockRequest request = new CreateCouponStockRequest(); 41 request.stockName = "微信支付代金券批次"; 42 request.comment = "零售批次"; 43 request.belongMerchant = "98568865"; 44 request.availableBeginTime = "2015-05-20T13:29:35.120+08:00"; 45 request.availableEndTime = "2015-05-20T13:29:35.120+08:00"; 46 request.stockUseRule = new StockRule(); 47 request.stockUseRule.maxCoupons = 100L; 48 request.stockUseRule.maxAmount = 5000L; 49 request.stockUseRule.maxAmountByDay = 400L; 50 request.stockUseRule.maxCouponsPerUser = 3L; 51 request.stockUseRule.naturalPersonLimit = false; 52 request.stockUseRule.preventApiAbuse = false; 53 request.patternInfo = new PatternInfo(); 54 request.patternInfo.description = "微信支付营销代金券"; 55 request.patternInfo.merchantLogo = "CDN地址"; 56 request.patternInfo.merchantName = "微信支付"; 57 request.patternInfo.backgroundColor = BackgroundColor.COLOR010; 58 request.patternInfo.couponImage = "https://qpic.cn/xxx"; 59 request.patternInfo.jumpTarget = JumpTarget.PAYMENT_CODE; 60 request.patternInfo.miniProgramAppid = "wx23232232323"; 61 request.patternInfo.miniProgramPath = "/path/index/index"; 62 request.couponUseRule = new CouponRule(); 63 request.couponUseRule.couponAvailableTime = new FavorAvailableTime(); 64 request.couponUseRule.couponAvailableTime.fixAvailableTime = new FixedAvailableTime(); 65 request.couponUseRule.couponAvailableTime.fixAvailableTime.availableWeekDay = new ArrayList<>(); 66 { 67 request.couponUseRule.couponAvailableTime.fixAvailableTime.availableWeekDay.add(1L); 68 }; 69 request.couponUseRule.couponAvailableTime.fixAvailableTime.beginTime = 0L; 70 request.couponUseRule.couponAvailableTime.fixAvailableTime.endTime = 3600L; 71 request.couponUseRule.couponAvailableTime.secondDayAvailable = false; 72 request.couponUseRule.couponAvailableTime.availableTimeAfterReceive = 7L; 73 request.couponUseRule.fixedNormalCoupon = new FixedValueStockMsg(); 74 request.couponUseRule.fixedNormalCoupon.couponAmount = 100L; 75 request.couponUseRule.fixedNormalCoupon.transactionMinimum = 100L; 76 request.couponUseRule.goodsTag = new ArrayList<>(); 77 { 78 request.couponUseRule.goodsTag.add("123321"); 79 }; 80 request.couponUseRule.tradeType = new ArrayList<>(); 81 { 82 request.couponUseRule.tradeType.add(TradeType.MICROAPP); 83 }; 84 request.couponUseRule.combineUse = false; 85 request.couponUseRule.availableItems = new ArrayList<>(); 86 { 87 request.couponUseRule.availableItems.add("123321"); 88 }; 89 request.couponUseRule.unavailableItems = new ArrayList<>(); 90 { 91 request.couponUseRule.unavailableItems.add("789987"); 92 }; 93 request.couponUseRule.availableMerchants = new ArrayList<>(); 94 { 95 request.couponUseRule.availableMerchants.add("9856000"); 96 }; 97 request.couponUseRule.limitCard = new CardLimitation(); 98 request.couponUseRule.limitCard.name = "精粹白金"; 99 request.couponUseRule.limitCard.bin = new ArrayList<>(); 100 { 101 request.couponUseRule.limitCard.bin.add("62542688"); 102 }; 103 request.noCash = false; 104 request.stockType = "NORMAL"; 105 request.outRequestNo = "example_out_request_no"; 106 request.extInfo = "{'exinfo1':'1234','exinfo2':'3456'}"; 107 try { 108 CreateCouponStockResponse response = client.run(request); 109 // TODO: 请求成功,继续业务逻辑 110 System.out.println(response); 111 } catch (WXPayUtility.ApiException e) { 112 // TODO: 请求失败,根据状态码执行不同的逻辑 113 e.printStackTrace(); 114 } 115 } 116 117 public CreateCouponStockResponse run(CreateCouponStockRequest request) { 118 String uri = PATH; 119 String reqBody = WXPayUtility.toJson(request); 120 121 Request.Builder reqBuilder = new Request.Builder().url(HOST + uri); 122 reqBuilder.addHeader("Accept", "application/json"); 123 reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId); 124 reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo,privateKey, METHOD, uri, reqBody)); 125 reqBuilder.addHeader("Content-Type", "application/json"); 126 RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody); 127 reqBuilder.method(METHOD, requestBody); 128 Request httpRequest = reqBuilder.build(); 129 130 // 发送HTTP请求 131 OkHttpClient client = new OkHttpClient.Builder().build(); 132 try (Response httpResponse = client.newCall(httpRequest).execute()) { 133 String respBody = WXPayUtility.extractBody(httpResponse); 134 if (httpResponse.code() >= 200 && httpResponse.code() < 300) { 135 // 2XX 成功,验证应答签名 136 WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey, 137 httpResponse.headers(), respBody); 138 139 // 从HTTP应答报文构建返回数据 140 return WXPayUtility.fromJson(respBody, CreateCouponStockResponse.class); 141 } else { 142 throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers()); 143 } 144 } catch (IOException e) { 145 throw new UncheckedIOException("Sending request to " + uri + " failed.", e); 146 } 147 } 148 149 private final String mchid; 150 private final String certificateSerialNo; 151 private final PrivateKey privateKey; 152 private final String wechatPayPublicKeyId; 153 private final PublicKey wechatPayPublicKey; 154 155 public CreateCouponStock(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) { 156 this.mchid = mchid; 157 this.certificateSerialNo = certificateSerialNo; 158 this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath); 159 this.wechatPayPublicKeyId = wechatPayPublicKeyId; 160 this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath); 161 } 162 163 public static class CreateCouponStockRequest { 164 @SerializedName("stock_name") 165 public String stockName; 166 167 @SerializedName("comment") 168 public String comment; 169 170 @SerializedName("belong_merchant") 171 public String belongMerchant; 172 173 @SerializedName("available_begin_time") 174 public String availableBeginTime; 175 176 @SerializedName("available_end_time") 177 public String availableEndTime; 178 179 @SerializedName("stock_use_rule") 180 public StockRule stockUseRule; 181 182 @SerializedName("pattern_info") 183 public PatternInfo patternInfo; 184 185 @SerializedName("coupon_use_rule") 186 public CouponRule couponUseRule; 187 188 @SerializedName("no_cash") 189 public Boolean noCash; 190 191 @SerializedName("stock_type") 192 public String stockType; 193 194 @SerializedName("out_request_no") 195 public String outRequestNo; 196 197 @SerializedName("ext_info") 198 public String extInfo; 199 } 200 201 public static class CreateCouponStockResponse { 202 @SerializedName("stock_id") 203 public String stockId; 204 205 @SerializedName("create_time") 206 public String createTime; 207 } 208 209 public static class StockRule { 210 @SerializedName("max_coupons") 211 public Long maxCoupons; 212 213 @SerializedName("max_amount") 214 public Long maxAmount; 215 216 @SerializedName("max_amount_by_day") 217 public Long maxAmountByDay; 218 219 @SerializedName("max_coupons_per_user") 220 public Long maxCouponsPerUser; 221 222 @SerializedName("natural_person_limit") 223 public Boolean naturalPersonLimit; 224 225 @SerializedName("prevent_api_abuse") 226 public Boolean preventApiAbuse; 227 } 228 229 public static class PatternInfo { 230 @SerializedName("description") 231 public String description; 232 233 @SerializedName("merchant_logo") 234 public String merchantLogo; 235 236 @SerializedName("merchant_name") 237 public String merchantName; 238 239 @SerializedName("background_color") 240 public BackgroundColor backgroundColor; 241 242 @SerializedName("coupon_image") 243 public String couponImage; 244 245 @SerializedName("jump_target") 246 public JumpTarget jumpTarget; 247 248 @SerializedName("mini_program_appid") 249 public String miniProgramAppid; 250 251 @SerializedName("mini_program_path") 252 public String miniProgramPath; 253 } 254 255 public static class CouponRule { 256 @SerializedName("coupon_available_time") 257 public FavorAvailableTime couponAvailableTime; 258 259 @SerializedName("fixed_normal_coupon") 260 public FixedValueStockMsg fixedNormalCoupon; 261 262 @SerializedName("goods_tag") 263 public List<String> goodsTag; 264 265 @SerializedName("trade_type") 266 public List<TradeType> tradeType; 267 268 @SerializedName("combine_use") 269 public Boolean combineUse; 270 271 @SerializedName("available_items") 272 public List<String> availableItems; 273 274 @SerializedName("unavailable_items") 275 public List<String> unavailableItems; 276 277 @SerializedName("available_merchants") 278 public List<String> availableMerchants = new ArrayList<String>(); 279 280 @SerializedName("limit_card") 281 public CardLimitation limitCard; 282 } 283 284 public enum BackgroundColor { 285 @SerializedName("COLOR010") 286 COLOR010, 287 @SerializedName("COLOR020") 288 COLOR020, 289 @SerializedName("COLOR030") 290 COLOR030, 291 @SerializedName("COLOR040") 292 COLOR040, 293 @SerializedName("COLOR050") 294 COLOR050, 295 @SerializedName("COLOR060") 296 COLOR060, 297 @SerializedName("COLOR070") 298 COLOR070, 299 @SerializedName("COLOR080") 300 COLOR080, 301 @SerializedName("COLOR081") 302 COLOR081, 303 @SerializedName("COLOR082") 304 COLOR082, 305 @SerializedName("COLOR090") 306 COLOR090, 307 @SerializedName("COLOR100") 308 COLOR100, 309 @SerializedName("COLOR101") 310 COLOR101, 311 @SerializedName("COLOR102") 312 COLOR102 313 } 314 315 public enum JumpTarget { 316 @SerializedName("PAYMENT_CODE") 317 PAYMENT_CODE, 318 @SerializedName("MINI_PROGRAM") 319 MINI_PROGRAM, 320 @SerializedName("DEFAULT_PAGE") 321 DEFAULT_PAGE 322 } 323 324 public static class FavorAvailableTime { 325 @SerializedName("fix_available_time") 326 public FixedAvailableTime fixAvailableTime; 327 328 @SerializedName("second_day_available") 329 public Boolean secondDayAvailable; 330 331 @SerializedName("available_time_after_receive") 332 public Long availableTimeAfterReceive; 333 } 334 335 public static class FixedValueStockMsg { 336 @SerializedName("coupon_amount") 337 public Long couponAmount; 338 339 @SerializedName("transaction_minimum") 340 public Long transactionMinimum; 341 } 342 343 public enum TradeType { 344 @SerializedName("MICROAPP") 345 MICROAPP, 346 @SerializedName("APPPAY") 347 APPPAY, 348 @SerializedName("PPAY") 349 PPAY, 350 @SerializedName("CARD") 351 CARD, 352 @SerializedName("FACE") 353 FACE, 354 @SerializedName("OTHER") 355 OTHER 356 } 357 358 public static class CardLimitation { 359 @SerializedName("name") 360 public String name; 361 362 @SerializedName("bin") 363 public List<String> bin = new ArrayList<String>(); 364 } 365 366 public static class FixedAvailableTime { 367 @SerializedName("available_week_day") 368 public List<Long> availableWeekDay = new ArrayList<Long>(); 369 370 @SerializedName("begin_time") 371 public Long beginTime; 372 373 @SerializedName("end_time") 374 public Long endTime; 375 } 376 377} 378
需配合微信支付工具库 wxpay_utility 使用,请参考Go
1package main 2 3import ( 4 "bytes" 5 "demo/wxpay_utility" // 引用微信支付工具库,参考 https://pay.weixin.qq.com/doc/v3/merchant/4015119334 6 "encoding/json" 7 "fmt" 8 "net/http" 9 "net/url" 10) 11 12func main() { 13 // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/merchant/4013070756 14 config, err := wxpay_utility.CreateMchConfig( 15 "19xxxxxxxx", // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756 16 "1DDE55AD98Exxxxxxxxxx", // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053 17 "/path/to/apiclient_key.pem", // 商户API证书私钥文件路径,本地文件路径 18 "PUB_KEY_ID_xxxxxxxxxxxxx", // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816 19 "/path/to/wxp_pub.pem", // 微信支付公钥文件路径,本地文件路径 20 ) 21 if err != nil { 22 fmt.Println(err) 23 return 24 } 25 26 request := &CreateCouponStockRequest{ 27 StockName: wxpay_utility.String("微信支付代金券批次"), 28 Comment: wxpay_utility.String("零售批次"), 29 BelongMerchant: wxpay_utility.String("98568865"), 30 AvailableBeginTime: wxpay_utility.String("2015-05-20T13:29:35.120+08:00"), 31 AvailableEndTime: wxpay_utility.String("2015-05-20T13:29:35.120+08:00"), 32 StockUseRule: &StockRule{ 33 MaxCoupons: wxpay_utility.Int64(100), 34 MaxAmount: wxpay_utility.Int64(5000), 35 MaxAmountByDay: wxpay_utility.Int64(400), 36 MaxCouponsPerUser: wxpay_utility.Int64(3), 37 NaturalPersonLimit: wxpay_utility.Bool(false), 38 PreventApiAbuse: wxpay_utility.Bool(false), 39 }, 40 PatternInfo: &PatternInfo{ 41 Description: wxpay_utility.String("微信支付营销代金券"), 42 MerchantLogo: wxpay_utility.String("CDN地址"), 43 MerchantName: wxpay_utility.String("微信支付"), 44 BackgroundColor: BACKGROUNDCOLOR_COLOR010.Ptr(), 45 CouponImage: wxpay_utility.String("https://qpic.cn/xxx"), 46 JumpTarget: JUMPTARGET_PAYMENT_CODE.Ptr(), 47 MiniProgramAppid: wxpay_utility.String("wx23232232323"), 48 MiniProgramPath: wxpay_utility.String("/path/index/index"), 49 }, 50 CouponUseRule: &CouponRule{ 51 CouponAvailableTime: &FavorAvailableTime{ 52 FixAvailableTime: &FixedAvailableTime{ 53 AvailableWeekDay: []int64{int64(1)}, 54 BeginTime: wxpay_utility.Int64(0), 55 EndTime: wxpay_utility.Int64(3600), 56 }, 57 SecondDayAvailable: wxpay_utility.Bool(false), 58 AvailableTimeAfterReceive: wxpay_utility.Int64(7), 59 }, 60 FixedNormalCoupon: &FixedValueStockMsg{ 61 CouponAmount: wxpay_utility.Int64(100), 62 TransactionMinimum: wxpay_utility.Int64(100), 63 }, 64 GoodsTag: []string{"123321"}, 65 TradeType: []TradeType{TRADETYPE_MICROAPP}, 66 CombineUse: wxpay_utility.Bool(false), 67 AvailableItems: []string{"123321"}, 68 UnavailableItems: []string{"789987"}, 69 AvailableMerchants: []string{"9856000"}, 70 LimitCard: &CardLimitation{ 71 Name: wxpay_utility.String("精粹白金"), 72 Bin: []string{"62542688"}, 73 }, 74 }, 75 NoCash: wxpay_utility.Bool(false), 76 StockType: wxpay_utility.String("NORMAL"), 77 OutRequestNo: wxpay_utility.String("example_out_request_no"), 78 ExtInfo: wxpay_utility.String("{'exinfo1':'1234','exinfo2':'3456'}"), 79 } 80 81 response, err := CreateCouponStock(config, request) 82 if err != nil { 83 fmt.Printf("请求失败: %+v\n", err) 84 // TODO: 请求失败,根据状态码执行不同的处理 85 return 86 } 87 88 // TODO: 请求成功,继续业务逻辑 89 fmt.Printf("请求成功: %+v\n", response) 90} 91 92func CreateCouponStock(config *wxpay_utility.MchConfig, request *CreateCouponStockRequest) (response *CreateCouponStockResponse, err error) { 93 const ( 94 host = "https://api.mch.weixin.qq.com" 95 method = "POST" 96 path = "/v3/marketing/favor/coupon-stocks" 97 ) 98 99 reqUrl, err := url.Parse(fmt.Sprintf("%s%s", host, path)) 100 if err != nil { 101 return nil, err 102 } 103 reqBody, err := json.Marshal(request) 104 if err != nil { 105 return nil, err 106 } 107 httpRequest, err := http.NewRequest(method, reqUrl.String(), bytes.NewReader(reqBody)) 108 if err != nil { 109 return nil, err 110 } 111 httpRequest.Header.Set("Accept", "application/json") 112 httpRequest.Header.Set("Wechatpay-Serial", config.WechatPayPublicKeyId()) 113 httpRequest.Header.Set("Content-Type", "application/json") 114 authorization, err := wxpay_utility.BuildAuthorization(config.MchId(), config.CertificateSerialNo(), config.PrivateKey(), method, reqUrl.RequestURI(), reqBody) 115 if err != nil { 116 return nil, err 117 } 118 httpRequest.Header.Set("Authorization", authorization) 119 120 client := &http.Client{} 121 httpResponse, err := client.Do(httpRequest) 122 if err != nil { 123 return nil, err 124 } 125 respBody, err := wxpay_utility.ExtractResponseBody(httpResponse) 126 if err != nil { 127 return nil, err 128 } 129 if httpResponse.StatusCode >= 200 && httpResponse.StatusCode < 300 { 130 // 2XX 成功,验证应答签名 131 err = wxpay_utility.ValidateResponse( 132 config.WechatPayPublicKeyId(), 133 config.WechatPayPublicKey(), 134 &httpResponse.Header, 135 respBody, 136 ) 137 if err != nil { 138 return nil, err 139 } 140 response := &CreateCouponStockResponse{} 141 if err := json.Unmarshal(respBody, response); err != nil { 142 return nil, err 143 } 144 145 return response, nil 146 } else { 147 return nil, wxpay_utility.NewApiException( 148 httpResponse.StatusCode, 149 httpResponse.Header, 150 respBody, 151 ) 152 } 153} 154 155type CreateCouponStockRequest struct { 156 StockName *string `json:"stock_name,omitempty"` 157 Comment *string `json:"comment,omitempty"` 158 BelongMerchant *string `json:"belong_merchant,omitempty"` 159 AvailableBeginTime *string `json:"available_begin_time,omitempty"` 160 AvailableEndTime *string `json:"available_end_time,omitempty"` 161 StockUseRule *StockRule `json:"stock_use_rule,omitempty"` 162 PatternInfo *PatternInfo `json:"pattern_info,omitempty"` 163 CouponUseRule *CouponRule `json:"coupon_use_rule,omitempty"` 164 NoCash *bool `json:"no_cash,omitempty"` 165 StockType *string `json:"stock_type,omitempty"` 166 OutRequestNo *string `json:"out_request_no,omitempty"` 167 ExtInfo *string `json:"ext_info,omitempty"` 168} 169 170type CreateCouponStockResponse struct { 171 StockId *string `json:"stock_id,omitempty"` 172 CreateTime *string `json:"create_time,omitempty"` 173} 174 175type StockRule struct { 176 MaxCoupons *int64 `json:"max_coupons,omitempty"` 177 MaxAmount *int64 `json:"max_amount,omitempty"` 178 MaxAmountByDay *int64 `json:"max_amount_by_day,omitempty"` 179 MaxCouponsPerUser *int64 `json:"max_coupons_per_user,omitempty"` 180 NaturalPersonLimit *bool `json:"natural_person_limit,omitempty"` 181 PreventApiAbuse *bool `json:"prevent_api_abuse,omitempty"` 182} 183 184type PatternInfo struct { 185 Description *string `json:"description,omitempty"` 186 MerchantLogo *string `json:"merchant_logo,omitempty"` 187 MerchantName *string `json:"merchant_name,omitempty"` 188 BackgroundColor *BackgroundColor `json:"background_color,omitempty"` 189 CouponImage *string `json:"coupon_image,omitempty"` 190 JumpTarget *JumpTarget `json:"jump_target,omitempty"` 191 MiniProgramAppid *string `json:"mini_program_appid,omitempty"` 192 MiniProgramPath *string `json:"mini_program_path,omitempty"` 193} 194 195type CouponRule struct { 196 CouponAvailableTime *FavorAvailableTime `json:"coupon_available_time,omitempty"` 197 FixedNormalCoupon *FixedValueStockMsg `json:"fixed_normal_coupon,omitempty"` 198 GoodsTag []string `json:"goods_tag,omitempty"` 199 TradeType []TradeType `json:"trade_type,omitempty"` 200 CombineUse *bool `json:"combine_use,omitempty"` 201 AvailableItems []string `json:"available_items,omitempty"` 202 UnavailableItems []string `json:"unavailable_items,omitempty"` 203 AvailableMerchants []string `json:"available_merchants,omitempty"` 204 LimitCard *CardLimitation `json:"limit_card,omitempty"` 205} 206 207type BackgroundColor string 208 209func (e BackgroundColor) Ptr() *BackgroundColor { 210 return &e 211} 212 213const ( 214 BACKGROUNDCOLOR_COLOR010 BackgroundColor = "COLOR010" 215 BACKGROUNDCOLOR_COLOR020 BackgroundColor = "COLOR020" 216 BACKGROUNDCOLOR_COLOR030 BackgroundColor = "COLOR030" 217 BACKGROUNDCOLOR_COLOR040 BackgroundColor = "COLOR040" 218 BACKGROUNDCOLOR_COLOR050 BackgroundColor = "COLOR050" 219 BACKGROUNDCOLOR_COLOR060 BackgroundColor = "COLOR060" 220 BACKGROUNDCOLOR_COLOR070 BackgroundColor = "COLOR070" 221 BACKGROUNDCOLOR_COLOR080 BackgroundColor = "COLOR080" 222 BACKGROUNDCOLOR_COLOR081 BackgroundColor = "COLOR081" 223 BACKGROUNDCOLOR_COLOR082 BackgroundColor = "COLOR082" 224 BACKGROUNDCOLOR_COLOR090 BackgroundColor = "COLOR090" 225 BACKGROUNDCOLOR_COLOR100 BackgroundColor = "COLOR100" 226 BACKGROUNDCOLOR_COLOR101 BackgroundColor = "COLOR101" 227 BACKGROUNDCOLOR_COLOR102 BackgroundColor = "COLOR102" 228) 229 230type JumpTarget string 231 232func (e JumpTarget) Ptr() *JumpTarget { 233 return &e 234} 235 236const ( 237 JUMPTARGET_PAYMENT_CODE JumpTarget = "PAYMENT_CODE" 238 JUMPTARGET_MINI_PROGRAM JumpTarget = "MINI_PROGRAM" 239 JUMPTARGET_DEFAULT_PAGE JumpTarget = "DEFAULT_PAGE" 240) 241 242type FavorAvailableTime struct { 243 FixAvailableTime *FixedAvailableTime `json:"fix_available_time,omitempty"` 244 SecondDayAvailable *bool `json:"second_day_available,omitempty"` 245 AvailableTimeAfterReceive *int64 `json:"available_time_after_receive,omitempty"` 246} 247 248type FixedValueStockMsg struct { 249 CouponAmount *int64 `json:"coupon_amount,omitempty"` 250 TransactionMinimum *int64 `json:"transaction_minimum,omitempty"` 251} 252 253type TradeType string 254 255func (e TradeType) Ptr() *TradeType { 256 return &e 257} 258 259const ( 260 TRADETYPE_MICROAPP TradeType = "MICROAPP" 261 TRADETYPE_APPPAY TradeType = "APPPAY" 262 TRADETYPE_PPAY TradeType = "PPAY" 263 TRADETYPE_CARD TradeType = "CARD" 264 TRADETYPE_FACE TradeType = "FACE" 265 TRADETYPE_OTHER TradeType = "OTHER" 266) 267 268type CardLimitation struct { 269 Name *string `json:"name,omitempty"` 270 Bin []string `json:"bin,omitempty"` 271} 272 273type FixedAvailableTime struct { 274 AvailableWeekDay []int64 `json:"available_week_day,omitempty"` 275 BeginTime *int64 `json:"begin_time,omitempty"` 276 EndTime *int64 `json:"end_time,omitempty"` 277} 278
应答参数
|
stock_id 必填 string
【批次号】微信为每个代金券批次分配的唯一ID。
create_time 必填 string
【创建时间】创建时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
应答示例
200 OK
1{ 2 "stock_id" : "98065001", 3 "create_time" : "2015-05-20T13:29:35.120+08:00" 4} 5
错误码
公共错误码
状态码 | 错误码 | 描述 | 解决方案 |
---|---|---|---|
400 | PARAM_ERROR | 参数错误 | 请根据错误提示正确传入参数 |
400 | INVALID_REQUEST | HTTP 请求不符合微信支付 APIv3 接口规则 | 请参阅 接口规则 |
401 | SIGN_ERROR | 验证不通过 | 请参阅 签名常见问题 |
500 | SYSTEM_ERROR | 系统异常,请稍后重试 | 请稍后重试 |
业务错误码
状态码 | 错误码 | 描述 | 解决方案 |
---|---|---|---|
400 | APPID_MCHID_NOT_MATCH | 商户号与AppID不匹配 | 请绑定调用接口的商户号和AppID后重试 |
400 | INVALID_REQUEST | OpenID与AppID不匹配 | 请使用AppID下的OpenID |
400 | INVALID_REQUEST | 活动已结束或未激活 | 请检查批次状态 |
400 | INVALID_REQUEST | 非法的商户号 | 请检查商户号是否正确 |
400 | MCH_NOT_EXISTS | 商户号不合法 | 请输入正确的商户号 |
400 | PARAM_ERROR | 回调URL不能为空 | 请填写回调URL |
400 | PARAM_ERROR | 回调商户不能为空 | 请填写回调商户 |
400 | PARAM_ERROR | 券ID必填 | 请填写券ID |
400 | PARAM_ERROR | AppID必填 | 请输入AppID |
400 | PARAM_ERROR | OpenID必填 | 请输入OpenID |
400 | PARAM_ERROR | 页大小超过阈值 | 请不要超过最大的页大小 |
400 | PARAM_ERROR | 输入时间格式错误 | 请输入正确的时间格式 |
400 | PARAM_ERROR | 批次号必填 | 请输入批次号 |
400 | PARAM_ERROR | 商户号必填 | 请输入商户号 |
400 | PARAM_ERROR | 非法的批次状态 | 请检查批次状态 |
403 | NO_AUTH | 你配置的信息需要开通特殊权限 | 请参考:QA方案 |
403 | NOT_ENOUGH | 批次预算不足 | 请补充预算 |
403 | REQUEST_BLOCKED | 调用商户无权限 | 请开通产品权限后再调用该接口 |
403 | REQUEST_BLOCKED | 商户无权发券 | 调用接口的商户号无权发券,请检查是否是自己的批次或是已授权的批次。 |
403 | REQUEST_BLOCKED | 批次不支持跨商户发券 | 该批次未做跨商户号的授权,请授权后再发放 |
403 | REQUEST_BLOCKED | 用户被限领拦截 | 用户领取已经达到上限,请调高上限或停止发放。 |
403 | REQUEST_BLOCKED | 活动未开始或已结束 | 该活动未开始或已结束 |
403 | USER_ACCOUNT_ABNORMAL | 用户非法 | 该用户账号异常,无法领券。商家可联系微信支付或让用户联系微信支付客服处理。 |
404 | RESOURCE_NOT_EXISTS | 批次不存在 | 请检查批次ID是否正确 |
429 | FREQUENCY_LIMITED | 请求过于频繁 | 稍后重试 |