源码地址:https://github.com/851151582/BmobPay.git
一、云端配置
1、实名认证
用户需要在Bmob我的控制台中进行实名认证。并创建自己的应用。同时获取自己的ApplicationId。
(Application ID在后台应用管理的 数据浏览->应用信息->应用密钥->Application ID)
2.下载支付的SDK
官网下载对应的支付SDK。
二、项目配置
1.AndroidManifest.xml配置
添加权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
添加下免责Activity(注意这个是在运行时加载的类,可以忽略IDE给出的红色标识)
<activity android:name="cn.bmob.pay.v3.act.PayAct" />
2.SDK文件添加
将下载的支付SDK的libs目录添加到项目下,包括<BmobPay_v3.x.x_xxxxxx.jar>和<xxx/libbmobwpay.so>,
so文件按项目需求添加(这个版本不需要支付宝jar包)
将下载的支付SDK的assets目录添加到项目下,包括<payassets.db>和<bp.db>,其中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进行修改,因为从Android 7.0开始,一个
应用提供自身文件给其它应用使用时,如果给出一个file://格式的URI的话,
应用会抛出FileUriExposedException。这是由于谷歌认为目标app可能不具有文件权限,需要解决,
解决方案可参看:http://blog.csdn.net/xiaoyu940601/article/details/55509907)。
检测支付宝是否安装逻辑
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示例,可满足基本的支付需求。