# 餐饮收银台怎么接团购验券？扫码枪输码、买单识别和交班对账

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

给餐厅做收银系统，团购验券的接口调用并不复杂，麻烦出在收银现场：扫码枪扫出来的有时是一串数字，有时是一个网址；高峰期收银员连按两次核销键；网络一卡，不知道券到底核没核掉；美团买单核销成功了，却找不到撤销凭证；到了交班，系统里的团购收入和平台后台对不上。这几件事要在收银台的设计里提前处理。

**一句话回答：** 收银台接团购验券按四步做：扫码枪当键盘用，回车结束，去掉空白后判断是券码还是抖音短链；先输码验券校验，收银员确认后再核销，只以返回的 `success` 为准；按结果分开入账，美团买单成功但没有撤销凭证，标记为不可在线撤销；交班时按券码和无限聚核账单订单号逐条核对，美团餐饮门店再用门店验券历史按日期核对。

- **扫码不猜平台。** 纯数字当券码，平台由收银员点选或用门店默认平台；抖音券二维码扫出的完整短链原样传；其他网址和文本直接提示，不发请求；
- **一张券先锁再核。** 收银员连点、扫码枪重复扫入，由收银台和服务端按券码去重，不靠接口拦截；
- **三种结果分开入账。** 套餐券、代金券保存撤销凭证；美团买单的 `consumeCredential` 为空数组，标记不可在线撤销；
- **重试后仍要核对结果。** 按允许的错误码用原请求重试；收到10500就停止重试，保存 `wxdgOrderNo`，核对原核销记录与当前业务订单，确认前不自动入账；
- **交班按状态分开统计。** 已核销、美团买单、凭证缺失、已撤销、待核对分开列，待核对的确认前不计入团购收入。

![餐饮收银台接团购验券示意：扫码枪输码按规则分流，输码验券校验时保存 ticketInfo 原文，验券只以 success 判断成功，交班按券码和无限聚核账单订单号核对；套餐券按对照表出菜、代金券按面值抵扣，都保存撤销凭证；美团买单成功但没有撤销凭证，标记不可在线撤销](assets/hero.png)

*示意图：通用做法，不是真实界面；接口规则以无限聚核当前公开API文档为准。*

## 一、扫码枪输码：先分流，再请求

收银台常用的扫码枪按键盘方式工作：扫一下，把内容逐字敲进当前输入框，末尾加一个回车。收银台监听回车，拿到整串内容后先在本地判断类型，再决定要不要请求接口。

![扫码枪输入分流示意：去掉空白后，纯数字作为券码，平台用收银员点选的按钮或门店默认平台；抖音券二维码扫出的完整短链按抖音原样传；其他网址如美团券二维码扫出的网址，提示输入二维码下方的数字券码；其他文本提示这不是团购券码](assets/01-scan-routing.png)

*示意图：分流规则为通用做法，平台以收银员点选或门店默认设置为准。*

| 扫到的内容 | 怎么判断 | 收银台怎么做 |
|---|---|---|
| 一串数字，可能带空格 | 去掉空白后只剩数字 | 作为券码；平台用收银员点选的美团或抖音按钮，没点选时用门店默认平台 |
| 抖音券二维码扫出的完整短链 | 抖音短链 | `platform` 传2，完整短链原样作为 `code` 校验 |
| 其他网址，如美团券二维码扫出的网址 | 是网址，但不是抖音短链 | 不解析，提示“请输入二维码下方的数字券码” |
| 其他文本 | 既不是数字，也不是网址 | 提示“这不是团购券码”，不发请求 |

分流规则和本站《小程序扫码核销团购券：美团券码、抖音二维码短链分别怎么处理？》一文相同：不按券码位数猜平台，也不拿同一个券码轮流试美团和抖音。平台选错时校验会失败，界面显示平台返回的原因，由收银员确认平台后再试。

收银现场还有几处细节：

- **输入法切到英文。** 中文输入法开着时，扫码枪敲进来的字符可能被输入法截住或变成全角，券码输入框获得焦点时切到英文输入；
- **以回车为结束。** 扫码枪按说明书设置为扫描后追加回车，收银台以回车判断一次输入结束，不靠输入停顿判断；
- **重复扫入只处理一次。** 同一个券码几秒内被扫入两次的，收银台只保留一次；
- **商品条码也是数字。** 收银员误扫了商品条码，会被当成券码送去校验，校验失败显示平台原因即可，不要为此按位数过滤；
- **美团券二维码扫出网址。** 请顾客打开券详情，收银员手输二维码下方的数字券码。

