TWA集成Google Play Billing调用request.show()返回RESULT_CANCELED错误求解
问题
我参照谷歌官方教程在TWA中实现Google Play Billing支付功能,调用const paymentResponse = await request.show();时出现如下报错:DOMException: Payment app returned RESULT_CANCELED code. This is how payment apps can close their activity programmatically.
相关代码
TWA应用JS侧执行代码
const service = await window.getDigitalGoodsService('https://play.google.com/billing'); const skuDetails = await service.getDetails(['gem']); let paymentMethods = [{ supportedMethods: "https://play.google.com/billing", data: { sku: skuDetails[0], } }]; let paymentDetails = { total: { label: `Total`, amount: {currency: `USD`, value: `10`} } }; const request = new PaymentRequest(paymentMethods, paymentDetails); const paymentResponse = await request.show();
未使用Bubblewrap,直接使用Android Studio开发以完全控制应用配置。
Android Manifest配置
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mwar.maliciouswar"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MaliciousWar"> <meta-data android:name="asset_statements" android:resource="@string/asset_statements" /> <activity android:name="com.google.androidbrowserhelper.trusted.LauncherActivity"> <!-- Edit android:value to change the url opened by the Trusted Web Activity --> <meta-data android:name="android.support.customtabs.trusted.DEFAULT_URL" android:value="https://mal-war.com?utm_source=twa" /> <meta-data android:name="android.support.customtabs.trusted.STATUS_BAR_COLOR" android:resource="@color/brown"/> <meta-data android:name="android.support.customtabs.trusted.STATUS_BAR_COLOR_DARK" android:resource="@color/brown" /> <meta-data android:name="android.support.customtabs.trusted.NAVIGATION_BAR_COLOR" android:resource="@color/brown" /> <meta-data android:name="android.support.customtabs.trusted.NAVIGATION_BAR_COLOR_DARK" android:resource="@color/brown" /> <meta-data android:name="android.support.customtabs.trusted.DISPLAY_MODE" android:value="immersive"/> <meta-data android:name="android.support.customtabs.trusted.SCREEN_ORIENTATION" android:value="landscape"/> <!-- <meta-data android:name="android.support.customtabs.trusted.SPLASH_IMAGE_DRAWABLE"--> <!-- android:resource="@drawable/splash"/>--> <!-- <meta-data android:name="android.support.customtabs.trusted.SPLASH_SCREEN_BACKGROUND_COLOR"--> <!-- android:resource="@color/backgroundColor"/>--> <!-- <meta-data android:name="android.support.customtabs.trusted.SPLASH_SCREEN_FADE_OUT_DURATION"--> <!-- android:value="300"/>--> <!-- <meta-data android:name="android.support.customtabs.trusted.FILE_PROVIDER_AUTHORITY"--> <!-- android:value="@string/provider_authority"/>--> <!-- This intent-filter adds the Trusted Web Activity to the Android Launcher --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <!-- This intent-filter allows the Trusted Web Activity to handle Intents to open airhorner.com. --> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE"/> <!-- Edit android:host to handle links to the target URL--> <data android:scheme="https" android:host="mal-war.com"/> </intent-filter> </activity> <activity android:name="com.google.androidbrowserhelper.trusted.FocusActivity" /> <!-- <provider--> <!-- android:name="androidx.core.content.FileProvider"--> <!-- android:authorities="com.example.twa.myapplication.fileprovider"--> <!-- android:grantUriPermissions="true"--> <!-- android:exported="false">--> <!-- <meta-data--> <!-- android:name="android.support.FILE_PROVIDER_PATHS"--> <!-- android:resource="@xml/filepaths" />--> <!-- </provider>--> <service android:name=".ExtraFeaturesService" android:exported="true"> <intent-filter> <action android:name="android.support.customtabs.trusted.TRUSTED_WEB_ACTIVITY_SERVICE"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </service> <activity android:name="com.google.androidbrowserhelper.playbilling.provider.PaymentActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:configChanges="keyboardHidden|keyboard|orientation|screenLayout|screenSize" android:exported="true"> <intent-filter> <action android:name="org.chromium.intent.action.PAY" /> </intent-filter> <meta-data android:name="org.chromium.default_payment_method_name" android:value="https://play.google.com/billing" /> </activity> <!-- This service checks who calls it at runtime. --> <service android:name="com.google.androidbrowserhelper.playbilling.provider.PaymentService" android:exported="true" > <intent-filter> <action android:name="org.chromium.intent.action.IS_READY_TO_PAY" /> </intent-filter> </service> </application> </manifest>
build.gradle配置
plugins { id 'com.android.application' } android { compileSdkVersion 30 buildToolsVersion "30.0.3" defaultConfig { applicationId "com.mwar.maliciouswar" minSdkVersion 23 // android 6.0 targetSdkVersion 30 versionCode 9 versionName "1.06" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } } dependencies { implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'com.google.android.material:material:1.3.0' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' implementation 'com.google.androidbrowserhelper:androidbrowserhelper:2.2.2' // implementation "com.android.billingclient:billing:4.0.0" implementation 'com.google.androidbrowserhelper:billing:1.0.0-alpha08' }
解决方案
- 修复SKU参数传递错误:当前代码将完整的
skuDetails[0]对象传给了paymentMethods的data.sku字段,实际要求传入SKU的字符串ID,修改为sku: skuDetails[0].id即可,这是触发该报错的最常见原因。 - 升级依赖版本解决兼容性问题:你使用的
com.google.androidbrowserhelper:billing:1.0.0-alpha08是早期测试版本,和androidbrowserhelper:2.2.2存在兼容性缺陷,建议将billing依赖升级到com.google.androidbrowserhelper:billing:1.1.0,无需单独引入billingclient依赖,billing库会自动适配对应版本的支付客户端。 - 检查测试环境配置:
- 确保当前测试的APK签名和你上传到Google Play后台的包签名完全一致
- 确保Google Play后台已经配置了ID为
gem的内购商品,且商品状态为已激活 - 测试设备登录的谷歌账号已加入应用的内购测试名单,没有被限制支付权限
- 确认TWA验证状态:检查asset_statements的数字资产链接是否验证通过,TWA未退化为普通自定义标签模式,只有完全信任的TWA才能调用Play Billing支付能力。
内容的提问来源于stack exchange,提问作者shamaseen
相关产品推荐
相关产品推荐

