---
url: "https://pay.weixin.qq.com/doc/brand/4016756233.md"
title: "【多次优惠-全场-满减券】API请求示例"
doc_id: 4016756233
---

>更新时间：2025.12.04

curlJavaGo

```


## 2. 多次优惠-全场-满减券 (usage_mode=PROGRESSIVE_BUNDLE, scope=ALL, type=NORMAL)

```
curl -X POST \
  https://api.mch.weixin.qq.com/brand/marketing/product-coupon/product-coupons \
  -H "Authorization: WECHATPAY-BRAND-SHA256-RSA2048 brand_id=\"XXXX\",..." \
  -H "Accept: application/json" \
  -H "Wechatpay-Serial: PUB_KEY_ID_XXXX"  \
  -H "Content-Type: application/json" \
  -d '{
    "out_request_no": "PROGRESSIVE_BUNDLE_ALL_NORMAL_20250101_002", # 必填，创建请求单号，品牌侧需保持唯一性，可使用数字、大小写字母、下划线_、短横线-组成，长度6-40字符
    "scope": "ALL", # 必填，优惠范围：ALL=全场券（券类型仅可配置NORMAL或DISCOUNT），SINGLE=单品券（券类型可配置NORMAL、DISCOUNT或EXCHANGE）
    "type": "NORMAL", # 必填，商品券类型：NORMAL=满减券，DISCOUNT=折扣券，EXCHANGE=兑换券（仅scope=SINGLE时可用）
    "usage_mode": "PROGRESSIVE_BUNDLE", # 必填，使用模式：SINGLE=单券（使用一次后失效），PROGRESSIVE_BUNDLE=多次优惠（由一组批次组成，用户按顺序使用，每次核销后发放下一张券）

    "progressive_bundle_usage_info": { # 当usage_mode=PROGRESSIVE_BUNDLE时必填，多次优惠模式信息
      "count": 5, # 必填，可使用次数，最少3次，最多15次
      "interval_days": 1 # 选填，每次优惠间隔天数，最少0天（不限制），最多7天
    },

    "display_info": { # 必填，展示信息
      "name": "全场满减券-5次递增优惠", # 必填，商品券名称
      "image_url": "https://wxpaylogo.qpic.cn/wxpaylogo/xxxxx/xxx", # 必填，商品图片URL
      "background_url": "https://wxpaylogo.qpic.cn/wxpaylogo/xxxxx/xxx", # 必填，背景图URL
      "detail_image_url_list": [ # 选填，详情图URL列表
        "https://wxpaylogo.qpic.cn/wxpaylogo/xxxxx/xxx"
      ]
    },

    "out_product_no": "Product_ProgressiveBundle_002", # 选填，外部商品ID

    "stock_bundle": { # 当usage_mode=PROGRESSIVE_BUNDLE时必填，批次组信息
      "remark": "全场满减券批次", # 选填，备注
      "coupon_code_mode": "WECHATPAY", # 必填，券Code分配模式

      "stock_send_rule": { # 必填，发放规则
        "max_count": 10000000, # 必填，总发放次数上限，最小1，最大100000000（1亿）
        "max_count_per_day": 100000, # 选填，每日发放上限，最小1，最大100000000（1亿）
        "max_count_per_user": 1 # 必填，每用户领取上限，最小1，最大100
      },

      "progressive_bundle_usage_rule": { # 当usage_mode=PROGRESSIVE_BUNDLE时必填，多次优惠使用规则
        "coupon_available_period": { # 必填，券可核销时间
          "available_begin_time": "2025-08-01T00:00:00+08:00", # 必填，开始时间，RFC3339格式
          "available_end_time": "2025-12-31T23:59:59+08:00", # 必填，结束时间，RFC3339格式
          "available_days": 30, # 选填，多次优惠有效天数，最少3天，最多365天（1年）
          "wait_days_after_receive": 0, # 选填，领取后N天生效，最少0天（立即生效），最多30天
          "interval_days": 1, # 选填，使用间隔天数，最少0天（不限制），最多7天
          "weekly_available_period": { # 选填，每周可用时间
            "day_list": ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY"] # 条件必填，可用星期（此示例仅工作日可用）
          },
          "irregular_available_period_list": [ # 选填，无规律可用时间段，最少1个，最多2个区间
            {
              "begin_time": "2025-10-01T00:00:00+08:00", # 当配置时必填，RFC3339格式
              "end_time": "2025-10-07T23:59:59+08:00" # 当配置时必填，RFC3339格式
            }
          ]
        },
        "special_first": false, # 选填，是否首笔特惠，可选值：true/false，默认false
        "normal_coupon_list": [ # 当type=NORMAL时必填，满减券规则列表，数量必须等于count（最少3个，最多15个）
          { "threshold": 10000, "discount_amount": 1000 }, # 第1次：满100减10（threshold=门槛金额分，0表示无门槛；discount_amount=减免金额分，最小1）
          { "threshold": 10000, "discount_amount": 1500 }, # 第2次：满100减15
          { "threshold": 10000, "discount_amount": 2000 }, # 第3次：满100减20
          { "threshold": 10000, "discount_amount": 2500 }, # 第4次：满100减25
          { "threshold": 10000, "discount_amount": 3000 }  # 第5次：满100减30
        ]
      },

      "usage_rule_display_info": { # 必填，使用规则展示信息
        "coupon_usage_method_list": ["OFFLINE", "MINI_PROGRAM", "APP", "PAYMENT_CODE"], # 必填，使用方式：OFFLINE/MINI_PROGRAM/APP/PAYMENT_CODE
        "mini_program_appid": "wx1234567890", # 条件必填，当包含MINI_PROGRAM时必填
        "mini_program_path": "/pages/index/product", # 条件必填，当包含MINI_PROGRAM时必填
        "app_path": "pages/index/product", # 条件必填，当包含APP时必填
        "usage_description": "全场可用，多次递增满减", # 必填，使用说明
        "coupon_available_store_info": { # 选填，可用门店信息
          "description": "所有门店可用", # 当配置时必填
          "mini_program_appid": "wx1234567890", # 选填
          "mini_program_path": "/pages/index/store-list" # 选填
        }
      },

      "coupon_display_info": { # 必填，用户券展示信息
        "code_display_mode": "QRCODE", # 必填，Code展示模式：INVISIBLE/BARCODE/QRCODE
        "background_color": "Color010", # 选填，背景颜色
        "entrance_mini_program": { # 选填，小程序入口
          "appid": "wx1234567890", # 当配置时必填
          "path": "/pages/index/product", # 当配置时必填
          "entrance_wording": "立即使用", # 当配置时必填
          "guidance_wording": "多次满减等你来" # 当配置时必填
        },
        "entrance_official_account": { # 选填，公众号入口
          "appid": "wx1234567890" # 当配置时必填
        },
        "entrance_finder": { # 选填，视频号入口
          "finder_id": "gh_12345678", # 当配置时必填
          "finder_video_id": "UDFsdf24df34dD456Hdf34", # 当配置时必填
          "finder_video_cover_image_url": "https://wxpaylogo.qpic.cn/wxpaylogo/xxxxx/xxx" # 当配置时必填
        }
      },

      "store_scope": "NONE", # 必填，可用门店范围

      "notify_config": { # 必填，事件通知配置
        "notify_appid": "wx4fd12345678" # 必填，通知AppID
      }
    }
  }'
```
```