```go
// 扫码枪输入以回车结束：去掉空白后分流，不按位数猜平台，也不轮流试两个平台
// picked 为收银员点选的平台，没点选时为门店默认平台，都没有时为0
func classifyScan(raw string, picked int) (platform int, code string, err error) {
	s := strings.Join(strings.Fields(raw), "") // 去掉空格、换行、制表符
	switch {
	case s == "":
		return 0, "", ErrEmpty
	case isDigits(s):
		if picked == 0 {
			return 0, "", ErrPickPlatform // 提示收银员点选美团或抖音
		}
		return picked, s, nil
	case isDouyinShortLink(s): // 抖音券二维码扫出的完整短链
		return 2, s, nil // 原样作为 code，不自己解析
	case isURL(s): // 其他网址，如美团券二维码扫出的网址
		return 0, "", errors.New("请输入二维码下方的数字券码")
	default:
		return 0, "", errors.New("这不是团购券码")
	}
}
```

## 二、一张券从扫码到入账

1. **扫码分流。** 按上一节得到平台和券码；
2. **输码验券校验。** 调用校验接口，确认页显示平台、套餐名 `ticketName` 和售价，保存返回的 `data.ticketInfo` 原文；校验是只读请求，不改变券的状态；
3. **先记账再核销。** 收银员确认后，服务端先写一条“核销中”记录，存下本次请求的完整参数（`shopId`、`platform`、`code`、`ticketInfo`、`num`），再调用验券；
4. **按结果入账。** 见下表；
5. **改订单金额。** 套餐券在订单里标记团购已付，代金券按面值抵扣，剩余金额走收银。

| 返回情况 | 怎么识别 | 收银台怎么入账 | 能否在收银台撤销 |
|---|---|---|---|
| 套餐券、代金券核销成功 | `success` 为 true，`consumeCredential` 与 `data` 条数相同 | 按 `data[i]` 保存 `consumeCredential[i]`；套餐券按对照表出菜，代金券按面值抵扣 | 能，在平台时限内 |
| 美团买单核销成功 | 美团门店，`success` 为 true、`data` 有值，`consumeCredential` 为空数组 | 计入团购收入，标记“美团买单、不可在线撤销” | 不能，需要处理的到美团商家后台按平台规则操作 |
| 成功但条数对不上 | `success` 为 true，凭证条数和 `data` 条数不同，又不是美团买单 | 先按已核销记账，转人工核对 | 核对完之前不显示 |
| 平台拒绝 | `success` 为 false，带平台原因 | 不抵扣，显示原因，例如“此券号不存在” | — |
| 结果未知 | 请求超时没拿到响应，或 `errorCode` 属于可重试的几种 | 按下一节的重试规则处理 | 结果确定前不显示 |

按无限聚核当前公开API文档，美团买单核销成功时不返回撤销凭证，所以买单只看核销结果识别，不要在校验阶段猜。买单核销成功同样计费，在交班报表里和套餐券、代金券分开列。

到店出示团购券的，收银员一般在点单时校验并核销套餐券；代金券在结账、应付金额确定后核销。两种券的核销时机和抵扣算法，与本站《扫码点餐小程序怎么用美团、抖音团购券？套餐券、代金券的核销时机和抵扣做法》一文相同。

## 三、连点、超时和10500

收银现场的重复请求很常见：收银员高峰期连按两次核销，网络卡顿时又点一次，或者两台收银机扫了同一张券。按无限聚核当前公开API文档，相同业务请求命中已成功的核销时会返回10500，但接口幂等不等于业务幂等，服务端提示不能替代业务系统按券码和自己的订单去重。

- **按钮先锁。** 点了核销后按钮立即置灰，结果回来前不能再点；
- **服务端按券码去重。** 同一门店、同一平台、同一券码已有“核销中”或“已核销”记录的，不再发新的核销请求，直接返回本地状态；
- **超时用原请求重试。** 只有 `errorCode` 为 `CONSUME_IN_PROGRESS`、`RESULT_UNKNOWN`、`SERVICE_UNAVAILABLE`、`PROVIDER_UNAVAILABLE`，或请求超时没拿到响应时，才用“核销中”记录里保存的原请求（包括 `ticketInfo` 和 `num`）有间隔、有上限地重试；`PLATFORM_REJECTED` 和 `ALREADY_CONSUMED`（10500）停止重试。抖音次卡结果未知时不自动重试，先查券状态或对账；
- **重试收到10500，先核对原记录。** 这表示命中了已成功的核销记录，但响应仍是 `success=false`，`data` 为 null、`consumeCredential` 为空数组；不能仅凭重试次数就把当前业务订单记为已核销；
- **本单没发过却收到10500。** 按 `message` 里的核销时间和门店核对是哪一单核销的，确认前不计入本单。

