修改商品券批次组发放预算
更新时间:2025.11.20服务商可以通过本接口批量修改商品券批次组内所有批次的投放预算。
注:本接口每次调用只能调整一个维度的投放预算,如果你需要调整多个维度的预算,请多次调用本接口。
前置条件:
已创建
usage_mode为PROGRESSIVE_BUNDLE的商品券对应的批次组批次组内批次未失效或过期
频率限制:20/s
接口说明
支持商户:【普通服务商】
请求方式:【POST】/v3/marketing/partner/product-coupon/product-coupons/{product_coupon_id}/stock-bundles/{stock_bundle_id}/update-budget
请求域名:【主域名】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
path 路径参数
product_coupon_id 必填 string
【商品券ID】 商品券的唯一标识,创建商品券时由微信支付生成
stock_bundle_id 必填 string
【批次组ID】 商品券批次组的唯一标识,由微信支付生成,本接口会同步修改批次组内所有批次的对应预算信息。请确保该批次组属于 product_coupon_id 对应的商品券
body 包体参数
out_request_no 必填 string(40)
【修改请求单号】 品牌修改批次发放次数的请求流水号,品牌侧需保持唯一性,可使用 数字、大小写字母、下划线_、短横线- 组成,长度在6-40个字符之间
update_mode 必填 string
【更新模式】 本接口每次只支持更新一种限额,请选择对应的模式,并传入对应的字段。如果你需要调整多个维度的限制,请使用不同的模式多次调用本接口
可选取值
MAX_COUNT: 更新批次发放次数总上限MAX_COUNT_PER_DAY: 更新批次每日发放次数上限
current_max_count 选填 integer
【当前批次发放次数总上限】 当前批次发放次数总上限,调用本接口前,请先通过查询商品券批次详情接口获取。当且仅当 update_mode 为 MAX_COUNT 时必传,其他模式下不应填写
target_max_count 选填 integer
【目标批次发放次数总上限】 将批次发放次数总上限更新为本值,允许小于当前批次发放次数总上限,但是不得小于当前已发放总次数。当且仅当 update_mode 为 MAX_COUNT 时必传,其他模式下不应填写
current_max_count_per_day 选填 integer
【当前批次每日发放次数上限】 当前批次每日发放次数上限,调用本接口前,请先通过查询商品券批次详情接口获取。当且仅当 update_mode 为 MAX_COUNT_PER_DAY 时必传,其他模式下不应填写
target_max_count_per_day 选填 integer
【目标批次每日发放次数上限】 将批次每日发放次数上限更新为本值,允许小于当前批次每日发放次数上限。当且仅当 update_mode 为 MAX_COUNT_PER_DAY 时必传,其他模式下不应填写
brand_id 必填 string
【品牌ID】 微信支付为品牌方分配的唯一标识,该品牌应与服务商存在授权关系
请求示例
POST
1curl -X POST \ 2 https://api.mch.weixin.qq.com/v3/marketing/partner/product-coupon/product-coupons/200000001/stock-bundles/123456789/update-budget \ 3 -H "Authorization: WECHATPAY2-SHA256-RSA2048 mchid=\"1900000001\",..." \ 4 -H "Accept: application/json" \ 5 -H "Content-Type: application/json" \ 6 -d '{ 7 "out_request_no" : "BUDGET1212512514", 8 "update_mode" : "MAX_COUNT", 9 "current_max_count" : 1, 10 "target_max_count" : 1, 11 "current_max_count_per_day" : 1, 12 "target_max_count_per_day" : 1, 13 "brand_id" : "120344" 14 }' 15
需配合微信支付工具库 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 UpdateStockBundleBudget { 26 private static String HOST = "https://api.mch.weixin.qq.com"; 27 private static String METHOD = "POST"; 28 private static String PATH = "/v3/marketing/partner/product-coupon/product-coupons/{product_coupon_id}/stock-bundles/{stock_bundle_id}/update-budget"; 29 30 public static void main(String[] args) { 31 // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340 32 UpdateStockBundleBudget client = new UpdateStockBundleBudget( 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 UpdateStockBundleBudgetRequest request = new UpdateStockBundleBudgetRequest(); 41 request.productCouponId = "200000001"; 42 request.stockBundleId = "123456789"; 43 request.outRequestNo = "BUDGET1212512514"; 44 request.updateMode = UpdateBudgetMode.MAX_COUNT; 45 request.currentMaxCount = 1L; 46 request.targetMaxCount = 1L; 47 request.currentMaxCountPerDay = 1L; 48 request.targetMaxCountPerDay = 1L; 49 request.brandId = "120344"; 50 try { 51 StockBundleEntity 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 StockBundleEntity run(UpdateStockBundleBudgetRequest request) { 61 String uri = PATH; 62 uri = uri.replace("{product_coupon_id}", WXPayUtility.urlEncode(request.productCouponId)); 63 uri = uri.replace("{stock_bundle_id}", WXPayUtility.urlEncode(request.stockBundleId)); 64 String reqBody = WXPayUtility.toJson(request); 65 66 Request.Builder reqBuilder = new Request.Builder().url(HOST + uri); 67 reqBuilder.addHeader("Accept", "application/json"); 68 reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId); 69 reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo,privateKey, METHOD, uri, reqBody)); 70 reqBuilder.addHeader("Content-Type", "application/json"); 71 RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody); 72 reqBuilder.method(METHOD, requestBody); 73 Request httpRequest = reqBuilder.build(); 74 75 // 发送HTTP请求 76 OkHttpClient client = new OkHttpClient.Builder().build(); 77 try (Response httpResponse = client.newCall(httpRequest).execute()) { 78 String respBody = WXPayUtility.extractBody(httpResponse); 79 if (httpResponse.code() >= 200 && httpResponse.code() < 300) { 80 // 2XX 成功,验证应答签名 81 WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey, 82 httpResponse.headers(), respBody); 83 84 // 从HTTP应答报文构建返回数据 85 return WXPayUtility.fromJson(respBody, StockBundleEntity.class); 86 } else { 87 throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers()); 88 } 89 } catch (IOException e) { 90 throw new UncheckedIOException("Sending request to " + uri + " failed.", e); 91 } 92 } 93 94 private final String mchid; 95 private final String certificateSerialNo; 96 private final PrivateKey privateKey; 97 private final String wechatPayPublicKeyId; 98 private final PublicKey wechatPayPublicKey; 99 100 public UpdateStockBundleBudget(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) { 101 this.mchid = mchid; 102 this.certificateSerialNo = certificateSerialNo; 103 this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath); 104 this.wechatPayPublicKeyId = wechatPayPublicKeyId; 105 this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath); 106 } 107 108 public static class UpdateStockBundleBudgetRequest { 109 @SerializedName("out_request_no") 110 public String outRequestNo; 111 112 @SerializedName("product_coupon_id") 113 @Expose(serialize = false) 114 public String productCouponId; 115 116 @SerializedName("stock_bundle_id") 117 @Expose(serialize = false) 118 public String stockBundleId; 119 120 @SerializedName("update_mode") 121 public UpdateBudgetMode updateMode; 122 123 @SerializedName("current_max_count") 124 public Long currentMaxCount; 125 126 @SerializedName("target_max_count") 127 public Long targetMaxCount; 128 129 @SerializedName("current_max_count_per_day") 130 public Long currentMaxCountPerDay; 131 132 @SerializedName("target_max_count_per_day") 133 public Long targetMaxCountPerDay; 134 135 @SerializedName("brand_id") 136 public String brandId; 137 } 138 139 public static class StockBundleEntity { 140 @SerializedName("stock_bundle_id") 141 public String stockBundleId; 142 143 @SerializedName("stock_list") 144 public List<StockEntityInBundle> stockList = new ArrayList<StockEntityInBundle>(); 145 } 146 147 public enum UpdateBudgetMode { 148 @SerializedName("MAX_COUNT") 149 MAX_COUNT, 150 @SerializedName("MAX_COUNT_PER_DAY") 151 MAX_COUNT_PER_DAY 152 } 153 154 public static class StockEntityInBundle { 155 @SerializedName("product_coupon_id") 156 public String productCouponId; 157 158 @SerializedName("stock_id") 159 public String stockId; 160 161 @SerializedName("remark") 162 public String remark; 163 164 @SerializedName("coupon_code_mode") 165 public ProgressiveBundleCouponCodeMode couponCodeMode; 166 167 @SerializedName("coupon_code_count_info") 168 public CouponCodeCountInfo couponCodeCountInfo; 169 170 @SerializedName("stock_send_rule") 171 public StockSendRule stockSendRule; 172 173 @SerializedName("progressive_bundle_usage_rule") 174 public StockUsageRule progressiveBundleUsageRule; 175 176 @SerializedName("stock_bundle_info") 177 public StockBundleInfo stockBundleInfo; 178 179 @SerializedName("usage_rule_display_info") 180 public UsageRuleDisplayInfo usageRuleDisplayInfo; 181 182 @SerializedName("coupon_display_info") 183 public CouponDisplayInfo couponDisplayInfo; 184 185 @SerializedName("notify_config") 186 public NotifyConfig notifyConfig; 187 188 @SerializedName("store_scope") 189 public StockStoreScope storeScope; 190 191 @SerializedName("sent_count_info") 192 public StockSentCountInfo sentCountInfo; 193 194 @SerializedName("state") 195 public StockState state; 196 197 @SerializedName("deactivate_request_no") 198 public String deactivateRequestNo; 199 200 @SerializedName("deactivate_time") 201 public String deactivateTime; 202 203 @SerializedName("deactivate_reason") 204 public String deactivateReason; 205 206 @SerializedName("brand_id") 207 public String brandId; 208 } 209 210 public enum ProgressiveBundleCouponCodeMode { 211 @SerializedName("WECHATPAY") 212 WECHATPAY, 213 @SerializedName("UPLOAD") 214 UPLOAD 215 } 216 217 public static class CouponCodeCountInfo { 218 @SerializedName("total_count") 219 public Long totalCount; 220 221 @SerializedName("available_count") 222 public Long availableCount; 223 } 224 225 public static class StockSendRule { 226 @SerializedName("max_count") 227 public Long maxCount; 228 229 @SerializedName("max_count_per_day") 230 public Long maxCountPerDay; 231 232 @SerializedName("max_count_per_user") 233 public Long maxCountPerUser; 234 } 235 236 public static class StockUsageRule { 237 @SerializedName("coupon_available_period") 238 public CouponAvailablePeriod couponAvailablePeriod; 239 240 @SerializedName("normal_coupon") 241 public NormalCouponUsageRule normalCoupon; 242 243 @SerializedName("discount_coupon") 244 public DiscountCouponUsageRule discountCoupon; 245 246 @SerializedName("exchange_coupon") 247 public ExchangeCouponUsageRule exchangeCoupon; 248 } 249 250 public static class StockBundleInfo { 251 @SerializedName("stock_bundle_id") 252 public String stockBundleId; 253 254 @SerializedName("stock_bundle_index") 255 public Long stockBundleIndex; 256 } 257 258 public static class UsageRuleDisplayInfo { 259 @SerializedName("coupon_usage_method_list") 260 public List<CouponUsageMethod> couponUsageMethodList = new ArrayList<CouponUsageMethod>(); 261 262 @SerializedName("mini_program_appid") 263 public String miniProgramAppid; 264 265 @SerializedName("mini_program_path") 266 public String miniProgramPath; 267 268 @SerializedName("app_path") 269 public String appPath; 270 271 @SerializedName("usage_description") 272 public String usageDescription; 273 274 @SerializedName("coupon_available_store_info") 275 public CouponAvailableStoreInfo couponAvailableStoreInfo; 276 } 277 278 public static class CouponDisplayInfo { 279 @SerializedName("code_display_mode") 280 public CouponCodeDisplayMode codeDisplayMode; 281 282 @SerializedName("background_color") 283 public String backgroundColor; 284 285 @SerializedName("entrance_mini_program") 286 public EntranceMiniProgram entranceMiniProgram; 287 288 @SerializedName("entrance_official_account") 289 public EntranceOfficialAccount entranceOfficialAccount; 290 291 @SerializedName("entrance_finder") 292 public EntranceFinder entranceFinder; 293 } 294 295 public static class NotifyConfig { 296 @SerializedName("notify_appid") 297 public String notifyAppid; 298 } 299 300 public enum StockStoreScope { 301 @SerializedName("NONE") 302 NONE, 303 @SerializedName("ALL") 304 ALL, 305 @SerializedName("SPECIFIC") 306 SPECIFIC 307 } 308 309 public static class StockSentCountInfo { 310 @SerializedName("total_count") 311 public Long totalCount; 312 313 @SerializedName("today_count") 314 public Long todayCount; 315 } 316 317 public enum StockState { 318 @SerializedName("AUDITING") 319 AUDITING, 320 @SerializedName("SENDING") 321 SENDING, 322 @SerializedName("PAUSED") 323 PAUSED, 324 @SerializedName("STOPPED") 325 STOPPED, 326 @SerializedName("DEACTIVATED") 327 DEACTIVATED 328 } 329 330 public static class CouponAvailablePeriod { 331 @SerializedName("available_begin_time") 332 public String availableBeginTime; 333 334 @SerializedName("available_end_time") 335 public String availableEndTime; 336 337 @SerializedName("available_days") 338 public Long availableDays; 339 340 @SerializedName("wait_days_after_receive") 341 public Long waitDaysAfterReceive; 342 343 @SerializedName("weekly_available_period") 344 public FixedWeekPeriod weeklyAvailablePeriod; 345 346 @SerializedName("irregular_available_period_list") 347 public List<TimePeriod> irregularAvailablePeriodList; 348 } 349 350 public static class NormalCouponUsageRule { 351 @SerializedName("threshold") 352 public Long threshold; 353 354 @SerializedName("discount_amount") 355 public Long discountAmount; 356 } 357 358 public static class DiscountCouponUsageRule { 359 @SerializedName("threshold") 360 public Long threshold; 361 362 @SerializedName("percent_off") 363 public Long percentOff; 364 } 365 366 public static class ExchangeCouponUsageRule { 367 @SerializedName("threshold") 368 public Long threshold; 369 370 @SerializedName("exchange_price") 371 public Long exchangePrice; 372 } 373 374 public enum CouponUsageMethod { 375 @SerializedName("OFFLINE") 376 OFFLINE, 377 @SerializedName("MINI_PROGRAM") 378 MINI_PROGRAM, 379 @SerializedName("APP") 380 APP, 381 @SerializedName("PAYMENT_CODE") 382 PAYMENT_CODE 383 } 384 385 public static class CouponAvailableStoreInfo { 386 @SerializedName("description") 387 public String description; 388 389 @SerializedName("mini_program_appid") 390 public String miniProgramAppid; 391 392 @SerializedName("mini_program_path") 393 public String miniProgramPath; 394 } 395 396 public enum CouponCodeDisplayMode { 397 @SerializedName("INVISIBLE") 398 INVISIBLE, 399 @SerializedName("BARCODE") 400 BARCODE, 401 @SerializedName("QRCODE") 402 QRCODE 403 } 404 405 public static class EntranceMiniProgram { 406 @SerializedName("appid") 407 public String appid; 408 409 @SerializedName("path") 410 public String path; 411 412 @SerializedName("entrance_wording") 413 public String entranceWording; 414 415 @SerializedName("guidance_wording") 416 public String guidanceWording; 417 } 418 419 public static class EntranceOfficialAccount { 420 @SerializedName("appid") 421 public String appid; 422 } 423 424 public static class EntranceFinder { 425 @SerializedName("finder_id") 426 public String finderId; 427 428 @SerializedName("finder_video_id") 429 public String finderVideoId; 430 431 @SerializedName("finder_video_cover_image_url") 432 public String finderVideoCoverImageUrl; 433 } 434 435 public static class FixedWeekPeriod { 436 @SerializedName("day_list") 437 public List<WeekEnum> dayList; 438 439 @SerializedName("day_period_list") 440 public List<PeriodOfTheDay> dayPeriodList; 441 } 442 443 public static class TimePeriod { 444 @SerializedName("begin_time") 445 public String beginTime; 446 447 @SerializedName("end_time") 448 public String endTime; 449 } 450 451 public enum WeekEnum { 452 @SerializedName("MONDAY") 453 MONDAY, 454 @SerializedName("TUESDAY") 455 TUESDAY, 456 @SerializedName("WEDNESDAY") 457 WEDNESDAY, 458 @SerializedName("THURSDAY") 459 THURSDAY, 460 @SerializedName("FRIDAY") 461 FRIDAY, 462 @SerializedName("SATURDAY") 463 SATURDAY, 464 @SerializedName("SUNDAY") 465 SUNDAY 466 } 467 468 public static class PeriodOfTheDay { 469 @SerializedName("begin_time") 470 public Long beginTime; 471 472 @SerializedName("end_time") 473 public Long endTime; 474 } 475 476} 477
需配合微信支付工具库 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 "time" 12) 13 14func main() { 15 // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340 16 config, err := wxpay_utility.CreateMchConfig( 17 "19xxxxxxxx", // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/partner/4013080340 18 "1DDE55AD98Exxxxxxxxxx", // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013058924 19 "/path/to/apiclient_key.pem", // 商户API证书私钥文件路径,本地文件路径 20 "PUB_KEY_ID_xxxxxxxxxxxxx", // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013038589 21 "/path/to/wxp_pub.pem", // 微信支付公钥文件路径,本地文件路径 22 ) 23 if err != nil { 24 fmt.Println(err) 25 return 26 } 27 28 request := &UpdateStockBundleBudgetRequest{ 29 ProductCouponId: wxpay_utility.String("200000001"), 30 StockBundleId: wxpay_utility.String("123456789"), 31 OutRequestNo: wxpay_utility.String("BUDGET1212512514"), 32 UpdateMode: UPDATEBUDGETMODE_MAX_COUNT.Ptr(), 33 CurrentMaxCount: wxpay_utility.Int64(1), 34 TargetMaxCount: wxpay_utility.Int64(1), 35 CurrentMaxCountPerDay: wxpay_utility.Int64(1), 36 TargetMaxCountPerDay: wxpay_utility.Int64(1), 37 BrandId: wxpay_utility.String("120344"), 38 } 39 40 response, err := UpdateStockBundleBudget(config, request) 41 if err != nil { 42 fmt.Printf("请求失败: %+v\n", err) 43 // TODO: 请求失败,根据状态码执行不同的处理 44 return 45 } 46 47 // TODO: 请求成功,继续业务逻辑 48 fmt.Printf("请求成功: %+v\n", response) 49} 50 51func UpdateStockBundleBudget(config *wxpay_utility.MchConfig, request *UpdateStockBundleBudgetRequest) (response *StockBundleEntity, err error) { 52 const ( 53 host = "https://api.mch.weixin.qq.com" 54 method = "POST" 55 path = "/v3/marketing/partner/product-coupon/product-coupons/{product_coupon_id}/stock-bundles/{stock_bundle_id}/update-budget" 56 ) 57 58 reqUrl, err := url.Parse(fmt.Sprintf("%s%s", host, path)) 59 if err != nil { 60 return nil, err 61 } 62 reqUrl.Path = strings.Replace(reqUrl.Path, "{product_coupon_id}", url.PathEscape(*request.ProductCouponId), -1) 63 reqUrl.Path = strings.Replace(reqUrl.Path, "{stock_bundle_id}", url.PathEscape(*request.StockBundleId), -1) 64 reqBody, err := json.Marshal(request) 65 if err != nil { 66 return nil, err 67 } 68 httpRequest, err := http.NewRequest(method, reqUrl.String(), bytes.NewReader(reqBody)) 69 if err != nil { 70 return nil, err 71 } 72 httpRequest.Header.Set("Accept", "application/json") 73 httpRequest.Header.Set("Wechatpay-Serial", config.WechatPayPublicKeyId()) 74 httpRequest.Header.Set("Content-Type", "application/json") 75 authorization, err := wxpay_utility.BuildAuthorization(config.MchId(), config.CertificateSerialNo(), config.PrivateKey(), method, reqUrl.RequestURI(), reqBody) 76 if err != nil { 77 return nil, err 78 } 79 httpRequest.Header.Set("Authorization", authorization) 80 81 client := &http.Client{} 82 httpResponse, err := client.Do(httpRequest) 83 if err != nil { 84 return nil, err 85 } 86 respBody, err := wxpay_utility.ExtractResponseBody(httpResponse) 87 if err != nil { 88 return nil, err 89 } 90 if httpResponse.StatusCode >= 200 && httpResponse.StatusCode < 300 { 91 // 2XX 成功,验证应答签名 92 err = wxpay_utility.ValidateResponse( 93 config.WechatPayPublicKeyId(), 94 config.WechatPayPublicKey(), 95 &httpResponse.Header, 96 respBody, 97 ) 98 if err != nil { 99 return nil, err 100 } 101 response := &StockBundleEntity{} 102 if err := json.Unmarshal(respBody, response); err != nil { 103 return nil, err 104 } 105 106 return response, nil 107 } else { 108 return nil, wxpay_utility.NewApiException( 109 httpResponse.StatusCode, 110 httpResponse.Header, 111 respBody, 112 ) 113 } 114} 115 116type UpdateStockBundleBudgetRequest struct { 117 OutRequestNo *string `json:"out_request_no,omitempty"` 118 ProductCouponId *string `json:"product_coupon_id,omitempty"` 119 StockBundleId *string `json:"stock_bundle_id,omitempty"` 120 UpdateMode *UpdateBudgetMode `json:"update_mode,omitempty"` 121 CurrentMaxCount *int64 `json:"current_max_count,omitempty"` 122 TargetMaxCount *int64 `json:"target_max_count,omitempty"` 123 CurrentMaxCountPerDay *int64 `json:"current_max_count_per_day,omitempty"` 124 TargetMaxCountPerDay *int64 `json:"target_max_count_per_day,omitempty"` 125 BrandId *string `json:"brand_id,omitempty"` 126} 127 128func (o *UpdateStockBundleBudgetRequest) MarshalJSON() ([]byte, error) { 129 type Alias UpdateStockBundleBudgetRequest 130 a := &struct { 131 ProductCouponId *string `json:"product_coupon_id,omitempty"` 132 StockBundleId *string `json:"stock_bundle_id,omitempty"` 133 *Alias 134 }{ 135 // 序列化时移除非 Body 字段 136 ProductCouponId: nil, 137 StockBundleId: nil, 138 Alias: (*Alias)(o), 139 } 140 return json.Marshal(a) 141} 142 143type StockBundleEntity struct { 144 StockBundleId *string `json:"stock_bundle_id,omitempty"` 145 StockList []StockEntityInBundle `json:"stock_list,omitempty"` 146} 147 148type UpdateBudgetMode string 149 150func (e UpdateBudgetMode) Ptr() *UpdateBudgetMode { 151 return &e 152} 153 154const ( 155 UPDATEBUDGETMODE_MAX_COUNT UpdateBudgetMode = "MAX_COUNT" 156 UPDATEBUDGETMODE_MAX_COUNT_PER_DAY UpdateBudgetMode = "MAX_COUNT_PER_DAY" 157) 158 159type StockEntityInBundle struct { 160 ProductCouponId *string `json:"product_coupon_id,omitempty"` 161 StockId *string `json:"stock_id,omitempty"` 162 Remark *string `json:"remark,omitempty"` 163 CouponCodeMode *ProgressiveBundleCouponCodeMode `json:"coupon_code_mode,omitempty"` 164 CouponCodeCountInfo *CouponCodeCountInfo `json:"coupon_code_count_info,omitempty"` 165 StockSendRule *StockSendRule `json:"stock_send_rule,omitempty"` 166 ProgressiveBundleUsageRule *StockUsageRule `json:"progressive_bundle_usage_rule,omitempty"` 167 StockBundleInfo *StockBundleInfo `json:"stock_bundle_info,omitempty"` 168 UsageRuleDisplayInfo *UsageRuleDisplayInfo `json:"usage_rule_display_info,omitempty"` 169 CouponDisplayInfo *CouponDisplayInfo `json:"coupon_display_info,omitempty"` 170 NotifyConfig *NotifyConfig `json:"notify_config,omitempty"` 171 StoreScope *StockStoreScope `json:"store_scope,omitempty"` 172 SentCountInfo *StockSentCountInfo `json:"sent_count_info,omitempty"` 173 State *StockState `json:"state,omitempty"` 174 DeactivateRequestNo *string `json:"deactivate_request_no,omitempty"` 175 DeactivateTime *time.Time `json:"deactivate_time,omitempty"` 176 DeactivateReason *string `json:"deactivate_reason,omitempty"` 177 BrandId *string `json:"brand_id,omitempty"` 178} 179 180type ProgressiveBundleCouponCodeMode string 181 182func (e ProgressiveBundleCouponCodeMode) Ptr() *ProgressiveBundleCouponCodeMode { 183 return &e 184} 185 186const ( 187 PROGRESSIVEBUNDLECOUPONCODEMODE_WECHATPAY ProgressiveBundleCouponCodeMode = "WECHATPAY" 188 PROGRESSIVEBUNDLECOUPONCODEMODE_UPLOAD ProgressiveBundleCouponCodeMode = "UPLOAD" 189) 190 191type CouponCodeCountInfo struct { 192 TotalCount *int64 `json:"total_count,omitempty"` 193 AvailableCount *int64 `json:"available_count,omitempty"` 194} 195 196type StockSendRule struct { 197 MaxCount *int64 `json:"max_count,omitempty"` 198 MaxCountPerDay *int64 `json:"max_count_per_day,omitempty"` 199 MaxCountPerUser *int64 `json:"max_count_per_user,omitempty"` 200} 201 202type StockUsageRule struct { 203 CouponAvailablePeriod *CouponAvailablePeriod `json:"coupon_available_period,omitempty"` 204 NormalCoupon *NormalCouponUsageRule `json:"normal_coupon,omitempty"` 205 DiscountCoupon *DiscountCouponUsageRule `json:"discount_coupon,omitempty"` 206 ExchangeCoupon *ExchangeCouponUsageRule `json:"exchange_coupon,omitempty"` 207} 208 209type StockBundleInfo struct { 210 StockBundleId *string `json:"stock_bundle_id,omitempty"` 211 StockBundleIndex *int64 `json:"stock_bundle_index,omitempty"` 212} 213 214type UsageRuleDisplayInfo struct { 215 CouponUsageMethodList []CouponUsageMethod `json:"coupon_usage_method_list,omitempty"` 216 MiniProgramAppid *string `json:"mini_program_appid,omitempty"` 217 MiniProgramPath *string `json:"mini_program_path,omitempty"` 218 AppPath *string `json:"app_path,omitempty"` 219 UsageDescription *string `json:"usage_description,omitempty"` 220 CouponAvailableStoreInfo *CouponAvailableStoreInfo `json:"coupon_available_store_info,omitempty"` 221} 222 223type CouponDisplayInfo struct { 224 CodeDisplayMode *CouponCodeDisplayMode `json:"code_display_mode,omitempty"` 225 BackgroundColor *string `json:"background_color,omitempty"` 226 EntranceMiniProgram *EntranceMiniProgram `json:"entrance_mini_program,omitempty"` 227 EntranceOfficialAccount *EntranceOfficialAccount `json:"entrance_official_account,omitempty"` 228 EntranceFinder *EntranceFinder `json:"entrance_finder,omitempty"` 229} 230 231type NotifyConfig struct { 232 NotifyAppid *string `json:"notify_appid,omitempty"` 233} 234 235type StockStoreScope string 236 237func (e StockStoreScope) Ptr() *StockStoreScope { 238 return &e 239} 240 241const ( 242 STOCKSTORESCOPE_NONE StockStoreScope = "NONE" 243 STOCKSTORESCOPE_ALL StockStoreScope = "ALL" 244 STOCKSTORESCOPE_SPECIFIC StockStoreScope = "SPECIFIC" 245) 246 247type StockSentCountInfo struct { 248 TotalCount *int64 `json:"total_count,omitempty"` 249 TodayCount *int64 `json:"today_count,omitempty"` 250} 251 252type StockState string 253 254func (e StockState) Ptr() *StockState { 255 return &e 256} 257 258const ( 259 STOCKSTATE_AUDITING StockState = "AUDITING" 260 STOCKSTATE_SENDING StockState = "SENDING" 261 STOCKSTATE_PAUSED StockState = "PAUSED" 262 STOCKSTATE_STOPPED StockState = "STOPPED" 263 STOCKSTATE_DEACTIVATED StockState = "DEACTIVATED" 264) 265 266type CouponAvailablePeriod struct { 267 AvailableBeginTime *string `json:"available_begin_time,omitempty"` 268 AvailableEndTime *string `json:"available_end_time,omitempty"` 269 AvailableDays *int64 `json:"available_days,omitempty"` 270 WaitDaysAfterReceive *int64 `json:"wait_days_after_receive,omitempty"` 271 WeeklyAvailablePeriod *FixedWeekPeriod `json:"weekly_available_period,omitempty"` 272 IrregularAvailablePeriodList []TimePeriod `json:"irregular_available_period_list,omitempty"` 273} 274 275type NormalCouponUsageRule struct { 276 Threshold *int64 `json:"threshold,omitempty"` 277 DiscountAmount *int64 `json:"discount_amount,omitempty"` 278} 279 280type DiscountCouponUsageRule struct { 281 Threshold *int64 `json:"threshold,omitempty"` 282 PercentOff *int64 `json:"percent_off,omitempty"` 283} 284 285type ExchangeCouponUsageRule struct { 286 Threshold *int64 `json:"threshold,omitempty"` 287 ExchangePrice *int64 `json:"exchange_price,omitempty"` 288} 289 290type CouponUsageMethod string 291 292func (e CouponUsageMethod) Ptr() *CouponUsageMethod { 293 return &e 294} 295 296const ( 297 COUPONUSAGEMETHOD_OFFLINE CouponUsageMethod = "OFFLINE" 298 COUPONUSAGEMETHOD_MINI_PROGRAM CouponUsageMethod = "MINI_PROGRAM" 299 COUPONUSAGEMETHOD_APP CouponUsageMethod = "APP" 300 COUPONUSAGEMETHOD_PAYMENT_CODE CouponUsageMethod = "PAYMENT_CODE" 301) 302 303type CouponAvailableStoreInfo struct { 304 Description *string `json:"description,omitempty"` 305 MiniProgramAppid *string `json:"mini_program_appid,omitempty"` 306 MiniProgramPath *string `json:"mini_program_path,omitempty"` 307} 308 309type CouponCodeDisplayMode string 310 311func (e CouponCodeDisplayMode) Ptr() *CouponCodeDisplayMode { 312 return &e 313} 314 315const ( 316 COUPONCODEDISPLAYMODE_INVISIBLE CouponCodeDisplayMode = "INVISIBLE" 317 COUPONCODEDISPLAYMODE_BARCODE CouponCodeDisplayMode = "BARCODE" 318 COUPONCODEDISPLAYMODE_QRCODE CouponCodeDisplayMode = "QRCODE" 319) 320 321type EntranceMiniProgram struct { 322 Appid *string `json:"appid,omitempty"` 323 Path *string `json:"path,omitempty"` 324 EntranceWording *string `json:"entrance_wording,omitempty"` 325 GuidanceWording *string `json:"guidance_wording,omitempty"` 326} 327 328type EntranceOfficialAccount struct { 329 Appid *string `json:"appid,omitempty"` 330} 331 332type EntranceFinder struct { 333 FinderId *string `json:"finder_id,omitempty"` 334 FinderVideoId *string `json:"finder_video_id,omitempty"` 335 FinderVideoCoverImageUrl *string `json:"finder_video_cover_image_url,omitempty"` 336} 337 338type FixedWeekPeriod struct { 339 DayList []WeekEnum `json:"day_list,omitempty"` 340 DayPeriodList []PeriodOfTheDay `json:"day_period_list,omitempty"` 341} 342 343type TimePeriod struct { 344 BeginTime *string `json:"begin_time,omitempty"` 345 EndTime *string `json:"end_time,omitempty"` 346} 347 348type WeekEnum string 349 350func (e WeekEnum) Ptr() *WeekEnum { 351 return &e 352} 353 354const ( 355 WEEKENUM_MONDAY WeekEnum = "MONDAY" 356 WEEKENUM_TUESDAY WeekEnum = "TUESDAY" 357 WEEKENUM_WEDNESDAY WeekEnum = "WEDNESDAY" 358 WEEKENUM_THURSDAY WeekEnum = "THURSDAY" 359 WEEKENUM_FRIDAY WeekEnum = "FRIDAY" 360 WEEKENUM_SATURDAY WeekEnum = "SATURDAY" 361 WEEKENUM_SUNDAY WeekEnum = "SUNDAY" 362) 363 364type PeriodOfTheDay struct { 365 BeginTime *int64 `json:"begin_time,omitempty"` 366 EndTime *int64 `json:"end_time,omitempty"` 367} 368
应答参数
200 OK
stock_bundle_id 必填 string(40)
【批次组ID】 商品券批次组的唯一标识,由微信支付生成
stock_list 必填 array[object]
【批次列表】 批次组内批次列表
| 属性 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
product_coupon_id 必填 string(40) 【商品券ID】 商品券的唯一标识,由微信支付生成 stock_id 必填 string(40) 【批次ID】 商品券批次的唯一标识,由微信支付生成 remark 选填 string(20) 【备注】 仅配置品牌可见,用于自定义信息 coupon_code_mode 必填 string 【券Code分配模式】 决定发券时用户商品券Code如何产生 可选取值
coupon_code_count_info 选填 object 【品牌方预上传的券Code数量信息】 当且仅当
stock_send_rule 必填 object 【发放规则】 发放规则
progressive_bundle_usage_rule 选填 object 【多次优惠使用规则】 本批次属于某个多次优惠批次组,这里记录的是本批次的使用规则,当且仅当
stock_bundle_info 必填 object 【批次组信息】 批次所在批次组信息
usage_rule_display_info 必填 object 【券使用规则展示信息】 券使用规则展示信息
coupon_display_info 必填 object 【用户商品券展示信息】 用户商品券在卡包中的展示详情,包括引导用户的自定义入口
notify_config 必填 object 【事件通知配置】 发生券相关事件时,微信支付会向服务商发送通知,需要提供通知相关配置
store_scope 必填 string 【可用门店范围】 控制该批次可以在品牌下哪些门店使用 可选取值
sent_count_info 必填 object 【已发放次数】 本批次已发放次数
state 必填 string 【批次状态】 商品券批次状态 可选取值
deactivate_request_no 选填 string(128) 【失效请求单号】 当且仅当 deactivate_time 选填 string 【失效时间】 当且仅当 deactivate_reason 选填 string(150) 【失效原因】 当且仅当 brand_id 必填 string 【品牌ID】 微信支付为品牌方分配的唯一标识,该品牌应与服务商存在授权关系 |
应答示例
200 OK
1{ 2 "stock_bundle_id" : "123456789", 3 "stock_list" : [ 4 { 5 "product_coupon_id" : "200000001", 6 "stock_id" : "123456789", 7 "remark" : "满减券", 8 "coupon_code_mode" : "UPLOAD", 9 "coupon_code_count_info" : { 10 "total_count" : 10000, 11 "available_count" : 999 12 }, 13 "stock_send_rule" : { 14 "max_count" : 10000000, 15 "max_count_per_day" : 10000, 16 "max_count_per_user" : 1 17 }, 18 "progressive_bundle_usage_rule" : { 19 "coupon_available_period" : { 20 "available_begin_time" : "2025-01-01T00:00:00+08:00", 21 "available_end_time" : "2025-10-01T00:00:00+08:00", 22 "available_days" : 10, 23 "wait_days_after_receive" : 1, 24 "weekly_available_period" : { 25 "day_list" : [ 26 "MONDAY" 27 ], 28 "day_period_list" : [ 29 { 30 "begin_time" : 60, 31 "end_time" : 86399 32 } 33 ] 34 }, 35 "irregular_available_period_list" : [ 36 { 37 "begin_time" : "2025-01-01T00:00:00+08:00", 38 "end_time" : "2025-10-01T00:00:00+08:00" 39 } 40 ] 41 }, 42 "normal_coupon" : { 43 "threshold" : 10000, 44 "discount_amount" : 100 45 }, 46 "discount_coupon" : { 47 "threshold" : 10000, 48 "percent_off" : 30 49 }, 50 "exchange_coupon" : { 51 "threshold" : 10000, 52 "exchange_price" : 100 53 } 54 }, 55 "stock_bundle_info" : { 56 "stock_bundle_id" : "123456789", 57 "stock_bundle_index" : 0 58 }, 59 "usage_rule_display_info" : { 60 "coupon_usage_method_list" : [ 61 "MINI_PROGRAM" 62 ], 63 "mini_program_appid" : "wx1234567890", 64 "mini_program_path" : "/pages/index/product", 65 "app_path" : "https://www.example.com/jump-to-app", 66 "usage_description" : "全场可用", 67 "coupon_available_store_info" : { 68 "description" : "可在上海市区的所有门店使用,详细列表参考小程序内信息为准", 69 "mini_program_appid" : "wx1234567890", 70 "mini_program_path" : "/pages/index/store-list" 71 } 72 }, 73 "coupon_display_info" : { 74 "code_display_mode" : "QRCODE", 75 "background_color" : "Color010", 76 "entrance_mini_program" : { 77 "appid" : "wx1234567890", 78 "path" : "/pages/index/product", 79 "entrance_wording" : "欢迎选购", 80 "guidance_wording" : "获取更多优惠" 81 }, 82 "entrance_official_account" : { 83 "appid" : "wx1234567890" 84 }, 85 "entrance_finder" : { 86 "finder_id" : "gh_12345678", 87 "finder_video_id" : "UDFsdf24df34dD456Hdf34", 88 "finder_video_cover_image_url" : "https://wxpaylogo.qpic.cn/wxpaylogo/xxxxx/xxx" 89 } 90 }, 91 "notify_config" : { 92 "notify_appid" : "wx4fd12345678" 93 }, 94 "store_scope" : "SPECIFIC", 95 "sent_count_info" : { 96 "total_count" : 100, 97 "today_count" : 10 98 }, 99 "state" : "SENDING", 100 "deactivate_request_no" : "1002600620019090123143254436", 101 "deactivate_time" : "2025-01-01T00:00+08:00", 102 "deactivate_reason" : "批次信息有误,重新创建", 103 "brand_id" : "120344" 104 } 105 ] 106} 107
错误码
以下是本接口返回的错误码列表。详细错误码规则,请参考微信支付接口规则-错误码和错误提示
状态码 | 错误码 | 描述 | 解决方案 |
|---|---|---|---|
400 | PARAM_ERROR | 参数错误 | 请根据错误提示正确传入参数 |
400 | INVALID_REQUEST | HTTP 请求不符合微信支付 APIv3 接口规则 | 请参阅 接口规则 |
401 | SIGN_ERROR | 验证不通过 | 请参阅 签名常见问题 |
500 | SYSTEM_ERROR | 系统异常,请稍后重试 | 请稍后重试 |
400 | INVALID_REQUEST | 已过期的批次不可修改发放预算 | 请确认批次是否处于有效期 |
400 | INVALID_REQUEST | 传入参数不符合业务规则 | 请参考文档中对每个字段的要求以及组合要求,确认请求参数是否满足 |
404 | NOT_FOUND | 未找到 product_coupon_id 对应的商品券 | 请确认 product_coupon_id 存在且属于当前品牌 |
404 | NOT_FOUND | 未找到 stock_id 对应的商品券批次 | 请确认 stock_id 存在且属于当前商品券 |
429 | RATELIMIT_EXCEEDED | 请求超过接口频率限制 | 请稍后使用原参数重试 |

