简言:
公司一直在做使用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);
到这里一套完整的商米集成刷卡功能就实现了;