微信小程序接入美团、抖音团购核销实战:从门店授权到核销与撤销
核销服务由无限聚核提供,美团、抖音团购核销一站式接入。

目录(11 节)
顾客买好团购券,打开你的微信小程序,选门店、输入券码、确认套餐。核销成功后,系统给他一份三小时的门店服务权益,接着就能预约或使用服务。

微信小程序接入美团、抖音团购核销,可以通过无限聚核(下文简称聚核)的 V2 服务零售聚合接口串起门店授权、预核销、核销与撤销。本文面向已有小程序和业务后端的开发团队,用 Java 示例把聚核接口的调用结果接回自己的预约或权益系统。
一、先把完整效果串起来
顾客侧需要选店、输码、确认和结果页。后台则要知道:这是谁的券、在哪家门店使用、对应什么套餐,以及成功后发什么权益。尚未确定接口申请路径,可以先看本系列的《微信小程序怎么接入美团、抖音团购核销?申请步骤、材料与成本对比》。
建议采用“小程序 → 自己的业务后端 → 无限聚核”的调用方式。小程序交互围绕自己的业务门店和确认单展开,后端负责权限、门店映射和接口调用,再把核销结果接回预约或会员系统。

下文使用 Java 11+ 与 Jackson 写接入示例,保留真实 HTTP 请求、JSON 参数和关键控制流,省略 import、完整服务类和框架配置。代码片段可放在同一服务类中,使用第三章的
postJson封装;这些是接入示例,不是聚核 SDK,本文未编译代码或调用真实业务接口。
business 是接入方的 BusinessPort 业务接口,负责权限、门店和商品映射、确认上下文、核销记录及权益操作;PreparedRedemption、Receipt 是自己的业务对象,只使用代码中所示访问器。adapter 的 String productId(int platform, String shopId, JsonNode prepareData) 负责商品识别,也由接入方实现。
二、把自己的门店对应到聚核门店
先分清三个层次:自己的业务门店、聚核的商户与门店、美团或抖音门店。聚核商户用于组织一组门店,本身不做授权和核销;本文把每家实际经营的业务门店对应到聚核商户下的一家具体门店,再核对它关联的平台门店。
业务调用使用保存下来的聚核门店 shopId。 别把自己系统的门店 ID、聚核商户 ID 或平台门店 ID 混在同一个字段里;核销类接口只接受具体门店 ID,传商户 ID 会直接返回错误。

在无限聚核开发者后台的门店列表页,可以看到商户卡片,以及商户下每家门店的美团、抖音授权状态和授权入口。

使用控制台准备门店时,先新建商户,再在该商户下新建门店。商户表单填写内部名称并选择业务类目,本文使用服务零售;门店表单在已选商户下填写具体门店名称。


