微包接入说明

集成说明

添加 .aar

请将 XXXXX.aar 放入 app/libs目录中

android{
        compileSdk 34
        defaultConfig {
          // 运行版本需要 21 <= target <= 34 
          targetSdk 34
        }
      
        compileOptions {
          sourceCompatibility JavaVersion.VERSION_1_8
          targetCompatibility JavaVersion.VERSION_1_8
        }
        // 必须加入此配置
        // 编译时确保微包SDK内部使用到的.so文件正常工作
        packagingOptions {
          // 必须添加, 防止.so被压缩导致函数签名异常问题
          doNotStrip "**/*.so"
          // 重复.so默认选择第一个打包
          // 若确保.so文件唯一可以不加此参数
          pickFirst "**/*.so"
        }
          
        repositories {
          flatDir { dirs 'libs' }
        }
      }
      
      dependencies {
          // 基础依赖
          implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
          implementation 'com.google.android.material:material:1.10.0'
          implementation 'androidx.appcompat:appcompat:1.6.1'
          implementation 'androidx.activity:activity:1.6.0'
          implementation 'androidx.fragment:fragment:1.6.2'
      
          def camerax_version = "1.3.1"
          implementation "androidx.camera:camera-core:${camerax_version}"
          implementation "androidx.camera:camera-camera2:${camerax_version}"
          implementation "androidx.camera:camera-lifecycle:${camerax_version}"
          implementation "androidx.camera:camera-view:${camerax_version}"
      
          implementation 'com.google.code.gson:gson:2.8.7'
          implementation 'com.alibaba.pdns:alidns-android-sdk:2.2.0'
      
          // 核心依赖
          implementation(name: 'belt-ids-sdk-production-release',ext: '.aar')
          // 专业版(与集成版2选1)
          implementation(name: 'wbx_professional_sdk_2.x.x',ext: '.aar')
          // 集成版(与专业版2选1)
          implementation(name: 'wbx_community_sdk_2.x.x',ext: '.aar')
      }
      

请添以下属性与配置确保人像在使用相机时能正常工作

<!-- 针对`android 11`及以后的设备出现.so被压缩导致人像无法使用的情况请进行如下设置 -->
      <application android:extractNativeLibs="true"/>
      
# 针对`APP Bundle`出现.so被压缩导致人像无法使用的情况请进行如下设置 
      # Disables compression for native libraries in Android App Bundles.
      android.bundle.enableUncompressedNativeLibs=false
      

备注:如果导入了 aar,但是在代码中却没有相关package,请 clean project,并且rebuild project,如果还是未找到,请 clean project 后删除根目录的 .idea 与 .gradle 文件夹,关闭Android Studio然后重新打开项目
或使用 'Invalidate Caches' 选择 'Clear VCS Log caches and indexes' 执行清楚缓存操作

添加移动端商编证书(XXXXXXXX.cer)

微包移动端SDK版本选用1.5.0或更新的版本,将不用执行此步骤.微包移动端SDK内部将自动会获取该商户证书.

注意:在22年7月(含7月)之前开通微包的商户不能使用‘自动获取商户证书功能’

将移动端商编证书(XXXXXXXX.cer)拷贝到assets目录下,证书可配置在assets的子目录中,具体配置方式请看 对外提供的方法 (WalletPay) 章节

添加静态活体(即:刷脸认证)

从微包2.0.0开始,人像将不在使用.lic授权文件
静态活体功能需要联系我司商务经理进行申请授权文件。
申请授权文件中的包名应该与要集成的App保持一致

获取到拿到License文件后(即:xxx.lic)

<application>
         <meta-data
                 android:name="com.ehking:android-sensetime:lic"
                 android:value="0d5e791c-1577-45e7-ade5-b29795b9aa95.lic" />
      </application>
      

当然你也可以通过 AndroidManifest 指定你的.lic名称

<meta-data
          android:name="com.ehking:android-sensetime:lic"
          android:value="YOU_CUSTOM_LICENCE_NAME.lic" />
      