需配合微信支付工具库 WXPayUtility 使用，请参考[Java](https://pay.weixin.qq.com/doc/brand/4015826861.md)

```
package com.java.demo;

import com.java.utils.WXPayBrandUtility; // 引用微信支付工具库，参考：https://pay.weixin.qq.com/doc/brand/4015826861
import com.google.gson.annotations.SerializedName;
import com.google.gson.annotations.Expose;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 创建商品券 - 多次优惠-全场-满减券
 * usage_mode=PROGRESSIVE_BUNDLE, scope=ALL, type=NORMAL
 */
public class AllNormalSequentialJava {
  private static String HOST = "https://api.mch.weixin.qq.com";
  private static String METHOD = "POST";
  private static String PATH = "/brand/marketing/product-coupon/product-coupons";

  public static void main(String[] args) {
    // TODO: 请准备商户开发必要参数，参考：https://pay.weixin.qq.com/doc/brand/4015415289
    AllNormalSequentialJava client = new AllNormalSequentialJava(
      "xxxxxxxx",                    // 品牌ID，是由微信支付系统生成并分配给每个品牌方的唯一标识符，品牌ID获取方式参考 https://pay.weixin.qq.com/doc/brand/4015415289
      "1DDE55AD98Exxxxxxxxxx",         // 品牌API证书序列号，如何获取请参考 https://pay.weixin.qq.com/doc/brand/4015407570
      "/path/to/apiclient_key.pem",     // 品牌API证书私钥文件路径，本地文件路径
      "PUB_KEY_ID_xxxxxxxxxxxxx",      // 微信支付公钥ID，如何获取请参考 https://pay.weixin.qq.com/doc/brand/4015453439
      "/path/to/wxp_pub.pem"           // 微信支付公钥文件路径，本地文件路径
    );

    CreateProductCouponRequest request = new CreateProductCouponRequest();
    request.outRequestNo = "PROGRESSIVE_BUNDLE_ALL_NORMAL_20250101_002"; // 必填，创建请求单号，6-40个字符
    request.scope = ProductCouponScope.ALL; // 必填，优惠范围：ALL-全场券
    request.type = ProductCouponType.NORMAL; // 必填，商品券类型：NORMAL-满减券
    request.usageMode = UsageMode.PROGRESSIVE_BUNDLE; // 必填，使用模式：PROGRESSIVE_BUNDLE-多次优惠
    // 必填，多次优惠模式信息(当usage_mode=PROGRESSIVE_BUNDLE时必填)
    request.progressiveBundleUsageInfo = new ProgressiveBundleUsageInfo();
    request.progressiveBundleUsageInfo.count = 5L; // 必填，可使用次数，最少3次，最多15次
    request.progressiveBundleUsageInfo.intervalDays = 1L; // 选填，每次优惠间隔天数，最少0天（不限制），最多7天
    // 必填，商品券展示信息
    request.displayInfo = new ProductCouponDisplayInfo();
    request.displayInfo.name = "全场满减券-5次递增优惠"; // 必填，商品券名称，最多12个字符
    request.displayInfo.imageUrl = "https://wxpaylogo.qpic.cn/wxpaylogo/xxxxx/xxx"; // 必填，商品券图片URL
    request.displayInfo.backgroundUrl = "https://wxpaylogo.qpic.cn/wxpaylogo/xxxxx/xxx"; // 选填，背景图URL
    request.displayInfo.detailImageUrlList = new ArrayList<>(); // 选填，详情图URL列表，最多6张
    {
      request.displayInfo.detailImageUrlList.add("https://wxpaylogo.qpic.cn/wxpaylogo/xxxxx/xxx");
    };
    request.outProductNo = "Product_ProgressiveBundle_002"; // 选填，商户侧商品券唯一标识
    // 必填，批次信息
    request.stockBundle = new StockForCreate();
    request.stockBundle.remark = "全场满减券批次"; // 选填，批次备注，最多60个字符
    request.stockBundle.couponCodeMode = CouponCodeMode.WECHATPAY; // 必填，券码模式：WECHATPAY/UPLOAD/API_ASSIGN
    // 必填，批次发放规则
    request.stockBundle.stockSendRule = new StockSendRule();
    request.stockBundle.stockSendRule.maxCount = 10000000L; // 必填，批次最大发放数量
    request.stockBundle.stockSendRule.maxCountPerDay = 100000L; // 选填，单日最大发放数量
    request.stockBundle.stockSendRule.maxCountPerUser = 1L; // 必填，单用户最大领取数量
    // 必填，多次优惠使用规则(当usage_mode=PROGRESSIVE_BUNDLE时必填)
    request.stockBundle.progressiveBundleUsageRule = new ProgressiveBundleUsageRule();
    // 必填，券可核销时间
    request.stockBundle.progressiveBundleUsageRule.couponAvailablePeriod = new CouponAvailablePeriod();
    request.stockBundle.progressiveBundleUsageRule.couponAvailablePeriod.availableBeginTime = "2025-08-01T00:00:00+08:00"; // 必填，可用开始时间(RFC3339格式)
    request.stockBundle.progressiveBundleUsageRule.couponAvailablePeriod.availableEndTime = "2025-12-31T23:59:59+08:00"; // 必填，可用结束时间(RFC3339格式)
    request.stockBundle.progressiveBundleUsageRule.couponAvailablePeriod.availableDays = 30L; // 选填，多次优惠有效天数，最少3天，最多365天
    request.stockBundle.progressiveBundleUsageRule.couponAvailablePeriod.waitDaysAfterReceive = 0L; // 选填，领取后N天生效，最少0天，最多30天
    request.stockBundle.progressiveBundleUsageRule.couponAvailablePeriod.intervalDays = 1L; // 选填，使用间隔天数，最少0天，最多7天
    request.stockBundle.progressiveBundleUsageRule.couponAvailablePeriod.weeklyAvailablePeriod = new FixedWeekPeriod(); // 选填，每周固定可用时间
    request.stockBundle.progressiveBundleUsageRule.couponAvailablePeriod.weeklyAvailablePeriod.dayList = new ArrayList<>(); // 条件必填，每周可用星期数
    {
      request.stockBundle.progressiveBundleUsageRule.couponAvailablePeriod.weeklyAvailablePeriod.dayList.add(WeekEnum.MONDAY);
      request.stockBundle.progressiveBundleUsageRule.couponAvailablePeriod.weeklyAvailablePeriod.dayList.add(WeekEnum.TUESDAY);
      request.stockBundle.progressiveBundleUsageRule.couponAvailablePeriod.weeklyAvailablePeriod.dayList.add(WeekEnum.WEDNESDAY);
      request.stockBundle.progressiveBundleUsageRule.couponAvailablePeriod.weeklyAvailablePeriod.dayList.add(WeekEnum.THURSDAY);
      request.stockBundle.progressiveBundleUsageRule.couponAvailablePeriod.weeklyAvailablePeriod.dayList.add(WeekEnum.FRIDAY);
    };
    request.stockBundle.progressiveBundleUsageRule.couponAvailablePeriod.irregularAvailablePeriodList = new ArrayList<>(); // 选填，不规则可用时间段列表
    {
      TimePeriod period = new TimePeriod();
      period.beginTime = "2025-10-01T00:00:00+08:00"; // 必填，开始时间(RFC3339格式)
      period.endTime = "2025-10-07T23:59:59+08:00"; // 必填，结束时间(RFC3339格式)
      request.stockBundle.progressiveBundleUsageRule.couponAvailablePeriod.irregularAvailablePeriodList.add(period);
    };
    request.stockBundle.progressiveBundleUsageRule.specialFirst = false; // 选填，首次优惠是否特殊
    // 条件必填，满减券使用规则列表(当type=NORMAL时必填，数量需与count一致)
    request.stockBundle.progressiveBundleUsageRule.normalCouponList = new ArrayList<>();
    {
      NormalCouponUsageRule rule1 = new NormalCouponUsageRule();
      rule1.threshold = 10000L; // 必填，门槛金额(单位：分)
      rule1.discountAmount = 1000L; // 必填，固定减免金额(单位：分)
      request.stockBundle.progressiveBundleUsageRule.normalCouponList.add(rule1);
      NormalCouponUsageRule rule2 = new NormalCouponUsageRule();
      rule2.threshold = 10000L;
      rule2.discountAmount = 1500L;
      request.stockBundle.progressiveBundleUsageRule.normalCouponList.add(rule2);
      NormalCouponUsageRule rule3 = new NormalCouponUsageRule();
      rule3.threshold = 10000L;
      rule3.discountAmount = 2000L;
      request.stockBundle.progressiveBundleUsageRule.normalCouponList.add(rule3);
      NormalCouponUsageRule rule4 = new NormalCouponUsageRule();
      rule4.threshold = 10000L;
      rule4.discountAmount = 2500L;
      request.stockBundle.progressiveBundleUsageRule.normalCouponList.add(rule4);
      NormalCouponUsageRule rule5 = new NormalCouponUsageRule();
      rule5.threshold = 10000L;
      rule5.discountAmount = 3000L;
      request.stockBundle.progressiveBundleUsageRule.normalCouponList.add(rule5);
    };
    // 必填，使用规则展示信息
    request.stockBundle.usageRuleDisplayInfo = new UsageRuleDisplayInfo();
    request.stockBundle.usageRuleDisplayInfo.couponUsageMethodList = new ArrayList<>(); // 必填，核销方式列表
    {
      request.stockBundle.usageRuleDisplayInfo.couponUsageMethodList.add(CouponUsageMethod.OFFLINE); // 线下核销
      request.stockBundle.usageRuleDisplayInfo.couponUsageMethodList.add(CouponUsageMethod.MINI_PROGRAM); // 小程序核销
      request.stockBundle.usageRuleDisplayInfo.couponUsageMethodList.add(CouponUsageMethod.APP); // APP核销
      request.stockBundle.usageRuleDisplayInfo.couponUsageMethodList.add(CouponUsageMethod.PAYMENT_CODE); // 付款码核销
    };
    request.stockBundle.usageRuleDisplayInfo.miniProgramAppid = "wx1234567890"; // 条件必填，支持小程序核销时必填
    request.stockBundle.usageRuleDisplayInfo.miniProgramPath = "/pages/index/product"; // 条件必填，支持小程序核销时必填
    request.stockBundle.usageRuleDisplayInfo.appPath = "pages/index/product"; // 条件必填，支持APP核销时必填
    request.stockBundle.usageRuleDisplayInfo.usageDescription = "全场可用，多次递增满减"; // 选填，使用说明
    request.stockBundle.usageRuleDisplayInfo.couponAvailableStoreInfo = new CouponAvailableStoreInfo(); // 选填，可用门店信息
    request.stockBundle.usageRuleDisplayInfo.couponAvailableStoreInfo.description = "所有门店可用"; // 选填，可用门店描述
    request.stockBundle.usageRuleDisplayInfo.couponAvailableStoreInfo.miniProgramAppid = "wx1234567890"; // 选填，门店小程序AppID
    request.stockBundle.usageRuleDisplayInfo.couponAvailableStoreInfo.miniProgramPath = "/pages/index/store-list"; // 选填，门店小程序路径
    // 必填，用户券展示信息
    request.stockBundle.couponDisplayInfo = new CouponDisplayInfo();
    request.stockBundle.couponDisplayInfo.codeDisplayMode = CouponCodeDisplayMode.QRCODE; // 必填，券码展示模式：INVISIBLE/BARCODE/QRCODE
    request.stockBundle.couponDisplayInfo.backgroundColor = "Color010"; // 选填，背景颜色
    request.stockBundle.couponDisplayInfo.entranceMiniProgram = new EntranceMiniProgram(); // 选填，小程序入口
    request.stockBundle.couponDisplayInfo.entranceMiniProgram.appid = "wx1234567890"; // 必填，小程序AppID
    request.stockBundle.couponDisplayInfo.entranceMiniProgram.path = "/pages/index/product"; // 必填，小程序路径
    request.stockBundle.couponDisplayInfo.entranceMiniProgram.entranceWording = "立即使用"; // 必填，入口文案
    request.stockBundle.couponDisplayInfo.entranceMiniProgram.guidanceWording = "多次满减等你来"; // 选填，引导文案
    request.stockBundle.couponDisplayInfo.entranceOfficialAccount = new EntranceOfficialAccount(); // 选填，公众号入口
    request.stockBundle.couponDisplayInfo.entranceOfficialAccount.appid = "wx1234567890"; // 必填，公众号AppID
    request.stockBundle.couponDisplayInfo.entranceFinder = new EntranceFinder(); // 选填，视频号入口
    request.stockBundle.couponDisplayInfo.entranceFinder.finderId = "gh_12345678"; // 必填，视频号ID
    request.stockBundle.couponDisplayInfo.entranceFinder.finderVideoId = "UDFsdf24df34dD456Hdf34"; // 选填，视频号视频ID
    request.stockBundle.couponDisplayInfo.entranceFinder.finderVideoCoverImageUrl = "https://wxpaylogo.qpic.cn/wxpaylogo/xxxxx/xxx"; // 选填，视频封面图URL
    request.stockBundle.notifyConfig = new NotifyConfig(); // 选填，事件通知配置
    request.stockBundle.notifyConfig.notifyAppid = "wx4fd12345678"; // 必填，通知AppID
    request.stockBundle.storeScope = StockStoreScope.NONE; // 必填，门店适用范围：NONE-不限制/ALL-全部门店/SPECIFIC-指定门店

    try {
      CreateProductCouponResponse response = client.run(request);
        // TODO: 请求成功，继续业务逻辑
        System.out.println(response);
    } catch (WXPayBrandUtility.ApiException e) {
        // TODO: 请求失败，根据状态码执行不同的逻辑
        e.printStackTrace();
    }
  }

  public CreateProductCouponResponse run(CreateProductCouponRequest request) {
    String uri = PATH;
    String reqBody = WXPayBrandUtility.toJson(request);

    Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
    reqBuilder.addHeader("Accept", "application/json");
    reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId);
    reqBuilder.addHeader("Authorization", WXPayBrandUtility.buildAuthorization(brand_id, certificateSerialNo,privateKey, METHOD, uri, reqBody));
    reqBuilder.addHeader("Content-Type", "application/json");
    RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody);
    reqBuilder.method(METHOD, requestBody);
    Request httpRequest = reqBuilder.build();

    // 发送HTTP请求
    OkHttpClient client = new OkHttpClient.Builder().build();
    try (Response httpResponse = client.newCall(httpRequest).execute()) {
      String respBody = WXPayBrandUtility.extractBody(httpResponse);
      if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
        // 2XX 成功，验证应答签名
        WXPayBrandUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey,
            httpResponse.headers(), respBody);

        // 从HTTP应答报文构建返回数据
        return WXPayBrandUtility.fromJson(respBody, CreateProductCouponResponse.class);
      } else {
        throw new WXPayBrandUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
      }
    } catch (IOException e) {
      throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
    }
  }

  private final String brand_id;
  private final String certificateSerialNo;
  private final PrivateKey privateKey;
  private final String wechatPayPublicKeyId;
  private final PublicKey wechatPayPublicKey;

  public AllNormalSequentialJava(String brand_id, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) {
    this.brand_id = brand_id;
    this.certificateSerialNo = certificateSerialNo;
    this.privateKey = WXPayBrandUtility.loadPrivateKeyFromPath(privateKeyFilePath);
    this.wechatPayPublicKeyId = wechatPayPublicKeyId;
    this.wechatPayPublicKey = WXPayBrandUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath);
  }

  public static class CreateProductCouponRequest {
    @SerializedName("out_request_no")
    public String outRequestNo;

    @SerializedName("scope")
    public ProductCouponScope scope;

    @SerializedName("type")
    public ProductCouponType type;

    @SerializedName("usage_mode")
    public UsageMode usageMode;

    @SerializedName("progressive_bundle_usage_info")
    public ProgressiveBundleUsageInfo progressiveBundleUsageInfo;

    @SerializedName("display_info")
    public ProductCouponDisplayInfo displayInfo;

    @SerializedName("out_product_no")
    public String outProductNo;

    @SerializedName("stock_bundle")
    public StockForCreate stockBundle;
  }

  public static class CreateProductCouponResponse {
    @SerializedName("product_coupon_id")
    public String productCouponId;

    @SerializedName("scope")
    public ProductCouponScope scope;

    @SerializedName("type")
    public ProductCouponType type;

    @SerializedName("usage_mode")
    public UsageMode usageMode;

    @SerializedName("progressive_bundle_usage_info")
    public ProgressiveBundleUsageInfo progressiveBundleUsageInfo;

    @SerializedName("display_info")
    public ProductCouponDisplayInfo displayInfo;

    @SerializedName("out_product_no")
    public String outProductNo;

    @SerializedName("state")
    public ProductCouponState state;

    @SerializedName("stock_bundle")
    public StockEntity stockBundle;
  }

  public enum ProductCouponScope {
    @SerializedName("ALL")
    ALL,
    @SerializedName("SINGLE")
    SINGLE
  }

  public enum ProductCouponType {
    @SerializedName("NORMAL")
    NORMAL,
    @SerializedName("DISCOUNT")
    DISCOUNT,
    @SerializedName("EXCHANGE")
    EXCHANGE
  }

  public enum UsageMode {
    @SerializedName("SINGLE")
    SINGLE,
    @SerializedName("PROGRESSIVE_BUNDLE")
    PROGRESSIVE_BUNDLE
  }

  public static class ProgressiveBundleUsageInfo {
    @SerializedName("count")
    public Long count;

    @SerializedName("interval_days")
    public Long intervalDays;
  }

  public static class ProductCouponDisplayInfo {
    @SerializedName("name")
    public String name;

    @SerializedName("image_url")
    public String imageUrl;

    @SerializedName("background_url")
    public String backgroundUrl;

    @SerializedName("detail_image_url_list")
    public List<String> detailImageUrlList;

    @SerializedName("original_price")
    public Long originalPrice;

    @SerializedName("combo_package_list")
    public List<ComboPackage> comboPackageList;
  }

  public static class StockForCreate {
    @SerializedName("remark")
    public String remark;

    @SerializedName("coupon_code_mode")
    public CouponCodeMode couponCodeMode;

    @SerializedName("stock_send_rule")
    public StockSendRule stockSendRule;

    @SerializedName("progressive_bundle_usage_rule")
    public ProgressiveBundleUsageRule progressiveBundleUsageRule;

    @SerializedName("usage_rule_display_info")
    public UsageRuleDisplayInfo usageRuleDisplayInfo;

    @SerializedName("coupon_display_info")
    public CouponDisplayInfo couponDisplayInfo;

    @SerializedName("notify_config")
    public NotifyConfig notifyConfig;

    @SerializedName("store_scope")
    public StockStoreScope storeScope;
  }

  public enum ProductCouponState {
    @SerializedName("AUDITING")
    AUDITING,
    @SerializedName("EFFECTIVE")
    EFFECTIVE,
    @SerializedName("DEACTIVATED")
    DEACTIVATED
  }

  public static class StockEntity {
    @SerializedName("product_coupon_id")
    public String productCouponId;

    @SerializedName("stock_id")
    public String stockId;

    @SerializedName("remark")
    public String remark;

    @SerializedName("coupon_code_mode")
    public CouponCodeMode couponCodeMode;

    @SerializedName("coupon_code_count_info")
    public CouponCodeCountInfo couponCodeCountInfo;

    @SerializedName("stock_send_rule")
    public StockSendRule stockSendRule;

    @SerializedName("progressive_bundle_usage_rule")
    public ProgressiveBundleUsageRule progressiveBundleUsageRule;

    @SerializedName("usage_rule_display_info")
    public UsageRuleDisplayInfo usageRuleDisplayInfo;

    @SerializedName("coupon_display_info")
    public CouponDisplayInfo couponDisplayInfo;

    @SerializedName("notify_config")
    public NotifyConfig notifyConfig;

    @SerializedName("store_scope")
    public StockStoreScope storeScope;

    @SerializedName("sent_count_info")
    public StockSentCountInfo sentCountInfo;

    @SerializedName("state")
    public StockState state;

    @SerializedName("deactivate_request_no")
    public String deactivateRequestNo;

    @SerializedName("deactivate_time")
    public String deactivateTime;

    @SerializedName("deactivate_reason")
    public String deactivateReason;
  }

  public static class ProgressiveBundleUsageRule {
    @SerializedName("coupon_available_period")
    public CouponAvailablePeriod couponAvailablePeriod;

    @SerializedName("special_first")
    public Boolean specialFirst;

    @SerializedName("normal_coupon_list")
    public List<NormalCouponUsageRule> normalCouponList;

    @SerializedName("discount_coupon_list")
    public List<DiscountCouponUsageRule> discountCouponList;

    @SerializedName("exchange_coupon_list")
    public List<ExchangeCouponUsageRule> exchangeCouponList;
  }

  public static class NormalCouponUsageRule {
    @SerializedName("threshold")
    public Long threshold;

    @SerializedName("discount_amount")
    public Long discountAmount;
  }

  public static class DiscountCouponUsageRule {
    @SerializedName("threshold")
    public Long threshold;

    @SerializedName("percent_off")
    public Long percentOff;
  }

  public static class ExchangeCouponUsageRule {
    @SerializedName("threshold")
    public Long threshold;

    @SerializedName("exchange_price")
    public Long exchangePrice;
  }

  public static class ComboPackage {
    @SerializedName("name")
    public String name;

    @SerializedName("pick_count")
    public Long pickCount;

    @SerializedName("choice_list")
    public List<ComboPackageChoice> choiceList = new ArrayList<ComboPackageChoice>();
  }

  public static class ComboPackageChoice {
    @SerializedName("name")
    public String name;

    @SerializedName("price")
    public Long price;

    @SerializedName("count")
    public Long count;

    @SerializedName("image_url")
    public String imageUrl;

    @SerializedName("mini_program_appid")
    public String miniProgramAppid;

    @SerializedName("mini_program_path")
    public String miniProgramPath;
  }

  public enum CouponCodeMode {
    @SerializedName("WECHATPAY")
    WECHATPAY,
    @SerializedName("UPLOAD")
    UPLOAD,
    @SerializedName("API_ASSIGN")
    API_ASSIGN
  }

  public static class StockSendRule {
    @SerializedName("max_count")
    public Long maxCount;

    @SerializedName("max_count_per_day")
    public Long maxCountPerDay;

    @SerializedName("max_count_per_user")
    public Long maxCountPerUser;
  }

  public static class UsageRuleDisplayInfo {
    @SerializedName("coupon_usage_method_list")
    public List<CouponUsageMethod> couponUsageMethodList = new ArrayList<CouponUsageMethod>();

    @SerializedName("mini_program_appid")
    public String miniProgramAppid;

    @SerializedName("mini_program_path")
    public String miniProgramPath;

    @SerializedName("app_path")
    public String appPath;

    @SerializedName("usage_description")
    public String usageDescription;

    @SerializedName("coupon_available_store_info")
    public CouponAvailableStoreInfo couponAvailableStoreInfo;
  }

  public static class CouponDisplayInfo {
    @SerializedName("code_display_mode")
    public CouponCodeDisplayMode codeDisplayMode;

    @SerializedName("background_color")
    public String backgroundColor;

    @SerializedName("entrance_mini_program")
    public EntranceMiniProgram entranceMiniProgram;

    @SerializedName("entrance_official_account")
    public EntranceOfficialAccount entranceOfficialAccount;

    @SerializedName("entrance_finder")
    public EntranceFinder entranceFinder;
  }

  public static class NotifyConfig {
    @SerializedName("notify_appid")
    public String notifyAppid;
  }

  public enum StockStoreScope {
    @SerializedName("NONE")
    NONE,
    @SerializedName("ALL")
    ALL,
    @SerializedName("SPECIFIC")
    SPECIFIC
  }

  public static class CouponCodeCountInfo {
    @SerializedName("total_count")
    public Long totalCount;

    @SerializedName("available_count")
    public Long availableCount;
  }

  public static class StockSentCountInfo {
    @SerializedName("total_count")
    public Long totalCount;

    @SerializedName("today_count")
    public Long todayCount;
  }

  public enum StockState {
    @SerializedName("AUDITING")
    AUDITING,
    @SerializedName("SENDING")
    SENDING,
    @SerializedName("PAUSED")
    PAUSED,
    @SerializedName("STOPPED")
    STOPPED,
    @SerializedName("DEACTIVATED")
    DEACTIVATED
  }

  public static class CouponAvailablePeriod {
    @SerializedName("available_begin_time")
    public String availableBeginTime;

    @SerializedName("available_end_time")
    public String availableEndTime;

    @SerializedName("available_days")
    public Long availableDays;

    @SerializedName("wait_days_after_receive")
    public Long waitDaysAfterReceive;

    @SerializedName("interval_days")
    public Long intervalDays;

    @SerializedName("weekly_available_period")
    public FixedWeekPeriod weeklyAvailablePeriod;

    @SerializedName("irregular_available_period_list")
    public List<TimePeriod> irregularAvailablePeriodList;
  }

  public enum CouponUsageMethod {
    @SerializedName("OFFLINE")
    OFFLINE,
    @SerializedName("MINI_PROGRAM")
    MINI_PROGRAM,
    @SerializedName("APP")
    APP,
    @SerializedName("PAYMENT_CODE")
    PAYMENT_CODE
  }

  public static class CouponAvailableStoreInfo {
    @SerializedName("description")
    public String description;

    @SerializedName("mini_program_appid")
    public String miniProgramAppid;

    @SerializedName("mini_program_path")
    public String miniProgramPath;
  }

  public enum CouponCodeDisplayMode {
    @SerializedName("INVISIBLE")
    INVISIBLE,
    @SerializedName("BARCODE")
    BARCODE,
    @SerializedName("QRCODE")
    QRCODE
  }

  public static class EntranceMiniProgram {
    @SerializedName("appid")
    public String appid;

    @SerializedName("path")
    public String path;

    @SerializedName("entrance_wording")
    public String entranceWording;

    @SerializedName("guidance_wording")
    public String guidanceWording;
  }

  public static class EntranceOfficialAccount {
    @SerializedName("appid")
    public String appid;
  }

  public static class EntranceFinder {
    @SerializedName("finder_id")
    public String finderId;

    @SerializedName("finder_video_id")
    public String finderVideoId;

    @SerializedName("finder_video_cover_image_url")
    public String finderVideoCoverImageUrl;
  }

  public static class FixedWeekPeriod {
    @SerializedName("day_list")
    public List<WeekEnum> dayList;

    @SerializedName("day_period_list")
    public List<PeriodOfTheDay> dayPeriodList;
  }

  public static class TimePeriod {
    @SerializedName("begin_time")
    public String beginTime;

    @SerializedName("end_time")
    public String endTime;
  }

  public enum WeekEnum {
    @SerializedName("MONDAY")
    MONDAY,
    @SerializedName("TUESDAY")
    TUESDAY,
    @SerializedName("WEDNESDAY")
    WEDNESDAY,
    @SerializedName("THURSDAY")
    THURSDAY,
    @SerializedName("FRIDAY")
    FRIDAY,
    @SerializedName("SATURDAY")
    SATURDAY,
    @SerializedName("SUNDAY")
    SUNDAY
  }

  public static class PeriodOfTheDay {
    @SerializedName("begin_time")
    public Long beginTime;

    @SerializedName("end_time")
    public Long endTime;
  }

}

```

需配合微信支付工具库 wxpay\_utility 使用，请参考[Go](https://pay.weixin.qq.com/doc/brand/4015826866.md)

```
package main

import (
	"bytes"
	"demo/wxpay_brand_utility" // 引用微信支付工具库，参考 https://pay.weixin.qq.com/doc/brand/4015826866
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"time"
)

// 创建商品券 - 多次优惠-全场-满减券
// usage_mode=PROGRESSIVE_BUNDLE, scope=ALL, type=NORMAL
func main() {
	// TODO: 请准备商户开发必要参数，参考：https://pay.weixin.qq.com/doc/brand/4015415289
	config, err := wxpay_brand_utility.CreateBrandConfig(
		"xxxxxxxx",                   // 品牌ID，是由微信支付系统生成并分配给每个品牌方的唯一标识符，品牌ID获取方式参考 https://pay.weixin.qq.com/doc/brand/4015415289
		"1DDE55AD98Exxxxxxxxxx",      // 品牌API证书序列号，如何获取请参考 https://pay.weixin.qq.com/doc/brand/4015407570
		"/path/to/apiclient_key.pem", // 品牌API证书私钥文件路径，本地文件路径
		"PUB_KEY_ID_xxxxxxxxxxxxx",   // 微信支付公钥ID，如何获取请参考 https://pay.weixin.qq.com/doc/brand/4015453439
		"/path/to/wxp_pub.pem",       // 微信支付公钥文件路径，本地文件路径
	)
	if err != nil {
		fmt.Println(err)
		return
	}

	request := &CreateProductCouponRequest{
		OutRequestNo: wxpay_brand_utility.String("PROGRESSIVE_BUNDLE_ALL_NORMAL_20250101_002"), // 必填，创建请求单号，6-40个字符
		Scope:        PRODUCTCOUPONSCOPE_ALL.Ptr(),                                     // 必填，优惠范围：ALL-全场券
		Type:         PRODUCTCOUPONTYPE_NORMAL.Ptr(),                                   // 必填，商品券类型：NORMAL-满减券
		UsageMode:    USAGEMODE_PROGRESSIVE_BUNDLE.Ptr(),                                       // 必填，使用模式：PROGRESSIVE_BUNDLE-多次优惠
		// 必填，多次优惠模式信息(当usage_mode=PROGRESSIVE_BUNDLE时必填)
		ProgressiveBundleUsageInfo: &ProgressiveBundleUsageInfo{
			Count:        wxpay_brand_utility.Int64(5), // 必填，可使用次数，最少3次，最多15次
			IntervalDays: wxpay_brand_utility.Int64(1), // 选填，每次优惠间隔天数，最少0天，最多7天
		},
		// 必填，商品券展示信息
		DisplayInfo: &ProductCouponDisplayInfo{
			Name:          wxpay_brand_utility.String("全场满减券-5次递增优惠"),                        // 必填，商品券名称，最多12个字符
			ImageUrl:      wxpay_brand_utility.String("https://wxpaylogo.qpic.cn/wxpaylogo/xxxxx/xxx"), // 必填，商品券图片URL
			BackgroundUrl: wxpay_brand_utility.String("https://wxpaylogo.qpic.cn/wxpaylogo/xxxxx/xxx"), // 选填，背景图URL
			DetailImageUrlList: []string{ // 选填，详情图URL列表，最多6张
				"https://wxpaylogo.qpic.cn/wxpaylogo/xxxxx/xxx",
			},
		},
		OutProductNo: wxpay_brand_utility.String("Product_ProgressiveBundle_002"), // 选填，商户侧商品券唯一标识
		// 必填，批次信息
		StockBundle: &StockForCreate{
			Remark:         wxpay_brand_utility.String("全场满减券批次"), // 选填，批次备注，最多60个字符
			CouponCodeMode: COUPONCODEMODE_WECHATPAY.Ptr(),          // 必填，券码模式：WECHATPAY/UPLOAD/API_ASSIGN
			// 必填，批次发放规则
			StockSendRule: &StockSendRule{
				MaxCount:        wxpay_brand_utility.Int64(10000000), // 必填，批次最大发放数量
				MaxCountPerDay:  wxpay_brand_utility.Int64(100000),   // 选填，单日最大发放数量
				MaxCountPerUser: wxpay_brand_utility.Int64(1),        // 必填，单用户最大领取数量
			},
			// 必填，多次优惠使用规则(当usage_mode=PROGRESSIVE_BUNDLE时必填)
			ProgressiveBundleUsageRule: &ProgressiveBundleUsageRule{
				// 必填，券可核销时间
				CouponAvailablePeriod: &CouponAvailablePeriod{
					AvailableBeginTime:   wxpay_brand_utility.String("2025-08-01T00:00:00+08:00"), // 必填，可用开始时间(RFC3339格式)
					AvailableEndTime:     wxpay_brand_utility.String("2025-12-31T23:59:59+08:00"), // 必填，可用结束时间(RFC3339格式)
					AvailableDays:        wxpay_brand_utility.Int64(30),                           // 选填，多次优惠有效天数，最少3天，最多365天
					WaitDaysAfterReceive: wxpay_brand_utility.Int64(0),                            // 选填，领取后N天生效，最少0天，最多30天
					IntervalDays:         wxpay_brand_utility.Int64(1),                            // 选填，使用间隔天数，最少0天，最多7天
					// 选填，每周固定可用时间
					WeeklyAvailablePeriod: &FixedWeekPeriod{
					DayList: []WeekEnum{ // 条件必填，每周可用星期数（此示例仅工作日可用）
						WEEKENUM_MONDAY,
						WEEKENUM_TUESDAY,
						WEEKENUM_WEDNESDAY,
						WEEKENUM_THURSDAY,
						WEEKENUM_FRIDAY,
					},
					},
					// 选填，不规则可用时间段列表
					IrregularAvailablePeriodList: []TimePeriod{
						{
							BeginTime: wxpay_brand_utility.String("2025-10-01T00:00:00+08:00"), // 必填，开始时间(RFC3339格式)
							EndTime:   wxpay_brand_utility.String("2025-10-07T23:59:59+08:00"), // 必填，结束时间(RFC3339格式)
						},
					},
				},
				SpecialFirst: wxpay_brand_utility.Bool(false), // 选填，首次优惠是否特殊
				// 条件必填，满减券使用规则列表(当type=NORMAL时必填，数量需与count一致)
				NormalCouponList: []NormalCouponUsageRule{
					{Threshold: wxpay_brand_utility.Int64(10000), DiscountAmount: wxpay_brand_utility.Int64(1000)}, // 必填: Threshold-门槛金额, DiscountAmount-固定减免金额
					{Threshold: wxpay_brand_utility.Int64(10000), DiscountAmount: wxpay_brand_utility.Int64(1500)},
					{Threshold: wxpay_brand_utility.Int64(10000), DiscountAmount: wxpay_brand_utility.Int64(2000)},
					{Threshold: wxpay_brand_utility.Int64(10000), DiscountAmount: wxpay_brand_utility.Int64(2500)},
					{Threshold: wxpay_brand_utility.Int64(10000), DiscountAmount: wxpay_brand_utility.Int64(3000)},
				},
			},
			// 必填，使用规则展示信息
			UsageRuleDisplayInfo: &UsageRuleDisplayInfo{
				CouponUsageMethodList: []CouponUsageMethod{ // 必填，核销方式列表
					COUPONUSAGEMETHOD_OFFLINE,      // 线下核销
					COUPONUSAGEMETHOD_MINI_PROGRAM, // 小程序核销
					COUPONUSAGEMETHOD_APP,          // APP核销
					COUPONUSAGEMETHOD_PAYMENT_CODE, // 付款码核销
				},
				MiniProgramAppid: wxpay_brand_utility.String("wx1234567890"),        // 条件必填，支持小程序核销时必填
				MiniProgramPath:  wxpay_brand_utility.String("/pages/index/product"), // 条件必填，支持小程序核销时必填
				AppPath:          wxpay_brand_utility.String("pages/index/product"),  // 条件必填，支持APP核销时必填
				UsageDescription: wxpay_brand_utility.String("全场可用，多次递增满减"),         // 选填，使用说明
				// 选填，可用门店信息
				CouponAvailableStoreInfo: &CouponAvailableStoreInfo{
					Description:      wxpay_brand_utility.String("所有门店可用"),              // 选填，可用门店描述
					MiniProgramAppid: wxpay_brand_utility.String("wx1234567890"),          // 选填，门店小程序AppID
					MiniProgramPath:  wxpay_brand_utility.String("/pages/index/store-list"), // 选填，门店小程序路径
				},
			},
			// 必填，用户券展示信息
			CouponDisplayInfo: &CouponDisplayInfo{
				CodeDisplayMode: COUPONCODEDISPLAYMODE_QRCODE.Ptr(),      // 必填，券码展示模式：INVISIBLE/BARCODE/QRCODE
				BackgroundColor: wxpay_brand_utility.String("Color010"), // 选填，背景颜色
				// 选填，小程序入口
				EntranceMiniProgram: &EntranceMiniProgram{
					Appid:           wxpay_brand_utility.String("wx1234567890"),         // 必填，小程序AppID
					Path:            wxpay_brand_utility.String("/pages/index/product"), // 必填，小程序路径
					EntranceWording: wxpay_brand_utility.String("立即使用"),                 // 必填，入口文案
					GuidanceWording: wxpay_brand_utility.String("多次满减等你来"),               // 选填，引导文案
				},
				// 选填，公众号入口
				EntranceOfficialAccount: &EntranceOfficialAccount{
					Appid: wxpay_brand_utility.String("wx1234567890"), // 必填，公众号AppID
				},
				// 选填，视频号入口
				EntranceFinder: &EntranceFinder{
					FinderId:                 wxpay_brand_utility.String("gh_12345678"),                             // 必填，视频号ID
					FinderVideoId:            wxpay_brand_utility.String("UDFsdf24df34dD456Hdf34"),                  // 选填，视频号视频ID
					FinderVideoCoverImageUrl: wxpay_brand_utility.String("https://wxpaylogo.qpic.cn/wxpaylogo/xxxxx/xxx"), // 选填，视频封面图URL
				},
			},
			// 选填，事件通知配置
			NotifyConfig: &NotifyConfig{
				NotifyAppid: wxpay_brand_utility.String("wx4fd12345678"), // 必填，通知AppID
			},
			StoreScope: STOCKSTORESCOPE_NONE.Ptr(), // 必填，门店适用范围：NONE-不限制/ALL-全部门店/SPECIFIC-指定门店
		},
	}

	response, err := CreateProductCoupon(config, request)
	if err != nil {
		fmt.Printf("请求失败: %+v\n", err)
		// TODO: 请求失败，根据状态码执行不同的处理
		return
	}

	// TODO: 请求成功，继续业务逻辑
	fmt.Printf("请求成功: %+v\n", response)
}

func CreateProductCoupon(config *wxpay_brand_utility.BrandConfig, request *CreateProductCouponRequest) (response *CreateProductCouponResponse, err error) {
	const (
		host   = "https://api.mch.weixin.qq.com"
		method = "POST"
		path   = "/brand/marketing/product-coupon/product-coupons"
	)

	reqUrl, err := url.Parse(fmt.Sprintf("%s%s", host, path))
	if err != nil {
		return nil, err
	}
	reqBody, err := json.Marshal(request)
	if err != nil {
		return nil, err
	}
	httpRequest, err := http.NewRequest(method, reqUrl.String(), bytes.NewReader(reqBody))
	if err != nil {
		return nil, err
	}
	httpRequest.Header.Set("Accept", "application/json")
	httpRequest.Header.Set("Wechatpay-Serial", config.WechatPayPublicKeyId())
	httpRequest.Header.Set("Content-Type", "application/json")
	authorization, err := wxpay_brand_utility.BuildAuthorization(config.BrandId(), config.CertificateSerialNo(), config.PrivateKey(), method, reqUrl.RequestURI(), reqBody)
	if err != nil {
		return nil, err
	}
	httpRequest.Header.Set("Authorization", authorization)

	client := &http.Client{}
	httpResponse, err := client.Do(httpRequest)
	if err != nil {
		return nil, err
	}
	respBody, err := wxpay_brand_utility.ExtractResponseBody(httpResponse)
	if err != nil {
		return nil, err
	}
	if httpResponse.StatusCode >= 200 && httpResponse.StatusCode < 300 {
		err = wxpay_brand_utility.ValidateResponse(
			config.WechatPayPublicKeyId(),
			config.WechatPayPublicKey(),
			&httpResponse.Header,
			respBody,
		)
		if err != nil {
			return nil, err
		}
		response := &CreateProductCouponResponse{}
		if err := json.Unmarshal(respBody, response); err != nil {
			return nil, err
		}

		return response, nil
	} else {
		return nil, wxpay_brand_utility.NewApiException(
			httpResponse.StatusCode,
			httpResponse.Header,
			respBody,
		)
	}
}

type CreateProductCouponRequest struct {
	OutRequestNo        *string                   `json:"out_request_no,omitempty"`
	Scope               *ProductCouponScope       `json:"scope,omitempty"`
	Type                *ProductCouponType        `json:"type,omitempty"`
	UsageMode           *UsageMode                `json:"usage_mode,omitempty"`
	ProgressiveBundleUsageInfo *ProgressiveBundleUsageInfo      `json:"progressive_bundle_usage_info,omitempty"`
	DisplayInfo         *ProductCouponDisplayInfo `json:"display_info,omitempty"`
	OutProductNo        *string                   `json:"out_product_no,omitempty"`
	StockBundle         *StockForCreate           `json:"stock_bundle,omitempty"`
}

type CreateProductCouponResponse struct {
	ProductCouponId     *string                   `json:"product_coupon_id,omitempty"`
	Scope               *ProductCouponScope       `json:"scope,omitempty"`
	Type                *ProductCouponType        `json:"type,omitempty"`
	UsageMode           *UsageMode                `json:"usage_mode,omitempty"`
	ProgressiveBundleUsageInfo *ProgressiveBundleUsageInfo      `json:"progressive_bundle_usage_info,omitempty"`
	DisplayInfo         *ProductCouponDisplayInfo `json:"display_info,omitempty"`
	OutProductNo        *string                   `json:"out_product_no,omitempty"`
	State               *ProductCouponState       `json:"state,omitempty"`
	StockBundle         *StockEntity              `json:"stock_bundle,omitempty"`
}

type ProductCouponScope string

func (e ProductCouponScope) Ptr() *ProductCouponScope { return &e }

const (
	PRODUCTCOUPONSCOPE_ALL    ProductCouponScope = "ALL"
	PRODUCTCOUPONSCOPE_SINGLE ProductCouponScope = "SINGLE"
)

type ProductCouponType string

func (e ProductCouponType) Ptr() *ProductCouponType { return &e }

const (
	PRODUCTCOUPONTYPE_NORMAL   ProductCouponType = "NORMAL"
	PRODUCTCOUPONTYPE_DISCOUNT ProductCouponType = "DISCOUNT"
	PRODUCTCOUPONTYPE_EXCHANGE ProductCouponType = "EXCHANGE"
)

type UsageMode string

func (e UsageMode) Ptr() *UsageMode { return &e }

const (
	USAGEMODE_SINGLE     UsageMode = "SINGLE"
	USAGEMODE_PROGRESSIVE_BUNDLE UsageMode = "PROGRESSIVE_BUNDLE"
)

type ProgressiveBundleUsageInfo struct {
	Count        *int64 `json:"count,omitempty"`
	IntervalDays *int64 `json:"interval_days,omitempty"`
}

type ProductCouponDisplayInfo struct {
	Name               *string        `json:"name,omitempty"`
	ImageUrl           *string        `json:"image_url,omitempty"`
	BackgroundUrl      *string        `json:"background_url,omitempty"`
	DetailImageUrlList []string       `json:"detail_image_url_list,omitempty"`
	OriginalPrice      *int64         `json:"original_price,omitempty"`
	ComboPackageList   []ComboPackage `json:"combo_package_list,omitempty"`
}

type StockForCreate struct {
	Remark               *string               `json:"remark,omitempty"`
	CouponCodeMode       *CouponCodeMode       `json:"coupon_code_mode,omitempty"`
	StockSendRule        *StockSendRule        `json:"stock_send_rule,omitempty"`
	ProgressiveBundleUsageRule  *ProgressiveBundleUsageRule  `json:"progressive_bundle_usage_rule,omitempty"`
	UsageRuleDisplayInfo *UsageRuleDisplayInfo `json:"usage_rule_display_info,omitempty"`
	CouponDisplayInfo    *CouponDisplayInfo    `json:"coupon_display_info,omitempty"`
	NotifyConfig         *NotifyConfig         `json:"notify_config,omitempty"`
	StoreScope           *StockStoreScope      `json:"store_scope,omitempty"`
}

type ProductCouponState string

func (e ProductCouponState) Ptr() *ProductCouponState { return &e }

const (
	PRODUCTCOUPONSTATE_AUDITING    ProductCouponState = "AUDITING"
	PRODUCTCOUPONSTATE_EFFECTIVE   ProductCouponState = "EFFECTIVE"
	PRODUCTCOUPONSTATE_DEACTIVATED ProductCouponState = "DEACTIVATED"
)

type StockEntity struct {
	ProductCouponId      *string               `json:"product_coupon_id,omitempty"`
	StockId              *string               `json:"stock_id,omitempty"`
	Remark               *string               `json:"remark,omitempty"`
	CouponCodeMode       *CouponCodeMode       `json:"coupon_code_mode,omitempty"`
	CouponCodeCountInfo  *CouponCodeCountInfo  `json:"coupon_code_count_info,omitempty"`
	StockSendRule        *StockSendRule        `json:"stock_send_rule,omitempty"`
	ProgressiveBundleUsageRule  *ProgressiveBundleUsageRule  `json:"progressive_bundle_usage_rule,omitempty"`
	UsageRuleDisplayInfo *UsageRuleDisplayInfo `json:"usage_rule_display_info,omitempty"`
	CouponDisplayInfo    *CouponDisplayInfo    `json:"coupon_display_info,omitempty"`
	NotifyConfig         *NotifyConfig         `json:"notify_config,omitempty"`
	StoreScope           *StockStoreScope      `json:"store_scope,omitempty"`
	SentCountInfo        *StockSentCountInfo   `json:"sent_count_info,omitempty"`
	State                *StockState           `json:"state,omitempty"`
	DeactivateRequestNo  *string               `json:"deactivate_request_no,omitempty"`
	DeactivateTime       *time.Time            `json:"deactivate_time,omitempty"`
	DeactivateReason     *string               `json:"deactivate_reason,omitempty"`
}

type ProgressiveBundleUsageRule struct {
	CouponAvailablePeriod *CouponAvailablePeriod    `json:"coupon_available_period,omitempty"`
	SpecialFirst          *bool                     `json:"special_first,omitempty"`
	NormalCouponList      []NormalCouponUsageRule   `json:"normal_coupon_list,omitempty"`
	DiscountCouponList    []DiscountCouponUsageRule `json:"discount_coupon_list,omitempty"`
	ExchangeCouponList    []ExchangeCouponUsageRule `json:"exchange_coupon_list,omitempty"`
}

type NormalCouponUsageRule struct {
	Threshold      *int64 `json:"threshold,omitempty"`
	DiscountAmount *int64 `json:"discount_amount,omitempty"`
}

type DiscountCouponUsageRule struct {
	Threshold  *int64 `json:"threshold,omitempty"`
	PercentOff *int64 `json:"percent_off,omitempty"`
}

type ExchangeCouponUsageRule struct {
	Threshold     *int64 `json:"threshold,omitempty"`
	ExchangePrice *int64 `json:"exchange_price,omitempty"`
}

type ComboPackage struct {
	Name       *string              `json:"name,omitempty"`
	PickCount  *int64               `json:"pick_count,omitempty"`
	ChoiceList []ComboPackageChoice `json:"choice_list,omitempty"`
}

type ComboPackageChoice struct {
	Name             *string `json:"name,omitempty"`
	Price            *int64  `json:"price,omitempty"`
	Count            *int64  `json:"count,omitempty"`
	ImageUrl         *string `json:"image_url,omitempty"`
	MiniProgramAppid *string `json:"mini_program_appid,omitempty"`
	MiniProgramPath  *string `json:"mini_program_path,omitempty"`
}

type CouponCodeMode string

func (e CouponCodeMode) Ptr() *CouponCodeMode { return &e }

const (
	COUPONCODEMODE_WECHATPAY  CouponCodeMode = "WECHATPAY"
	COUPONCODEMODE_UPLOAD     CouponCodeMode = "UPLOAD"
	COUPONCODEMODE_API_ASSIGN CouponCodeMode = "API_ASSIGN"
)

type StockSendRule struct {
	MaxCount        *int64 `json:"max_count,omitempty"`
	MaxCountPerDay  *int64 `json:"max_count_per_day,omitempty"`
	MaxCountPerUser *int64 `json:"max_count_per_user,omitempty"`
}

type UsageRuleDisplayInfo struct {
	CouponUsageMethodList    []CouponUsageMethod       `json:"coupon_usage_method_list,omitempty"`
	MiniProgramAppid         *string                   `json:"mini_program_appid,omitempty"`
	MiniProgramPath          *string                   `json:"mini_program_path,omitempty"`
	AppPath                  *string                   `json:"app_path,omitempty"`
	UsageDescription         *string                   `json:"usage_description,omitempty"`
	CouponAvailableStoreInfo *CouponAvailableStoreInfo `json:"coupon_available_store_info,omitempty"`
}

type CouponDisplayInfo struct {
	CodeDisplayMode         *CouponCodeDisplayMode   `json:"code_display_mode,omitempty"`
	BackgroundColor         *string                  `json:"background_color,omitempty"`
	EntranceMiniProgram     *EntranceMiniProgram     `json:"entrance_mini_program,omitempty"`
	EntranceOfficialAccount *EntranceOfficialAccount `json:"entrance_official_account,omitempty"`
	EntranceFinder          *EntranceFinder          `json:"entrance_finder,omitempty"`
}

type NotifyConfig struct {
	NotifyAppid *string `json:"notify_appid,omitempty"`
}

type StockStoreScope string

func (e StockStoreScope) Ptr() *StockStoreScope { return &e }

const (
	STOCKSTORESCOPE_NONE     StockStoreScope = "NONE"
	STOCKSTORESCOPE_ALL      StockStoreScope = "ALL"
	STOCKSTORESCOPE_SPECIFIC StockStoreScope = "SPECIFIC"
)

type CouponCodeCountInfo struct {
	TotalCount     *int64 `json:"total_count,omitempty"`
	AvailableCount *int64 `json:"available_count,omitempty"`
}

type StockSentCountInfo struct {
	TotalCount *int64 `json:"total_count,omitempty"`
	TodayCount *int64 `json:"today_count,omitempty"`
}

type StockState string

func (e StockState) Ptr() *StockState { return &e }

const (
	STOCKSTATE_AUDITING    StockState = "AUDITING"
	STOCKSTATE_SENDING     StockState = "SENDING"
	STOCKSTATE_PAUSED      StockState = "PAUSED"
	STOCKSTATE_STOPPED     StockState = "STOPPED"
	STOCKSTATE_DEACTIVATED StockState = "DEACTIVATED"
)

type CouponAvailablePeriod struct {
	AvailableBeginTime           *string          `json:"available_begin_time,omitempty"`
	AvailableEndTime             *string          `json:"available_end_time,omitempty"`
	AvailableDays                *int64           `json:"available_days,omitempty"`
	WaitDaysAfterReceive         *int64           `json:"wait_days_after_receive,omitempty"`
	IntervalDays                 *int64           `json:"interval_days,omitempty"`
	WeeklyAvailablePeriod        *FixedWeekPeriod `json:"weekly_available_period,omitempty"`
	IrregularAvailablePeriodList []TimePeriod     `json:"irregular_available_period_list,omitempty"`
}

type CouponUsageMethod string

func (e CouponUsageMethod) Ptr() *CouponUsageMethod { return &e }

const (
	COUPONUSAGEMETHOD_OFFLINE      CouponUsageMethod = "OFFLINE"
	COUPONUSAGEMETHOD_MINI_PROGRAM CouponUsageMethod = "MINI_PROGRAM"
	COUPONUSAGEMETHOD_APP          CouponUsageMethod = "APP"
	COUPONUSAGEMETHOD_PAYMENT_CODE CouponUsageMethod = "PAYMENT_CODE"
)

type CouponAvailableStoreInfo struct {
	Description      *string `json:"description,omitempty"`
	MiniProgramAppid *string `json:"mini_program_appid,omitempty"`
	MiniProgramPath  *string `json:"mini_program_path,omitempty"`
}

type CouponCodeDisplayMode string

func (e CouponCodeDisplayMode) Ptr() *CouponCodeDisplayMode { return &e }

const (
	COUPONCODEDISPLAYMODE_INVISIBLE CouponCodeDisplayMode = "INVISIBLE"
	COUPONCODEDISPLAYMODE_BARCODE   CouponCodeDisplayMode = "BARCODE"
	COUPONCODEDISPLAYMODE_QRCODE    CouponCodeDisplayMode = "QRCODE"
)

type EntranceMiniProgram struct {
	Appid           *string `json:"appid,omitempty"`
	Path            *string `json:"path,omitempty"`
	EntranceWording *string `json:"entrance_wording,omitempty"`
	GuidanceWording *string `json:"guidance_wording,omitempty"`
}

type EntranceOfficialAccount struct {
	Appid *string `json:"appid,omitempty"`
}

type EntranceFinder struct {
	FinderId                 *string `json:"finder_id,omitempty"`
	FinderVideoId            *string `json:"finder_video_id,omitempty"`
	FinderVideoCoverImageUrl *string `json:"finder_video_cover_image_url,omitempty"`
}

type FixedWeekPeriod struct {
	DayList       []WeekEnum       `json:"day_list,omitempty"`
	DayPeriodList []PeriodOfTheDay `json:"day_period_list,omitempty"`
}

type TimePeriod struct {
	BeginTime *string `json:"begin_time,omitempty"`
	EndTime   *string `json:"end_time,omitempty"`
}

type WeekEnum string

func (e WeekEnum) Ptr() *WeekEnum { return &e }

const (
	WEEKENUM_MONDAY    WeekEnum = "MONDAY"
	WEEKENUM_TUESDAY   WeekEnum = "TUESDAY"
	WEEKENUM_WEDNESDAY WeekEnum = "WEDNESDAY"
	WEEKENUM_THURSDAY  WeekEnum = "THURSDAY"
	WEEKENUM_FRIDAY    WeekEnum = "FRIDAY"
	WEEKENUM_SATURDAY  WeekEnum = "SATURDAY"
	WEEKENUM_SUNDAY    WeekEnum = "SUNDAY"
)

type PeriodOfTheDay struct {
	BeginTime *int64 `json:"begin_time,omitempty"`
	EndTime   *int64 `json:"end_time,omitempty"`
}

```