微包移动端接入说明

当前微包专业版SDK版本为 1.1.10 当前文档为Android原生专业版接入文档 uniapp或Flutter请与技术支持沟通获取相关对接资料

集成说明

添加 .aar

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

groovy
android{
    repositories {
        flatDir { dirs 'libs' }
    }
}
dependencies {
// 专业版
implementation(name: "wbx_professional_sdk_1.x.x", ext: "aar")
// 集成版
implementation(name: "wbx_community_sdk_1.x.x", ext: "aar")
// 备注:专业版与集成版二选一
// 增值服务,可选
implementation(name: "services_1.x.x", ext: "aar")
}

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

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

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

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

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

静态活体功能需要联系我司商务经理进行申请授权文件。 申请授权文件中的包名应该与要集成的App保持一致

获取到拿到License文件后(即:xxx.lic) - 将 (示例)AAAA-BBBB-CCCC-DDDD.lic 拷贝至 assets 目录下, 即: assets/AAAA-BBBB-CCCC-DDDD.lic

- 需要 (示例)AAAA-BBBB-CCCC-DDDD.lic 文件名称改为 SenseIDLivenessSilent.lic

- 也可以在 AndroidManifest.xml 中配置 <meta-data> 直接指明lic文件名称

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

当然你也可以通过 AndroidManifest 指定你的.lic名称 xml <meta-data android:name="com.ehking:android-sensetime:lic" android:value="aaaaaa-bbbb-cccc-dddd-eeeeeeeeee.lic" />

NOTE1:Demo中没有活体认证文件,需要联系我司商务进行申请授权文件。

NOTE2:如果想在Demo试用申请授权文件,需要商户手动修改Demo应用的包名(包名与授权文件申请的包名必须一致)。

添加依赖

groovy
android{
   compileOptions {
      sourceCompatibility JavaVersion.VERSION18
      targetCompatibility JavaVersion.VERSION18
   }
}
dependencies {
    implementation 'com.android.support:appcompat-v7:28+'
    implementation 'com.android.support:design:28+'
    implementation 'com.google.code.gson:gson:latest.integration'
    implementation 'com.alibaba.pdns:alidns-android-sdk:latest.integration'
    implementation 'dnsjava:dnsjava:latest.integration'
    implementation 'org.slf4j:slf4j-api:latest.integration'
}

androidX

主体项目是AndroidX,使用微包SDK的时候依然需要添加以下3个com.android.support依赖;

groovy
dependencies {
    implementation 'com.android.support:appcompat-v7:28+'
    implementation 'com.android.support:design:28+'
    implementation 'com.google.code.gson:gson:latest.integration'
    implementation 'com.alibaba.pdns:alidns-android-sdk:latest.integration'
    implementation 'dnsjava:dnsjava:latest.integration'
    implementation 'org.slf4j:slf4j-api:latest.integration'
}

请在 `gradle.properties` 中添加以下内容 [官方文档请看这里]

