开发实战

抖音团购核销接口怎么接?和美团不一样的几个地方

核销服务由无限聚核提供,美团、抖音团购核销一站式接入。

目录(11 节)
  1. 一、先确认要接的是哪一套接口
  2. 二、调用凭证:抖音一个应用一份,美团一个商家一份
  3. 三、验券准备和验券:一次准备只配一次验券
  4. 四、一次扫码,可能扫出好几张券
  5. 五、扫二维码,拿到的是短链
  6. 六、金额单位是分,字段还很多
  7. 七、判断成功:先看三层 error_code,再逐张看结果
  8. 八、撤销:1小时内,带上 verify_id 和 certificate_id
  9. 九、自己对接:先入驻,再过三项验收
  10. 十、不想自己办资质:以无限聚核为例
  11. 十一、常见问题

美团团购核销刚接好,老板紧接着就会问:“抖音的券能不能也核?”不少开发者以为照着美团的代码改改域名和字段就行,做起来才发现两边差得不少。美团顾客报一串数字就能验,抖音顾客多半直接亮二维码。美团拿明文券码就能核销,抖音必须先调“验券准备”,换出一个 verify_token 和加密券码。美团价格是元,抖音是分。连判断“成功”该看哪个字段,两边都不一样。

下面按开发顺序把这些差异列出来。抖音部分依据抖音开放平台“生活服务商家应用”的接口文档和技术服务商接入文档,2026年9月29日查看。

一句话回答: 抖音团购券核销用的是抖音开放平台生活服务的 /goodlife/v1/fulfilment/certificate/ 系列接口,顺序固定为“验券准备 → 验券”,验券后1小时内可以撤销。和美团相比,最要紧的有四点:

  • 抖音用应用级 client_token 调用,每次请求用 poi_id 指定门店;
  • 每次验券前都要重新调验券准备,用返回的 verify_token 和 encrypted_code 去核销,不能传明文券码;
  • 顾客出示的二维码扫出来是短链,要取跳转后长链接里的 object_id;
  • 金额单位是分;判断成功要同时看 data.error_code、extra.error_code 和每张券的 verify_results[].result。

自己对接,要先入驻抖音服务商平台,再通过联调、压测、安全三项验收。不想自己办资质,可以通过无限聚核这类第三方接口,和美团共用一套验券、核销接口,platform 传2。

左边是美团团购券,顾客报数字券码,验券后直接核销;右边是抖音团购券,扫二维码得到短链,经验券准备换出 verify_token 和加密券码后再验券
差异示意:画面为示意图,不是平台真实页面。

一、先确认要接的是哪一套接口

抖音开放平台上叫“核销”的接口不止一套。最常见的混淆是这两套:

生活服务商家应用(本文讲的) 抖音小程序交易系统
券从哪来 商家在抖音来客上架团购,顾客在抖音App团购页购买 商家自己的抖音小程序里下单
验券相关接口 GET /goodlife/v1/fulfilment/certificate/prepare/、POST /goodlife/v1/fulfilment/certificate/verify/ /api/apps/trade/v2/fulfillment/delivery_prepare、delivery_verify
门店标识 poi_id 以小程序交易文档为准

判断方法:顾客的券是在抖音App团购页买的,商家在抖音来客后台能看到这笔订单,就用生活服务这一套。网上搜到的示例代码,路径里带 /api/apps/trade/ 的属于小程序交易系统,拿来核销团购券是调不通的。

还有一个小细节:生活服务接口的路径都以 / 结尾,接入文档特意写了“/不可省略”。从美团代码改过来时顺手删掉结尾斜杠,是很常见的低级错误。

二、调用凭证:抖音一个应用一份,美团一个商家一份

美团 抖音
调用凭证 每个商家单独授权,各有一套 access token 和 refresh token 一个应用一个 client_token,所有已授权商家共用
商家怎么授权 商家打开授权链接,登录美团确认 商家在抖音来客后台把应用授权给服务商,或者在服务商的系统里完成授权
凭证过期 用 refresh token 续期;refresh token 失效,这家店要重新授权 重新生成 client_token,商家不用操作

抖音所有接口的请求头都要带 access-token,值是 /oauth/client_token/ 返回的 data.access_token。它是应用级凭证,带来三个后果:

  1. 集中生成和缓存。 多台服务器部署时,快过期前统一刷新。刷新要加分布式锁,拿到锁以后再看一眼缓存,如果别的机器已经刷新过就直接用,免得几台机器同时刷新、互相顶掉;
  2. 门店全靠 poi_id 区分。 凭证里没有门店信息。库里要存好“自己的门店 ↔ 抖音 poi_id”的映射,传错了轻则报无权限,重则把券核到别的门店;
  3. 连锁场景多一个参数。 验券准备接口的 account_id,文档写的是“云连锁/共管场景下,挂靠商户必传,其余场景可不传”。

