目录
前段时间项目中使用到了微信支付和支付宝支付,所以顺便把另外一个主流的支付(银联支付)也学习了一下,再次把此次学习的知识作于一个记录。
银联支付技术文档地址
官方文档地址:https://open.unionpay.com
支付流程图
简要说明一下流程,首先后台向银联支付系统推送订单,银联支付系统会返回这个订单交易流水号,后台会把这个交易流水号返回给APP端,接着APP端调支付控件支付;待银联支付系统处理完交易,将结果通知给APP端和后台,最后APP端去后台验签订单信息,验签通过则支付成功,反之则失败。
调用步骤
- 1、获取交易流水号
@Override
public void run() {
String tn = null;
InputStream is;
try {
String url = TN_URL_01;
URL myURL = new URL(url);
URLConnection ucon = myURL.openConnection();
ucon.setConnectTimeout(120000);
is = ucon.getInputStream();
int i = -1;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((i = is.read()) != -1) {
baos.write(i);
}
tn = baos.toString();
is.close();
baos.close();
} catch (Exception e) {
e.printStackTrace();
}
Message msg = mHandler.obtainMessage();
msg.obj = tn;
mHandler.sendMessage(msg);
}
非UI线程中异步调用,返回交易流水号后调起支付。
- 2、调支付启动支付控件
@Override
public boolean handleMessage(Message msg) {
Log.e(LOG_TAG, " " + "" + msg.obj);
if (mLoadingDialog.isShowing()) {
mLoadingDialog.dismiss();
}
String tn = "";
if (msg.obj == null || ((String) msg.obj).length() == 0) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("错误提示");
builder.setMessage("网络连接失败,请重试!");
builder.setNegativeButton("确定",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.create().show();
} else {
tn = (String) msg.obj;
/**
* 通过银联工具类启动支付插件
*/
doStartUnionPayPlugin(this, tn, mMode);
}
return false;
}
PS:doStartUnionPayPlugin(this, tn, mMode)中tn为交易流水号,mMode为环境标记,00表示生产环境,01表示测试环境。
- 3、处理支付控件返回的支付结果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
/**
* 处理支付控件返回的支付结果
*/
if (data == null) {
return;
}
String msg = "";
/**
* 支付控件返回字符串:success、fail、cancel 分别代表支付 成功,支付失败,支付取消
*/
String str = data.getExtras().getString("pay_result");
if (str.equalsIgnoreCase("success")) {
// 支付成功后,extra中如果存在result_data,取出校验
if (data.hasExtra("result_data")) {
String result = data.getExtras().getString("result_data");
try {
JSONObject resultJson = new JSONObject(result);
String sign = resultJson.getString("sign");
String dataOrg = resultJson.getString("data");
// 验签证书同后台验签证书进行校验
// 如果校验不通过则支付失败
boolean ret = verify(dataOrg, sign, mMode);
if (ret) {
// 验证通过后,显示支付结果
msg = "支付成功!";
} else {
// 验证不通过后的处理
// 建议调后台查询支付结果
msg = "支付失败!";
}
} catch (JSONException e) {
}
} else {
// 未收到签名信息
// 建议调后台查询支付结果
}
} else if (str.equalsIgnoreCase("fail")) {
msg = "支付失败!";
} else if (str.equalsIgnoreCase("cancel")) {
msg = "用户取消了支付";
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("支付结果通知");
builder.setMessage(msg);
builder.setInverseBackgroundForced(true);
// builder.setCustomTitle();
builder.setNegativeButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.create().show();
}
注意事项
环境选择
mMode为00代表生产环境,01代表测试环境,如果是测试环境下,不去后台验签,否则一直不能通过。
支付回调处理
生产环境下如果支付失败后,最好去后台查询支付结果,确保结果的准确性。