第三方支付的简单操作

第三方支付指的是第三方平台与各银行签约,在买方与卖方之间实现中介担保,从而增强了支付交易的安全性。国内常用的支付平台主要是支付宝和微信支付,其中支付宝的市场份额为71.5%,微信支付的市场份额为15.99%,也就是说这两家垄断了八分之七的支付市场(2015年数据)。除此之外,还有几个app开发会用到的支付平台,包括:银联支付,主要用于公共事业缴费,如水电煤、有线电视、移动电信等等的充值;易宝支付,主要用于各种报名考试的缴费,特别是公务员与事业单位招考;快钱,被万达收购,主要用于航空旅行、教育培训、游戏娱乐等网站的支付;京东支付,主要用于京东商城的支付;百度钱包,主要用于百度系的电商平台。

因为第三方支付只是个中介,交易流程要多次确认,所以app若要集成支付sdk,得进行以下处理:

1、除了作为买方的用户自己拥有支付账号,开发者还得申请作为卖方的商户账号。

2、支付过程中,虽然允许app直接与第三方支付平台通信,但是最好app要有自己的后台服务器,由自己的后台与第三方平台进行通信。这样做的好处是,一方面自己后台掌握了用户交易记录,做账有依据,管理也方便;另一方面,关键交易在自己后台处理,也减少了恶意篡改的风险。

3、为保证信息安全,需对关键数据进行加密处理,如支付宝采用RSA+BASE64算法,微信支付采用MD5算法,银联支付采用RSA算法。

支付宝支付

交易流程

支付宝支付的交易流程大致如下:

1、按照指定格式封装好交易信息;

2、对交易信息进行RSA加密与URL编码;

3、调用支付接口,传入加密好的信息串;(这步要另开线程处理,不能放在UI线程中)

4、支付宝sdk在界面下方弹出支付窗口,用户输入支付帐号信息,提交支付;

5、收到支付完成的结果,判断支付状态是成功还是失败;

集成步骤

支付宝sdk的集成比较简单,除了必要的权限外,无需再修改AndroidManifest.xml,jar包也只要导入alipaySdk-20160516.jar。

代码方面,支付宝官方给的demo采用了Thread+Handler的异步处理模式,不过该模式要把代码写在Activity中,不便管理和维护,而本文的测试代码将它改为Android自带的异步任务处理即AsyncTask方式

测试帐号

支付宝官方demo没有给出测试的商户账号,下面是我在网上找到的测试帐号:

[java]view plaincopy

1.// 商户PID

2.publicstaticfinalString PARTNER ="2088811977704990";

3.// 商户收款账号

4.publicstaticfinalString SELLER ="dev@ifensi.com";

5.// 商户私钥,pkcs8格式

6.publicstaticfinalString RSA_PRIVATE =

7."MIICXQIBAAKBgQDlQ468L1A7Q+GG80/Z8f3IsSiiFIluSxfTTSuJ/XSPzvYS+bMZ"

8.+"AQLMqq/nGhkp+1Q5pHF9LAQtQS3gL2pqzbKdtvZSsy/tNFFQcGCsgK2ygMl+MW/F"

9.+"g/ufx7c1jy1kZAeDyl1m302dnRrtSgDalkgH7FKRcmDxbXPTnFGHbg9zMQIDAQAB"

10.+"AoGAa28wGQF28H7L1Yh5V+FtkrlqGCHVkQjBfnRAPea205kheRzoD4SIwk4OJhb1"

11.+"ydWLz4M+53BT+Lz9eXveu3PvCdQe9zMIVC5dKUNVYCvvcHZ+Ot8HriiuwGPb3Quu"

12.+"twbnLGM5gxxPDo0yUyWrfaVn/qR35mS6TDfmgowVG8CmBpECQQDzuhodR/Jgxrtn"

13.+"tka+88alyy+BfjUZqNloPuE7JfXrpOxH5lodk7Y4lTki/dlo5BrK+hrismLFr9Du"

14.+"ueAJ7G9dAkEA8M8C6VnpUMAK5+rYcjKnQssDqcMfurKYEil1BD/TUdSbLI6v8p02"