美团正好相反,凭证跟着商家走。每家店的 refresh token 都要可靠地存下来:刷新拿到新的 refresh token 后,先写数据库,再更新缓存。异步保存丢了一次,那家店就只能重新授权。两套凭证的管理逻辑差别很大,不要硬套进同一个类。

三、验券准备和验券:一次准备只配一次验券

抖音团购券核销分两步,这是和美团差别最大的地方。

第一步,验券准备。 code(明文券码)和 encrypted_data(从二维码解析出来的标识)二选一,poi_id 必传:

GET /goodlife/v1/fulfilment/certificate/prepare/?poi_id=<门店poi_id>&encrypted_data=<URL编码后的object_id>
access-token: <client_token>

返回里核销要用的主要是这几项(其他字段省略,数值为虚构):

{
  "data": {
    "error_code": 0,
    "verify_token": "<本次验券标识>",
    "order_id": "<订单ID>",
    "certificates": [
      {
        "encrypted_code": "<加密券码>",
        "expire_time": 1790000000,
        "amount": { "original_amount": 29900, "pay_amount": 26900 },
        "sku": { "sku_id": "<商品ID>", "title": "精洗10次卡", "groupon_type": 3 },
        "time_card": { "times_count": 10, "times_used": 3 }
      }
    ]
  },
  "extra": { "error_code": 0, "logid": "<抖音日志ID>" }
}

第二步,验券。 把上一步的 verify_token 和挑出来的 encrypted_code 传回去:

POST /goodlife/v1/fulfilment/certificate/verify/
access-token: <client_token>
Content-Type: application/json

{
  "verify_token": "<验券准备返回的 verify_token>",
  "poi_id": "<门店poi_id>",
  "encrypted_codes": ["<验券准备返回的 encrypted_code>"]
}

文档里这几句要看仔细:

  • 验券准备和验券接口的“调用次数需要一一对应”;已经验券成功的,“当前二维码会失效”,要用刷新后的二维码再调用;
  • 验券准备“只返回未使用状态的券信息”,而且“不返回明文券码,只返回加密券码”;
  • encrypted_codes 的说明是“验券准备接口返回的加密抖音券码”。

落到代码里,常见的坑有这几个:

把明文券码塞进 encrypted_codes。 从美团迁移过来最容易犯,平台会报“加密码解密失败”一类的错误,网上不少求助帖都是这个原因。明文券码只能用在验券准备的 code 参数里。

缓存 verify_token 重试。 核销失败或超时后,拿旧的 verify_token 再调一次验券,不符合“一一对应”。结果明确失败的,重新调验券准备再验。结果不明的(超时、连接断开),先查券状态,确认没核掉再重来。

券正在转赠。 转赠中的券,验券准备返回空数组。页面上别只写“券无效”,提示“这张券可能正在转赠中,请确认后再试”,能少接不少客服电话。

提货券少算张数。 文档写明,提货券订单一个订单多张券只会返回一个 certificate_id。按 certificate_id 去重计数的,这里会算少。

certificate_id 的精度。 验券准备响应里的 certificate_id 在文档中标为64位整数。Node.js 直接 JSON.parse 可能丢精度,用支持大整数的解析方式,或者按字符串处理。

四、一次扫码,可能扫出好几张券

抖音团购二维码对应的是订单。文档写明,扫码后“可返回当前订单下可用的全部券码信息”。顾客买了3张洗车券,今天只洗1次,验券准备会把3张都返回来。

所以核销前要让顾客选数量,只取需要的那几个 encrypted_code,不要把 certificates 整组塞进 encrypted_codes。一次核掉3张,顾客第二天才发现,已经过了1小时的撤销时限,只能走平台售后。

次卡是另一种情况:一张券,多次使用。time_card 里 times_count 是总次数,times_used 是已用次数。验券接口文档对 encrypted_codes 的说明是:“多次卡商品,如果需要一次核销多份,list中传多个相同encrypted_code”。一张洗车次卡今天洗两台车,就把同一个加密券码放两次。放之前先算 times_count - times_used 够不够,不够就别发请求。

五、扫二维码,拿到的是短链

