You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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库会自动适配对应版本的支付客户端。
  • 检查测试环境配置:
    1. 确保当前测试的APK签名和你上传到Google Play后台的包签名完全一致
    2. 确保Google Play后台已经配置了ID为gem的内购商品,且商品状态为已激活
    3. 测试设备登录的谷歌账号已加入应用的内购测试名单,没有被限制支付权限
  • 确认TWA验证状态:检查asset_statements的数字资产链接是否验证通过,TWA未退化为普通自定义标签模式,只有完全信任的TWA才能调用Play Billing支付能力。

内容的提问来源于stack exchange,提问作者shamaseen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 06:57:04