簡言:
公司一直在做使用pos設備有關的項目,選用的是商米的商戶,設備主要實現功能就是刷卡功能與打印小票功能,商家提供了一個簡單的demo,剛開始就讓人蒙圈, 查閱百度,各種博客,發現關於商米設備的很少,所以只能硬着頭皮,看開發文檔,一步一步實現了。
1.設備
我現在主要針對的設備是P1 4G的設備,既能刷卡功能,又有小票打印功能,v1設備只支持打印小票,
2 .對於商米功能的簡介
SunmiPaySDK 是 Sunmi 基於固件封裝的貼近 java 開發者的一套調用硬件的接口,開發中通過該 SDK 可以快速調用
Sunmi 金融機具相應的固件接口,實現自己相關業務邏輯的開發。SDK 主要包含:設備信息基礎模塊,卡操作模塊,密碼鍵
盤模塊,EMV 模塊,安全模塊。
3.如何集成商米(重點來嘍)
1. 查看自己的設備機型, 我的是P1-4G,
2. 點開設置—>應用—>右上角—>點擊選擇顯示系統應用
P1N 或 P1-4G 機具上已安裝 SunmiPayHardwareService 版本 3.1.2 或者更高版本
確保 P1N 或 P1-4G 機具已安裝 SunmiPaySDKService 版本 1.0.6 或者更高版本
3. android studio 如何集成
1) 在app目錄下添加這個aar 包(商米給的demo中有)
在app的build.gradle中
2)在商米提供的demo中,
3) 創建一個application 來實現商米的初始化
application的實現
public static int pikIndex = 14; /** * 獲取讀卡模塊 */ public static ReadCardOpt mReadCardOpt; /** * RSA公私鑰操作模塊 */ public static SecurityOpt mSecurityOpt; public static final String TAG = "MyApplication"; private SunmiPayKernel mSunmiPayKernel; @Override public void onCreate() { super.onCreate(); mApplicationContext = getApplicationContext(); LogManager.isDebug = true; NetworkHelper.initOkHttp(); conn(); AidlUtil.getInstance().connectPrinterService(this); } /** * 連接支付SDK */ private void conn() { mSunmiPayKernel = SunmiPayKernel.getInstance(); mSunmiPayKernel.connectPayService(mConnCallback,getApplicationContext()); } /** * 連接狀態回調 */ private SunmiPayKernel.ConnectCallback mConnCallback = new SunmiPayKernel.ConnectCallback() { @Override public void onServiceConnected() { Log.e("wl","連接成功"); try { mReadCardOpt = mSunmiPayKernel.mReadCardOpt; mSecurityOpt = mSunmiPayKernel.mSecurityOpt; //存儲KEK,TMK,PIK,MAK,TDK,各種默認的密鑰 initSecretKey(); } catch (Exception e) { e.printStackTrace(); } } @Override public void onServiceDisconnected() { Log.e("wl","鏈接失敗"); } @Override public void illegal() { Log.e("wl","非法調用"); } }; /** * 存儲KEK,TMK,PIK,MAK,TDK,各種默認的密鑰 * * @throws RemoteException */ public static void initSecretKey() throws RemoteException { byte[] kekByte = Utils.hexStr2Bytes("11111111111111111111111111111111"); byte[] tmkByte = Utils.hexStr2Bytes("F40379AB9E0EC533F40379AB9E0EC533"); byte[] checkValueByte = Utils.hexStr2Bytes("82E13665B4624DF5"); /** * CheckValue的計算過程: KEK(明文) TMK(密文) workKey(密文) KEK解密TMK(密文)得到TMK(明文) 用TMK(明文)解密workKey(密文)得到workKey(明文) 用workKey(明文)加密16個0 取前8位是CheckValue */ //測試時請將主密鑰和工作密鑰存入以下索引 try { int rec = mSecurityOpt.saveKey(AidlConstants.Security.KEY_TYPE_KEK, kekByte, checkValueByte, 1, AidlConstants.Security.KEY_ALG_TYPE_3DES, 10, false); int rec1 = mSecurityOpt.saveKey(AidlConstants.Security.KEY_TYPE_TMK, tmkByte, checkValueByte, 10, AidlConstants.Security.KEY_ALG_TYPE_3DES, 11, true); int rec2 = mSecurityOpt.saveKey(AidlConstants.Security.KEY_TYPE_TDK, tmkByte, checkValueByte, 11, AidlConstants.Security.KEY_ALG_TYPE_3DES, 12, true); int rec3 = mSecurityOpt.saveKey(AidlConstants.Security.KEY_TYPE_MAK, tmkByte, checkValueByte, 11, AidlConstants.Security.KEY_ALG_TYPE_3DES, 13, true); int rec4 = mSecurityOpt.saveKey(AidlConstants.Security.KEY_TYPE_PIK, tmkByte, checkValueByte, 11, AidlConstants.Security.KEY_ALG_TYPE_3DES, pikIndex, true); LogManager.e("secutirysaveKey", rec + ":" + rec1 + ":" + rec2 + ":" + rec3 + ":" + rec4); } catch (RemoteException e) { e.printStackTrace(); } } //獲取全局的上下文 public static Context getGlobalAppLication(){ return mApplicationContext; }
4) 調取刷卡 打印等功能;
/** * 實現刷卡用能 */ private void shuaCard() { cardType = AidlConstants.CardType.MIFARE.getValue(); try { readCardOpt.checkCard(cardType, readCardCallback, 60); } catch (RemoteException e) { e.printStackTrace(); Toast.show(ScanActivity.this, "檢卡失敗,重新刷卡!"); finish(); } } /** * 檢卡回調 */ private ReadCardCallback readCardCallback = new ReadCardCallback.Stub() { @Override public void onCardDetected(CardInfo cardInfo) throws RemoteException { Message message = new Message(); message.what = 0x01; message.obj = cardInfo; mHandler.sendMessage(message); } @Override public void onError(int i, String s) throws RemoteException { Message message = new Message(); message.what = 0x02; message.obj = "code:" + i + " message:" + s; mHandler.sendMessage(message); } @Override public void onStartCheckCard() throws RemoteException { LogManager.e(TAG, "onStartCheckCard:正在檢卡"); } }; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 0x01: CardInfo cardInfo = (CardInfo) msg.obj; String uuid = cardInfo.uuid; (獲取參數成功) break; case 0x02: Toast.show(ScanActivity.this, "檢卡失敗請重新檢卡!"); finish(); break; } } };
5) 商米的打印功能
String content = "消費憑證(" + title + ")\n" + "***********歡迎光臨***********\n\n"
+ "訂單金額:" + orderAmountDou + "\n"
+ "優惠金額:" + s + "\n"
+ "實付金額:" + shiAmount + "\n"
+ "支付方式:" + payTypeStr + "\n"
+ "油品:" + oilNum + "#\n"
+ "------------------------------\n"
+ "門店名稱:" + storeName + "\n"
+ "訂單號:" + orderNumber + "\n"
+ "" + time + "\n\n";
AidlUtil.getInstance().printText(content, 24, true, false);
到這裏一套完整的商米集成刷卡功能就實現了;