顾客在抖音App里打开团购券,出示的是二维码。用 wx.scanCode 或扫码枪扫出来,是一个抖音短链。按抖音文档:

  1. 访问短链,拿到跳转后的长链接;
  2. 取长链接里 object_id 参数的值作为 encrypted_data,URL 编码后再传;
  3. 只认 object_id 这一个参数,域名、路径和其他参数都可能调整;
  4. 短链长度不固定,不要限制长度,也不要截断。

顾客也可以报二维码下方的数字券码,这时用 code 参数。两个入口最后调的是同一个验券准备接口。扫码入口的完整做法,可以参考本站《小程序扫码核销团购券:美团券码、抖音二维码短链分别怎么处理?》一文。

六、金额单位是分,字段还很多

抖音团购券金额字段示意:售价、实付、划线价单位都是分,美团以元为单位
金额字段示意:字段来自抖音开放平台验券准备接口文档,金额为虚构示例。

美团验券返回的套餐价是以元为单位的小数,比如 79.9;抖音验券准备的 amount 里全是以分为单位的整数,比如 7990。常用的几个:

字段 文档说明 用途
original_amount 原价,单位分 套餐售价,对账主要看它
pay_amount 实付金额,单位分 顾客实际付了多少
list_market_amount 划线价,单位分 页面上划掉的那个价
merchant_ticket_amount 商家营销金额,单位分 商家自己出的优惠
platform_discount_amount 平台优惠金额,单位分 平台补贴

original_amount 虽然叫“原价”,指的是套餐售价,划线价另有 list_market_amount,别弄反。两个平台的券放进同一张表对账时,统一存成以分为单位的整数,不要用浮点数存元。

七、判断成功:先看三层 error_code,再逐张看结果

抖音验券响应结构:两层 error_code 为0且逐张结果成功才算成功,保存撤销凭证
响应结构示意:字段来自抖音开放平台验券接口文档,数值为虚构。

美团的验券接口,看顶层 code 是不是 OP_SUCCESS,再核对返回的券码和数量。抖音要看三处:

  1. data.error_code 不为0:请求失败,原因在 data.description;
  2. extra.error_code 或 extra.sub_error_code 不为0:同样按失败处理,原因在 extra.description 和 extra.sub_description;
  3. 前两层都为0,还要逐张看 data.verify_results[].result,文档写的是“0表示成功,非0表示失败”。

抖音的技术服务商入驻指南里专门提醒过:“验券接口返回的验券结果 result 字段必须进行业务匹配检查”,result 非0“表示业务侧提示而非技术异常”。一次核销多张券时,完全可能一张成功、一张失败。这时按“部分成功”处理:成功的那张发放权益,失败的那张单独提示。

每张成功的券,把 verify_id 和 certificate_id 存下来,撤销时要用。extra.logid 也存上,找抖音技术支持排查问题时要提供它。

// 按三层 error_code 和逐张 result 判断抖音验券结果
type verifyResp struct {
	Data struct {
		ErrorCode     int64  `json:"error_code"`
		Description   string `json:"description"`
		VerifyResults []struct {
			Result        int64  `json:"result"`
			VerifyID      string `json:"verify_id"`
			CertificateID string `json:"certificate_id"`
		} `json:"verify_results"`
	} `json:"data"`
	Extra struct {
		ErrorCode      int64  `json:"error_code"`
		SubErrorCode   int64  `json:"sub_error_code"`
		Description    string `json:"description"`
		SubDescription string `json:"sub_description"`
		Logid          string `json:"logid"`
	} `json:"extra"`
}

func judge(r verifyResp) (ok []Voucher, failed int, err error) {
	if r.Data.ErrorCode != 0 {
		return nil, 0, fmt.Errorf("验券失败 %d %s logid=%s", r.Data.ErrorCode, r.Data.Description, r.Extra.Logid)
	}
	if r.Extra.ErrorCode != 0 || r.Extra.SubErrorCode != 0 {
		return nil, 0, fmt.Errorf("验券失败 %d/%d %s %s logid=%s", r.Extra.ErrorCode, r.Extra.SubErrorCode,
			r.Extra.Description, r.Extra.SubDescription, r.Extra.Logid)
	}
	for _, v := range r.Data.VerifyResults {
		if v.Result != 0 {
			failed++ // 业务侧提示,逐张处理,不能把整笔当成功
			continue
		}
		ok = append(ok, Voucher{VerifyID: v.VerifyID, CertificateID: v.CertificateID}) // 撤销要用,必须落库
	}
	return ok, failed, nil
}

