一、云端配置
1、实名认证
用户需要在Bmob我的控制台中进行实名认证。并创建自己的应用。同时获取自己的ApplicationId。
(Application ID在后台应用管理的 数据浏览->应用信息->应用密钥->Application ID)
2.下载支付的SDK
官网下载对应的支付SDK。
二、项目配置
1.AndroidManifest.xml配置
添加权限
添加下免责Activity(注意这个是在运行时加载的类,可以忽略IDE给出的红色标识)
2.SDK文件添加
将下载的支付SDK的libs目录添加到项目下,包括和,
so文件按项目需求添加(这个版本不需要支付宝jar包)
将下载的支付SDK的assets目录添加到项目下,包括和,其中bp.db其实是apk文件,是微信支付插件
3.修改混淆规则
在proguard-rules.pro 文件中红添加
-libraryjars libs/BmobPay_v3.x.x_xxxxxx.jar -keepclasseswithmembers class c.b.** { *; } -keep interface c.b.PListener{ *; } -keep interface c.b.QListener{ *; }
4.build.gradle添加
在app中的build.gradle中的android节点下添加:
sourceSets { main { jniLibs.srcDirs = ['libs']//将so文件目录指向libs目录 } }
引用外部so文件:
将so文件放在app/libs目录下。修改build.gradle文件,增加sourceSets将jniLibs重定向到libs目录。
(或者也可以只需在app/src/main目录下创建jniLibs目录,然后将so文件按平台存放于对应子目录下即可)
三、支付实现过程
1、初始化BmobPay对象。
可以在支付时再初始化。
BP.init(APPID);
2、自选择支付方式
根据用户的选择判断是支付宝支付还是微信支付。在支付时传入不同的值。
/**
* 第4个参数为true时调用支付宝支付,为false 时调用微信支付
*/
BP.pay("商品名称", "商品描述", 0.02, true, new Plistener(){...});
3.支付前检测。
在调用支付之前,一般需要做检查,在选择使用支付宝支付时检测用户手机是否安装支付宝,
在使用微信支付时检测用户手机是否安装微信,同时还需要检测用户是否安装微信支付插件
(此处在7.0的系统需要对官方给出的demo进行修改,因为从Android7.0开始,一个
应用提供自身文件给其它应用使用时,如果给出一个file://格式的URI的话,
应用会抛出FileUriExposedException。这是由于谷歌认为目标app可能不具有文件权限,需要解决,
检测支付宝是否安装逻辑
if (!checkPackageInstalled("com.eg.android.AlipayGphone", "https://www.alipay.com")) { // 支付宝支付要求用户已经安装支付宝客户端 Toast.makeText(PayActivity.this, "请安装支付宝客户端", Toast.LENGTH_SHORT) .show(); return; }
检测微信及微信支付插件
if (checkPackageInstalled("com.tencent.mm", "http://weixin.qq.com")) {// 需要用微信支付时,要安装微信客户端,然后需要插件 // 有微信客户端,看看有无微信支付插件 int pluginVersion = BP.getPluginVersion(this); if (pluginVersion < PLUGINVERSION) {// 为0说明未安装支付插件, // 否则就是支付插件的版本低于官方最新版 Toast.makeText( PayActivity.this, pluginVersion == 0 ? "监测到本机尚未安装支付插件,无法进行支付,请先安装插件(无流量消耗)" : "监测到本机的支付插件不是最新版,最好进行更新,请先更新插件(无流量消耗)", Toast.LENGTH_SHORT).show(); // installBmobPayPlugin("bp.db"); installApk("bp.db"); return; }
4.支付流程及回调方法
showDialog("正在获取订单...\nSDK版本号:" + BP.getPaySdkVersion()); //final String name = getName(); final String name = mGoodsName; try { Intent intent = new Intent("android.intent.action.PAY"); //自行修改 intent.addCategory("android.intent.category.PAY"); //自行修改 ComponentName cn = new ComponentName("com.bmob.app.sport", "com.bmob.app.sport.wxapi.BmobActivity"); intent.setComponent(cn); this.startActivity(intent); } catch (Throwable e) { e.printStackTrace(); } BP.pay(name, mGoodsDescription, mPayMoney, whichPay, new PListener() { // 因为网络等原因,支付结果未知(小概率事件),出于保险起见稍后手动查询 @Override public void unknow() { Toast.makeText(PayActivity.this, "支付结果未知,请稍后手动查询", Toast.LENGTH_SHORT) .show(); tv.append(name + "'s pay status is unknow\n\n"); hideDialog(); } // 支付成功,如果金额较大请手动查询确认 @Override public void succeed() { Toast.makeText(PayActivity.this, "支付成功!", Toast.LENGTH_SHORT).show(); tv.append(name + "'s pay status is success\n\n"); hideDialog(); } // 无论成功与否,返回订单号 @Override public void orderId(String orderId) { // 此处应该保存订单号,比如保存进数据库等,以便以后查询 order.setText(orderId); tv.append(name + "'s orderid is " + orderId + "\n\n"); showDialog("获取订单成功!请等待跳转到支付页面~"); } // 支付失败,原因可能是用户中断支付操作,也可能是网络原因 @Override public void fail(int code, String reason) { // 当code为-2,意味着用户中断了操作 // code为-3意味着没有安装BmobPlugin插件 if (code == -3) { Toast.makeText( PayActivity.this, "监测到你尚未安装支付插件,无法进行支付,请先安装插件(已打包在本地,无流量消耗),安装结束后重新支付", Toast.LENGTH_SHORT).show(); // installBmobPayPlugin("bp.db"); installApk("bp.db"); } else { Toast.makeText(PayActivity.this, "支付中断!", Toast.LENGTH_SHORT) .show(); } tv.append(name + "'s pay status is fail, error code is \n" + code + " ,reason is " + reason + "\n\n"); hideDialog(); } });
5、查询订单及回调方法
showDialog("正在查询订单..."); final String orderId = getOrder(); BP.query(orderId, new QListener() { @Override public void succeed(String status) { Toast.makeText(PayActivity.this, "查询成功!该订单状态为 : " + status, Toast.LENGTH_SHORT).show(); tv.append("pay status of" + orderId + " is " + status + "\n\n"); hideDialog(); } @Override public void fail(int code, String reason) { Toast.makeText(PayActivity.this, "查询失败", Toast.LENGTH_SHORT).show(); tv.append("query order fail, error code is " + code + " ,reason is \n" + reason + "\n\n"); hideDialog(); } });
四、检测及安装插件的辅助功能程序
1、检查是否安装微信及支付宝
/** * 检查某包名应用是否已经安装 * * @param packageName 包名 * @param browserUrl 如果没有应用市场,去官网下载 * @return */ private boolean checkPackageInstalled(String packageName, String browserUrl) { try { // 检查是否有支付宝客户端 getPackageManager().getPackageInfo(packageName, 0); return true; } catch (PackageManager.NameNotFoundException e) { // 没有安装支付宝,跳转到应用市场 try { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("market://details?id=" + packageName)); startActivity(intent); } catch (Exception ee) {// 连应用市场都没有,用浏览器去支付宝官网下载 try { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(browserUrl)); startActivity(intent); } catch (Exception eee) { Toast.makeText(PayActivity.this, "您的手机上没有没有应用市场也没有浏览器,我也是醉了,你去想办法安装支付宝/微信吧", Toast.LENGTH_SHORT).show(); } } } return false; }
2.安装Apk插件
/** * 在6.0之后的应用不能隐式开启一个安装应用的界面,需要做修改。。。 * @param s 安装插件apk的名字,bp.db */ private void installApk(String s) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { //申请权限 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUESTPERMISSION); } else { installBmobPayPlugin(s); } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUESTPERMISSION) { if (permissions[0].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { installBmobPayPlugin("bp.db"); } else { //提示没有权限,安装不了 Toast.makeText(PayActivity.this,"您拒绝了权限,这样无法安装支付插件",Toast.LENGTH_LONG).show(); } } } } /** * 安装assets里的apk文件 * * @param fileName */ void installBmobPayPlugin(String fileName) { try { InputStream is = getAssets().open(fileName); File file = new File(Environment.getExternalStorageDirectory() + File.separator + fileName + ".apk"); if (file.exists()) file.delete(); file.createNewFile(); FileOutputStream fos = new FileOutputStream(file); byte[] temp = new byte[1024]; int i = 0; while ((i = is.read(temp)) > 0) { fos.write(temp, 0, i); } fos.close(); is.close(); Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //Intent intent = new Intent("android.intent.action.VIEW"); //intent.addCategory("android.intent.category.DEFAULT"); intent.setDataAndType(Uri.parse("file://" + file), "application/vnd.android.package-archive"); startActivity(intent); } catch (Exception e) { e.printStackTrace(); } }
文章程序参看Bmob官方给出的demo示例,可满足基本的支付需求。