在接入之前先看下文档支付宝扫脸接入文档,
https://docs.open.alipay.com/20180402104715814204/intro
https://doc.open.alipay.com/docs/doc.htm?docType=1&articleId=108568
这里一定要详细了解官方提供的API,问下支付宝那边的文档是不是最新的,避免一些不必要的坑.
接入
第一步:创建应用(后台)
第二步:配置密钥(后台)
第三步:搭建和配置开发环境(后台)
1.下载服务端SDK(后台)
2.接口调用配置(后台)
第四步:接口调用(前端)
这里就不细说了, API上都有说明,大家看看就明白了
技术接入流程图:
添加项目依赖:
第一个我用来请求数据,第二个我用来解析数据第三个是支付宝api那里的下载
(这里说一下,我项目之前用的是Rxjava,在对应的位置写请求,报线程错误,在子线程也是报这个错,所以就用async来请求,结果是可以)
在MerchantInfo配置自己需要的数据
看需求填写自己的所需数据参数,根据文档需要什么参数就写什么参数
private Map mockInfo() {
Map merchantInfo = new HashMap();
//以下信息请根据真实情况填写
//机具编号,便于关联商家管理的机具
DeviceAPI api = APIManager.getInstance().getDeviceAPI();
String sn = api.getDeviceSn();
merchantInfo.put("deviceNum", sn);//deviceNum 必填项,商户机具终端编号,和当面付请求的terminal_id 保持一致
return merchantInfo;
}
这里自己写的用android-async-http-master.jar请求数据用fastJson-1.1.45.jar解析
然后
//获取zimId和zimInitClientData调用人脸初始化
String zimId = products.get(0).getZimId();
String zimInitClientData = products.get(0).getZimInitClientData();
smile(zimId, zimInitClientData);
Log.e("TAG", "zimid----------------"+zimId);
Log.e("TAG", "zimInitClientData----------------"+zimInitClientData);
/**
* 发起刷脸支付请求.
* @param zimId 刷脸付token,从服务端获取,不要mock传入
* @param protocal 刷脸付协议,从服务端获取,不要mock传入
*/
//. 唤起人脸识别
private void smile(String zimId, String protocal) {
Map params = new HashMap();
params.put(KEY_INIT_RESP_NAME, protocal);
//个询问支付宝那边的.我也不知道干嘛用的
/* start: 如果是预输入手机号方案,请加入以下代码,填入会员绑定的手机号,必须与支付宝帐号对应的手机号一致 */
params.put("phone_number", "1381XXXXX");
/* end: --------------------------------------------- */
zoloz.zolozVerify(zimId, params, new ZolozCallback() {
@Override
public void response(final Map smileToPayResponse) {
if (smileToPayResponse == null) {
return;
}
String code = (String)smileToPayResponse.get("code");
String fToken = (String)smileToPayResponse.get("ftoken");
String subCode = (String)smileToPayResponse.get("subCode");
String msg = (String)smileToPayResponse.get("msg");
//刷脸成功
if (CODE_SUCCESS.equalsIgnoreCase(code) && fToken != null) {
//promptText("刷脸成功,返回ftoken为:" + fToken);
//这里在Main线程,网络等耗时请求请放在异步线程中
//后续这里可以发起支付请求
//https://docs.open.alipay.com/api_1/alipay.trade.pay
//需要修改两个参数
//scene固定为security_code
//auth_code为这里获取到的fToken值
//支付一分钱,支付需要在服务端发起,这里只是模拟
sharedPreference = ISharedPreference.getInstance(getApplication());//获取保存的token
//联网发送信息给服务器(自己的服务器)
String register = "http://test.shanghkj.com/api/merchant/SmTradePay";
//这里是要传送的参数
RequestParams params = new RequestParams();
params.put("token",sharedPreference.getToken());
params.put("remark",dataBinding.generalNote.getText().toString());//备注
params.put("code",fToken);//传ftonen
params.put("total_amount",dataBinding.generalCount.getText().toString());//金额
params.put("desc","描述");
client.post(register, params, new AsyncHttpResponseHandler(){
@Override
public void onSuccess(String content) {
Log.e("TAG", "content---第二步的成功-------------"+content);
}
@Override
public void onFailure(Throwable error, String content) {
Log.e("TAG", "content-------第二步的失败---------"+content);
}
});
}
}
});
}
然后就对接到第三步了就完成简单的支付了
因为涉及敏感字段
第四步,第五步,建议在服务端实现
public class GeneralActivity extends BaseActivity implements View.OnClickListener {
//使用AsyncHttpClient,实现联网的声明
public AsyncHttpClient client = new AsyncHttpClient();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//扫脸用的,要是不行就放在首页开始初始化
zoloz = com.alipay.zoloz.smile2pay.service.Zoloz.getInstance(getApplicationContext());
dataBinding.collectionSearch.setOnClickListener(this);
dataBinding.sweep.setOnClickListener(this);
dataBinding.sweepReceive.setOnClickListener(this);
dataBinding.bankCardReceive.setOnClickListener(this);
dataBinding.fristDepositList.setOnClickListener(this);//押金收款
dataBinding.generalCount.setFilters(new InputFilter[]{new AmountFilter()});
showKeyBoard(dataBinding.generalCount);
if (SystemUtil.getSystemModel().contains("P1")) {
dataBinding.bankCardReceive.setVisibility(View.VISIBLE);
} else {
dataBinding.bankCardReceive.setVisibility(View.GONE);
}
@Override
public void onClick(View v) {
Intent intent;
switch (v.getId()) {
case R.id.frist_deposit_list:
// intent = new Intent(GeneralActivity.this, DepositActivity.class);
// startActivity(intent);
// finish();
Log.e("TAG", "去往扫脸收银");
if (TextUtils.isEmpty(dataBinding.generalCount.getText().toString())) {
Snackbar.make(v, "请输入收款金额!", Snackbar.LENGTH_SHORT).show();
return;
}
smilePay();
break;
//收款列表
case R.id.collection_list:
intent = new Intent(GeneralActivity.this, GatherListActivity.class);
startActivity(intent);
break;
//普通收款查询
case R.id.collection_search:
intent = new Intent(GeneralActivity.this, SearchGaActivity.class);
startActivity(intent);
break;
}
/*----------------------------扫脸--------------------------------我是分割线--------------以下------------------扫脸---------------------------------------------------*/
/**
* 发起刷脸支付请求,先zolozGetMetaInfo获取本地app信息,然后调用服务端获取刷脸付协议.
*/
// 值为"1000"调用成功
// 值为"1003"用户选择退出
// 值为"1004"超时
// 值为"1005"用户选用其他支付方式
static final String CODE_SUCCESS = "1000";
static final String CODE_EXIT = "1003";
static final String CODE_TIMEOUT = "1004";
static final String CODE_OTHER_PAY = "1005";
static final String TXT_EXIT = "已退出刷脸支付";
static final String TXT_TIMEOUT = "操作超时";
static final String TXT_OTHER_PAY = "已退出刷脸支付";
static final String TXT_OTHER = "抱歉未支付成功,请重新支付";
//刷脸支付相关
static final String SMILEPAY_CODE_SUCCESS = "10000";
static final String SMILEPAY_SUBCODE_LIMIT = "ACQ.PRODUCT_AMOUNT_LIMIT_ERROR";
static final String SMILEPAY_SUBCODE_BALANCE_NOT_ENOUGH = "ACQ.BUYER_BALANCE_NOT_ENOUGH";
static final String SMILEPAY_SUBCODE_BANKCARD_BALANCE_NOT_ENOUGH = "ACQ.BUYER_BANKCARD_BALANCE_NOT_ENOUGH";
static final String SMILEPAY_TXT_LIMIT = "刷脸支付超出限额,请选用其他支付方式";
static final String SMILEPAY_TXT_EBALANCE_NOT_ENOUGH = "账户余额不足,支付失败";
static final String SMILEPAY_TXT_BANKCARD_BALANCE_NOT_ENOUGH = "账户余额不足,支付失败";
static final String SMILEPAY_TXT_FAIL = "抱歉未支付成功,请重新支付";
static final String SMILEPAY_TXT_SUCCESS = "刷脸支付成功";
private Zoloz zoloz;
private ISharedPreference sharedPreference;
private List products;
private void smilePay() {
zoloz.zolozGetMetaInfo(mockInfo(), new ZolozCallback() {
// 解析zolozGetMetaInfo返回的结果,如果成功,则请求商户服务端调用人脸初始化接口
@Override
public void response(Map smileToPayResponse) {
if (smileToPayResponse == null) {
Log.e("TAG", "response is null");
// promptText("5----------"+TXT_OTHER);
return;
}
String code = (String)smileToPayResponse.get("code");
String metaInfo = (String)smileToPayResponse.get("metainfo");
Log.e("TAG", "code----------------"+code);//1000值为"1000"调用成功
Log.e("TAG", "metaInfo----------------"+metaInfo);
//获取metainfo成功
if (CODE_SUCCESS.equalsIgnoreCase(code) && metaInfo != null) {
// 2. 刷脸初始化
//这里用Rxjava 联网请求报线程错误
//然后找了两个个jar包android-async-http-master.jar和fastJson-1.1.45.jar
//android-async-http-master.jar请求数据用fastJson-1.1.45.jar解析
Log.e("TAG", "-------获取metainfo成功并开始初始化人脸----"+metaInfo);
sharedPreference = ISharedPreference.getInstance(getApplication());//获取保存的token
//联网发送信息给服务器(自己的服务器)
String register = "http://test.shanghkj.com/api/merchant/smilepayInit";
//这里是要传送的参数
RequestParams params = new RequestParams();
params.put("token",sharedPreference.getToken());
params.put("all",metaInfo);
//开始联网请求
client.post(register,params ,new AsyncHttpResponseHandler(){
//成功
@Override
public void onSuccess(String content) {
Log.e("TAG", "woyao chenggh 安居客符号化---------"+content);
//这里去解析数据content
JSONObject jsonObject = JSON.parseObject(content);
String proInfo = jsonObject.getString("data");
products = JSON.parseArray(proInfo, FacePayBean.DataBean.class);
//获取zimId和zimInitClientData调用人脸初始化
String zimId = products.get(0).getZimId();
String zimInitClientData = products.get(0).getZimInitClientData();
smile(zimId, zimInitClientData);//唤起人脸识别
UIUtils.getHandler().postDelayed(new Runnable() {
@Override
public void run() {
// removeCurrentActivity();//销毁当前的activity
}
},2000);
}
@Override
public void onFailure(Throwable error, String content) {
Toast.makeText(GeneralActivity.this, "网络异常,调用失败!", Toast.LENGTH_SHORT).show();
}
} );
}
}
});
}
public static final String KEY_INIT_RESP_NAME = "zim.init.resp";
/**
* 发起刷脸支付请求.
* @param zimId 刷脸付token,从服务端获取,不要mock传入
* @param protocal 刷脸付协议,从服务端获取,不要mock传入
*/
//. 唤起人脸识别
private void smile(String zimId, String protocal) {
Map params = new HashMap();
params.put(KEY_INIT_RESP_NAME, protocal);
/* start: 如果是预输入手机号方案,请加入以下代码,填入会员绑定的手机号,必须与支付宝帐号对应的手机号一致 */
// 这句代码就是扫脸之后会有一个用户输入手机号的页面,您要是写这一行,就不需要用户去手动输入,会直接把用户手机号显示在页面,
// 不写的话需要用户手动去输入
// params.put("phone_number", "1381XXXXX");
/* end: --------------------------------------------- */
zoloz.zolozVerify(zimId, params, new ZolozCallback() {
@Override
public void response(final Map smileToPayResponse) {
if (smileToPayResponse == null) {
// promptText("2----------"+TXT_OTHER);
Toast.makeText(GeneralActivity.this, TXT_OTHER, Toast.LENGTH_SHORT).show();
return;
}
String code = (String)smileToPayResponse.get("code");
String fToken = (String)smileToPayResponse.get("ftoken");
String subCode = (String)smileToPayResponse.get("subCode");
String msg = (String)smileToPayResponse.get("msg");
//刷脸成功
if (CODE_SUCCESS.equalsIgnoreCase(code) && fToken != null) {
//promptText("刷脸成功,返回ftoken为:" + fToken);
//这里在Main线程,网络等耗时请求请放在异步线程中
//后续这里可以发起支付请求
//https://docs.open.alipay.com/api_1/alipay.trade.pay
//需要修改两个参数
//scene固定为security_code
//auth_code为这里获取到的fToken值
//支付一分钱,支付需要在服务端发起,这里只是模拟
sharedPreference = ISharedPreference.getInstance(getApplication());//获取保存的token
//联网发送信息给服务器(自己的服务器)
String register = "http://test.shanghkj.com/api/merchant/SmTradePay";
//这里是要传送的参数
RequestParams params = new RequestParams();
params.put("token",sharedPreference.getToken());
params.put("remark",dataBinding.generalNote.getText().toString());//备注
params.put("code",fToken);//传ftonen
params.put("total_amount",dataBinding.generalCount.getText().toString());//金额
params.put("desc","描述");
client.post(register, params, new AsyncHttpResponseHandler(){
@Override
public void onSuccess(String content) {
Log.e("TAG", "content---第二步的成功-------------"+content);
ScanPayBean scanPayBean = model.scanPay.get();
if (scanPayBean != null) {
print(scanPayBean);
String contentSm = "扫脸收款成功 ¥" + dataBinding.generalCount.getText().toString() + " " + getCurrentTime();
//显示打印dialog
showPrintDialog(scanPayBean);
model.startGt(ISharedPreference.getInstance(getApplication()).getCid(), "尚瀚支付推送提醒", contentSm, () -> {
});
}
}
@Override
public void onFailure(Throwable error, String content) {
Log.e("TAG", "content-------第二步的失败---------"+content);
}
});
}
}
});
}
/*----------------------------扫脸--------------------------------我是分割线----------以上----------------------扫脸---------------------------------------------------*/
//获取当前时间
private String getCurrentTime() {
SimpleDateFormat simpleDateFormat = (SimpleDateFormat) SimpleDateFormat.getDateInstance();
simpleDateFormat.applyPattern("MM-dd HH:mm:SS");
return simpleDateFormat.format(new Date());
}
@Override
protected void onDestroy() {
super.onDestroy();
zoloz.zolozUninstall();
if (dialog != null) {
dialog.dismiss();
}
}
}