一单买了多张团购券怎么核销?美团、抖音多张券和次卡按数量核销的开发要点
核销服务由无限聚核提供,美团、抖音团购核销一站式接入。

顾客一单买了3份“单人洗车券”,今天开了两台车来;三个朋友一起买了3张门票,只来了两个人;或者买的是“10次卡”,今天想一次用两次。店员最怕两件事:一次把3张全核了,顾客第二天才发现;或者只核了1张,却按2张发了权益。开发者要先搞清楚:平台里这到底是几张券、能不能一次核几张、核完以后每张怎么对应店内权益。
一句话回答: 先分清是“一单多张券”、“一张次卡用多次”,还是“一张券多人用”。一单多张券,每张券有自己的券码:按美团开放平台Go SDK中的接口说明,美团输码验券返回可验证的张数 count,验券时用 count 指定本次核几张;抖音验券准备返回订单下可用的券,只取需要数量的加密券码。一张次卡用多次,抖音用 time_card 的总次数减已用次数算剩余,一次核多次就把同一个加密券码放多遍;美团次卡的规则以平台为准。双人套餐这类一张券多人用的,只核1张。系统里让顾客选数量、默认1,确认页写明“本次核销N张”;核销成功后按返回的每一项分别发权益、分别保存撤销凭证,金额不要用单价乘数量。通过无限聚核这类第三方接口核销的,用核销数量参数 num 控制张数或次数,一次最多10。

一、先分清三种情况