重复请求的响应形如：

```json
{
  "success": false,
  "code": 10500,
  "message": "优惠券已于:2026-10-04 12:05:31核销;门店:<门店名>",
  "traceId": "<链路 ID>",
  "wxdgOrderNo": "<无限聚核账单订单号>",
  "data": null,
  "consumeCredential": [],
  "platformResult": null
}
```

重试收到10500时，保存响应里的 `wxdgOrderNo`、核销时间和门店，先标记“待核对”。结合原请求、本地业务订单和门店验券历史，确认确属本单且尚未入账后再补记一次；已有本地成功记录的直接复用，不能重复抵扣或出菜。没有首次成功响应就没有撤销凭证，不得编造凭证，收银台不显示撤销按钮，需要撤销的转人工处理。

```go
// 验券返回后入账：p 是发请求前写入的“核销中”记录，保存了完整的原请求
func onConsumeResult(ctx context.Context, p *Pending, resp *ConsumeResponse, timeout bool) error {
	if resp == nil && !timeout {
		return p.MarkReview(ctx, "响应为空：先查券状态或对账")
	}
	switch {
	case timeout || retryable(resp.ErrorCode):
		if p.DouyinTimesCard {
			return p.MarkReview(ctx, "抖音次卡结果未知：先查券状态或对账") // 不自动重试
		}
		return p.RetrySame(ctx) // 原请求原样重试，有间隔、有上限，超限转待核对
	case resp.Success && p.Platform == 1 && len(resp.ConsumeCredential) == 0:
		return p.MarkConsumed(ctx, resp, NotCancelable) // 美团买单：成功，没有撤销凭证
	case resp.Success && len(resp.ConsumeCredential) == len(resp.Data):
		return p.MarkConsumed(ctx, resp, Cancelable) // 按 data[i] 保存 consumeCredential[i]
	case resp.Success:
		return p.MarkReview(ctx, "凭证条数和核销条数对不上")
	case resp.Code == 10500:
		return p.MarkReview(ctx, "已核销提示：保存账单订单号并核对原业务订单，确认前不入账")
	default:
		return p.MarkFailed(ctx, resp.Message) // 平台拒绝等：不抵扣，显示原因
	}
}
```

## 四、交班对账

![交班对账示意：已核销计入团购收入，按券码和 wxdgOrderNo 核对，可在平台时限内撤销；美团买单计入团购收入并单独标记，不能在线撤销；收到10500但缺少首次成功记录的先待核对，确认属于本单且未入账后补记一次，不显示撤销；已撤销不计入团购收入；所有待核对项确认前不计入；美团餐饮 orderId、paymentDetail 为空，金额用 dealPrice 或 payAmount](assets/02-shift-reconcile.png)

*示意图：数据口径以无限聚核当前公开API文档为准。*

交班时，收银台的团购收入要和平台的验券记录对得上。几处口径：

- **两个订单号别混。** 顶层 `wxdgOrderNo` 是无限聚核系统账单订单号，可用于问题定位和查询账单订单；`data[].orderId` 是平台订单号，美团餐饮固定为空字符串。本地按券码 `receiptCode` 加 `wxdgOrderNo` 关联，美团餐饮的 `receiptCode` 可能是14位，原样保存；
- **金额用售卖价，口径统一。** 验券结果的 `dealPrice` 是售卖价（元），`payAmount` 是售卖价（分），报表选一个口径，不要混加；美团餐饮校验结果的 `actualPayAmount` 为 null，验券结果的 `paymentDetail` 为空数组、`merchantAmount` 和 `platformAmount` 为空字符串，实付和结算金额不从验券结果里取；
- **美团餐饮逐日核对验券历史。** 用美团餐饮原生接口“门店验券历史”按日期查询，返回美团原始报文，按券码和本地记录逐条比对。这个接口的 `offset` 是查询起始位置，从0开始，不是页码；`limit` 建议不超过200，翻页时 `offset` 加上本页条数，直到某页返回的条数少于 `limit`；
- **结算金额查结算明细。** 需要每张券的结算金额时，用“结算明细”按券码查询，券码参数不超过12位，以文档为准；“团购券交易快照”可以按券码查这张券的交易价格快照；
- **抖音门店和每日汇总。** 抖音门店的对账和每日汇总做法，见本站《团购核销怎么对账？美团、抖音核销记录与自有系统的每日核对方法》一文；
- **待核对清零再交班。** 结果未知、凭证缺失的记录，交班前查券状态或对账确认；确认前不计入团购收入，交接单上单独列出。

