開發本質
智能POS機本質上就是一個Android手機,我們要開發的支付軟件從本質上也是一個普通的app,只不過這個Android手機是根據指定商家進行配置的,所以我們開發的app也只能給特定POS機使用,POS機廠家通過審覈商家材料定製出商家POS機,商家就可以在POS機的應用商店下載並使用商家自己的app進行支付收銀操作。
商家現在的操作場景是在PC系統收銀調起POS機app,這就是在雲端使用消息推送把支付相關信息推送給POS機,POS機後臺服務接收到支付信息後,調起app並顯示相關信息,確認後進行支付,支付行爲完成後,根據支付結果進行響應並傳給PC系統
開發方式
支付功能開發的過程大部分POS機只有兩種:
1.集成支付相關的接口
這種方式就是我們自己做一個收銀app,集成了POS機廠商的SDK,這種方式我們要做收銀,查詢訂單,撤銷訂單這些收銀app都有的功能,同時在搭建項目的時候也要引入二維碼掃描與生成庫等第三方庫。這種方式過於費時費力。
2.調用POS機自帶的收銀app
POS機上自帶廠家或者代理商的收銀APP,通常這個app是允許其他應用調用的。開發的app在需要收銀時通過Intent調用收銀APP的收銀Activity,並傳入相關的支付參數,待支付成功或失敗後會攜帶相關參數返回給我們的app,我們再返回給系統後臺進行數據保存。我們現在用的就是這種方式
綁定POS機
首先app可能安裝在多個POS機上,那在PC系統上開單或者充值時,如何確定讓哪一個POS機來進行支付行爲。這就需要在POS機安裝app後進行綁定POS機,當然也會存在解綁後再重新綁定的情況,所以需要在app的啓動頁把POS機相關信息傳給後臺,讓後臺可以綁定這個POS機給系統店鋪。
POS機相關信息就包括SN碼與友盟的token
獲取POS機sn碼 (Serial Number 產品序列號)
SN碼是POS機的唯一標識,起碼同一個廠家裏SN碼是不同的,可以直接在設備背面看到。
不同的POS機廠商有不同的SN碼配置,代碼獲取的話,有的直接獲取Android SN碼就可以,有的卻需要通過廠商Jar文件調用相關服務獲取
1.設備sn碼直接獲取 (易通的聯迪POS)
Aandroid設備系統信息裏就有SN碼,可以通過android.os.Build.SERIAL來獲取sn碼
2.廠商自定義設備SN碼 (新大陸星POS)
通過Build.SERIAL獲取的sn碼與設備背面明顯不一致,所以推測通過相關廠商接口調用才能得到。
新大陸星POS是引入廠商jar文件,調用相關接口得到
原理是通過綁定系統服務,使用AIDL得到相關參數,具體代碼和jar必須通過與廠商技術人員協商就行獲取
友盟token碼
在POS機使用中,經常是我們的app未被打開,在系統發送支付信息時也能把消息發送到App,這就是使用了Android中的消息推送。
token是友盟在其推送消息時的唯一標識,它就相當於設備的唯一碼。當然其它推送平臺也會有類似token的唯一碼。
集成好友盟推送SDK後,在打開app時,就會通過調用註冊方法獲取token
POS機接收支付消息
後端與app端都集成了友盟推送SDK,並通過Appkey等參數配置,確保後臺調起的app就是POS機中的app。
原理:app通過集成友盟推送SDK,POS機系統後臺有一個Service服務在與友盟進行通信,後端通過集成的友盟推送SDK推送支付信息到POS機上,POS機的Service服務接收到信息後打開app支付信息頁面,並顯示支付信息
支付功能的實現
在App的支付信息顯示頁面使用startActivityForResult方法能夠跳轉到POS機自帶的收銀APP的指定頁面,該方法可以攜帶支付方式、支付金額等參數調起了收銀app的收銀頁面,收銀頁面根據支付信息進行收銀,支付失敗或者成功都會把結果數據回調給app,在app支付信息顯示頁面的onActivityResult方法中對返回的intent實例的攜帶參數進行分析,得到支付結果數據,並傳給後臺
//設置要跳轉的收銀app的包名與收銀頁面的類名
ComponentName component = new ComponentName("com.landicorp.android.sdectonsale",
"com.landicorp.android.sdectonsale.MainActivity");
Intent intent = new Intent();
intent.setComponent(component);
//支付方式
intent.putExtra("transName", "微信支付");
//支付金額
intent.putExtra("amount", "1");
//自定義訂單號
intent.putExtra("orderInfo", "87533700744");
startActivityForResult(intent, REQUEST_PAY);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_PAY) {
Bundle bundle = data.getExtras();
if (bundle != null) {
switch (resultCode) {
case Activity.RESULT_OK:
/**
* 金額 amount-value-000000000001
* 卡號(銀行卡支付纔會有值,否則爲空) cardNo-value-null
* 終端號 terminalId-value-56066311
* 憑證號 traceNo-value-000015
* 條形碼,商戶訂單號 barcode-value-201901210741837381
* 批次號 batchNo-value-000002
* 商戶編號 merchantId-value-870451073990352
* 參考號 referenceNo-value-210741837381
* 日期 date-value-0121
* 時間 time-value-154251
* 髮卡行(銀行卡支付纔會有值,否則爲空) issue-value-null
* 商戶名 merchantName-value-個體戶XX
*/
Toast.makeText(mContext, "交易成功", Toast.LENGTH_SHORT).show();
break;
case Activity.RESULT_CANCELED:
//用戶取消
//45 請使用芯片
String reason = data.getStringExtra(Constants.BUNDLE_REASON);
LogUtil.e(TAG, "onActivityResult--fail-" + reason);
if (reason != null) {
Toast.makeText(mContext, "交易失敗", Toast.LENGTH_SHORT).show();
}
break;
default:
finish();
break;
}
}
}
super.onActivityResult(requestCode, resultCode, data);
}
App上線
我們做好的app要能讓客戶使用,就要上傳到POS機上的應用商店,而根據設備商代理層次的不同,分爲兩種上線流程
1.開發者通過廠商提供的開發者平臺上線app
我們需要在開發者平臺網站註冊商戶賬號,提供資質證明,審覈通過後提交app,進行審覈,審覈成功後可以在定製POS的應用市場中查詢到app,並下載使用
2.設備商上線app
開發者把app提供給設備商,設備商拿到app後,進行簽名上傳等操作,相當於他們是開發者,我們使用他們的定製應用市場得到我們應用的下載使用權
在我看來,智能POS機只是一個低版本的Android機,有的是高級定製,比如新大陸的POS機,整個系統都是定製過的,各種界面都是新大陸自己在原生基礎上進行改動,刪除的刪除,替換的替換,有的是低級定製,比如易通的迪聯POS機,看上去僅僅像是自己做了一個Launcher,然後只顯示自己要顯示的應用,其他系統設置都是原生界面,有的可以跳轉,有的不給顯示,所以無從跳轉。
本文是從我GitHub上的博客轉過來的,此時再讀修改了部分內容,詳細可見JovenHe的博客