在 Webview 中处理 Payment Gateway 会被应用商店拒绝吗?
明确结论
不一定会被拒绝。应用商店审核关注的不是“有没有使用 WebView”,而是用户购买的内容是什么,支付流程是否绕过了商店规定的支付系统。
一般可以按以下情况判断:
- 购买实体商品或线下服务,例如外卖、酒店、机票、打车、快递和电商商品,通常可以在 WebView 中使用第三方支付。
- 购买供应用内使用的数字内容、会员订阅、虚拟币或功能解锁,通常必须使用 Apple In-App Purchase 或 Google Play Billing。即使把支付页面放进 WebView,也无法规避这一要求,拒审风险仍然较高。
- 用户已经在其他平台购买内容,应用只允许登录后使用,部分类型的应用可以采用“仅消费”模式。不过,能否展示购买入口、价格或外部链接,仍要根据应用类别、上架地区和当时的商店政策判断。
- 如果应用参加了特定地区的外部支付或替代计费计划,可以按照对应计划接入,但需要满足资格、信息披露、跳转方式和交易报告等要求。
因此,“不接入移动端支付 SDK,所有款项统一通过 WebView 收取”并不是可靠的过审方案。
为什么 WebView 仍然可能违规
审核人员判断的是交易本身,不是支付页面使用原生 UI、WebView,还是外部浏览器。
例如,用户在 WebView 中付款后获得以下权益,通常仍会被视为应用内数字购买:
- 解锁高级功能;
- 开通会员或自动续费订阅;
- 购买课程、视频、电子书等数字内容;
- 购买游戏道具、金币或积分;
- 扩充云端存储空间;
- 去除广告;
- 获得只能在应用内使用的服务额度。
即使款项通过 Stripe、PayPal、支付宝或自建收银台支付,也不会改变商品属于数字商品这一事实。审核方可能把这种设计认定为绕过平台计费,导致应用被拒或被要求修改。情况严重时,后续版本的审核也可能受到影响。
如果 WebView 用来支付实体商品或现实世界中交付的服务,通常可以使用第三方支付,例如购买衣服、预约家政、支付餐费或预订酒店。
推荐的处理方式
1. 先对商品进行分类
分类时不要只看支付渠道,还要确认用户购买的权益最终在哪里交付。
| 购买内容 | 推荐支付方式 |
|---|---|
| 应用内会员、数字内容、虚拟道具、功能解锁 | Apple In-App Purchase / Google Play Billing |
| 实体商品、外卖、交通、酒店、线下服务 | 第三方支付,可使用 WebView |
| 已在网站购买、应用内仅登录使用 | 可考虑仅消费模式 |
| 符合特定地区政策的外部支付 | 按对应商店计划和地区规则实施 |
如果同一个应用既销售实体商品,也销售数字权益,需要拆分结算流程,不能把所有商品都送入 WebView 收银台。
2. 在客户端建立支付路由
下面的示例说明了基本的分类方式。商品类型应由可信的服务端数据决定,不能只依赖客户端传入的字符串。
type ProductKind =
| "digital_content"
| "subscription"
| "virtual_currency"
| "physical_goods"
| "offline_service";
function selectPaymentChannel(kind: ProductKind) {
switch (kind) {
case "digital_content":
case "subscription":
case "virtual_currency":
return "store_billing";
case "physical_goods":
case "offline_service":
return "web_checkout";
default:
throw new Error("Unsupported product kind");
}
}
数字商品应进入平台支付流程。只有实体商品或线下服务才进入 WebView 收银台。
3. iOS 数字商品使用 StoreKit
以下代码只说明原生购买流程的基本结构。实际项目还要处理交易验证、恢复购买、退款和订阅状态同步。
import StoreKit
func purchase(product: Product) async throws {
let result = try await product.purchase()
switch result {
case .success(let verification):
let transaction = try verification.payloadValue
// 将交易信息发送到服务端验证后再发放权益
await transaction.finish()
case .pending:
// 等待家长批准或其他延迟确认
break
case .userCancelled:
break
@unknown default:
break
}
}
不要只凭客户端返回的成功状态发放数字权益。更稳妥的方式是让服务端验证交易,再根据有效的订阅状态控制用户权限。
4. Android 数字商品使用 Google Play Billing
Android 应通过 BillingClient 查询商品并发起购买,不应加载网页收银台。
val billingClient = BillingClient.newBuilder(context)
.setListener(purchasesUpdatedListener)
.enablePendingPurchases()
.build()
billingClient.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(
billingResult: BillingResult
) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
// 查询 ProductDetails,并通过 launchBillingFlow 发起购买
}
}
override fun onBillingServiceDisconnected() {
// 安排重连
}
})
购买完成后,还需要验证 purchaseToken,并根据商品类型执行确认或消费操作。不要只在本地保存“已购买”标志。
5. WebView 只承载允许的交易
如果用户购买的是实体商品或线下服务,可以在 WebView 中加载 HTTPS 收银台:
import WebKit
final class CheckoutViewController: UIViewController {
private let webView = WKWebView()
override func viewDidLoad() {
super.viewDidLoad()
webView.frame = view.bounds
webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(webView)
guard let url = URL(
string: "https://checkout.example.com/orders/ORDER_ID"
) else {
return
}
webView.load(URLRequest(url: url))
}
}
服务端必须校验订单金额、商品类型和支付状态。不能因为客户端传入了 physical_goods,就把数字会员伪装成实体商品。
上架前的检查清单
提交审核前,至少要检查以下事项:
- WebView 中是否出现数字会员、充值或功能解锁等购买入口;
- 应用内的按钮、文案或客服提示是否引导用户绕过商店支付;
- 服务端是否可能向 iOS 或 Android 客户端下发不符合政策的网页购买入口;
- 商品是否同时包含实体权益和数字权益;
- 已购买用户登录后,应用是否只提供内容消费;
- 外部支付是否只在允许的国家或地区展示;
- 应用是否参加了对应商店的替代计费或外部链接计划;
- 审核账号能否完整体验登录、恢复购买和订阅管理流程;
- 隐私政策、退款规则和订阅说明是否与实际流程一致。
容易误判的情况
网页支付完成后再回到应用
是否跳出应用并不是判断依据。即使用户通过 Safari 或系统浏览器完成交易,只要购买的是应用内数字权益,仍可能受到商店计费规则限制。
WebView 中显示一个“联系客服购买”按钮
通过客服、二维码、兑换码或聊天消息引导用户购买数字权益,也可能被认定为规避平台支付。改变购买入口的形式,通常无法解决商品性质带来的问题。
应用只是现有网站的客户端
这类应用可能适合采用“仅消费”模式,让用户在其他地方完成注册或购买,再到应用内登录并使用已有权益。不过,应用内能否说明购买方法、展示价格或提供外部链接,需要根据应用类别、商店地区和当时生效的政策分别确认。
最稳妥的方案
如果销售的是应用内数字内容或功能,默认使用 Apple In-App Purchase 和 Google Play Billing。如果销售的是实体商品或线下服务,可以继续通过 WebView 使用第三方支付。
对于覆盖多个国家和地区的应用,提交审核前应重新核对 Apple App Review Guidelines 和 Google Play Payments policy。外部支付规则会随地区、应用类型和计划资格而变化,不能因为其他应用已经上线,就认定自己的实现也一定能够通过审核。
备注:内容仅供参考。
