PAYATHON 2026

Google Developer subscription 订单为何从 Payment Pending 变为 Payme

支付小周

结论

Payment Pending 变为 Payment declined,说明 Google Play 在免费试用结束后尝试收取首期订阅费用,但付款未成功,因此取消了订单。

这通常不代表用户主动取消了订阅。日志已经明确说明取消原因:

Reason: Payment declined.

付款失败也可能与用户操作有关,例如删除付款方式、停用银行卡或拒绝交易。但仅凭订单状态无法确定具体原因,开发者通常也无法取得银行提供的详细拒付信息。

为什么会先显示 Payment Pending

7 天免费试用结束后,Google Play 会创建续费订单,并尝试从用户的付款方式扣款。扣款结果尚未确认时,订单可能显示为 Payment Pending。

常见流程如下:

免费试用结束
    ↓
创建首期付费订单
    ↓
Payment Pending
    ↓
扣款成功:订阅进入有效状态
或
扣款失败:Payment declined → 订单取消

常见的付款失败原因包括:

  • 银行卡余额或信用额度不足;
  • 银行拒绝该笔交易;
  • 银行卡过期、被冻结或已经失效;
  • 用户需要重新验证付款资料;
  • Google Payments 风控系统拦截了交易;
  • 用户删除或更换了付款方式;
  • 某些付款方式需要用户额外确认,但用户没有及时完成。

示例中的订单在约两天后被取消,说明 Google Play 等待或尝试处理付款后,仍然未能完成扣款。不过,两天并不是固定期限。实际处理时间可能受付款方式、国家或地区,以及 Google Play 订阅恢复策略的影响。

与用户主动取消的区别

这两种情况的含义不同:

  • 用户主动取消:用户关闭自动续订。一般仍可继续使用订阅权益,直到已支付的订阅周期结束。
  • 付款被拒绝:Google Play 尝试收费,但付款机构或支付系统没有批准交易。订单可能进入宽限期、账号保留状态,也可能直接失效,具体取决于订阅配置和 Google Play 当时适用的规则。

当前日志记录的是付款被拒绝,不是普通的用户主动取消:

Payment declined
Process for cancelling the order was initiated.
Reason: Payment declined.

Payment declined
The order was cancelled.

应如何处理

1. 不要根据控制台页面直接授予权益

服务端应以 Google Play 返回的购买状态和订阅有效期为准。只有确认付款已经完成且订阅有效,才能授予或继续保留付费权益。

仍处于待处理状态的购买不能按已付款订单处理。

2. 在客户端检查购买状态

通过 Google Play Billing Library 查询购买记录时,需要区分 PURCHASED 和 PENDING:

billingClient.queryPurchasesAsync(
    QueryPurchasesParams.newBuilder()
        .setProductType(BillingClient.ProductType.SUBS)
        .build()
) { billingResult, purchases ->

    if (billingResult.responseCode != BillingClient.BillingResponseCode.OK) {
        return@queryPurchasesAsync
    }

    for (purchase in purchases) {
        when (purchase.purchaseState) {
            Purchase.PurchaseState.PURCHASED -> {
                // 将 purchaseToken 发送到服务端验证。
                verifyPurchaseOnServer(purchase.purchaseToken)
            }

            Purchase.PurchaseState.PENDING -> {
                // 付款尚未完成,不授予正式订阅权益。
                showPaymentPendingMessage()
            }

            else -> {
                // 未购买或购买已失效。
                revokeSubscriptionAccess()
            }
        }
    }
}

PENDING 订单之后可能付款成功,也可能失败,因此不能只在首次购买时检查一次。

3. 在服务端验证订阅

客户端状态不能作为唯一依据。服务端应使用 purchaseToken 调用 Google Play Developer API,核对订阅状态、有效期和付款情况。

伪代码示例:

if subscription.paymentConfirmed
   and subscription.expiryTime > currentTime
   and subscription.notRevoked:
    grantAccess()
else:
    denyOrLimitAccess()

不要因为本地保存了 isPremium = true 就永久开放权益,也不要仅凭客户端回调认定付款成功。

4. 监听订阅状态变化

如果应用有服务端,建议接入 Real-time Developer Notifications。收到通知后,再调用 Google Play Developer API 查询最新状态。

至少需要处理以下状态:

  • 购买成功;
  • 续订成功;
  • 付款待处理;
  • 订阅取消;
  • 订阅过期;
  • 订阅撤销;
  • 付款问题恢复;
  • 宽限期或账号保留状态变化。

通知只表示状态可能已经变化,最终的业务判断仍应以 API 查询结果为准。

5. 给用户提供清楚的提示

付款失败时,可以提示用户前往 Google Play 更新付款方式,例如:

Google Play 未能完成订阅付款。请检查余额、银行卡状态或更新付款方式。付款确认前,订阅权益可能暂时不可用。

不要向用户显示“你取消了订阅”,因为当前记录不能证明这是用户主动取消的。

注意事项

  • 开发者无法自行重新扣款,也不应直接收集用户的银行卡信息。付款问题应由用户在 Google Play 中处理。
  • 不要依赖固定的“两天后取消”逻辑。付款重试、宽限期和账号保留行为可能随订阅配置及 Google Play 政策变化。
  • Payment Pending 既不代表付款成功,也不代表付款失败,只表示付款尚无最终结果。
  • 如果大量订单都出现相同问题,应检查目标市场支持的付款方式、订阅配置和测试账号环境。不过,最终的拒付原因通常只有用户、Google Payments 或发卡机构能够确认。
  • 测试购买与真实购买的生命周期可能不同,不能根据测试订单的时间规律推断生产环境。
  • 排查旧订单时,应以订单发生时适用的 Google Play 规则为准。现代 Billing Library 和订阅状态名称不一定与 2017 年控制台完全一致。

备注:内容仅供参考。