Tip1: Demo中没有活体认证文件,需要联系我司商务进行申请授权文件。
Tip2: 如果想在Demo试用申请授权文件,需要商户手动修改Demo应用的包名(包名与授权文件申请的包名必须一致)。

SDK 中使用到的权限

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
          <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
          <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
          <uses-permission android:name="android.permission.READ_PHONE_STATE" />
          <uses-permission android:name="android.permission.BLUETOOTH" />
          <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
          <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
          <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
          <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
          <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
          <uses-permission android:name="android.permission.CAMERA" />
          <uses-permission android:name="android.permission.VIBRATE" />
          <uses-permission android:name="android.permission.INTERNET" />
          <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
          
          <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
          <uses-permission android:name="android.permission.WAKE_LOCK" />
      
          <!-- 读取手机号码与接收短信权限为敏感权限,如需要请自行添加  -->
          <!-- 此功能为适配部分手机使用短信支付时不能自动填充短信的问题  -->
          <!-- 具体请查看 '对外提供的方法 (WalletPay)' 章节-->
          <!-- <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />-->
          <!-- <uses-permission android:name="android.permission.RECEIVE_SMS" />-->
      

混淆例外

-dontwarn com.ehking.**
      -keep class com.ehking.**{*;}
      
      -dontwarn net.bean.**
      -keep class net.bean.**{*;}
      
      -dontwarn com.livedetect.**
      -keep class com.livedetect.**{*;}
      
      -dontwarn ccom.sensetime.**
      -keep class com.sensetime.**{*;}
      
      -dontwarn com.hisign.**
      -keep class com.hisign.**{*;}
      
      -keep class com.alibaba.pdns.** {*;}
      
      -dontwarn org.xbill.DNS.**
      -keep class org.xbill.DNS.**{*;}
      
      -dontwarn org.slf4j.**
      -keep class org.slf4j.**{*;}
      
      //若选用集成版还需要加入此例外
      -dontwarn com.payeasenet.**
      -keep class com.payeasenet.sdk.**{*;}
      

基本使用

// 设置钱包
      WalletPay.setWallet(/*商户商编ID*/"89XXXXX95", /*用户钱包ID*/"XXXXXXXXXXXXXXXXXX");
      
      // 业务类型。{@code AuthType.RECHARGE}充值业务
      AuthType businessCode = AuthType.RECHARGE;
      // 注册业务执行回调
      OnEvokeResultListenerAdapter listener = new OnEvokeResultListenerAdapter(){
          
          // 所有的回调都会先触发此方法
          @override
          public void onEvokeResult(AuthType businessCode, Status status, String cause){ 
              /*_*/
          }
      
          // 可选方法:充值业务回调
          @override
          public void onRechargeResult(Status status, String cause){
              // 注销业务执行回调
              WalletPay.removeOnEvokeResultListenerList(this);
          }
          
          /*其它各业务可选回调*/
      };
      // 关于Token 请看 '唤起业务' 章节
      String token = "XXXX"
      String requestId = String.valueOf(System.currentTimeMillis());
      WalletPay.evoke(token, businessCode, requestId, listener);
      

自定义Activity Style

    <!-- 可覆写此样式 -->
          <style name="Wbx.SDK.Theme.Base.Custom" parent="Wbx.SDK.Theme.Base">
      
          </style>
      

唤起业务

基本所有业务都需要使用到token

token 是服务端生成的动态码,需要请求后台进行获取。

专业版中token的获取并非由SDK供应商直接提供,而是需要商户服务端进行开发相应接口(即:预下单接口,具体可看微包服务端接入文档),商户的移动端从商户服务端接口获取到返回的token再传入WalletPayevoke方法中

