GooglePay: API 文档

GooglePay API 文档

本文档详细介绍了 GooglePay 库的 API 接口、参数说明以及在不同场景下的使用方法。

1. 初始化 (Initialization)

ApplicationonCreate 方法中初始化 GooglePayClient

kotlin 复制代码
class App : Application(), GooglePayService {

    override fun onCreate() {
        super.onCreate()
        // 初始化 GooglePayClient
        GooglePayClient.getInstance()
            .initBillingClient(this, this) // 传入 Application Context 和 GooglePayService 实现
            .setDebug(true) // 开启调试模式,输出日志
            .setSubscription(false) // 是否支持订阅,默认为 false
            .setSubscriptionMode(SubscriptionMode.MultiModal) // 设置订阅模式
            .setInterval(15) // 设置自动刷新间隔(秒),默认 15秒
            .registerActivitys(listOf(MainActivity::class.java)) // 注册需要触发自动刷新的 Activity
    }

    // 实现 GooglePayService 接口的方法...
}

2. 核心类与接口

2.1 GooglePayClient

GooglePayClient 是库的核心入口,单例模式。

  • getInstance(): 获取单例实例。
  • initBillingClient(context: Application, service: GooglePayService): 初始化客户端。
  • setDebug(isDebug: Boolean): 设置是否开启调试日志。
  • setSubscription(isSubscription: Boolean): 设置是否支持订阅功能。
  • setSubscriptionMode(mode: SubscriptionMode): 设置订阅模式。
  • setInterval(interval: Int) : 设置在指定 Activity onResume 时触发刷新购买状态的最小时间间隔(单位:秒),默认 15 秒。
  • registerActivitys(activitys: List<Class>) : 注册需要触发自动刷新的 Activity 类。当这些 Activity onResume 且距离上次刷新超过 interval 时,会自动调用 queryPurchases()
  • getPayService() : 获取具体的支付服务 (OneTimeServiceSubscriptionService)。
  • queryPurchases(): 查询并刷新当前的购买状态(包括一次性商品和订阅)。
  • isGoogleAvailable(context: Context?): 检查 Google Play 服务是否可用。
  • endConnection(): 断开 BillingClient 连接。

2.2 GooglePayService

业务端需要实现的接口,用于提供商品 ID 和处理购买结果。

  • getOneTimeConsumableProducts(): 返回一次性消耗型商品 ID 列表。
  • getOneTimeNonConsumableProducts(): 返回一次性非消耗型商品 ID 列表。
  • getSubscribeProducts(): 返回订阅商品 ID 列表。
  • handlePurchasesProcess(isPay: Boolean, productType: BillingProductType, purchases: Purchase): 处理购买交易,验证订单并确认。

3. 支付服务 (Payment Services)

通过 GooglePayClient.getInstance().getPayService<T>() 获取。

3.1 OneTimeService (一次性商品服务)

用于处理消耗型和非消耗型商品。

  • launchBillingFlow(activity: Activity, billingParams: BillingParams): 启动支付流程。
  • queryProductDetails(productIds: List): 查询商品详情。

3.2 SubscriptionService (订阅服务)

用于处理订阅商品。

  • launchBillingFlow(activity: Activity, billingSubsParams: BillingSubsParams): 启动订阅支付流程。
  • querySubsOfferDetails(subsOfferParams: SubsOfferParams): 查询订阅商品详情(包括 Offer)。
  • queryAckSubscribePurchases(productIds: List?): 查询当前有效的订阅。

4. 参数说明 (Parameters)

4.1 BillingParams (一次性购买参数)

用于 OneTimeService.launchBillingFlow

字段 类型 说明
accountId String 业务方标识用户的唯一 ID (obfuscatedAccountId)
productId String Google Play 后台配置的商品 ID
chargeNo String 业务方生成的订单号 (obfuscatedProfileId)

构建示例:

kotlin 复制代码
val params = BillingParams.Builder()
    .setAccountId("user_123")
    .setProductId("coin_100")
    .setChargeNo("order_abc_456")
    .build()

4.2 BillingSubsParams (订阅购买参数)

用于 SubscriptionService.launchBillingFlow

字段 类型 说明
accountId String 业务方标识用户的唯一 ID
productId String Google Play 后台配置的订阅商品 ID
chargeNo String 业务方生成的订单号
offerToken String 订阅商品的 Offer Token (从 AppSubscribeDetails 获取)