HTTP 超时、连接断开、响应解析失败,这三种情况都不是“失败”,是“结果未知”,券可能已经核掉了。先调券状态查询接口 GET /goodlife/v1/fulfilment/certificate/get/ 确认,再决定发不发权益、要不要重试。

八、撤销:1小时内,带上 verify_id 和 certificate_id

抖音“撤销核销”接口文档写明,验券超过一个小时就不可再撤销,撤销后订单状态由“已使用”改回“待使用”;extra.error_code 和 data.error_code 均为0,才代表撤销成功。请求里带验券时保存的 verify_id 和 certificate_id。

美团是10分钟,两个平台差了6倍。系统里的撤销按钮要按平台分别倒计时。撤销功能怎么做、超时了怎么办,本站《团购券核销错了能撤销吗?》一文里有完整说明。

九、自己对接:先入驻,再过三项验收

抖音技术服务商接入进度示意:入驻认证、创建应用、开通解决方案、基础配置、验收准备,联调、压测、安全三项验收,最后应用上线和商家授权
接入流程示意:依据抖音开放平台技术服务商接入文档整理(2026年9月29日查看),不是真实后台界面。

直接调用上面这些接口,前提是你已经是抖音生活服务的技术服务商,而且应用已经上线。按抖音开放平台的技术服务商入驻指南,大致要走这些环节:

  1. 入驻并认证。 在服务商平台认证“生活服务商家应用代开发”能力,文档写的是“平台一般在 10 个工作日内完成审核”,通过后还要做对公认证。认证条件包括注册满一年、注册资本不低于100万元、经营范围含技术开发服务、同主体 ICP 备案(2026年9月10日核对,以平台当前要求为准);
  2. 创建应用。 创建“第三方生活服务商家应用”,审核时效1个工作日;
  3. 开通解决方案。 核销能力在行业解决方案里,比如“到综行业团购解决方案”“到店餐饮解决方案”,可以整体开通,也可以按能力开通;
  4. 基础配置。 包括 Webhooks 和 SPI 地址注册,以及 IP 白名单。白名单是可选项,启用后所有接口请求的源 IP 都必须在白名单里;
  5. 验收准备。 绑定测试店铺,把测试用的抖音账号加白;
  6. 联调、压测、安全三项验收,全部通过后申请应用上线;
  7. 商家授权。 应用上线后,商家把应用授权给你,你才能调这家商家的接口。

三项验收里,容易卡住的是这些细节。

联调验收。 用例里填的订单号和 logid 必须来自测试店铺的测试账号。测试商品名称必须包含“测试”,售卖有效期、使用有效期都不能超过14天,提交后人工审核,时效1个工作日。测试店铺不对外展示,下单要在抖音来客后台“商品管理 → 更多 → 生成二维码”,用加白的抖音账号扫码购买。调用商品创建接口时,请求头要加 Rpc-Persist-Life-Test-Data-Access: all。

压测验收。 压的是你提供给抖音调用的 SPI 接口。压测请求都带 X-Stress-Tag: 1 请求头,服务端要识别它,别把压测请求当成真实订单处理。点“发起调试”时,抖音会取参数文件第一条数据重复请求两次,接口没做去重就会出问题。通过标准是成功率大于99.95%(接口返回 error_code=0 才算成功),PCT99 耗时不超过压测计划里配置的超时时长。压测时段只能选周一到周四的23:00到次日7:00。

安全验收。 要逐项提交材料:可登录的系统地址和测试账号;登录口令至少8位、包含三种以上字符,登录页有验证码或访问频次限制;手机号、姓名等隐私字段脱敏展示,手机号保留前3位和后4位;client_secret、client_token 加密存储,不能硬编码、不能明文保存,也不能下发给客户端;从开放平台拿到的敏感字段加密存储,文档推荐 AES256 一类算法;接入 WAF 并提供最近一个月的拦截记录或购买凭证,只开放必要端口。

这些要求都合理,加起来却是实打实的工作量。只想让自己的小程序或门店设备能核抖音券,走完整套流程往往不划算。

十、不想自己办资质:以无限聚核为例