(https://developer.android.com/jetpack/androidx/migrate)groovy
android.useAndroidX=true
android.enableJetifier=true

SDK 中使用到的权限

xml
    <uses-permission android:name="android.permission.ACCESSNETWORKSTATE" />
    <uses-permission android:name="android.permission.ACCESSFINELOCATION" />
    <uses-permission android:name="android.permission.READPHONESTATE" android:maxSdkVersion="29"/>
    <uses-permission android:name="android.permission.WRITEEXTERNALSTORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNALSTORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORDAUDIO" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />

    可以去除敏感权限,walletPay#setDisableSensitivePermissions(true)
    <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" tools:node="remove" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" tools:node="remove" />

混淆例外

groovy
-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.**{*;}

增值服务SDK(可选集成)

kotlin
// 设置回调对象 walletPayCallback() 
// 增值服务只会返回错误与用户取消的回调
ValueAddedServices.setServicePayCallback(
(source, status, errorMessage) -> Log.i(TAG, StringX.plus("来源:", source, "处理结果:", status, "错误原因:", errorMessage).toString())
)
// 再调用SDK 里的evoke()方法,
// 请确保传的参数不为空, 传的参数token值与业务类型对应.
ValueAddedServices.getInstance().evoke(
        merchantId: String, 
        walletId: String,
        token: String,
        // ServiceAuthType.VALUE_ADDED 增值服务
        source: String,
        activity: Activity
)

基本使用

java
// 商户商编ID
String merchantId = "89XXXXX95";
// 商户钱包ID
String walletId = "XXXXXXXXXXXXXXXXXX";
// 业务类型。{@code AuthType.RECHARGE}充值业务
AuthType authType = AuthType.RECHARGE;
// 注册业务执行回调
OnEvokeResultListenerAdapter listener = new OnEvokeResultListenerAdapter(){
    // 充值业务回调
    @override
    public void onRechargeResult(Status status, String cause){
        // 注销业务执行回调
        WalletPay.removeOnEvokeResultListenerList(this);
    }/*各业务回调*/
};
// 关于Token 请看 '唤起业务' 章节
String token = "XXXX"
WalletPay.evoke(merchantId, walletId, token, authType, listener);

自定义Activity Style

xml
    //可覆写此样式
    <style name="CustomWbxSdkTheme" parent="WbxSdkTheme.Base">>
    </style>

唤起业务

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

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

专业版中token的获取并非由SDK供应商直接提供,而是需要商户服务端进行开发相应接口(即:预下单接口,

具体可看微包服务端接入文档),商户的移动端从商户服务端接口获取到返回的token在传入 {@code WalletPay#evoke} 中

java
Map<String, Object> map = new HashMap<>();
map.put(/*...*/)
// ... 
netApiService.fetchWalletRecharge(map, it -> {
    WalletPay.evoke(
    "89XXXXX95", 
    "XXXXXXXXXXXXXXXXXX", 
    // 从商户服务端获取 Token
    it.getToken(), 
    AuthType.RECHARGE, 
    new OnEvokeResultListenerAdapter(){
        // ...
    }
});

提供的业务(AuthType)

java
enum AuthType  {
    VERIFY_CERT("安装数字证书"),
    FIRSTSET_PASSWORD("设置支付密码"),
    ACCESS_SAFETY("安全设置"),
    ACCESS_SAFETY_OPEN_FACE("开启人脸识别"),
    ACCESS_CARDlIST("绑卡管理"),
    VALUE_ADDED("增值服务"),
    VALIDATE_PASSWORD("确认密码"),
    INSTALL_CERT("Token可空, 直接启动安装证书页面"),
    MANUAL_CHECK_CER("手动下载证书"),
    AUTO_CHECK_CER("自动下载证书"),
    AUTH_PERSON("人像认证"),
    // 以下为收银台业务
    RECHARGE("充值"),
    TRANSFER("转账"),
    WITHHOLDING("提现"),
    REDPACKET("发红包"),
    @Deprecated // 已经过期, 请使用 APP_PAY
    ONLINEPAY("订单支付"),
    APP_PAY("微包支付和服务号订单支付"),
}

对外提供的方法 (WalletPay)

java
/**
 * 获取附加结果数据
 * 目前仅用在扫码付功能中,提供查询订单能力, 具体返回内容可查看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(禁用)后请在主工程Manifest.xml中添加以下内容; 编译时会自动删除该权限, 避免提交平台出现敏感权限报警;
 *  <pre>
 *      <uses-permission android:name="android.permission.READPHONENUMBERS" tools:node="remove" />
 *      <uses-permission android:name="android.permission.RECEIVE_SMS" tools:node="remove" />
 *  </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 setOnEvokeResultListener(OnEvokeResultListener listener);
/**
 * 屏幕适配例外名单
 * 如果你使用的是 AndroidAutoSize 框架,
 * 需要将例外名单进行添加
 * 防止页面出现适配问题
 * {@link https://github.com/JessYanCoding/AndroidAutoSize}
 */
public static List<Class<?>> notRequiredScreenAdaptList();
/**
 * @param  merchantId  商户商编.
 * @param  walletId  钱包Id.
 * @param  token   调起业务需要的token.
 * @param  source  调起业务的code.
 * @param  requestId 唯一标识,后台查询业务使用, 一般时间戳作为入参
 *                  {@code System#currentTimeMillis()}
 * @param  onEvokeResultListener  注册唤起业务结果监听
 */
public static void evoke(
    String merchantId, 
    String walletId, 
    String token, 
    AuthType source, 
    OnEvokeResultListener listener, 
    String requestId
);
/**
 * 清除钱包缓存
 * 使用这个函数请慎重,除非你能保证业务未执行或已经结束在使用它,
 * 因为,如果在业务唤起阶段中使用,业务将会被中断或出现异常
 */
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.yourcustomloading_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) 

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

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

备注:商户使用 WalletPay#evoke 调用的收银台业务无法从商户的移动端指定支付方式。微包SDK在真正唤起该收银台业务前会从微包的服务端获取支付方式。

关于业务回调 (OnEvokeResultListener)

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

回调内容

java
/**
 * 所有业务的回调都会触发此方法
 * @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 onValueAddedResult(/型参与上相同/)
// 确认密码
void onValidatePasswordResult(/型参与上相同/)
// 手动下载证书
void onManualCheckCerResult(/型参与上相同/)
// 自动下载证书
void onAutoCheckCerResult(/型参与上相同/)
// 人像认证
void onAuthPersonResult(/型参与上相同/)
// 发起充值
void onRechargeResult(/型参与上相同/)
// 发起转账
void onTransferResult(/型参与上相同/)
// 发起提现
void onWithholdingResult(/型参与上相同/)
// 发起发红包
void onRedPacketResult(/型参与上相同/)
// 订单支付
void onOnlinePayResult(/型参与上相同/)
// 微包支付和服务号支付
void onAppPayResult(/型参与上相同/)

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

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

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

需要注意: SDK中收银台业务的回调状态仅表示业务代码业务提交结果而非订单状态,在提交结果状态是Status.SUCCESS/SEND/PROCESS中仍
需要商户移动端从商户服务端轮询获取该笔订单的实际状态

需要轮询的订单业务码:

- RECHARGE("充值")

- TRANSFER("转账")

- REDPACKET("发红包")

- ONLINEPAY("订单支付")

- APP_PAY("微包支付和服务号订单支付")

其它可配置项

java
public class DemoApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // 设置Http请求超时时间,默认值10秒,设置少于10秒设置无效依然使用默认值
        EhkingConstants.Http.setTimeoutSeconds(10);
        // 抓取崩溃日志存储至外部存储器目录中
        // 存储位置:
        // android 11+ "/sdcard/Android/data/com.payeasenet.webox/files/Alarms/crash/"
        // low version "/sdcard/wbx/files/Alarms/crash/"
        CrashHandler.getInstance(this);
    }
}

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

SDK内部异常抓取

Java
public class DemoApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        CrashHandler.getInstance(this);
    }
}

编译问题

依赖冲突

groovy
android{
   // 配置全局依赖剔除
   configurations {
      // 包名仅示例效果,请根据自身情况填写
      compile.exclude group: 'org.slf4j', module: 'slf4j-api'
   }
// 配置全局库强制引用
   configurations.all {
      resolutionStrategy {
         force 'org.slf4j:slf4j-android:1.7.21'
      }
   }
}
// 非全局配置,仅针对某个引用依赖
dependencies {
   implementation(name: "wbxprofessionalsdk_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路径是否正确

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

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

groovy
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' }

常见异常

  1. 钱包初始化失败,检查你设置的参数是否正确
  2. 获取证书失败
  3. decrypt error
  4. 活体检测,报绑定包名错误
  5. No such file or directory
  6. open failure: EACCES (Permission denied)
  7. decrypt failure
  8. java.lang.IllegalArgumentException: no private key configuration , merchantId:[XXXXXXXXX]
  9. Targeting S+ (version 31 and above) requires that one of FLAGIMMUTABLE or FLAGMUTABLE be specified when creating a PendingIntent.

版本更新说明

Last Version - 修复了一些问题 - APP_PAY业务增加折扣提示 - 优化开户后下载证书业务流程

1.1.9 - 优化部分代码 - SDK内部增加DNS解析

1.1.8 - 优化内部代码 - 修改新增运行时权限提示与授权流程 - 精简相关依赖

1.1.7 - 根据支付渠道可用短信验证码支付 - 修复一些问题

1.1.6 - 增加我的付款码功能

1.1.5 - 简化接入流程 - 优化内部代码

1.1.4 - 优化网络请求相关功能

1.1.3 - 修复活体认证的相关BUG

1.1.2 - 上传证件可从相册中选取

1.1.1 - 增加用户上传身份证功能 - 将活体认证 common-silent 集成至SDK中

1.1.0 - 新增银行卡ocr - 新增修改标题栏文字颜色,按钮文字颜色 - 优化用户体验 - 修复部分兼容性问题

1.0.7.1 - 增值信用卡信息采集

1.0.7 - 增加刷脸支付

1.0.6 - 增加刷脸支付与密码确认功能 - 增加微包服务号支付唤起功能 - 增值服务功能拆分 - 增加银联侧无跳转

1.0.5 - sdk部分功能优化 - 增加增加增值服务功能

1.0.4 - 增加订单支付功能

1.0.3 - SDK唤醒时间优化2期 - 静默活体跟换UI样式 - 增加安全键盘功能:为了安全起见防止截屏录屏功能,返回取消通知 - 增加删除证书功能 - 增加顺序数字键盘从1开始

1.0.2 - SDK唤醒时间优化1期 - 转账、发红包支持配置是否仅使用余额支付

1.0.1 - 支付键盘是否乱序可配置

1.0.0 - 微包SDK正式发布