15.+"mv1ApuTVtQQypZJKIFfurGk0g0QlvzLZ5QJAGfY38+iHDAH/UnPbI1oKTfzPyaZs"

16.+"95fB2NXh3hAUGw7NUHdcIAxs+6gBlxWdRAwQQpDTrlQ8KzyoL9XC5Ku3zQJBALO8"

17.+"j5vEtFTFQl6f9zYlgJpmFTHcpg4fx0mnD+RAD2aAneHADquzlFJSvLLVEn2tyG+0"

18.+"pQdHGqotTDi94L65IdECQQDb1h+5kugCu47IxsDkrLRsKVcr8dSDMORyeT1L0HWR"

19.+"ctramBu+2PBz2UKC6+9dQ+ZQH4XTKpBSvkyZH4mYi1de";

20.//  // 支付宝公钥

21.//  public static final String RSA_PUBLIC = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRAFljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQEB/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5KsiNG9zpgmLCUYuLkxpLQIDAQAB";

下面是支付宝支付的示例代码:

[java]view plaincopy

1.importjava.io.UnsupportedEncodingException;

2.importjava.net.URLEncoder;

3.importjava.text.SimpleDateFormat;

4.importjava.util.Date;

5.importjava.util.Locale;

6.importjava.util.Random;

7.

8.importcom.alipay.sdk.app.PayTask;

9.importcom.example.exmpay.alipay.bean.AlipayConstants;

10.importcom.example.exmpay.alipay.bean.PayResult;

11.importcom.example.exmpay.alipay.util.SignUtils;

12.

13.importandroid.app.Activity;

14.importandroid.app.AlertDialog;

15.importandroid.app.ProgressDialog;

16.importandroid.content.Context;

17.importandroid.content.DialogInterface;

18.importandroid.os.AsyncTask;

19.importandroid.text.TextUtils;

20.importandroid.widget.Toast;

21.

