如果是公司的产品,那么也就不存在问题了,Ping++对所有支付做了一个集成。如果开发者个人想接入支付系统,这个申请过程几乎是不大可能的。而Bmob为广大开发人员提供的统一、正规的收费手段,让没有企业认证的个人开发者,也能通过支付宝和微信向用户收费。但是有一个缺点,支持的渠道少,只支持支付宝和微信。此外,微信支付还要安装一个插件,用户体验及其不好。
官方的文档在这里Android支付SDK
接入Bomb也很简单,首先下载BmobPay_Sdk_V1.0.2a.zip
将Lib中的四个jar文件拷到项目中的libs目录下,将plugin目录中的assets拷到项目的main目录下。如图
![/ Android 个人开发者接入支付功能](http://www.mobile-open.com/wp-content/uploads/2015/09/2015092908394937.png)
声明权限<"http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;">
由于微信支付需要安装它的插件,所以如果在root的设备上我们希望能够静默安装,否则使用正常的安装方式,静默安装需要一个权限。
在AndroidManifest.xml的Application标签下添加以下内容,声明组件
1 | <span style= "font-size: medium;" ><code class = "hljs" > <!-- bmob pay sdk activity begin ,please put below code into application tag --> |
3 | <!-- bmob pay sdk activity end --></code></span> |
在您的应用程序主Activity的onCreate中调用如下方法:(Application ID在后台应用管理的 数据浏览->应用信息->应用密钥->Application ID)
1 | <span style= "font-size: medium;" ><code class = "hljs" > private BmobPay bmobPay = null ; |
2 | BmobPay.init(context,你的Application ID); |
3 | bmobPay = new BmobPay(MainActivity. this );</code></span> |
调用支付宝支付
1 | <span style= "font-size: medium;" ><code class = "hljs" >bmobPay.pay( 0.01 , 某商品,这里是商品描述, new PayListener() { |
3 | public void orderId(String s) { |
5 | Toast.makeText(MainActivity. this , 订单号: + s, Toast.LENGTH_SHORT).show(); |
9 | public void succeed() { |
10 | Toast.makeText(MainActivity. this , 支付成功, Toast.LENGTH_SHORT).show(); |
14 | public void fail( int i, String s) { |
15 | Toast.makeText(MainActivity. this , 支付失败: + s, Toast.LENGTH_SHORT).show(); |
19 | public void unknow() { |
20 | Toast.makeText(MainActivity. this , 未知, Toast.LENGTH_SHORT).show(); |
调用微信支付,微信支付需要安装插件,我们首先尝试进行静默安装,如果返回异常,则进行正常安装。我们需要编写一个工具类
1 | <span style= "font-size: medium;" ><code class = "hljs" > public class PackageUtils { |
3 | public static String moveFileFromAssetsToSdcard(Context context, String fileName) { |
4 | return moveFileFromAssetsToSdcard(context,fileName,fileName); |
6 | public static String moveFileFromAssetsToSdcard(Context context, String fileName, String tempName) { |
8 | FileOutputStream fos = null ; |
10 | is = context.getAssets().open(fileName); |
11 | File file = new File(Environment.getExternalStorageDirectory() |
12 | .getPath() + / + tempName); |
14 | fos = new FileOutputStream(file); |
15 | byte [] temp = new byte [ 1024 ]; |
17 | while ((i = is.read(temp)) > 0 ) { |
18 | fos.write(temp, 0 , i); |
20 | return file.getAbsolutePath(); |
21 | } catch (IOException e) { |
27 | } catch (IOException e) { |
34 | } catch (IOException e) { |
46 | * @return 0 means normal, 1 means file not exist, 2 means other exception error |
48 | public static int installSlient(Context context, String filePath) { |
49 | File file = new File(filePath); |
50 | if (filePath == null || filePath.length() == 0 || (file = new File(filePath)) == null || file.length() <= 0 |
51 | || !file.exists() || !file.isFile()) { |
55 | String[] args = {pm, install, -r, filePath}; |
56 | ProcessBuilder processBuilder = new ProcessBuilder(args); |
58 | Process process = null ; |
59 | BufferedReader successResult = null ; |
60 | BufferedReader errorResult = null ; |
61 | StringBuilder successMsg = new StringBuilder(); |
62 | StringBuilder errorMsg = new StringBuilder(); |
65 | process = processBuilder.start(); |
66 | successResult = new BufferedReader( new InputStreamReader(process.getInputStream())); |
67 | errorResult = new BufferedReader( new InputStreamReader(process.getErrorStream())); |
69 | while ((s = successResult.readLine()) != null ) { |
72 | while ((s = errorResult.readLine()) != null ) { |
75 | } catch (IOException e) { |
78 | } catch (Exception e) { |
83 | if (successResult != null ) { |
84 | successResult.close(); |
86 | if (errorResult != null ) { |
89 | } catch (IOException e) { |
92 | if (process != null ) { |
96 | if (successMsg.toString().contains(Success) || successMsg.toString().contains(success)) { |
101 | Log.e(installSlient, successMsg: + successMsg + , ErrorMsg: + errorMsg); |
105 | public static void installNormal(Context context, String fileName) { |
106 | File file = new File(fileName); |
107 | Intent intent = new Intent(Intent.ACTION_VIEW); |
108 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
109 | intent.setDataAndType(Uri.parse(file: |
110 | application/vnd.android. package -archive); |
111 | context.startActivity(intent); |
需要将assets目录下的插件拷到文件系统中,然后调用静默安装方法,如果返回0,则安装成功,否则调用正常安装方法。我们可以在微信支付的回调函数中判断是否安装过插件。
1 | <span style= "font-size: medium;" ><code class = "hljs" >bmobPay.payByWX( 0.01 , 某商品,这里是商品描述, new PayListener() { |
3 | public void orderId(String s) { |
5 | Toast.makeText(MainActivity. this , 订单号: + s, Toast.LENGTH_SHORT).show(); |
9 | public void succeed() { |
10 | Toast.makeText(MainActivity. this , 支付成功, Toast.LENGTH_SHORT).show(); |
14 | public void fail( int i, String s) { |
16 | Toast.makeText(MainActivity. this , 未安装支付插件,正在准备安装 + s, Toast.LENGTH_SHORT).show(); |
17 | String tempFile = PackageUtils.moveFileFromAssetsToSdcard(MainActivity. this , BmobPayPlugin.apk); |
18 | Log.e(TAG, installFile: + tempFile); |
19 | int installResult = PackageUtils.installSlient(MainActivity. this ,tempFile); |
20 | Log.e(TAG, installResult: + installResult); |
22 | PackageUtils.installNormal(MainActivity. this ,tempFile); |
24 | Toast.makeText(MainActivity. this , 插件安装成功! + s, Toast.LENGTH_SHORT).show(); |
27 | Toast.makeText(MainActivity. this , 支付失败: + s, Toast.LENGTH_SHORT).show(); |
31 | public void unknow() { |
32 | Toast.makeText(MainActivity. this , 未知, Toast.LENGTH_SHORT).show(); |
支付过程中会生成一个订单,该订单开发者需要自己进行存储,可以用该订单号进行查询支付状态
1 | <span style= "font-size: medium;" ><code class = "hljs" >bmobPay.query(orderId, new OrderQueryListener() { |
3 | public void succeed(String s) { |
4 | Toast.makeText(MainActivity. this , 查询结果: + s, Toast.LENGTH_SHORT).show(); |
8 | public void fail( int i, String s) { |
9 | Toast.makeText(MainActivity. this , 查询失败: + s, Toast.LENGTH_SHORT).show(); |
succeed回调说明查询成功(并不是说支付成功),返回的status有NOTPAY和SUCCESS两种可能,只有返回SUCCESS才说明支付成功。
支付过程中可能会返回错误码,常见的错误码如下
![/ Android 个人开发者接入支付功能](http://www.mobile-open.com/wp-content/uploads/2015/09/2015092908395139.png)
还有一点需要注意的就是
当上一次支付操作尚未完成时,如果BmobPay对象发起再次请求,PayListener会回调fail方法返回并10077错误码,以免生成多个订单
如果使用过程中出现了阻塞(比如异常强制关闭支付插件页面,会导致一直不能再发起请求,这是小概率事件),则调用此方法进行BmobPay的重置
仅对下一次请求生效,而不是永久消除限制。
如果你想查询订单的详细信息,可以使用GET请求,使用Bomb的Restful API发起查询,返回结果是一个json字符串,详细内容如下
效果图
![/ Android 个人开发者接入支付功能](http://www.mobile-open.com/wp-content/uploads/2015/09/2015092908395241.jpg)
![/ Android 个人开发者接入支付功能](http://www.mobile-open.com/wp-content/uploads/2015/09/2015092908395444.jpg)
![/ Android 个人开发者接入支付功能](http://www.mobile-open.com/wp-content/uploads/2015/09/2015092908395546.jpg)
后台订单查询
![Android 个人开发者接入支付功能](http://www.mobile-open.com/wp-content/uploads/2015/09/2015092908395748.png)