shopId。如果要把门店入驻放进自己的 SaaS 后台,可以接聚核的“创建商户或门店”接口 store/create,同样分两步:不传 masterShopId 时只创建一个商户,返回的 data.shopId 是商户 ID,不会自动创建门店;再传 masterShopId 在该商户下创建具体门店,这次返回的 data.shopId 才是后续授权和核销使用的门店 ID。业务类目 businessCategory 只在创建商户时生效,门店继承所属商户。
String createMerchant(String merchantName) throws IOException, InterruptedException {
business.requireAccountAdmin();
ObjectNode request = json.createObjectNode().put("shopName", merchantName)
.put("businessCategory", "service_retail"); // 服务零售;到店餐饮为 dining
String merchantId = postJson("store/create", request.toString()).requireData()
.path("shopId").asText();
if (merchantId.isBlank()) throw new IllegalStateException("Missing merchant id");
business.saveMerchant(merchantId);
return merchantId; // 商户 ID 只用于创建门店,不用于授权和核销
}
String createStore(String localStoreId, String shopName, String masterShopId)
throws IOException, InterruptedException {
business.requireStoreAdmin(localStoreId);
ObjectNode request = json.createObjectNode().put("shopName", shopName)
.put("masterShopId", masterShopId);
String shopId = postJson("store/create", request.toString()).requireData()
.path("shopId").asText();
if (shopId.isBlank()) throw new IllegalStateException("Missing store id");
business.saveStoreMapping(localStoreId, shopId, masterShopId);
return shopId;
}
示例先用 createMerchant 建好商户并保存商户 ID,再为每家业务门店调用 createStore。创建出来的门店还要完成平台授权。建议在映射记录旁保留平台门店的核对结果,方便后续发现“顾客选的是 A 店,实际关联了 B 店”这类配置问题。
三、完成商家授权,把凭据放到服务端
门店创建、获取授权链接、商家完成授权,是三个步骤。先在控制台从对应门店发起美团或抖音授权,商家完成后,再核对平台门店与授权状态。拿到一个链接,还不能把门店标成已授权。
自建入驻流程时,聚核 API 文档中的“获取美团/抖音授权链接”接口接受具体门店 shopId 和 platform;平台值为 1 美团、2 抖音,成功时 data 是授权 URL。
String authorizationUrl(String localStoreId, int platform)
throws IOException, InterruptedException {
business.requireStoreAdmin(localStoreId);
String shopId = business.shopId(localStoreId);
ObjectNode request = json.createObjectNode()
.put("shopId", shopId).put("platform", platform);
JsonNode data = postJson("get/auth/url", request.toString()).requireData();
if (!data.isTextual() || data.textValue().isBlank()) {
throw new IllegalStateException("Missing authorization URL");
}
return data.textValue(); // 展示给商家;授权完成后另行核对门店和状态
}
从无限聚核开发者后台的开发者中心获取当前账号 API key,保存在自己的服务端。API Host 按聚核快速开始文档填写,同样放在服务端配置里;请求头示例为 Authorization: Bearer <key>。
private final ObjectMapper json = new ObjectMapper();
private final HttpClient http = HttpClient.newHttpClient();
private String apiHost; // 聚核快速开始文档中的 API Host,从服务端配置注入
private String apiKey; // 从自己的服务端配置注入,不放进小程序
static final class ApiResponse {
final int httpStatus;
final JsonNode body;
ApiResponse(int httpStatus, JsonNode body) {
this.httpStatus = httpStatus;
this.body = body;
}
boolean isSuccess() {
return body.path("success").isBoolean() && body.path("success").booleanValue();
}
String errorCode() {
return body.path("errorCode").asText(""); // 失败分支按它处理,不按中文提示匹配
}
JsonNode requireData() {
if (!isSuccess()) throw new IllegalStateException("API result requires handling");
return body.path("data");
}
}
ApiResponse postJson(String path, String requestJson)
throws IOException, InterruptedException {
HttpRequest request = HttpRequest.newBuilder(URI.create(
apiHost + "/api/hexiao/v2/" + path))
.timeout(Duration.ofSeconds(10)) // 本例的客户端超时设置
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestJson)).build();
HttpResponse<String> response = http.send(request, HttpResponse.BodyHandlers.ofString());
JsonNode body;
try {
body = json.readTree(response.body());
} catch (JsonProcessingException e) {
body = NullNode.getInstance(); // 保留 HTTP 状态,由调用处分类
}
return new ApiResponse(response.statusCode(), body == null ? NullNode.getInstance() : body);
}
小程序请求到达自己的后端时,要先检查用户和业务门店权限,再查映射调用接口。聚核会校验门店是否属于当前账号,你自己的用户权限仍由业务后端负责。
四、接口按用途接,不必一次全部铺开
先做顾客确认与核销,再补商品配置、门店入驻和售后页面。下表都是聚核提供的接口,除注明外使用 POST,路径以 /api/hexiao/v2/ 为前缀;参数与响应以聚核 API 文档中的对应接口为准。
| 能力 | 接口路径后半段 | 本文如何使用 |
|---|---|---|
| 预核销(输码验券校验) | ddzh-tuangou-receipt-prepare |
必接,检查具体券并取得核销凭证 |
| 核销(验券) | ddzh-tuangou-receipt-consume |
必接,顾客确认使用后执行 |
| 获取团购信息 | ddzh-tuangou-deal-queryshopdeal |
用于展示套餐、配置本地权益映射 |
| 创建商户或门店 | store/create |
自建入驻后台时接,先建商户再建门店 |
| 获取授权链接 | get/auth/url |
把商家授权整合进自己的后台时接 |
| 撤销核销 | ddzh-tuangou-receipt-cancel |
有撤销售后流程时接 |
| 美团查询已验券信息 | meituan/ddzh/tuangou/receipt/getconsumed |
核销或撤销结果仍不确定时核对 |
| 抖音券状态查询 | douyin/goodlife/v1/fulfilment/certificate/get/(GET) |
核销或撤销结果仍不确定时核对 |
文档把预核销称为“输码验券校验”,把真正执行核销的接口称为“验券”。开发时可以在自己的封装里明确命名为 prepare 和 consume,避免在顾客尚未确认时误调后者。最后两行是聚核提供的美团、抖音原生查询接口,保持平台原始响应,请求头要带 X-Store-Id 指定门店。
五、先认识套餐,再决定发什么权益
商品列表解决的是“这家店卖什么”。例如将某个平台商品配置成“三小时服务权益”,后续识别到这款商品,自己的系统才知道该给顾客什么。
建议用 平台+聚核门店+平台商品 ID 作为映射条件。套餐名称用于展示,不能只靠名称判断商品;不同平台的同名套餐也应分别配置。
void configureProduct(String localStoreId, int platform, int page, int pageSize,
String selectedDealId, String benefitId)
throws IOException, InterruptedException {
business.requireStoreAdmin(localStoreId);
String shopId = business.shopId(localStoreId);
ObjectNode request = json.createObjectNode().put("shopId", shopId)
.put("platform", platform).put("offset", page).put("limit", pageSize);
JsonNode deals = postJson("ddzh-tuangou-deal-queryshopdeal", request.toString()).requireData();
for (JsonNode deal : deals) {
if (selectedDealId.equals(deal.path("dealId").asText())) {
business.saveProductMapping(platform, shopId, deal.deepCopy(), benefitId);
return;
}
}
throw new IllegalArgumentException("Selected product is not in this page");
}
示例把管理员在当前页选中的商品与本地 benefitId 关联,并保存这条商品记录;美团券后面要用其中的套餐名称 title 和售卖价 price 做预匹配。三小时服务对应哪一个 benefitId,由自己的权益系统配置。
聚核“获取团购信息”接口的 offset 是页码,从 1 开始,limit 是每页条数,最大 100;列表中的 price、marketPrice 单位是元。
套餐配置完成后,可以按自己的业务需要同步或维护。顾客每次用券仍要预核销:列表有这款商品,不等于他输入的这张券可以使用。
六、预核销后展示确认页,保存原始凭证
顾客选好门店、平台并输入券码,后端先找出聚核门店 shopId,以同一组 shopId、platform、code 调用预核销(聚核文档称“输码验券校验”)。成功后展示套餐和本地对应权益,等顾客确认。
预核销成功时,统一的 data 里有这几项,其中几处容易接错:
ticketName是套餐名称;payAmount是售卖价,单位分;dealPrice也是售卖价,单位元;actualPayAmount是顾客实付,单位分,可能为空。展示时换算清楚,不能与商品列表的金额单位混用。ticketInfo是后续核销要原样回传的字符串。不要解析后重组、删字段或替换它。ticketData是抖音官方券信息 JSON,美团券为空字符串。- 响应里没有统一的商品 ID,也没有门店 ID;后续调用始终使用自己保存的聚核门店
shopId。
ObjectNode prepare(String localStoreId, int platform, String code, int num)
throws IOException, InterruptedException {
String userId = business.requireUserAccess(localStoreId);
String shopId = business.shopId(localStoreId);
if (num < 1 || num > 10) throw new IllegalArgumentException("Invalid quantity"); // 接口允许 1–10
ObjectNode request = json.createObjectNode().put("shopId", shopId)
.put("platform", platform).put("code", code);
JsonNode data = postJson("ddzh-tuangou-receipt-prepare", request.toString()).requireData();
// 抖音从 ticketData 读取商品;美团用 ticketName + dealPrice 与已配置商品预匹配
String productId = adapter.productId(platform, shopId, data.deepCopy());
if (productId == null || productId.isBlank()) {
throw new IllegalStateException("Product needs review"); // 识别不到或命中多个
}
String benefitId = business.findBenefit(platform, shopId, productId);
if (benefitId == null) throw new IllegalStateException("Configure product mapping first");
String ticketInfo = data.path("ticketInfo").textValue();
if (ticketInfo == null || ticketInfo.isEmpty() || !data.path("payAmount").isNumber()) {
throw new IllegalStateException("Incomplete prepare response");
}
ObjectNode consumeRequest = request.deepCopy().put("num", num).put("ticketInfo", ticketInfo);
String contextId = business.savePending(userId, consumeRequest.toString(),
productId, benefitId, data.deepCopy());
return json.createObjectNode().put("contextId", contextId)
.put("ticketName", data.path("ticketName").asText()).put("benefitId", benefitId)
.put("payAmountYuan", data.path("payAmount").decimalValue().movePointLeft(2));
}
adapter.productId 按平台识别商品:抖音券从 ticketData 里读取商品;美团券用套餐名称 ticketName 和售卖价 dealPrice,与这家门店已配置的商品标题和售卖价对照,命中唯一一个才继续。识别不到、命中多个或没配置映射,就停在确认页之前,提示管理员补配置,别按套餐名称猜测后发权益。ticketInfo 只作为不透明凭证原样保存、回传,不拆解它来做商品匹配。核销成功后,响应 data[] 里的 dealId 才是最终商品依据。数量 num 来自本次业务确认,一次最多 10。
返回对象中的 contextId、benefitId、payAmountYuan 是自己的小程序接口字段;聚核请求体只有代码中列出的真实参数。savePending 要原样保存 consumeRequest.toString(),核销时直接读取该字符串;同时保存预核销的 data,后面判断是否为抖音次卡时要用。确认页只给小程序必要的展示数据与自己的上下文 ID。券码、门店、数量和原始凭证留在服务端,后续从同一个上下文读取。预核销成功时,顾客还没有完成实际核销。
七、确认核销;按 errorCode 决定重试还是核对
顾客点击确认后,小程序提交上下文 ID。后端核对上下文归属,取出已保存的 shopId、platform、code、num、ticketInfo,调用聚核核销接口(文档称“验券”)。进入成功处理的依据是顶层 success 为布尔值 true,不能只看 HTTP 状态、code 或某个平台内部字段。
失败时按响应里的 errorCode 处理。聚核 API 文档的重试规则是:只有 CONSUME_IN_PROGRESS、RESULT_UNKNOWN、SERVICE_UNAVAILABLE、PROVIDER_UNAVAILABLE 可以自动重试,而且必须使用原请求原参数。 请求超时、连接中断这类没拿到响应的情况,也只用原请求重试。五个参数全部保持不变,包括 ticketInfo;不要为了重试再预核销,也不要换券码、门店或数量。
static final Set<String> RETRYABLE = Set.of(
"CONSUME_IN_PROGRESS", "RESULT_UNKNOWN", "SERVICE_UNAVAILABLE", "PROVIDER_UNAVAILABLE");
void consume(String contextId) throws InterruptedException {
PreparedRedemption context = business.loadOwnedPending(contextId);
if (business.hasSuccess(context.id())) return;
final String requestJson = context.requestJson(); // 循环前固定,逐字复用
// 抖音次卡结果未知时不自动重试,直接转入查券状态或对账
final int maxAttempts = context.douyinTimeCard() ? 1 : 3;
JsonNode last = NullNode.getInstance();
for (int attempt = 0; attempt < maxAttempts; attempt++) {
if (attempt > 0) Thread.sleep(1000L * attempt); // 本例的有限串行退避
ApiResponse reply;
try {
reply = postJson("ddzh-tuangou-receipt-consume", requestJson);
} catch (IOException e) { // 包含 HttpTimeoutException;不捕获本地履约异常
continue;
}
last = reply.body.deepCopy();
if (reply.isSuccess()) {
saveFirstSuccess(context, reply.body); // 在网络重试的 catch 之外
return;
}
String errorCode = reply.errorCode();
if ("ALREADY_CONSUMED".equals(errorCode)) {
business.markAlreadyConsumed(context.id(), last); // 按 wxdgOrderNo 核对原单,不补发权益
return;
}
if (!RETRYABLE.contains(errorCode)) {
business.stopAttempt(context.id(), last); // PLATFORM_REJECTED、参数、授权、次数不足等
return;
}
}
business.markPending(context.id(), last); // 仍未确定:查券状态或对账
}
上述重试次数、间隔与客户端超时是本例的配置值。InterruptedException 向上传播,调用方可终止等待;首次成功的保存和权益处理不在网络异常的 catch 内,本地业务异常不会触发这一循环再次核销。douyinTimeCard() 由自己根据预核销保存的 ticketData 判断:certificates[].time_card 有值就是抖音次卡。聚核文档写明,抖音次卡结果未知时禁止自动重试,应先查询平台券状态或完成对账。
分支用 errorCode,不用 code:结果未知、参数错误、门店未授权、次数不足等都使用 code=10001,不能写成“10001 就重试”;平台明确拒绝 PLATFORM_REJECTED 的 code 是 10000,或 10000 加平台业务码(如美团 1006 返回 11006)。所以 code=10000 也不代表成功,成功只看 success。平台拒绝、参数和授权类错误要停止自动重试,把原因展示给顾客或店员。
还有一个边界:接口幂等不等于每次重复请求都返回同一份成功数据。 已成功的请求再次提交时,接口返回 success=false、code=10500、errorCode=ALREADY_CONSUMED,wxdgOrderNo 是原核销单号,data 为空,consumeCredential 为空数组。如果首次响应丢失,后来只收到这个已核销提示,就停止自动重试,用 wxdgOrderNo 定位原单,并用美团“查询已验券信息”或抖音“券状态查询”核对;不能凭这个提示直接补发权益,也不能据此编造撤销凭证。
对顾客而言,超时意味着结果还没确定。页面可显示“正在确认核销结果”,不要立刻提示失败、引导他重新输码:券如果已经核销,重新输码会在预核销阶段被平台拒绝,反而更难解释。
八、先保存成功结果,再完成自己的业务
首次收到明确成功时,保存原 shopId、platform、聚核核销单号 wxdgOrderNo、核销明细 data[] 和顶层 consumeCredential 数组。data[] 每项含商品 dealId、套餐名称 dealTitle、券码 receiptCode 和平台订单号 orderId;wxdgOrderNo 是聚核的账单订单号,orderId 是平台订单 ID,两者不能混用。凭证与 data 明细按下标对应,后续撤销需要使用相应项的原凭证。
void saveFirstSuccess(PreparedRedemption context, JsonNode response) {
// 保存完整首次响应:wxdgOrderNo、data、consumeCredential,以及上下文中的原请求
Receipt receipt = business.saveFirstSuccess(context, response.deepCopy());
if (!business.dealIdsMatch(receipt.id(), context.productId())) {
business.markNeedsReview(receipt.id()); // data[].dealId 与预核销识别的商品不一致
return;
}
try {
business.grantOnce(receipt.id(), context.benefitId());
business.markFulfilled(receipt.id());
} catch (RuntimeException e) {
business.enqueueFulfillment(receipt.id()); // 只补处理自己的权益
}
}
saveFirstSuccess 要保存首次完整响应,并把 data[i] 与 consumeCredential[i] 对应起来,同时保留上下文中的原请求;后续调用不能覆盖掉这份首次记录。美团券的商品是预匹配出来的,核销返回的 dealId 与之不一致时转人工,不发权益。聚核保证的是接口幂等,同一请求不会重复核销;它不会代替你的预约、时长或会员系统完成发放,也不能替代你按券码和自己的业务订单做的去重。
如果核销已明确成功,写入权益时发生本地异常,就根据保存的成功记录补处理本地业务。不要重新核销已成功的券;页面可以分别表达“核销成功”和“权益正在处理”,让顾客知道当前进度。
九、需要撤销时,使用首次成功的原凭证
顾客选错套餐或取消使用时,先按自己的规则检查权益能否撤回。已使用的服务如何处理,由业务规则决定。撤销核销与消费者付款退款要分开处理,调用撤销接口不等于完成退款,钱怎么退,走平台售后流程。平台对撤销还有时限,本系列《团购券核销错了能撤销吗?美团10分钟、抖音1小时的撤销规则与开发要点》有详细说明。
聚核的统一撤销接口支持美团、抖音,传原核销的 shopId、platform 和 consumeCredential 字符串数组,一次 1 到 10 项。它适用于有有效凭证且符合平台规则的记录,不能承诺所有券、所有历史核销都能撤销。撤销不收费,但没有幂等:相同凭证重复请求会再次投递到平台。所以网络异常或结果未知时,先用美团“查询已验券信息”或抖音“券状态查询”核对券状态,再决定是否重新发起撤销。
void cancel(String receiptId) throws InterruptedException {
Receipt receipt = business.loadCancellableOwned(receiptId); // 校验归属及权益可撤回
List<String> credentials = business.selectedOriginalCredentials(receipt);
if (credentials.isEmpty() || credentials.size() > 10) {
throw new IllegalStateException("Select 1 to 10 original credentials");
}
ObjectNode request = json.createObjectNode().put("shopId", receipt.shopId())
.put("platform", receipt.platform());
ArrayNode values = request.putArray("consumeCredential");
credentials.forEach(values::add);
ApiResponse reply;
try {
reply = postJson("ddzh-tuangou-receipt-cancel", request.toString());
} catch (IOException e) { // 撤销没有幂等:先查券状态,不自动重发
for (String credential : credentials) business.markCancellationPending(receiptId, credential);
return;
}
String errorCode = reply.errorCode();
if ("CREDENTIAL_INVALID".equals(errorCode) || "CANCEL_UNSUPPORTED".equals(errorCode)) {
for (String credential : credentials) {
business.recordCancellationRejected(receiptId, credential, errorCode); // 整个请求被拒
}
return;
}
Map<String, JsonNode> items = new HashMap<>();
if (reply.body.path("data").isArray()) {
for (JsonNode item : reply.body.path("data")) {
items.put(item.path("consumeCredential").asText(), item);
}
}
for (String credential : credentials) {
JsonNode item = items.get(credential);
String status = item == null ? "unknown" : item.path("status").asText("unknown");
switch (status) {
case "succeeded":
business.saveCancellationSucceeded(receiptId, credential);
try {
business.revokeOnce(receiptId, credential);
} catch (RuntimeException e) {
business.enqueueRevocation(receiptId, credential);
}
break;
case "rejected":
business.recordCancellationRejected(receiptId, credential, item.path("message").asText());
break;
case "unknown":
default:
business.markCancellationPending(receiptId, credential);
}
}
}
selectedOriginalCredentials 只取已保存的首次成功凭证,按本次选定明细组成字符串数组;无法找到某项响应时,示例会将该项记为待核对。撤销响应要逐项看:succeeded 表示该项成功,rejected 表示拒绝,unknown 表示结果未知。只有全部成功时顶层 success 才是 true、code 为 10000,否则 code 为 10001;部分成功时,即使顶层为 false,也要处理已明确成功的项。凭证无效或记录不支持撤销时,整个请求返回 CREDENTIAL_INVALID 或 CANCEL_UNSUPPORTED。若撤销已成功但本地权益撤回失败,同样留下本地补处理记录。
十、联调按业务结果验收
接口能返回 JSON,还要确认页面、门店和权益串得上。下面是供你的团队执行的联调清单,本文未运行这些示例,也未进行真实券预核销、核销或撤销测试。
| 检查场景 | 预期处理 |
|---|---|
| 基础配置 | 核对服务端凭据、小程序后端 HTTPS 和微信请求合法域名配置 |
| 门店与授权 | 业务门店对应正确的聚核门店而不是商户,美团、抖音门店和授权状态分别核对 |
| 商品配置 | 平台、门店、商品映射正确;同名商品不会误发权益 |
| 预核销成功 | 商品已唯一识别,只展示确认页,原 ticketInfo 已保存,尚未发权益 |
| 核销明确成功 | wxdgOrderNo、明细及凭证保存完整,dealId 已核对,自己的权益只发放一次 |
平台拒绝 PLATFORM_REJECTED |
展示原因,停止自动重试 |
超时或可重试的 errorCode |
复用原五个参数,有间隔、有上限;未确定前不报成功或确定失败 |
| 抖音次卡结果未知 | 不自动重试,查券状态或对账 |
已核销 ALREADY_CONSUMED 但缺首次结果 |
停止自动重试,按 wxdgOrderNo 和券状态核对,不直接补发权益 |
| 本地履约异常 | 根据已保存的成功记录补处理自己的业务 |
| 撤销与部分成功 | 按原凭证逐项处理;未知项先查券状态,不重复发撤销 |
十一、微信小程序接入团购核销常见问题
微信小程序接入美团团购核销怎么做?
本文的服务零售接入流程是:把业务门店映射到无限聚核商户下的具体门店,完成美团门店授权并核对绑定关系;业务后端使用 platform=1 调用无限聚核的预核销接口“输码验券校验”,取得原始 ticketInfo,并用套餐名称和售卖价与已配置的商品预匹配。顾客确认后,再带上同一门店、平台、券码、数量和 ticketInfo 调用“验券”接口完成核销,保存首次成功结果、核对返回的 dealId 后处理自己的权益。
微信小程序接入抖音团购核销怎么做?
先完成无限聚核门店对应的抖音门店授权,并核对抖音商品与自己业务权益的映射。小程序通过自己的业务后端调用无限聚核接口,后端使用 platform=2,按“预核销、顾客确认、核销”的顺序处理,从预核销返回的 ticketData(抖音官方券信息)识别商品,原样保存和回传 ticketInfo。美团与抖音的授权状态分别核对,不能用美团授权代替抖音授权;抖音次卡核销结果未知时不自动重试,先查券状态。
微信小程序团购核销必须接哪些接口?
本文采用的无限聚核 V2 服务零售两阶段流程中,预核销“输码验券校验”与核销“验券”是核心接口。商户、门店和商家授权可以先在无限聚核控制台完成,也可以接创建商户或门店、获取授权链接接口;需要在自己的后台配置套餐权益时接获取团购信息,需要撤回核销时再接撤销核销接口,不是把所有接口都列为必接。
微信小程序接入团购核销,为什么要先预核销?
在无限聚核 V2 服务零售聚合接口中,美团和抖音的新核销请求都要先调用“输码验券校验”,取得同一 shopId、platform、code 对应的 ticketInfo,同时拿到套餐名称、售卖价等确认页需要的信息。预核销用于检查券当前能否使用、准备确认上下文,不代表核销成功,也不发放权益;顾客确认后才核销。核销重试复用原请求,不重新预核销。
团购核销接口超时后怎么重试?
按无限聚核 API 文档的重试规则,只有 errorCode 为 CONSUME_IN_PROGRESS、RESULT_UNKNOWN、SERVICE_UNAVAILABLE、PROVIDER_UNAVAILABLE,或请求超时没拿到响应时,才由业务后端有间隔、有上限地重发首次请求的 shopId、platform、code、num、ticketInfo,不换参数、不重新预核销,同一请求不会被重复核销。PLATFORM_REJECTED 要停止重试;收到 ALREADY_CONSUMED(10500)但缺少首次成功记录时转入核对,不直接补发权益;抖音次卡结果未知时不自动重试,先查券状态或对账。
本文的接入示例调用了无限聚核的哪些接口?
都在 /api/hexiao/v2/ 下:创建商户或门店 store/create、获取美团/抖音授权链接 get/auth/url、获取团购信息 ddzh-tuangou-deal-queryshopdeal、输码验券校验 ddzh-tuangou-receipt-prepare、验券 ddzh-tuangou-receipt-consume 和撤销核销 ddzh-tuangou-receipt-cancel。它们都是无限聚核提供的 V2 服务零售聚合接口,同一套路径用 platform 区分美团(1)和抖音(2)。核销或撤销结果仍不确定时,还可以用无限聚核提供的美团“查询已验券信息”、抖音“券状态查询”原生接口核对券状态。
开始开发时,对照无限聚核 API 文档,按门店映射、授权、预核销、核销、撤销的顺序联调,再把结果接回自己的预约或权益系统。