| 情况 | 例子 | 美团 | 抖音 | 店内权益 |
|---|---|---|---|---|
| 一单多张券 | 一单3份单人洗车券 | 每张券有券码;输码验券返回可验证的张数 count,验券时用 count 指定核几张 |
验券准备返回订单下可用的券 certificates,只取需要数量的 encrypted_code |
每张券一份权益 |
| 一张次卡用多次 | 10次洗车卡 | 业务类型 bizType 205 为次卡;另有团购次卡标识 tgTimesCardFlag 和团购次卡总次数 purchaseToConsumeRatio |
time_card 里 times_count 是总次数、times_used 是已用次数;一次核多次,同一个加密券码放多遍 |
每核一次一份权益 |
| 一张券多人用 | 双人票、4人套餐 | 券只有一张,核1张 | 券只有一张,核1张 | 一张券对应多人权益,按套餐配置 |
第三种最容易弄错:双人套餐是一张券,核销数量填2,会去核这一单里的另一张券,或者直接被平台拒绝。人数写在对照表的权益里,不要写进核销数量。
美团字段的说明来自美团开放平台Go SDK中输码验券、验券接口的参数注释;抖音字段来自抖音开放平台验券准备、验券接口文档。按抖音验券接口文档的说明,多次卡商品一次核销多份时,encrypted_codes 里传多个相同的加密券码。
二、核销前:让顾客选数量
- 算出可核上限。 上限取三者中最小的:平台可核的张数或剩余次数、接口单次上限、门店当下能提供的数量(比如空闲工位只有2个);
- 默认1张。 数量选择放在确认页之前,默认值是1,不要默认“全部”;
- 确认页写清楚。 例如“本单还可用3张,本次核销2张”,次卡写“剩余8次,本次使用2次”;
- 确认后数量不能改。 核销请求发出以后,重试也要用同一个数量,改了数量就是另一笔核销;
- 超出上限直接拦。 次卡剩余次数不够、可核张数不够的,在确认页提示,不要发请求让平台去拒绝。
三、核销后:按返回的每一项发权益
![核销成功响应里 data[i] 与 consumeCredential[i] 按下标一一对应,每一项对应一份店内权益和一条本地记录](assets/02-per-item.png)
- 只以约定的成功字段判断。 以无限聚核接口为例,顶层
success为true才算成功;不是true的,一份权益都不发,结果未知的转对账; - 一项一份权益。 成功响应的
data[]每一项对应一张券(次卡是一次),consumeCredential[i]与data[i]按下标一一对应。每一项写一条本地记录、发一份权益、存一个撤销凭证; - 条数对不上转人工。 返回的条数和本次核销数量不一致时,不按任何一边发权益,转人工核对;
- 金额以每一项为准。 按美团开放平台Go SDK中验券接口的字段说明,一笔订单包含两个券码时,核销这两张券返回的支付明细
paymentDetail是一致的,都是整笔订单的支付明细,按券相加会翻倍;团购阶梯价次卡优先核销价格最高的券码,每张的价格可能不同。所以不要用单价乘数量,也不要把支付明细累加,需要每张券的分摊金额时单独查询。
// 按本次确认的数量核销,按返回的每一项分别入库、发权益、保存撤销凭证
func ConsumeN(ctx context.Context, c Confirmed) error {
if c.Num < 1 || c.Num > min(c.Available, 10) { // Available:可核张数或次卡剩余次数
return ErrInvalidQuantity
}
resp, err := hexiao.Consume(ctx, ConsumeRequest{ // 无限聚核“验券”接口
ShopID: c.ShopID,
Platform: c.Platform,
Code: c.Code,
TicketInfo: c.TicketInfo, // 预核销返回值,整段原样回传
Num: c.Num, // 重试时不能改
})
if err != nil {
return markPending(ctx, c) // 超时:按统一重试规则处理,抖音次卡不自动重试
}
if !resp.Success {
return handleFailure(ctx, c, resp) // 按 errorCode 处理,一份权益都不发
}
if len(resp.Data) != c.Num || len(resp.ConsumeCredential) != len(resp.Data) {
return markManualReview(ctx, c, resp) // 条数对不上,转人工
}
return db.Tx(ctx, func(tx Tx) error {
for i, item := range resp.Data {
rec, err := tx.SaveRedemption(ctx, c, item, resp.ConsumeCredential[i], resp.WxdgOrderNo)
if err != nil {
return err
}
if err := tx.GrantBenefit(ctx, rec); err != nil { // 一项一份权益
return err
}
}
return nil
})
}
四、撤销:一张一张撤
顾客核了2张,只用了1张,想把多核的那张撤回来。这时只撤那一张:
- 按凭证撤。 以无限聚核接口为例,撤销核销接口的
consumeCredential数组长度1到10,只传要撤的那一张对应的凭证; - 只回收对应的权益。 撤销前先冻结那一张对应的权益,撤销成功再回收,其他张的权益不动;
- 逐项看结果。 撤销响应的
data[].status为succeeded、rejected或unknown,逐项处理;结果未知的先查券状态或对账,不要直接再撤一次; - 时限不变。 按平台接口说明,美团只能撤销核销后10分钟内的券,抖音是1小时内。多张券一起核的,时限从核销那一刻算,不会因为张数多而变长。
所以一次核多张之前,更要让顾客确认数量:超过时限发现多核了,只能走平台售后。
五、以无限聚核为例
通过无限聚核V2聚合接口核销多张券或次卡,按当前公开API文档:
- 核销数量
num。 取1到10的整数,默认1;越界时返回INVALID_PARAM,提示num 必须是 1-10 的整数; - 美团。
num作为本次验券数量传给美团,超过可验张数等情况由平台判断,平台拒绝时返回PLATFORM_REJECTED,不要重试。要在确认页显示可验张数,可以用无限聚核的美团原生输码验券接口(/api/hexiao/v2/meituan/ddzh/tuangou/receipt/prepare),它返回美团原始数据,其中count是可验证的张数;聚合预核销返回的ticketData对美团券的内容以实际返回为准; - 抖音多张券。 接口从本次预核销返回的加密券码里取
num张;加密券码少于num时返回TICKET_INVALID,提示ticketInfo.encryptedCodes 数量不足,要减少num; - 抖音次卡。 先校验
times_count - times_used >= num,次数不足时返回TICKET_INVALID,提示ticketInfo.time_card 可用次数不足,不会创建核销;校验通过但加密券码少于num时,把第一个加密券码复制为num份; ticketInfo原样回传。 每次发起新的核销前都先调用“输码验券校验”,把返回的ticketInfo整段原样传给核销接口;次卡剩余次数可以从抖音的ticketData里读出来展示给顾客;- 重试时数量不能变。 同一张券正在核销时换一个
num再发,会返回CONSUME_IN_PROGRESS;与已有核销记录参数不一致时返回IDEMPOTENCY_CONFLICT,不要改参数重放。
按统一的重试规则,只有 errorCode 为 CONSUME_IN_PROGRESS、RESULT_UNKNOWN、SERVICE_UNAVAILABLE、PROVIDER_UNAVAILABLE,或请求超时没拿到响应时,才用首次请求的原样参数(包括 num)有间隔、有上限地重试,不换参数、不重新预核销,也不要让顾客重新输码;PLATFORM_REJECTED 和 ALREADY_CONSUMED(10500)要停止重试。抖音次卡结果未知时不自动重试,先查券状态或对账。
POST /api/hexiao/v2/ddzh-tuangou-receipt-consume
Authorization: Bearer <key>
Content-Type: application/json
{
"shopId": 123,
"platform": 1,
"code": "<券码>",
"ticketInfo": "<预核销返回的 ticketInfo 原文>",
"num": 2
}
美团另有次卡批量验券一类的原生接口,一次提交多个券码各自的数量,也可以通过无限聚核的原生接口调用;按接口说明,数量大于1时会查询同一个团单的其他券码一并核销,用之前同样要让顾客确认数量。
六、三种接入方式怎么选
| 比较项 | 成品核销系统 | 自己申请美团、抖音开放能力 | 通过第三方核销接口(如无限聚核) |
|---|---|---|---|
| 多张券、次卡 | 取决于系统是否支持选数量、逐张撤销 | 按两个平台的规则分别实现 | 一个核销数量参数覆盖两个平台;抖音次卡剩余次数由接口先校验 |
| 资质和资金 | 按系统方收费 | 美团服务零售团购核销开通时保证金账户余额须达到10万元;抖音生活服务商家应用代开发要求注册资本不低于100万元等(2026年9月10日核对,以官方后台为准) | 不需要自己满足平台服务商的保证金和安全资质;不收接口接入费,核销按当前账号适用的充值档位计费,撤销核销免费 |
| 灵活度 | 受限于系统现有功能 | 最高 | 高:数量选择和权益发放逻辑自己掌控 |
| 主要风险 | 数据和功能依赖系统方 | 周期长、审核不确定 | 依赖服务商稳定性,要先看文档、错误码和对账能力 |
七、上线前验收清单
用测试券把下面每一条走一遍:
- 一单3张券核2张:平台剩1张可用,本地2条记录、2份权益、2个撤销凭证;
- 次卡一次核2次:平台剩余次数减2,本地2份权益;
- 次卡剩1次却选2次:在确认页拦截,或接口返回次数不足,不产生核销;
- 双人套餐:只核1张,发双人权益;
- 核2张后撤销其中1张:只回收那一份权益;
- 核销超时后重试:数量和首次请求一致;
- 金额:同一订单多张券,支付明细不重复相加。
八、常见问题
美团一单买了多张团购券,可以一次核销几张吗?
可以。按美团开放平台Go SDK中的接口说明,输码验券返回可验证的张数 count,验券时用 count 指定本次核几张,不超过可验证的张数。让顾客选数量、默认1,核销成功后按返回的每一项分别发权益。
抖音一个订单有多张券,怎么只核其中几张?
验券准备会返回订单下可用的券,只把需要数量的 encrypted_code 放进验券请求,不要把整组都传进去。核销前让顾客确认数量。
次卡一次想用两次怎么核销?
抖音次卡按验券接口文档的说明,在 encrypted_codes 里放两个相同的加密券码;放之前用 times_count 减 times_used 算剩余次数,不够就不发请求。美团次卡的规则以平台为准。
双人套餐要核销两张吗?
不用。双人套餐是一张券,核1张,在对照表里把这张券配置成双人权益。核销数量填2,会去核这一单里的另一张券,或者被平台拒绝。
多核了一张券,能只撤销那一张吗?
能,在平台时限内按那一张的撤销凭证撤销:美团按开放平台SDK说明是核销后10分钟内,抖音是1小时内。撤销前先冻结那一张对应的权益,撤销成功再回收,其他张不动。
一次核销多张券,金额怎么算?
以返回的每一项为准,不要用单价乘数量。按美团开放平台Go SDK的字段说明,同一订单多张券核销返回的支付明细是一致的,都是整单的,按券相加会翻倍。
通过无限聚核核销多张券,num 参数怎么传?
num 取1到10,是本次核销的张数(次卡是次数)。美团按验券数量传给平台;抖音多张券从预核销返回的加密券码里取 num 张,不够时返回 TICKET_INVALID;抖音次卡先校验剩余次数。重试时 num 必须和首次请求一致,成功后按 data[i] 和 consumeCredential[i] 逐项保存。
核销、撤销接口的字段和错误码以无限聚核当前公开API文档为准。