Map<String, Object> map = new HashMap<>();
      map.put(/*...*/)
      // ... 
      netApiService.fetchWalletRecharge(map, it -> {
          WalletPay.evoke(
          // 从商户服务端获取 Token
          it.getToken(), 
          // 业务类型
          AuthType.RECHARGE, 
          // 订单号,可用于排查微包排查日志
          String.valueOf(System.currentTimeMillis()),
          // 回调监听适配器
          new OnEvokeResultListenerAdapter(){
              // ...
          }
      });
      

提供的业务(AuthType)

enum AuthType  {
          VERIFY_CERT("安装数字证书"),
          FIRSTSET_PASSWORD("设置支付密码"),
          ACCESS_SAFETY("支付设置"),
          ACCESS_SAFETY_OPEN_FACE("开启人脸识别"),
          ACCESS_CARDlIST("绑卡管理"),
          VALIDATE_PASSWORD("确认密码"),
          SILENCE_RESCIND("解除沉默账户"),
          INSTALL_CERT("Token可空, 直接启动安装证书页面"),
          MANUAL_CHECK_CER("手动下载证书"),
          AUTO_CHECK_CER("自动下载证书"),
          AUTH_PERSON("人像认证"),
          // 以下为收银台业务
          RECHARGE("充值"),
          TRANSFER("转账"),
          WITHHOLDING("提现"),
          REDPACKET("发红包"),
          APP_PAY("微包支付和服务号订单支付"),
          WEB_PAY("WEB支付"),
      }
      

对外提供的方法 (WalletPay)

/**
       * 获取附加结果数据
       * 目前仅用在扫码付功能中,提供查询订单能力, 具体返回内容可查看Demo中扫码付相关代码
       */
      public static Object getResultObject();
      
      /**
       * 设置证书目录
       * 也可以通过<meta-data>标签的方式进行注册
       * 关于使用优先级:
       *  1. setCertificateDirectory
       *  2. <meta-data>
       * 注意:若不设置路径,则会从 assets的根目录查找证书
       * <pre>
       *     <meta-data 
       *         android:name="com.ehking:android-webox:cert-dir"
       *         android:value="YOUR CER DIR"
       *     />
       * </pre>
       * 
       * @param dir 示例:e/g/a/cer,
       * 
       * 关于商编证书的特别注意事项:
       * 商户会持有两个 'XXXXX.cer'的证书(即:公钥与私钥),分别用在移动端与服务端。
       * 如果使用错误,会出现业务启动失败(即:证书解密失败问题)
       */
      public static void setCertificateDirectory(String dir);
      
      /**
       *  是否禁用敏感权限;
       *  禁用敏感权限,ture禁用/false不禁用; 
       *  禁用后, 收银台短信码支付方式, 不会自动获取短信验证码
       *  默认为true;若改为false后需要在AndroidManifest.xml中添加以下权限
       *  <pre>
       *      <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
       *      <uses-permission android:name="android.permission.RECEIVE_SMS" />
       *  </pre>
       */
      public static void setDisableSensitivePermissions(boolean disable)
      
      /**
       * 获取当前密码验证页面的验证方式
       * @return PayAuthType
       */
      public static PayAuthType getCurrentDefaultValidatePasswordType();
      
      /**
       * 设置密码验证页面的验证方式(非支付收银台支付校验方式)
       * 默认为支付密码确认{@link PayAuthType.PAY_PASSWORD}
       */
      public static void setDefaultPayModeOfVerifyPwd(PayAuthType type);
      
      /**
       * 添加唤起业务结果监听
       */
      public static void addOnEvokeResultListener(OnEvokeResultListener listener);
      
      
      /**
       * 删除唤起业务结果监听
       * 业务结束务必注销监听,否则某些业务可能会通知多次
       */
      public static void removeOnEvokeResultListener(OnEvokeResultListener listener);
      
      /**
       * 屏幕适配例外名单
       * 如果你使用的是 AndroidAutoSize 框架,
       * 需要将例外名单进行添加
       * 防止页面出现适配问题
       * {@link https://github.com/JessYanCoding/AndroidAutoSize}
       */
      public static List<Class<?>> notRequiredScreenAdaptList();
      
      /**
       * 设置钱包, 若未开户(无walletId),可仅填写商户ID(merchantId)
       * 开完户获取到的WalletId需要设置
       */
      public static void setWallet(@NonNull String merchantId, @Nullable String walletId)
      
      /**
       * @param  token   调起业务需要的token.
       * @param  source  调起业务的code.
       * @param  requestId 唯一标识,后台查询业务使用, 一般时间戳作为入参
       *         {@code System#currentTimeMillis()}
       * @param  onEvokeResultListener  注册唤起业务结果监听
       */
      public static void evoke(
          String token, 
          AuthType source, 
          String requestId,
          OnEvokeResultListener listener
      );
      
      /**
       * AppPay支付,是否由微包显示支付结果页面
       */
      public static void setNeedDisplayAppPayPaymentResultPage(boolean display);
      
      /**
       * 清除钱包缓存
       * 使用这个函数请慎重,除非你能保证业务未执行或已经结束在使用它,
       * 因为,如果在业务唤起阶段中使用,业务将会被中断或出现异常
       */
      public static void clearWalletCache();
      
      /**
       * 获取当前SDK版本号
       */
      public static String getSdkVersion();
      
      /**
       * 设置Debug模式
       * @param debug true开启Debug模式/false关闭Debug模式
       * 如果开启Debug模式则会多出相应的Toast提示以及堆栈日志
       */
      public static void setDebug(Boolean isDebug);
      
      /**
       * 设置随机数字键盘
       * @param random true开启随机数字键盘/false关闭随机数字键盘
       */
      public static void setRandomKeyboard(Boolean random);
      
      /**
       * 删除证书
       * 备注:指开户后从服务端下载或手动安装存储在存储器中的证书,
       *      非商编证书(XXXXXX.cer)
       * @param walletId 要删除的钱包ID
       * @return Map<String, Object>
       * <pre>
       * {
       *   "delResult" : Boolean, // 是否删除成功
       *   "cerFile" : String, // 证书路径
       *   "existCer" : Boolean, // 证书是否存在
       * }
       * </pre>
       */
      public static Map<String, Object> deleteCert(String walletId);
      
      /**
       * 设置装饰布局(仅支持按钮与Toolbar)
       * 布局类型由 com.ehking.sdk.wepay.platform.decoration.WidgetCate 提供
       * 可以设置渐变色背景 接收类型 Drawable 
       * 可以设置文字颜色 接收类型 ColorStateList
       * 若空则由SDK提供默认的背景与文字颜色
       */
      public static void setWidgetDecoration(List<WidgetDecoration> list);
      
      /**
       * 设置toolbar返回键样式
       * @param ToolBarBackColorStyle
       * <pre>
       * enum ToolBarBackColorStyle{
       *    AUTO, // 自动设置, BLACK/WHITE
       *    BLACK, // 黑色样式
       *    WHITE, // 白色样式
       * }
       * </pre>
       */
      public static void setToolBarBackImg(ToolBarBackColorStyle style);
      
      /**
       * 私钥证书是否存在 
       * 备注:指开户后从服务端下载或手动安装存储在存储器中的证书,
       *      非商编证书(XXXXXX.cer)
       * @param walletId 如果空则查询当前钱包ID的私钥证书,
       *                 如果有值则查询指定钱包ID是否有证书
       * @return Boolean 证书存在 true, 反之 false
       */
      public static Boolean existsPrivateKeyCerFile(String walletId);
      
      /**
       * 获取设备号码(即:android.provider.Settings.Secure.ANDROID_ID)
       */
      public static String getDeviceNumber();
      
      /**
       * 可以调用此方法关闭 Loading 弹窗
       */
      public static void dismissLoading(Activity activity);
      
      /**
       * 自定义Loading
       *
       * 只接收带有 Context 型参的构造函数
       * <pre>
       *   public LoadingDialog(Context context) {
       *      super(context, R.style.your_custom_loading_dialog);
       *   }
       * </pre>
       *
       * NOTE:不要将构造函数混淆,否则无法反射到此函数签名
       * <pre>
       * // 这里展示的是Demo中自定义Loading剔除混淆
       * -keep class com.payeasenet.webox.platform.widget.loading.LoadingDialog{public *;}
       * </pre>
       */
      public static void setCustomLoading(Class<? extends AlertDialog> clz);
      
      /**
       * 自定义权限申请提示内容
       */
      public static void setCustomPermission(CustomPermission customPermission) 
      

密码验证枚举说明 (密码验证页面使用)

enum PayAuthType{
          PAY_PASSWORD("默认密码"),
          FORCE_PAY_PASSWORD("强制密码"),
          FACE_SCAN("刷脸"),
          FORCE_FACE_SCAN("强制刷脸"),
          FINGERPRINT("指纹"),
          UNKNOWN("")
      }
      

AuthType.VALIDATE_PASSWORD业务适用

备注:商户使用WalletPayevoke方法调用收银台业不能指定为包支付具体验密方式。微包的收银台业务验密由微包服务端指定。

关于业务回调 (OnEvokeResultListener)

// 回调接口
      public interface OnEvokeResultListener
      
      // 为了方便,微包提供了适配类
      public class OnEvokeResultListenerAdapter implements OnEvokeResultListener
      

回调内容

/**
       * 所有业务的回调都会触发此方法
       * @param source 业务类型
       * @param status 回调状态
       * @param cause 原因
       * 备注:成功类型也可能会带有原因
       * Status的父类
       * 具体说明请看 '关于业务回调状态类型' 章节
       */
      void onEvokeResult(AuthType source, IStatus status, String cause);
      
      // 校验数字证书校验
      void onVerifyCertResult(Status status, String cause)
      
      // 首次设置支付密码
      void onFirstPasswordResult(Status status, String cause)
      
      // 唤起安全设置页面
      void onAccessSafetyResult(/*型参与上相同*/)
      
      // 唤起安全设置开启人脸
      void onAccessSafetyOpenFaceResult(/*型参与上相同*/)
      
      // 唤起卡列表页面
      void onAccessCardListResult(/*型参与上相同*/)
      
      // 确认密码
      void onValidatePasswordResult(/*型参与上相同*/)
      
      // 手动下载证书
      void onManualCheckCerResult(/*型参与上相同*/)
      
      // 自动下载证书
      void onAutoCheckCerResult(/*型参与上相同*/)
      
      // 人像认证
      void onAuthPersonResult(/*型参与上相同*/)
      
      // 发起充值
      void onRechargeResult(/*型参与上相同*/)
      
      // 发起转账
      void onTransferResult(/*型参与上相同*/)
      
      // 发起提现
      void onWithholdingResult(/*型参与上相同*/)
      
      // 发起发红包
      void onRedPacketResult(/*型参与上相同*/)
      
      // 微包支付和服务号支付
      void onAppPayResult(/*型参与上相同*/)
      
      // Web支付
      void onWebPayResult(/*型参与上相同*/)
      
      // 解除沉默账户
      void onSilenceRescindResult(Status status, String cause);
      

关于业务回调状态类型 (Status)

普通业务与收银台业务的回调状态枚举

enum Status{
          SEND("发起成功"),
          PROCESS("处理中"),
          SUCCESS("成功"),
          FAIL("发起失败/失败"),
          CANCEL("取消"),
          UNKNOWN(""),
      }
      

需要注意:

微包收银台业务的回调状态仅表示业务提交结果而非订单状态,若回调结果状态是Status.SUCCESSStatus.SENDStatus.PROCESS仍需要商户自行查询获取该笔订单的实际状态.

其它可配置项

public class DemoApplication extends Application {
      
          @Override
          public void onCreate() {
              super.onCreate();
              // 设置是否为Debug模式
              WalletPay.setDebug(BuildConfig.DEBUG);
              // 是否禁用敏感权限
              WalletPay.setDisableSensitivePermissions(true);
              // 默认最少为10秒,少于10秒设置无效
              WbxSdkConstants.Http.setTimeoutSeconds(30);
              // 设置按系统返回键时关闭缓冲弹窗上限次数
              WbxSdkConstants.GlobalConfig.setBackPressedLimitCountOnLoadingTip(1);
              // 是否禁用按系统返回键时关闭缓冲弹窗功能
              WbxSdkConstants.GlobalConfig.setDisableBackPressedOnLoadingTip(false);
              // @author:         zhiwei@payeasenet.com 2022/4/26 16:30
              // @description:    默认可不设置,会自动走阿里的域名解析
              // WbxSdkConstants.Http.setDns(new DnsResolver());
          }
      }
      

设置 AppBarLayout 的高度

<!-- 覆写此资源 -->
      <dimen name="wbx_sdk_app_bar_layout_elevation">0dp</dimen>
      

编译问题与异常的解决说明

编译问题

依赖冲突

android{
         // 配置全局依赖剔除
         configurations {
            // 包名仅示例效果,请根据自身情况填写
            compile.exclude group: 'org.slf4j', module: 'slf4j-api'
         }
          
         // 配置全局库强制引用
         configurations.all {
            resolutionStrategy {
               force 'org.slf4j:slf4j-android:1.7.21'
            }
         }
      }
      
      // 非全局配置,仅针对某个引用依赖
      dependencies {
         implementation(name: "wbx_professional_sdk_1.x.x", ext: "aar"){
            // 你可以指定剔除某个依赖
            exclude group: 'com.android.support'
            exclude group: 'e.g.a', module: 'xx'
         }
      // 或者你可以强制指定以当前版本为准
         implementation('com.android.support:support-v4:27') {
            // 这个方法在高Gradle版本中已经失效,强制指定只能使用全局方式
            force = true
         }
      }
      

更多解决依赖冲突的方式请自行网上查找资料

导入aar不生效

如果导入了 aar,但是在代码中却没有相关package,请 clean project,并且rebuild project,如果还是未找到,请 clean project 后删除根目录的 .idea 与 .gradle 文件夹,关闭Android Studio然后重新打开项目

一般来说clean并且rebuild后就可以找到相关package了

演示项目,AS编译报错

  1. Project中gradle版本是否已经下载到本地
  2. local.properties 中Android SDK路径是否正确

依赖下载慢(可选国内镜像)

请根据自己的需求选择相关镜像库

maven { url 'https://maven.aliyun.com/repository/central' }
      maven { url 'https://maven.aliyun.com/repository/public' }
      maven { url 'https://maven.aliyun.com/repository/jcenter' }
      maven { url 'https://maven.aliyun.com/repository/google' }
      maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
      

常见异常

    implementation 'androidx.work:work-runtime:2.7.1' // For Java
          implementation 'androidx.work:work-runtime-ktx:2.7.1' // For Kotlin
      
    android { 
              packagingOptions { 
                doNotStrip "**/*.so"
                pickFirst "**/*.so"
              } 
          }
      
    <!-- 从 Android 10(API 级别 29)开始, 还需要设置此参数为true -->
          <application android:extractNativeLibs="true" />
      
<?xml version="1.0" encoding="utf-8"?>
      <manifest xmlns:tools="http://schemas.android.com/tools"
      xmlns:android="http://schemas.android.com/apk/res/android">
      
          <application
              android:allowBackup="true"
              tools:replace="android:allowBackup" />
      </manifest>
      

版本更新说明

2.2.2

2.2.1

2.2.0

2.1.0

1.7.0

1.6.5

1.6.4

1.6.3

1.6.2

1.6.1

1.6.0

1.5.4

1.5.3

1.5.2

1.5.1

1.5.0

1.4.1

1.4.0

1.3.3

1.3.2

1.3.1

1.3.0

1.2.0

1.1.10

1.1.9

1.1.8

1.1.7

1.1.6

1.1.5

1.1.4

1.1.3

1.1.2

1.1.1

1.1.0

1.0.7.1

1.0.7

1.0.6

1.0.5

1.0.4

1.0.3

1.0.2

1.0.1

1.0.0