Flutter-Dart中GooglePayButton添加新信用卡时提示无效支付方式错误
问题描述
开发Flutter-Dart应用时,使用GooglePayButton实现支付功能,添加新信用卡时提示错误“invalid payment method, OR_CCREU_O1”,但该信用卡在其他应用可正常添加并完成支付。已绑定到Google Pay的信用卡能成功完成测试支付,已集成Stripe支付,且拥有Google Pay和Google Cloud开发者账户。怀疑是Google Pay或Google Cloud的配置问题导致新卡添加被阻止,Android项目中同时配置了com.google.android.gms:play-services-wallet的18.0.0和19.2.1版本,不确定是否必要。
解决建议
统一Play Services Wallet版本:项目中同时存在多个版本会引发依赖冲突,移除旧版本引用,仅保留最新稳定版(19.2.1),确保
android/app/build.gradle的dependencies中只有一行:implementation 'com.google.android.gms:play-services-wallet:19.2.1'检查Google Pay Merchant Profile配置:
- 确认Merchant Profile中开启了允许添加新卡的选项,部分商户配置可能默认限制仅使用已绑定卡片
- 验证Google Cloud Console中Wallet API已正确启用,且关联的Merchant ID与应用配置完全一致
完善GooglePayConfiguration参数:
确保googlePayConfig包含新卡添加所需的完整配置,示例如下:final googlePayConfig = PaymentConfiguration.fromJson({ 'environment': 'TEST', // 正式环境切换为PRODUCTION 'apiVersion': 2, 'apiVersionMinor': 0, 'allowedPaymentMethods': [ { 'type': 'CARD', 'parameters': { 'allowedAuthMethods': ['PAN_ONLY', 'CRYPTOGRAM_3DS'], 'allowedCardNetworks': ['AMEX', 'DISCOVER', 'MASTERCARD', 'VISA'], 'allowPrepaidCards': true, 'allowCreditCards': true }, 'tokenizationSpecification': { 'type': 'PAYMENT_GATEWAY', 'parameters': { 'gateway': 'stripe', 'stripe:publishableKey': '你的Stripe公钥', 'stripe:version': '2023-10-16' // 匹配Stripe SDK版本 } } } ] });测试环境务必使用Stripe官方提供的测试信用卡(如4242 4242 4242 4242),避免真实卡片触发验证限制。
验证Stripe集成配置:
- 确认Stripe Dashboard中已启用Google Pay,且关联的Merchant ID与Google Pay配置一致
- 检查Stripe SDK版本(20.37.4)与Google Pay SDK版本的兼容性,建议使用官方推荐的版本组合
检查Android清单与权限:
确保AndroidManifest.xml中已添加<meta-data android:name="com.google.android.gms.wallet.api.enabled" android:value="true"/>,且应用的applicationId与Google Cloud Console中注册的应用ID完全匹配。更新设备Google Pay应用:
旧版本的Google Pay应用可能存在兼容性问题,确保设备上的Google Pay为最新版本。
相关代码与配置
GooglePayButton调用代码
GooglePayButton( paymentConfiguration: googlePayConfig, paymentItems: const [ PaymentItem( label: 'Total', amount: '2.00', status: PaymentItemStatus.final_price, ) ], type: GooglePayButtonType.pay, margin: const EdgeInsets.only(top: 15.0), onPaymentResult: (result) { // log(result.toString()); String res = result.toString(); }, onError: (error) { }, loadingIndicator: const Center( child: CircularProgressIndicator(), ),
版本信息
flutter --version Flutter 3.16.7 • channel stable • https://github.com/flutter/flutter.git Framework • revision ef1af02aea (7 weeks ago) • 2024-01-11 15:19:26 -0600 Engine • revision 4a585b7929 Tools • Dart 3.2.4 • DevTools 2.28.5 Dart SDK version: 3.2.4 (stable) (Thu Dec 21 19:13:53 2023 +0000) on "windows_x64"
Android配置文件
android\app\build.gradle
plugins { id 'com.google.gms.google-services' id "com.android.application" id "kotlin-android" id "dev.flutter.flutter-gradle-plugin" // Add the Crashlytics Gradle plugin id("com.google.firebase.crashlytics") } def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { localPropertiesFile.withReader('UTF-8') { reader -> localProperties.load(reader) } } def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '1' } def flutterVersionName = localProperties.getProperty('flutter.versionName') if (flutterVersionName == null) { flutterVersionName = '1.0' } android { namespace "com.xxxx" compileSdkVersion 34 ndkVersion flutter.ndkVersion compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } sourceSets { main.java.srcDirs += 'src/main/kotlin' } defaultConfig { applicationId "com.xxxx" minSdkVersion 21 targetSdkVersion 34 multiDexEnabled true versionCode flutterVersionCode.toInteger() versionName flutterVersionName } buildTypes { release { signingConfig signingConfigs.debug } } } flutter { source '../..' } dependencies { implementation 'com.android.support:multidex:1.0.3' implementation 'com.google.android.gms:play-services-wallet:19.2.1' implementation 'com.stripe:stripe-android:20.37.4' implementation(platform("com.google.firebase:firebase-bom:32.7.0")) implementation("com.google.firebase:firebase-crashlytics-ndk") implementation("com.google.firebase:firebase-analytics") }
android\app\src\main\AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <application android:usesCleartextTraffic="true" android:label="xxxxxxx" android:name="${applicationName}" android:icon="@mipmap/ic_launcher"> <activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop" android:theme="@style/NormalTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize"> <meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme" /> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <meta-data android:name="flutterEmbedding" android:value="2" /> <meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="xxxxxxx"/> <meta-data android:name="com.google.android.gms.wallet.api.enabled" android:value="true"/> </application> <queries> <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="sms" /> </intent> <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="tel" /> </intent> <intent> <action android:name="android.intent.action.SENDTO" /> <data android:scheme="mailto" /> </intent> </queries> </manifest>
android\build.gradle
buildscript { ext.kotlin_version = '1.9.0' repositories { google() mavenCentral() } dependencies { classpath 'com.google.gms:google-services:4.3.15' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1' classpath 'com.android.tools.build:gradle:7.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { repositories { google() mavenCentral() } } rootProject.buildDir = '../build' subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" } subprojects { project.evaluationDependsOn(':app') } tasks.register("clean", Delete) { delete rootProject.buildDir }
android\settings.gradle
pluginManagement { def flutterSdkPath = { def properties = new Properties() file("local.properties").withInputStream { properties.load(it) } def flutterSdkPath = properties.getProperty("flutter.sdk") assert flutterSdkPath != null, "flutter.sdk not set in local.properties" return flutterSdkPath } settings.ext.flutterSdkPath = flutterSdkPath() includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") plugins { id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false id 'com.google.gms.google-services' version '4.4.1' apply false } } include ":app" apply from: "${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle/app_plugin_loader.gradle"
内容的提问来源于stack exchange,提问作者cealex

