开发本质
智能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码
友盟token码
是友盟在其推送消息时的唯一标识,它就相当于设备的唯一码。当然其它推送平台也会有类似token的唯一码。
集成好友盟推送SDK后,在打开app时,就会通过调用注册方法获取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得到相关参数
bindService(intent,mConnection, Context.BIND_AUTO_CREATE); 绑定系统服务
- 第一个参数是一个明确指定了要绑定的service的Intent.通过给的service的Action字符串得出
- 第二个参数是ServiceConnection对象.
- 第三个参数是一个标志,它表明绑定中的操作.它一般应是BIND_AUTO_CREATE,这样就会在service不存在时创建一个.其它可选的值是BIND_DEBUG_UNBIND和BIND_NOT_FOREGROUND,不想指定时设为0即可.
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//绑定成功
aidlDeviceService = AidlDeviceService.Stub.asInterface(service);
AidlSystem aidlSystem = AidlSystem.Stub.asInterface(aidlDeviceService.getSystemService());
aidlSystem.setAppSwitchKeyEnabled(false);
LogUtil.e(TAG, "getSerialNo: "+aidlSystem.getSerialNo() );
}
@Override
public void onServiceDisconnected(ComponentName name) {
//解除绑定
aidlDeviceService = null;
}
};
POS机接收支付消息
在POS机使用中,经常是我们的app未被打开,在系统发送支付信息时也能把消息发送到App,这就是使用了Android中的消息推送。
后端与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-个体户王长举
*/
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,然后只显示自己要显示的应用,其他系统设置都是原生界面,有的可以跳转,有的不给显示,所以无从跳转。