```http
POST /api/hexiao/v2/meituan/dining/tuangou/coupon/queryListByDate
Authorization: Bearer <key>
X-Store-Id: 123
Content-Type: application/json

{
  "date": "2026-10-04",
  "offset": 0,
  "limit": 200
}
```

`X-Store-Id` 传收银机绑定的系统门店 ID，和核销时的 `shopId` 是同一个门店。

## 五、收银台撤销

- **只对有凭证的记录显示撤销。** 美团买单、凭证缺失的记录不显示撤销按钮；
- **撤销要留痕。** 收银台撤销建议要求店长权限或填写原因，记录操作人和时间；
- **按凭证撤，逐项看结果。** 调用餐饮撤销接口，一次传1到10个凭证，`data[].status` 为 `succeeded`、`rejected` 或 `unknown`；平台拒绝时 `message` 为“平台拒绝撤销：<平台原因>”；
- **撤销成功再改单。** 撤销成功后才回退订单里的团购抵扣，顾客按撤销后的金额结账；被拒或结果未知的，抵扣先保留，转人工；
- **结果未知先查再撤。** 撤销接口不做幂等，相同凭证重复请求会再次发给平台；`unknown` 时先查券状态或对账，再决定是否重新撤销；
- **注意时限。** 抖音按开放平台说明是核销后1小时内可以撤销（2026年10月4日核对）；美团餐饮的撤销时限以美团规则为准，收银员核错了当场撤。更多撤销场景见本站《团购券核销错了能撤销吗？美团10分钟、抖音1小时的撤销规则与开发要点》一文。

## 六、以无限聚核为例

| 收银台动作 | 路由（POST） | 计费 |
|---|---|---|
| 扫码后校验 | `/api/hexiao/v2/dining-tuangou-receipt-prepare` | 免费 |
| 确认核销 | `/api/hexiao/v2/dining-tuangou-receipt-consume` | 核销成功计费，美团买单核销成功同样计费 |
| 核错撤销 | `/api/hexiao/v2/dining-tuangou-receipt-cancel` | 免费 |
| 拉套餐建对照表 | `/api/hexiao/v2/dining-tuangou-deal-queryshopdeal` | 免费 |

美团餐饮门店的对账查询用原生接口，请求头带 `Authorization: Bearer <key>` 和 `X-Store-Id: <系统门店 ID>`：

| 用途 | 原生接口（POST） | 主要参数 |
|---|---|---|
| 逐日核对验券 | `/api/hexiao/v2/meituan/dining/tuangou/coupon/queryListByDate` | `date`；`offset` 从0开始；`limit` 建议不超过200 |
| 查单张券结算金额 | `/api/hexiao/v2/meituan/dining/tuangou/coupon/queryTradeDetail` | `couponCode`，不超过12位 |
| 查券的交易价格快照 | `/api/hexiao/v2/meituan/dining/tuangou/ng/coupon/getCouponPriceInfo` | `code` |
| 查套餐的使用限制 | `/api/hexiao/v2/meituan/dining/tuangou/coupon/queryDealAttr` | `dealIds`，最多50个，英文逗号分隔 |

- **`shopId` 用具体门店。** 收银机绑定一家具体门店的系统门店 ID，传商户 ID 会返回 HTTP 400；
- **原生接口只做查询。** 按无限聚核当前公开API文档，验券、核销与撤销请使用核销聚合接口；原生查询返回美团原始报文，字段以美团文档为准；
- **只认 `success`。** 顶层 `code` 首次成功通常为10000，重复请求为10500，不能单独用来判断成功；
- **餐厅走餐饮路由。** 门店类目是到店餐饮的，用 `dining-tuangou-*` 路由，和服务零售的区别见本站《餐厅怎么接美团、抖音团购核销？到店餐饮接口和服务零售接口的区别》一文。

## 七、三种接入方式怎么选

| 比较项 | 成品餐饮收银系统 | 自己申请美团、抖音开放能力 | 通过第三方核销接口（如无限聚核） |
|---|---|---|---|
| 扫码、买单和交班对账 | 看系统是否支持扫码枪分流、买单标记和团购对账 | 自己实现，美团餐饮和抖音分别对接 | 收银流程自己实现，接口提供校验、核销、撤销和美团餐饮验券历史等查询 |
| 资质和资金 | 按系统方收费 | 美团服务零售团购核销开通时保证金账户余额须达到10万元，到店餐饮的开通要求以美团技术服务合作中心为准；抖音生活服务商家应用代开发要求注册资本不低于100万元等（2026年9月10日核对，以官方后台为准） | 不需要自己满足平台服务商的保证金和安全资质；不收接口接入费，核销按当前账号适用的充值档位计费，撤销核销免费 |
| 灵活度 | 受限于系统现有功能 | 高 | 高：收银流程和交班报表自己掌控 |
| 主要风险 | 数据和功能依赖系统方 | 周期长，两个平台都要对接和验收 | 依赖服务商稳定性，要先看文档、错误码和对账能力 |

