第三方支付
第三方支付指的是第三方平台与各银行签约,在买方与卖方之间实现中介担保,从而增强了支付交易的安全性。国内常用的支付平台主要是支付宝和微信支付,其中支付宝的市场份额为71.5%,微信支付的市场份额为15.99%,也就是说这两家垄断了八分之七的支付市场(2015年数据)。除此之外,还有几个app开发会用到的支付平台,包括:银联支付,主要用于公共事业缴费,如水电煤、有线电视、移动电信等等的充值;易宝支付,主要用于各种报名考试的缴费,特别是公务员与事业单位招考;快钱,被万达收购,主要用于航空旅行、教育培训、游戏娱乐等网站的支付;京东支付,主要用于京东商城的支付;百度钱包,主要用于百度系的电商平台。因为第三方支付只是个中介,交易流程要多次确认,所以app若要集成支付sdk,得进行以下处理:
1、除了作为买方的用户自己拥有支付账号,开发者还得申请作为卖方的商户账号。
2、支付过程中,虽然允许app直接与第三方支付平台通信,但是最好app要有自己的后台服务器,由自己的后台与第三方平台进行通信。这样做的好处是,一方面自己后台掌握了用户交易记录,做账有依据,管理也方便;另一方面,关键交易在自己后台处理,也减少了恶意篡改的风险。
3、为保证信息安全,需对关键数据进行加密处理,如支付宝采用RSA+BASE64算法,微信支付采用MD5算法,银联支付采用RSA算法。有关数据加密算法的说明参见《 Android开发笔记(七十二)数据加密算法》。
支付宝支付
交易流程
支付宝支付的交易流程大致如下:1、按照指定格式封装好交易信息;
2、对交易信息进行RSA加密与URL编码;
3、调用支付接口,传入加密好的信息串;(这步要另开线程处理,不能放在UI线程中)
4、支付宝sdk在界面下方弹出支付窗口,用户输入支付帐号信息,提交支付;
5、收到支付完成的结果,判断支付状态是成功还是失败;
集成步骤
支付宝sdk的集成比较简单,除了必要的权限外,无需再修改AndroidManifest.xml,jar包也只要导入alipaySdk-20160516.jar。代码方面,支付宝官方给的demo采用了Thread+Handler的异步处理模式,不过该模式要把代码写在Activity中,不便管理和维护,因此我的测试代码将它改造为Android自带的异步任务处理即AsyncTask方式,有关AsyncTask的说明参见《 Android开发笔记(四十九)异步任务处理AsyncTask》。
测试帐号
支付宝官方demo没有给出测试的商户账号,下面是我在网上找到的测试帐号: // 商户PID
public static final String PARTNER = "2088811977704990";
// 商户收款账号
public static final String SELLER = "dev@ifensi.com";
// 商户私钥,pkcs8格式
public static final String RSA_PRIVATE =
"MIICXQIBAAKBgQDlQ468L1A7Q+GG80/Z8f3IsSiiFIluSxfTTSuJ/XSPzvYS+bMZ"
+"AQLMqq/nGhkp+1Q5pHF9LAQtQS3gL2pqzbKdtvZSsy/tNFFQcGCsgK2ygMl+MW/F"
+"g/ufx7c1jy1kZAeDyl1m302dnRrtSgDalkgH7FKRcmDxbXPTnFGHbg9zMQIDAQAB"
+"AoGAa28wGQF28H7L1Yh5V+FtkrlqGCHVkQjBfnRAPea205kheRzoD4SIwk4OJhb1"
+"ydWLz4M+53BT+Lz9eXveu3PvCdQe9zMIVC5dKUNVYCvvcHZ+Ot8HriiuwGPb3Quu"
+"twbnLGM5gxxPDo0yUyWrfaVn/qR35mS6TDfmgowVG8CmBpECQQDzuhodR/Jgxrtn"
+"tka+88alyy+BfjUZqNloPuE7JfXrpOxH5lodk7Y4lTki/dlo5BrK+hrismLFr9Du"
+"ueAJ7G9dAkEA8M8C6VnpUMAK5+rYcjKnQssDqcMfurKYEil1BD/TUdSbLI6v8p02"
+"mv1ApuTVtQQypZJKIFfurGk0g0QlvzLZ5QJAGfY38+iHDAH/UnPbI1oKTfzPyaZs"
+"95fB2NXh3hAUGw7NUHdcIAxs+6gBlxWdRAwQQpDTrlQ8KzyoL9XC5Ku3zQJBALO8"
+"j5vEtFTFQl6f9zYlgJpmFTHcpg4fx0mnD+RAD2aAneHADquzlFJSvLLVEn2tyG+0"
+"pQdHGqotTDi94L65IdECQQDb1h+5kugCu47IxsDkrLRsKVcr8dSDMORyeT1L0HWR"
+"ctramBu+2PBz2UKC6+9dQ+ZQH4XTKpBSvkyZH4mYi1de";
// // 支付宝公钥
// public static final String RSA_PUBLIC = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRAFljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQEB/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5KsiNG9zpgmLCUYuLkxpLQIDAQAB";
下面是支付宝支付的效果截图
下面是支付宝支付的示例代码
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Random;
import com.alipay.sdk.app.PayTask;
import com.example.exmpay.alipay.bean.AlipayConstants;
import com.example.exmpay.alipay.bean.PayResult;
import com.example.exmpay.alipay.util.SignUtils;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.text.TextUtils;
import android.widget.Toast;
public class AlipayTask extends AsyncTask<Void, Void, String> {
private static final String TAG = "AlipayTask";
private Context context;
private ProgressDialog dialog;
public AlipayTask(Context context) {
this.context = context;
}
@Override
protected void onPreExecute() {
if (TextUtils.isEmpty(AlipayConstants.PARTNER)
|| TextUtils.isEmpty(AlipayConstants.RSA_PRIVATE)
|| TextUtils.isEmpty(AlipayConstants.SELLER)) {
new AlertDialog.Builder(context).setTitle("警告").setMessage("需要配置PARTNER | RSA_PRIVATE| SELLER")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialoginterface, int i) {
}
}).show();
cancel(true);
} else {
dialog = ProgressDialog.show(context, "提示", "正在启动支付宝...");
}
}
@Override
protected String doInBackground(Void... params) {
String orderInfo = getOrderInfo("测试的商品", "该测试商品的详细描述", "0.01");
//特别注意,这里的签名逻辑需要放在服务端,切勿将私钥泄露在代码中!
String sign = sign(orderInfo);
try {
//仅需对sign 做URL编码
sign = URLEncoder.encode(sign, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//完整的符合支付宝参数规范的订单信息
final String payInfo = orderInfo + "&sign=\"" + sign + "\"&" + getSignType();
// 构造PayTask 对象
PayTask alipay = new PayTask((Activity) context);
// 调用支付接口,获取支付结果
String result = alipay.pay(payInfo, false);
return result;
}
@Override
protected void onPostExecute(String result) {
if (dialog != null) {
dialog.