PAYATHON 2026

支付宝小游戏支付成功后如何通知指定SPI接口

支付阿杰

结论

spi.alipay.user.gamecenter.payment.notify 是支付宝小游戏游戏币充值场景的服务提供接口(SPI)。支付成功后,支付宝游戏中心的支付系统会根据充值订单状态,主动调用开发者配置的 SPI 地址。小游戏前端不需要手动调用该接口,也不能将支付结果“转发”给它。

只有通过对应游戏币充值能力创建并完成支付的订单,才会进入这条通知链路。普通支付接口产生的异步通知不会自动转为该 SPI 通知。

通知流程

通常的处理流程如下:

  1. 小游戏发起游戏币充值。
  2. 支付宝生成并处理充值订单。
  3. 用户完成支付。
  4. 支付系统确认订单支付成功。
  5. 游戏中心更新充值订单状态。
  6. 支付宝开放平台根据应用配置,找到 spi.alipay.user.gamecenter.payment.notify 对应的服务地址。
  7. 支付宝服务器携带订单信息和签名,请求开发者服务器。
  8. 开发者服务器验签、校验订单,并执行游戏币到账或状态更新。
  9. 开发者按照 SPI 协议返回处理结果。
  10. 如果请求失败、超时或响应不符合协议,支付宝可能根据该能力的重试规则再次通知。

第 6~9 步都是服务端之间的调用,不受小游戏前端页面关闭或网络中断影响。

接入步骤

1. 确认使用的是游戏币充值能力

先确认订单确实由支付宝小游戏的游戏币充值能力创建。如果使用的是普通交易、当面付或其他支付产品,应处理对应产品的异步通知,而不是等待:

spi.alipay.user.gamecenter.payment.notify

具体开通条件和订单类型,以当前支付宝开放平台控制台及对应接口文档为准。

2. 配置并发布 SPI

在应用对应的支付宝小游戏或开放平台配置中,找到游戏币充值成功状态通知服务,填写支付宝可以通过公网访问的 HTTPS 地址。

只实现接口代码还不够。如果没有在平台完成配置、发布并使其生效,支付宝就无法把 SPI 请求路由到开发者服务器。

配置时需要确认:

  • SPI 是否属于当前小游戏应用;
  • 应用环境是否一致,例如沙箱与正式环境;
  • 服务地址是否可以从公网访问;
  • HTTPS 证书是否有效;
  • 应用公钥、支付宝公钥或证书配置是否匹配;
  • SPI 配置是否已经提交并生效。

3. 服务端接收请求并验签

下面是一个基于支付宝网关常见表单请求形式的 Java 示例。实际请求格式、字符集和响应结构,必须以该 SPI 的当前文档为准。

@PostMapping("/alipay/gamecenter/payment/notify")
public String paymentNotify(HttpServletRequest request) throws Exception {
    Map<String, String> params = new HashMap<>();

    request.getParameterMap().forEach((name, values) -> {
        if (values != null && values.length > 0) {
            params.put(name, values[0]);
        }
    });

    boolean verified = AlipaySignature.rsaCheckV1(
        params,
        alipayPublicKey,
        "UTF-8",
        "RSA2"
    );

    if (!verified) {
        throw new SecurityException("Alipay signature verification failed");
    }

    String method = params.get("method");
    if (!"spi.alipay.user.gamecenter.payment.notify".equals(method)) {
        throw new IllegalArgumentException("Unexpected SPI method: " + method);
    }

    String bizContent = params.get("biz_content");

    // 按当前 SPI 文档定义的字段反序列化 biz_content。
    // 不要只依据客户端支付结果发放游戏币。
    processPaymentNotification(bizContent);

    // 必须替换为当前 SPI 文档要求的成功响应结构。
    return buildSpiSuccessResponse();
}

如果接口使用 JSON 请求体,应读取原始请求体,并严格按照该 SPI 的签名规则验签,不能直接套用表单参数的验签代码。

4. 校验业务订单

验签成功只能说明请求来自持有对应私钥的一方,并不表示业务数据可以直接入账。服务端至少需要核对:

  • 支付宝订单号和商户订单号;
  • 订单是否属于当前应用;
  • 订单对应的用户和游戏角色;
  • 商品或游戏币档位;
  • 金额、币种及订单状态;
  • 订单是否已经处理;
  • 通知中的状态是否满足发放条件。

不要凭经验猜测业务字段名称,应以 spi.alipay.user.gamecenter.payment.notify 当前版本的参数定义为准。

5. 做好幂等处理

支付通知可能重复到达,因此游戏币发放必须通过唯一订单号进行幂等控制,不能把“接口被调用一次”当作判断依据。

BEGIN;

SELECT status
FROM game_recharge_order
WHERE merchant_order_no = ?
FOR UPDATE;

-- 仅当订单尚未到账时执行:
-- 1. 增加游戏币
-- 2. 将充值订单更新为到账状态
-- 3. 记录支付宝订单号和通知处理时间

COMMIT;

还可以在充值记录表上建立唯一约束:

CREATE UNIQUE INDEX uk_recharge_alipay_order
ON game_recharge_record(alipay_order_no);

这样即使支付宝重复通知,或者应用因超时而重复处理,也不会再次增加游戏币。

为什么支付成功后没有收到 SPI

常见原因有:

  1. 实际使用的不是游戏币充值产品,因此不会触发该 SPI。
  2. SPI 地址尚未配置、未发布,或配置在另一个应用下。
  3. 沙箱订单对应了正式环境地址,或正式订单使用了沙箱配置。
  4. 服务地址无法从公网访问,存在 DNS、防火墙、证书或网关限制。
  5. 接口响应超时,或返回格式不符合 SPI 协议。
  6. 验签使用了错误的支付宝公钥、证书或 sign_type。
  7. 网关提前消费了请求体,导致业务代码无法取得完整参数。
  8. 代码只处理了普通支付异步通知,没有实现 SPI 方法分发。
  9. 支付结果仍在处理中,尚未达到游戏币充值成功状态。
  10. 订单已经成功,但业务处理异常,且没有保存原始通知日志。

排查时,可以使用支付宝订单号或商户订单号查询订单状态,再结合开放平台调用记录、服务器访问日志和验签日志,判断请求停在哪一层。

注意事项

不要根据小游戏前端的支付成功回调直接发放游戏币。客户端回调可能受断网、页面关闭或请求伪造影响,不能作为可靠的到账依据。最终是否到账,应由服务端通知和订单状态共同确认。

收到通知后,应先保存必要的订单标识和处理结果,再返回成功响应。耗时操作可以交给内部队列处理,但必须确保消息已经可靠落库,否则可能出现支付宝认为通知成功、业务系统却没有完成到账的情况。

SPI 的请求参数、签名方式、成功响应结构和重试规则可能因接入模式而异。接入时应以应用控制台中该 SPI 的最新协议为准,不能把普通支付接口返回 "success" 的处理方式直接套用到 spi.alipay.user.gamecenter.payment.notify。

备注:内容仅供参考。