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 年控制台完全一致。
备注:内容仅供参考。