22.publicclassAlipayTaskextendsAsyncTask {

23.

24.privatestaticfinalString TAG ="AlipayTask";

25.privateContext context;

26.privateProgressDialog dialog;

27.

28.publicAlipayTask(Context context) {

29.this.context = context;

30.}

31.

32.@Override

33.protectedvoidonPreExecute() {

34.if(TextUtils.isEmpty(AlipayConstants.PARTNER)

35.|| TextUtils.isEmpty(AlipayConstants.RSA_PRIVATE)

36.|| TextUtils.isEmpty(AlipayConstants.SELLER)) {

37.newAlertDialog.Builder(context).setTitle("警告").setMessage("需要配置PARTNER | RSA_PRIVATE| SELLER")

38..setPositiveButton("确定",newDialogInterface.OnClickListener() {

39.publicvoidonClick(DialogInterface dialoginterface,inti) {

40.}

41.}).show();

42.cancel(true);

43.}else{

44.dialog = ProgressDialog.show(context,"提示","正在启动支付宝...");

45.}

46.}

47.

48.@Override

49.protectedString doInBackground(Void... params) {

50.String orderInfo = getOrderInfo("测试的商品","该测试商品的详细描述","0.01");

51.

52.//特别注意,这里的签名逻辑需要放在服务端,切勿将私钥泄露在代码中!

53.String sign = sign(orderInfo);

54.try{

55.//仅需对sign 做URL编码

56.sign = URLEncoder.encode(sign,"UTF-8");

57.}catch(UnsupportedEncodingException e) {

58.e.printStackTrace();

59.}

60.

61.//完整的符合支付宝参数规范的订单信息

62.finalString payInfo = orderInfo +"&sign=\""+ sign +"\"&"+ getSignType();

63.// 构造PayTask 对象

64.PayTask alipay =newPayTask((Activity) context);

65.// 调用支付接口,获取支付结果

66.String result = alipay.pay(payInfo,false);

67.returnresult;

68.}

69.

70.@Override

71.protectedvoidonPostExecute(String result) {

72.if(dialog !=null) {

73.dialog.dismiss();

74.}

75.

76.PayResult payResult =newPayResult(result);

77.

78.// 支付宝返回此次支付结果及加签,建议对支付宝签名信息拿签约时支付宝提供的公钥做验签

79.String resultInfo = payResult.getResult();

80.Toast.makeText(context,"resultInfo="+resultInfo, Toast.LENGTH_SHORT).show();

81.

82.String resultStatus = payResult.getResultStatus();

83.// 判断resultStatus 为“9000”则代表支付成功,具体状态码代表含义可参考接口文档

84.if(TextUtils.equals(resultStatus,"9000")) {

85.Toast.makeText(context,"支付宝缴费成功", Toast.LENGTH_SHORT).show();

86.}else{

87.// 判断resultStatus 为非“9000”则代表可能支付失败

88.// “8000”代表支付结果因为支付渠道原因或者系统原因还在等待支付结果确认,最终交易是否成功以服务端异步通知为准(小概率状态)

89.if(TextUtils.equals(resultStatus,"8000")) {

90.Toast.makeText(context,"支付宝缴费结果确认中", Toast.LENGTH_SHORT).show();

91.}else{

92.// 其他值就可以判断为支付失败,包括用户主动取消支付,或者系统返回的错误

93.Toast.makeText(context,"支付宝缴费失败"+payResult.getResult(), Toast.LENGTH_SHORT).show();

94.}

95.}

96.}

97.privateString getOrderInfo(String subject, String body, String price) {

98.// 签约合作者身份ID

99.String orderInfo ="partner="+"\""+ AlipayConstants.PARTNER +"\"";

100.// 签约卖家支付宝账号

101.orderInfo +="&seller_id="+"\""+ AlipayConstants.SELLER +"\"";

102.// 商户网站唯一订单号

103.orderInfo +="&out_trade_no="+"\""+ getOutTradeNo() +"\"";

104.// 商品名称

105.orderInfo +="&subject="+"\""+ subject +"\"";

106.// 商品详情

107.orderInfo +="&body="+"\""+ body +"\"";

108.// 商品金额

109.orderInfo +="&total_fee="+"\""+ price +"\"";

110.// 服务器异步通知页面路径

111.orderInfo +="¬ify_url="+"\""+"http://notify.msp.hk/notify.htm"+"\"";

112.// 服务接口名称, 固定值

113.orderInfo +="&service=\"mobile.securitypay.pay\"";

114.// 支付类型, 固定值

115.orderInfo +="&payment_type=\"1\"";

116.// 参数编码, 固定值

117.orderInfo +="&_input_charset=\"utf-8\"";

118.

119.// 设置未付款交易的超时时间,默认30分钟,一旦超时,该笔交易就会自动被关闭。

120.// 取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(无论交易何时创建,都在0点关闭)。

121.// 该参数数值不接受小数点,如1.5h,可转换为90m。

122.orderInfo +="&it_b_pay=\"30m\"";

123.

124.// extern_token为经过快登授权获取到的alipay_open_id,带上此参数用户将使用授权的账户进行支付

125.// orderInfo += "&extern_token=" + "\"" + extern_token + "\"";

126.

127.// 支付宝处理完请求后,当前页面跳转到商户指定页面的路径,可空

128.orderInfo +="&return_url=\"m.alipay.com\"";

129.

130.// 调用银行卡支付,需配置此参数,参与签名, 固定值 (需要签约《无线银行卡快捷支付》才能使用)

131.// orderInfo += "&paymethod=\"expressGateway\"";

132.

133.returnorderInfo;

134.}

135.

136.privateString getOutTradeNo() {

137.SimpleDateFormat format =newSimpleDateFormat("MMddHHmmss", Locale.getDefault());

138.Date date =newDate();

139.String key = format.format(date);

140.

141.Random r =newRandom();

142.key = key + r.nextInt();

143.key = key.substring(0,15);

144.returnkey;

145.}

146.

147.privateString sign(String content) {

148.returnSignUtils.sign(content, AlipayConstants.RSA_PRIVATE);

149.}

150.

151.privateString getSignType() {

152.return"sign_type=\"RSA\"";

153.}

154.

155.}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容