Catalog
Some time ago, WeChat payment and Alipay payment were used in the project, so another mainstream payment (UnionPay payment) was also studied.
UnionPayment Technical Document Address
Official Document Address: https://open.unionpay.com
Payment flow chart
Brief description of the process, first of all, the background to the UnionPayment System to push orders, UnionPayment System will return the order transaction flow number, the background will return the transaction flow number to the APP side, then the APP side to transfer payment control payment; after the UnionPayment System processing transactions, the results will be notified to the APP side and the background, and finally the APP side to the background to sign the order information, through the verification. Payment is successful, and vice versa.
Invocation step
- 1. Acquiring Trading Flow Number
@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);
}
Asynchronous calls are made in non UI threads, and the transaction flow number is returned to start payment.
- 2. Transfer Payment Start Payment Control
@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("Error prompt");
builder.setMessage("Network Connection Failure,Please Try Again!");
builder.setNegativeButton("Sure?",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.create().show();
} else {
tn = (String) msg.obj;
/**
* Start Payment Plug-in through UnionPay Tool Class
*/
doStartUnionPayPlugin(this, tn, mMode);
}
return false;
}
PS: doStartUnionPayPlugin(this, tn, mMode) has TN as the trade pipeline number, mMode as the environment marker, 00 as the production environment, 01 as the test environment.
- 3. Processing the payment results returned by the payment control
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
/**
* Processing Payment Result Returned by Payment Control
*/
if (data == null) {
return;
}
String msg = "";
/**
* Payment control returns strings: success, failure, cancel represent payment success, payment failure, payment cancellation, respectively
*/
String str = data.getExtras().getString("pay_result");
if (str.equalsIgnoreCase("success")) {
// After successful payment, if result_data exists in extra, check out
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");
// Verification of visa-checking documents with backstage visa-checking documents
// Payment fails if the check fails
boolean ret = verify(dataOrg, sign, mMode);
if (ret) {
// After verification, the payment result is displayed.
msg = "Payment success!";
} else {
// Processing after verification fails
// It is suggested to adjust the background to inquire about payment results.
msg = "Payment failure!";
}
} catch (JSONException e) {
}
} else {
// No signature information was received
// It is suggested to adjust the background to inquire about payment results.
}
} else if (str.equalsIgnoreCase("fail")) {
msg = "Payment failure!";
} else if (str.equalsIgnoreCase("cancel")) {
msg = "The user cancelled the payment";
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Notification of Payment Result");
builder.setMessage(msg);
builder.setInverseBackgroundForced(true);
// builder.setCustomTitle();
builder.setNegativeButton("Sure?", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.create().show();
}
Matters needing attention
-
Environmental choice
mMode is 00 for the production environment and 01 for the test environment. If it is under the test environment, do not go to the background to check the signature, otherwise it will never pass.
-
Payment callback processing
If payment fails in production environment, it is better to check the payment results in the background to ensure the accuracy of the results.