4.3 AppBillingResponseCode (响应码)

AppBillingResponseCode 定义了 Google Play Billing API 返回的所有可能的响应码。

代码 常量 说明
0 OK 请求成功
-200 FAIL 业务错误
-3 SERVICE_TIMEOUT 请求超时(已废弃,建议使用 SERVICE_UNAVAILABLE
-2 FEATURE_NOT_SUPPORTED 当前设备或 Google Play 不支持该功能(如订阅、商品详情等)
-1 SERVICE_DISCONNECTED 与 Google Play Billing 服务断开连接,可尝试重新连接
1 USER_CANCELED 用户在结算流程中主动取消
2 SERVICE_UNAVAILABLE 网络问题或 Google Play 服务不可用(如正在更新、离线等)
3 BILLING_UNAVAILABLE 当前设备上不支持 Google Play 结算
4 ITEM_UNAVAILABLE 商品在当前区域或账户不可用(例如未发布或已下架)
5 DEVELOPER_ERROR 开发者调用错误(如参数错误、API 调用顺序错误)
6 ERROR 一般错误(系统内部异常、未知问题等)
7 ITEM_ALREADY_OWNED 商品已拥有(如未消耗的消耗型商品或已购买的非消耗型商品)
8 ITEM_NOT_OWNED 操作失败,因为商品未拥有(尝试消耗或确认未拥有的商品)
12 NETWORK_ERROR 网络错误(新引入,用于明确网络失败场景)

使用示例:

kotlin 复制代码
when (responseCode) {
    AppBillingResponseCode.OK -> {
        // 处理成功
    }
    AppBillingResponseCode.USER_CANCELED -> {
        // 用户取消支付
    }
    AppBillingResponseCode.ITEM_ALREADY_OWNED -> {
        // 商品已拥有
    }
    AppBillingResponseCode.NETWORK_ERROR -> {
        // 网络错误,可以重试
    }
    else -> {
        // 处理其他错误
    }
}

4.4 AppProductDetails (商品详情模型)

AppProductDetails 表示一次性购买商品(消耗型或非消耗型)的详细信息。

字段 类型 说明
productId String 商品 ID(例如 com.xx.product.1
productName String 商品名称
formattedPrice String 格式化后的价格字符串(例如 "€7.99"
priceAmountMicros Long 以微单位表示的价格(例如价格为 "€7.99" 时,该值为 7990000
priceCurrencyCode String 货币代码(例如 "EUR"

查询商品详情示例:

kotlin 复制代码
val oneTimeService = GooglePayClient.getInstance().getPayService<OneTimeService>()

lifecycleScope.launch {
    oneTimeService.queryProductDetails(listOf("coin_100", "coin_500")).collect { result ->
        result.onSuccess { productList ->
            productList.forEach { product ->
                Log.d("Product", "ID: ${product.productId}")
                Log.d("Product", "名称: ${product.productName}")
                Log.d("Product", "价格: ${product.formattedPrice}")
                Log.d("Product", "货币: ${product.priceCurrencyCode}")
            }
        }
        result.onFailure { error ->
            Log.e("Product", "查询失败: ${error.message}")
        }
    }
}

4.5 AppSubscribeDetails (订阅详情模型)

AppSubscribeDetails 表示订阅商品的详细信息,包括定价阶梯。

字段 类型 说明
productId String 订阅商品 ID(例如 com.xx.subscription.monthly
productName String 订阅商品名称
pricingPhases List<PricingPhase> 定价阶梯列表(支持试用期、介绍价格等)

PricingPhase 字段:

字段 类型 说明
formattedPrice String 格式化后的价格字符串(例如 "€7.99"
priceAmountMicros Long 以微单位表示的价格(例如价格为 "€7.99" 时,该值为 7990000
priceCurrencyCode String 货币代码(例如 "EUR"

查询订阅详情示例:

kotlin 复制代码
val subscriptionService = GooglePayClient.getInstance().getPayService<SubscriptionService>()

lifecycleScope.launch {
    val params = SubsOfferParams.Builder()
        .setProductIds(listOf("monthly_vip", "yearly_vip"))
        .build()
    
    subscriptionService.querySubsOfferDetails(params).collect { result ->
        result.onSuccess { subscriptionList ->
            subscriptionList.forEach { subscription ->
                Log.d("Subscription", "ID: ${subscription.productId}")
                Log.d("Subscription", "名称: ${subscription.productName}")
                subscription.pricingPhases.forEach { phase ->
                    Log.d("Subscription", "阶梯价格: ${phase.formattedPrice}")
                }
            }
        }
    }
}

5. 支付事件监听 (Payment Event Listening)

GooglePayClient 使用 Kotlin Coroutines 的 SharedFlow 发送支付事件。

5.1 BillingPayEvent

支付事件密封类:

  • PaySuccessful(purchase: Purchase): 支付成功。
  • PayFailed(code: Int, message: String): 支付失败。
  • PayConsumeSuccessful(purchase: Purchase): 支付并消耗成功。
  • PayConsumeFailed(purchase: Purchase, code: Int, message: String): 支付成功但消耗失败。

5.2 在 Activity 中使用

建议在 onCreateonStart 中开始收集事件,使用 lifecycleScope 确保在生命周期结束时自动取消。

kotlin 复制代码
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    
    lifecycleScope.launch {
        // 使用 repeatOnLifecycle 确保只在活跃状态下收集
        repeatOnLifecycle(Lifecycle.State.STARTED) {
            GooglePayClient.getInstance().appBillingPayEventFlow.collect { event ->
                when (event) {
                    is BillingPayEvent.PaySuccessful -> {
                        // 处理支付成功
                        Log.d("Pay", "Success: ${event.purchase}")
                    }
                    is BillingPayEvent.PayFailed -> {
                        // 处理支付失败
                        Log.e("Pay", "Failed: ${event.code} - ${event.message}")
                    }
                    else -> {
                        // 其他状态
                    }
                }
            }
        }
    }
}

5.3 在 Dialog 中使用 (手动释放)

如果在 Dialog 中监听支付结果,需要注意协程作用域的管理。

  1. 使用 Dialog 所在的 Activity/Fragment 的 lifecycleScope: 这是最推荐的方式,与 Activity 生命周期绑定,无需手动释放。
  2. 使用自定义 Scope : 如果必须在 Dialog 内部管理,需要在 dismiss 时取消 Job。
kotlin 复制代码
class PayDialog(context: Context) : Dialog(context) {
    private val dialogScope = CoroutineScope(Dispatchers.Main + SupervisorJob())

    override fun show() {
        super.show()
        dialogScope.launch {
            GooglePayClient.getInstance().appBillingPayEventFlow.collect { event ->
                // 处理事件
                if (event is BillingPayEvent.PaySuccessful) {
                    dismiss()
                }
            }
        }
    }

    override fun dismiss() {
        super.dismiss()
        // 必须手动取消,防止内存泄漏
        dialogScope.cancel()
    }
}

6. 其他注意事项

  1. 生命周期 : GooglePayClient 内部处理了 Activity 的生命周期感知,但事件监听需要调用者自行管理 Scope。
  2. 消耗 : 对于一次性消耗型商品,库会自动进行消耗操作 (consumeAsync)。
  3. 确认 : 所有购买(包括订阅)都需要确认 (acknowledgePurchase),这部分逻辑在 GooglePayService.handlePurchasesProcess 中由业务层触发或库内部处理(具体取决于 handlePurchases 的实现,库默认会自动处理消耗,但确认逻辑通常需要业务端配合验证后调用)。

相关文档

相关推荐
云水木石1 小时前
Android 的下一个战场:Windows 应用与游戏?
android·windows·游戏
雨声不在1 小时前
Android文字渐变的实现
android·textview
GoldenPlayer2 小时前
KTS语法
android
GPTMirrors镜像系统2 小时前
谷歌Gemini"Something went wrong"错误解决方法:2步快速解除限制(2025最新教程)
google·gemini
GoldenPlayer2 小时前
后台服务Service销毁逻辑+单例造成的内存泄露
android
GoldenPlayer2 小时前
自定义APK&gradle全局配置文件
android
うちは止水2 小时前
Android Hal层开发流程
android·hal
李小轰_Rex2 小时前
把手机变成听诊器!摄像头 30 秒隔空测心率 - 开箱即用
android·音视频开发
为码消得人憔悴3 小时前
Android perfetto - 记录分析memory
android·性能优化
尤老师FPGA4 小时前
使用ZYNQ芯片和LVGL框架实现用户高刷新UI设计系列教程(第四十二讲)
android·java·ui