通过无限聚核的 V2 聚合接口,抖音和美团共用一套验券、核销接口,platform 传2代表抖音。无限聚核当前公开 API 文档写明:

  • 门店授权。 调 POST /api/hexiao/v2/get/auth/url,传具体门店 shopId 和 platform=2,把返回的链接发给商家,商家在抖音侧确认授权;
  • 验券。 调“输码验券校验”接口,code 传数字券码,或者扫码得到的完整短链。object_id 解析、client_token 和 poi_id 都由服务端处理;
  • 返回。 payAmount 是售卖价(分),dealPrice 是售卖价(元),actualPayAmount 是用户实付(分),和美团券口径一致。ticketInfo 是后续核销必需的凭证,要整段原样保存,不要解析;ticketData 是抖音官方响应 data 对象的完整原文,次卡剩余次数可以从这里读;
  • 核销。 调“验券”接口,把 ticketInfo 原样传回,num 是核销数量。次卡会先校验 time_card 剩余次数;
  • 判断结果。 只看顶层 success。成功时按下标保存 consumeCredential,撤销时要用。platformResult 保留抖音原始的 data 和 extra,排查问题时看它;
  • 计费。 预核销不计费,核销计费,撤销免费。
POST /api/hexiao/v2/ddzh-tuangou-receipt-prepare
Authorization: Bearer <key>
Content-Type: application/json

{
  "shopId": 123,
  "platform": 2,
  "code": "<扫码得到的完整短链,或数字券码>"
}

有两件事,走第三方接口也不会变:每次核销前都要重新预核销,“一次准备配一次验券”的规则还在;撤销时限仍然是1小时。

自己入驻抖音服务商 通过第三方接口(如无限聚核)
资质 入驻认证、对公认证 不需要自己的服务商资质
上线前 联调、压测、安全三项验收 商家授权后用真实券调试
自己要实现的 client_token、poi_id 映射、验券准备、短链解析、三层结果判断 调统一的验券、核销、撤销接口
能用的能力 解决方案里开通的全部能力 以第三方开放的接口为准
成本 研发、验收和持续运维 按核销次数付费

十一、常见问题

抖音团购券能直接用明文券码核销吗?

不能直接核销。明文券码只能作为验券准备接口的 code 参数,验券接口的 encrypted_codes 要传验券准备返回的加密券码。把明文券码直接传给验券接口,会报加密码解密失败一类的错误。

抖音验券报“加密码解密失败”是什么原因?

最常见的原因是 encrypted_codes 里传了明文券码,或者传了别的订单、上一次验券准备得到的加密券码。每次验券前重新调验券准备,用这一次返回的 verify_token 和 encrypted_code。

同一个 verify_token 可以用两次吗?

不建议。抖音文档要求验券准备和验券的调用次数一一对应,验券成功后二维码会失效。明确失败的,重新调验券准备再验;结果未知的,先查券状态再决定。

顾客买了3张券,扫码后只想用1张怎么办?

扫码后验券准备会返回这个订单下全部可用的券。让顾客选数量,只把对应数量的 encrypted_code 放进 encrypted_codes,不要整组传入。

抖音次卡怎么一次核销多次?

按抖音验券接口文档,多次卡一次核销多份时,在 encrypted_codes 里放多个相同的加密券码。放之前用 time_card 的 times_count 减去 times_used 算出剩余次数,次数不够就不要发起核销。

抖音团购核销接口的金额单位是什么?

抖音验券准备返回的金额都以分为单位,original_amount 是套餐售价,pay_amount 是用户实付,划线价是 list_market_amount。美团套餐价以元为单位,两个平台混合对账时统一换算成分。

抖音团购券核销后多久内可以撤销?

抖音撤销核销接口文档写明,验券超过一个小时就不可再撤销。撤销要带验券时返回的 verify_id 和 certificate_id,data.error_code 和 extra.error_code 均为0才算撤销成功。

不是抖音服务商,能调用抖音团购核销接口吗?

不能直接调用。抖音生活服务接口要求服务商完成入驻认证、开通解决方案、通过联调压测安全三项验收并上线应用,商家还要把应用授权给你。没有这些条件的,可以用已接入抖音的门店系统,或者通过无限聚核这类第三方接口核销。

通过无限聚核核销抖音券,和核销美团券有什么不同?

接口是同一套,platform 传2代表抖音,code 除了数字券码,还可以传扫码得到的完整抖音短链。金额口径两个平台一致:payAmount 和 actualPayAmount 以分为单位,dealPrice 以元为单位。抖音的撤销时限是1小时,美团是10分钟。

免费接入 · 按次计费

把美团、抖音团购核销接进你的业务

无限聚核提供美团、抖音、大众点评团购核销 API:不收接入费、无需保证金,核销成功才计费。

技术支持无限聚核白水客户经理联系名片及微信二维码