## 八、上线前验收清单

用测试门店和测试券把下面每一条走一遍：

- 扫数字券码（带空格的也算）：去掉空白后按点选的平台校验；没点选平台、门店也没配默认平台的，提示先选平台；
- 扫抖音券二维码：按抖音校验，完整短链原样传；
- 扫出其他网址：提示“请输入二维码下方的数字券码”，不发请求；扫出其他文本：提示“这不是团购券码”；
- 中文输入法开着时扫码：券码照常识别；
- 连按两次核销：只发出一次核销请求；
- 核销超时：按允许的错误码用原请求重试；收到10500的停止重试、转待核对，确认原业务订单前不抵扣、不出菜，也不显示撤销；
- 美团买单核销（门店有这类核销时）：标记不可在线撤销，计入团购收入；
- 撤销一张券：撤销成功后订单抵扣回退；美团买单、凭证缺失的记录没有撤销按钮；
- 交班：五种状态分开列，待核对的不计入团购收入；美团餐饮门店当日验券历史和本地记录逐条对上。

## 九、常见问题

### 扫码枪能直接扫美团、抖音团购券吗？

能。扫码枪按键盘方式输入，扫出的内容以回车结束，收银台去掉空白后分流：纯数字当券码，按收银员点选或门店默认的平台校验；抖音券二维码扫出的完整短链，按抖音原样传给校验接口；美团券二维码扫出网址的，不解析，提示输入二维码下方的数字券码。

### 收银台怎么判断一张券是美团的还是抖音的？

不按券码位数猜。数字券码由收银员点选美团或抖音，没点选的用门店默认平台；只有抖音券二维码扫出的完整短链可以直接按抖音处理。平台选错时校验会失败，界面显示平台返回的原因，由收银员确认平台后再试，不要拿同一个券码轮流试两个平台。

### 怎么识别美团买单核销？

看核销结果。按无限聚核当前公开API文档，美团买单核销成功时不返回撤销凭证：美团门店核销成功、`data` 有值，顶层 `consumeCredential` 却是空数组的，按买单处理。这类记录计入团购收入，标记为不可在线撤销，前台不显示撤销按钮；需要处理的到美团商家后台按平台规则操作。

### 核销超时后重试返回10500，这张券算核销成功了吗？

10500 表示命中了已成功的核销记录，但不能直接当作本次业务订单核销成功。响应仍为 `success=false`，`data` 为 null、`consumeCredential` 为空数组。停止重试，保存 `wxdgOrderNo`、核销时间和门店，结合原请求与门店验券历史核对；确认属于本单且未入账后，才补记一次。缺少首次成功记录的先标记待核对，不自动抵扣或出菜，也不显示撤销按钮。

### 交班时团购券怎么对账？

本地记录按已核销、美团买单、凭证缺失、已撤销、待核对分开统计，待核对的确认前不计入团购收入。关联用券码加无限聚核账单订单号 `wxdgOrderNo`，不用平台订单号，美团餐饮的 `orderId` 是空的；美团餐饮门店再用门店验券历史按日期逐条核对，每张券的结算金额按券码查结算明细。

### 收银员核错了券，能在收银台撤销吗？

有撤销凭证的能，在平台时限内按这张券的 `consumeCredential` 撤销：抖音按开放平台说明是核销后1小时内，美团餐饮以美团规则为准。撤销成功后再回退订单里的团购抵扣；美团买单和凭证缺失的记录不能在线撤销，转人工处理。

### 收银台通过无限聚核接团购验券，要调哪些接口？

核销用三个餐饮聚合接口：扫码后调用输码验券校验（免费），收银员确认后调用验券（核销成功计费），核错时调用撤销核销（免费），`shopId` 用收银机绑定的具体门店。美团餐饮门店对账可以再用原生查询接口：门店验券历史按日期查，结算明细按券码查，请求头用 `X-Store-Id` 传同一个门店 ID。

收银台验券、核销、撤销和美团餐饮原生查询接口的字段和错误码以无限聚核当前公开API文档为准。
