如果是公司的産品,那麼也就不存在問題了,Ping++對所有支付做了一個內建。如果開發者個人想接入支付系統,這個申請過程幾乎是不大可能的。而Bmob為廣大開發人員提供的統一、正規的收費手段,讓沒有企業認證的個人開發者,也能通過支付寶和微信向使用者收費。但是有一個缺點,支援的管道少,隻支援支付寶和微信。此外,微信支付還要安裝一個插件,使用者體驗及其不好。
官方的文檔在這裡Android支付SDK
接入Bomb也很簡單,首先下載下傳BmobPay_Sdk_V1.0.2a.zip
将Lib中的四個jar檔案拷到項目中的libs目錄下,将plugin目錄中的assets拷到項目的main目錄下。如圖
聲明權限<"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) { |
7 | InputStream is = null ; |
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)) > ) { |
20 | return file.getAbsolutePath(); |
21 | } catch (IOException e) { |
27 | } catch (IOException e) { |
34 | } catch (IOException e) { |
48 | public static int installSlient(Context context, String filePath) { |
49 | File file = new File(filePath); |
50 | if (filePath == null || filePath.length() == || (file = new File(filePath)) == null || file.length() <= |
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: // + 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); |
21 | if (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才說明支付成功。
支付過程中可能會傳回錯誤碼,常見的錯誤碼如下
還有一點需要注意的就是
當上一次支付操作尚未完成時,如果BmobPay對象發起再次請求,PayListener會回調fail方法傳回并10077錯誤碼,以免生成多個訂單
如果使用過程中出現了阻塞(比如異常強制關閉支付插件頁面,會導緻一直不能再發起請求,這是小機率事件),則調用此方法進行BmobPay的重置
僅對下一次請求生效,而不是永久消除限制。
如果你想查詢訂單的詳細資訊,可以使用GET請求,使用Bomb的Restful API發起查詢,傳回結果是一個json字元串,詳細内容如下
效果圖
背景訂單查詢