智能POS機項目原理分析

開發本質

智能POS機本質上就是一個Android手機,我們要開發的支付軟件從本質上也是一個普通的app,只不過這個Android手機是根據指定商家進行配置的,所以我們開發的app也只能給特定POS機使用,POS機廠家通過審覈商家材料定製出商家POS機,商家就可以在POS機的應用商店下載並使用商家自己的app進行支付收銀操作。

商家現在的操作場景是在PC系統收銀調起POS機app,這就是在雲端使用消息推送把支付相關信息推送給POS機,POS機後臺服務接收到支付信息後,調起app並顯示相關信息,確認後進行支付,支付行爲完成後,根據支付結果進行響應並傳給PC系統

易通POS星POS

開發方式

支付功能開發的過程大部分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的博客

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章