Flutter 发布 apk 无法在 PayHere 进行支付

Flutter release apk can't proceed payment in PayHere

我的 flutter 应用程序无法在发布 apk 的 PayHere 支付网关中进行支付。在调试模式和 运行 发布模式下的应用程序工作正常。但仅在构建和 运行ning 发布 apk 时出现错误。

这很可能是 Android 发布版本的代码缩小的问题。建议的解决方案是通过添加适当的 ProGuard 规则来尝试防止 PayHere 代码在发布版本中被剥离。

添加 ProGuard 规则

  1. 在您的 Flutter 项目目录中,找到“android”文件夹。
  2. 导航到“app”子文件夹。
  3. 创建一个名为 "proguard-rules.pro" 的新文件(如果尚不存在)。
  4. 在文本编辑器中打开上述 ProGuard 文件。
  5. 将以下行复制并粘贴到 ProGuard 文件的末尾(这将从代码 shrinking/minifcation 中排除所有与 PayHere SDK 相关的 类)。
-keep class lk.payhere.** { *; }

指示Android使用ProGuard文件

  1. 打开“android/app/build.gradle”文件。
  2. 找到 buildTypes > 释放块。
  3. 如果还没有,请添加以下行。
minifyEnabled true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

“build.gradle”文件中的最终结果应如下所示:

android {
 compileSdkVersion 29

  // ...

  buildTypes {
    release {

      signingConfig signingConfigs.debug

      // the code we added...

      minifyEnabled true
      useProguard true
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

    }
  }
}

最后,

做一个干净的构建,看看你的问题是否得到解决。

如果问题仍然存在,请尝试在 PayHere Flutter SDK 的错误处理程序中添加一个警报弹出窗口,以查看是否返回可读错误。

类似于:

PayHere.startPayment(
  paymentObject, 
  (paymentId) {
    print("One Time Payment Success. Payment Id: $paymentId");
  }, 
  (error) { 
    print("One Time Payment Failed. Error: $error");
    // add alert code here
  }, 
  () { 
    print("One Time Payment Dismissed");
  }
);

不得已的办法是自己联系 PayHere 寻求支持。如果是这种情况,您可以将它们邮寄至 techsupport@payhere.lk


请注意,ProGuard 规则也适用于 Android 的 R8 代码,根据 documentation

When building the release version of your app, by default, R8 automatically performs the compile-time tasks described above for you. However, you can disable certain tasks or customize R8’s behavior through ProGuard rules files. In fact, R8 works with all of your existing ProGuard rules files, so updating the Android Gradle plugin to use R8 should not require you to change your existing rules.

根本原因

该问题是由 Flutter 的 R8 代码收缩引起的,如 here. Since Android Gradle version 3.4.0, R8 does not use Proguard under the hood as mentioned here 所述,对于 Release 版本默认情况下是打开的。但是,R8 仍然使用确切格式的混淆规则文件,只有在明确提供的情况下才将 类 排除在 obfuscated/removed 之外。否则,未使用的代码将从最终产品中删除。

据了解,Flutter 和 Dart 内部用于 link PayHere Android SDK 和 PayHere Flutter Dart 组件之间的 MethodChannels 受到此代码混淆过程的影响。

解决方案

有两种方法可以解决这个问题。如果开发人员扩展现有代码库,第一个提供更多的灵活性。第二种解决方案是快速“修补程序”,它禁用代码混淆以方便应用。

注意:在执行下文提到的解决方案之前,请维护现有代码库的备份。即使启用了版本控制,也建议执行此步骤,因为 .gitignore 定义可能不会跟踪对包含敏感信息的文件的更改。

1。使用 Android Proguard 规则

的解决方案

如果您愿意手动创建 Pro-guard 规则文件或您已经配置了 Pro-guard 规则,则首选此解决方案。所需步骤如下所述。

  1. 在您喜欢的 IDE.

    中打开您的 Flutter 项目
  2. 在“/android/app”文件夹中创建一个名为“proguard-rules.pro”的新文件。

  3. 在上面第 2 步创建的“proguard-rules.pro”文件中添加以下代码行。

    #Flutter Wrapper
    -keep class io.flutter.app.** { *; } 
    -keep class io.flutter.plugin.** { *; } 
    -keep class io.flutter.util.** { *; } 
    -keep class io.flutter.view.** { *; } 
    -keep class io.flutter.** { *; }
    -keep class io.flutter.plugins.** { *; } 
    
    #the required rule
    -keep class lk.payhere.** { *; }
    

以上代码排除了所有默认的 Flutter 库和 PayHere Android SDK 类。确保您没有重叠的规则。如果您已经有一个现有的“proguard-rules.pro”文件,只需添加最后一行。

  1. 打开位于“/android/app”文件夹中的“build.gradle”文件。
  2. 在顶级“android”块中找到“buildTypes”块。请注意,在这个问题的上下文中,开发人员正在为发布模式构建 Flutter 应用程序,并且应该已经编写了“buildTypes”块。
  3. 指示 Android 构建系统保持代码 minification/obfuscation 开启,并使用以下突出显示的代码使用步骤 3 中定义的 Proguard 规则。

请注意,如果您之前已经设置过 Proguard,则可以跳过此步骤。

android {
  compileSdkVersion 29
   sourceSets {
     main.java.srcDirs += 'src/main/kotlin'
  }
   lintOptions {
     disable 'InvalidPackage'
  }
   defaultConfig {
     // Android configurations are usually here
  }
   // Signing Configurations are usually here
   buildTypes {
     release {
       signingConfig signingConfigs.debug

       // add these code lines
       minifyEnabled true
       useProguard true
       proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    } 
  }
}
  1. 执行 Flutter clean 任务并构建您的 Release APK。您的问题现在应该已经解决了。

2。通过禁用修改解决

如果您不需要在您的 Release APK 中进行代码混淆或缩小,您可以简单地为 Android 代码完全禁用此功能。下面提到了所需的步骤。

  1. 在您喜欢的 IDE

    中打开您的 Flutter 项目
  2. 打开“/android/app”文件夹中的“build.gradle”文件。

  3. 找到“android”块,在其中找到“buildTypes”和“release”块。

  4. 添加以下提到的代码以禁用代码修改。

    android {
        compileSdkVersion 29
        sourceSets {
            main.java.srcDirs += 'src/main/kotlin'
        }
    
        lintOptions {
            disable 'InvalidPackage'
        }
    
        defaultConfig {
            // Android configurations are usually here
        }
        // Signing Configurations are usually here
        buildTypes {
            release {
                signingConfig signingConfigs.debug
    
                // add these code lines
                minifyEnabled false
                shrinkResources false
            } 
        }
    }
    
  5. 执行 Flutter clean 任务并构建您的 Release APK。您的问题现在应该已经解决了。

编码愉快:D