概述
Android就业面试技巧系列-技术篇(支付相关)
关于支付,相信很多同学都不陌生,而且这也是找工作面试官问的高频问题,这一篇文章主要就是向大家详细介绍一下支付的一些流程。
支付难不难?
> 不难,都是属于第三方的东西.难度不大
支付安不安全?
> 肯定是安全的.因为这些都是大公司的产品.都有自己的安全策略;
做一个支付需要多久?
项目评估时间和实际开发有出入的,一般是两倍关系
比如你一天能搞完,那你至少评估2天
前期准备工作可能就是 一周左右
程序员实际集成时间
* 项目评估
* 支付宝:大概5分钟.
* 银联支付:大概5分钟.
* 微信支付:大概10分钟.
支付流程_从生活出发
1. 选择商品
2. 选择支付方式
3. 处理支付结果
1. 成功
2. 失败
3. 取消
支付流程_从app开发角度(保证可以先完成功能)
1. 拼接支付信息,post到服务器;-->request
1. 支付信息包含支付方式
2. 服务器:***是我们自己的服务器***
3. 支付协议:`http://mobileif.maizuo.com/version3/orderform/order?version=2`
2. 服务器返回`支付串码`;--->reponse
请求的url(支付协议/确认订单协议): http://mobileif.maizuo.com/version3/orderform/order?version=2
请求方式:post
post参数形式:jsonString
输入参数:
> 不难,都是属于第三方的东西.难度不大
支付安不安全?
> 肯定是安全的.因为这些都是大公司的产品.都有自己的安全策略;
做一个支付需要多久?
项目评估时间和实际开发有出入的,一般是两倍关系
比如你一天能搞完,那你至少评估2天
前期准备工作可能就是 一周左右
程序员实际集成时间
* 项目评估
* 支付宝:大概5分钟.
* 银联支付:大概5分钟.
* 微信支付:大概10分钟.
支付流程_从生活出发
1. 选择商品
2. 选择支付方式
3. 处理支付结果
1. 成功
2. 失败
3. 取消
支付流程_从app开发角度(保证可以先完成功能)
1. 拼接支付信息,post到服务器;-->request
1. 支付信息包含支付方式
2. 服务器:***是我们自己的服务器***
3. 支付协议:`http://mobileif.maizuo.com/version3/orderform/order?version=2`
2. 服务器返回`支付串码`;--->reponse
请求的url(支付协议/确认订单协议): http://mobileif.maizuo.com/version3/orderform/order?version=2
请求方式:post
post参数形式:jsonString
输入参数:
[Java]
纯文本查看
复制代码
1
2
|
{
"goodInfos"
:[{
"goodCounts"
:
"1"
,
"goodExtInfo"
:{},
"goodIDs"
:
"361"
,
"goodType"
:
"1"
}],
"loginFlag"
:
"0"
,
"mobile"
:
"18682036558"
,
"orderId"
:
"0"
,
"otherInfo"
:{
"agentID"
:
"0-maizuo"
,
"channelID"
:
"31"
,
"clientID"
:
"31"
},
"payDatas"
:{
"discountInfo"
:{
"activeID"
:
"0"
,
"discountID"
:
"0"
,
"discountPrice"
:
""
},
"payInfo"
:[{
"bankType"
:
"7"
,
"payCount"
:
"3200"
,
"payTicketCount"
:
"1"
,
"payType"
:
"1"
}],
"payPass"
:
""
,
"returnUrl"
:
""
,
"totalPrice"
:
"3200"
},
"processPath"
:
"1"
,
"sessionKey"
:
"mqneaadqapkpkqshxvdj"
,
"userID"
:
"200394160"
}
输出结果{
"result"
:
"ok"
,
"payExtInfo"
:{
"alipayVerifyKey"
:
"_input_charset="UTF-8"&body="卖座网电子影票"&it_b_pay="1h"¬ify_url="http%3A%2F%2Fpay.maizuo.com%2FmobileBack.htm"&out_trade_no="201507238712113008"&partner="2088411628331920"&payment_type="1"&seller_id="2088411628331920"&service="mobile.securitypay.pay"&subject="深圳金逸影城沙井店(2D通兑票1张)"&total_fee="32.00"&sign="M0O0Ej5J13A25SAWupc5a6vAGmJnblx2CvuWF2dwFGxMZ%2BxlRWmp%2F6ZDfI8Y%2FFJbjiEqE99MAsKh%0AfIBQqP4Y1TyNkbY0XixQFPgAAqsqwGqYJSDtqUFWRgje%2B8pI1KuxfPE3UcDZs4hxDZoP%2Bdof%2Bldf%0AKQmximUyqT5Crtwj1Ag%3D"&sign_type="RSA""
},
"bankType"
:
""
,
"userId"
:
"200394160"
,
"resource"
:{
"rel"
:
"view"
,
"link"
:
"/orderform/200394160/201507238712113008"
},
"payType"
:
"7"
,
"payUrl"
:
""
,
"orderId"
:
"201507238712113008"
,
"uniqueKey"
:
"D5585vO8624915A11z"
,
"timeNow"
:
"1437622208552"
}
|
3. 拿着支付串码,调用第三方服务,完成支付-->5分钟 (调用支付宝服务)
下载文档和 demo 来处理
4. 处理支付结果
1. 同步返回:支付后通知我们自己的apk
2. 异步通知:支付后通知我们的server
什么是支付串码
这个是自己定义的一个概念.其实就是第三步调用起第三方支付平台`核心支付方法所需要的参数`
集成支付宝流程
1. 我们自己要和支付宝签约(商户签约).-->运营去签合同
2. 秘钥配置-->协助运营完成秘钥的配置(公钥互换),可能程序员会参与
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
|
// 合作身份者ID,以2088开头由16位纯数字组成的字符串
public
static
final
String ALIPAY_PartnerID =
""
;
// 商户签约支付宝账号
public
static
final
String ALIPAY_SellerID =
""
;
// 商户的私钥(MD5)
public
static
final
String ALIPAY_MD5_KEY =
""
;
// 商户私钥(RSA),用户自动生成
public
static
final
String ALIPAY_PartnerPrivKey =
""
;
// 支付宝公钥,无需修改该值 demo里面有的
public
static
final
String ALIPAY_PubKey =
""
;
|
3. 集成支付宝-->必须是程序员去做.
1. 下载sdk/demo/文档
2. demo尝试的去运行
1. 出现了错误:因为缺少运行必须的,DEFAULT_PARTNER,DEFAULT_SELLER,如果1,2步完成的话,我们在这个时候就可以有`DEFAULT_PARTNER,DEFAULT_SELLER`
3. 开始集成-->`参照移动快捷支付应用集成接入包支付接口接入与使用规则.pdf`
1. 添加jar,alipay.jar
2. 添加lib,alipay_lib
3. 添加了一个activity
4. 添加了一些权限
5. 调用支付的核心代码
[Java]
纯文本查看
复制代码
1
2
3
4
5
6
|
// 3.调用第三方服务,完成支付
//获取Alipay对象,构造参数为当前Activity和Handler实例对象
AliPay alipay =
new
AliPay(MainActivity.
this
, mHandler);
//调用pay方法,将订单信息传入
//同步返回 取消操作 支付成功 支付失败(网络异常)
String payResult = alipay.pay(alipayVerifyKey);
|
6. 处理支付结果--->支付宝处理支付结果用的handler机制
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
/**---------------demo里面处理支付结果的代码---------------**/
/*Result result = new Result((String) msg.obj);
switch (msg.what) {
case RQF_PAY:
case RQF_LOGIN: {
Toast.makeText(ExternalPartner.this, result.getResult(), Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
*/
/**---------------老师实际开发处理支付结果的代码---------------**/
/*Result.sResult = (String) msg.obj;
Logger.i(TAG, "strRet:" + Result.sResult);
try {
String errorMsg = Result.getPayResult();
Logger.i(TAG, "errorMsg:" + errorMsg);
if (!"".equals(errorMsg)) {
Toast.makeText(getApplicationContext(), errorMsg, 0).show();
if ("操作成功".equals(errorMsg)) {
payOk();//支付成功可以调到订单界面
} else {
payFail();//可以弹出对话框进行重复支付
}
}
} catch (Exception e) {
e.printStackTrace();
if (!PayActivity.this.isFinishing()) {
BaseHelper.showDialog(PayActivity.this, "提示", Result.sResult + ",如有疑问请联系卖座客服:4001808400", R.drawable.infoicon);
}
}
}
};*/
|
支付宝demo分析
* 查看demo发现他的`支付串码`,是在客户端生成的.这个和老师所讲的.支付串码由服务器生成.有出入;
* 为了不暴露我们privatekey,我们应该把生成支付串码的过程交给我们的服务器
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
/**---------------生成支付串码的过程 begin---------------**/
Log.i(
"ExternalPartner"
,
"onItemClick"
);
String info = getNewOrderInfo(position);
//其实下面的操作应该是server端去完成.不然我们会暴露privatekey---begin---add_by_billy
//所有我们会把info的具体内容用jsonString的形式.post给server进行签名.然后返回签名后的结果---add_by_billy
String sign = Rsa.sign(info, Keys.PRIVATE);
sign = URLEncoder.encode(sign);
info +=
"&sign=""
+ sign +
""&"
+ getSignType();
Log.i(
"ExternalPartner"
,
"start pay"
);
// start the pay.
Log.i(TAG,
"info = "
+ info);
//其实下面的操作应该是server端去完成.不然我们会暴露privatekey---end---add_by_billy
final
String orderInfo = info;
/**---------------生成支付串码的过程 end---------------**/
|
支付串码_自己定义的一个概念
> 支付串码就是调用第三方应用的时候需要的一些核心的参数 按照第三方支付的规范码
支付串码在支付宝就相当于订单信息
支付串码在银联就相当于交易流水号
支付串码在微信就相当于订单信息
银联支付
* 银联支付,就`只需要一个交易流水号`就可以,而且看代码比较简单,重点是,`银联强制要求生产支付串码的过程必须交给我们的服务端`
* 集成形式
* 内嵌apk形式:就是把一个apk放到我们的assets目录下面-->老的方式
* 新版本so库形式:在libs下面就有很多的so库.已经不需要在assets目录下面放置apk
* 模式:
* 测试模式:银联会给我们提供一个测试环境+提供了一个银联的账号/密码
* 正式模式:就必须使用真实的账号/密码
* 运行demo看效果:
* 集成步骤:
* 1.添加libs里面相关的东西;
* 2.添加activity配置
[XML]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
|
<
activity
android:name
=
"com.unionpay.uppay.PayActivityEx"
android:configChanges
=
"orientation|keyboardHidden|screenSize"
android:excludeFromRecents
=
"true"
android:label
=
"@string/app_name"
android:screenOrientation
=
"portrait"
android:windowSoftInputMode
=
"adjustResize"
/>
<
activity
android:name
=
"com.unionpay.uppay.PayActivity"
android:configChanges
=
"orientation|keyboardHidden|screenSize"
android:excludeFromRecents
=
"true"
android:screenOrientation
=
"portrait"
/>
|
* 3.添加权限
[XML]
纯文本查看
复制代码
1
2
3
4
|
<!-- uupay -->
<
uses-permission
android:name
=
"android.permission.CHANGE_NETWORK_STATE"
/>
<
uses-permission
android:name
=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<
uses-permission
android:name
=
"android.permission.READ_PHONE_STATE"
/>
|
* 4.调用核心的支付方法
[Java]
纯文本查看
复制代码
1
2
3
4
5
6
7
8
|
//拿着支付串码
System.out.println(
"alipayVerifyKey:"
+ alipayVerifyKey);
// 3.调用第三方服务,完成支付
// “00” – 银联正式环境
// “01” – 银联测试环境,该环境中不发生真实交易
//tn 交易流水号
UPPayAssistEx.startPayByJAR(MainActivity.
this
, PayActivity.
class
,
null
,
null
,
alipayVerifyKey,
"00"
);
|
* 5.处理支付结果
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
/**---------------银联处理支付结果---------------**/
protected
void
onActivityResult(
int
requestCode,
int
resultCode, Intent data) {
/*************************************************
*
* 步骤4:处理银联手机支付控件返回的支付结果
*
************************************************/
if
(data ==
null
) {
return
;
}
String msg =
""
;
/*
* 支付控件返回字符串:success、fail、cancel 分别代表支付成功,支付失败,支付取消
*/
String str = data.getExtras().getString(
"pay_result"
);
if
(str.equalsIgnoreCase(
"success"
)) {
msg =
"支付成功!"
;
}
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();
}
|
微信支付
* 直接运行demo,发现最后提示错误,发现工程下面有一个debug.keystore
* 想要运行.可以如下操作
* 自定义keystore
* 或者直接导出的时候用工程下面的debug.keystore去签名
window-----Android----Build----Custom debug keystore:微信debug.keystore的路径
如果上面的apk用微信支付还报错的话,那么就需要把apk签名(debug.keystore)打包生成的apk
先将该app注册到微信,然后再调用支付界面支付就可以了
* 微信支付的安全策略之一:必须包名和keystore签名需要一致 即利用包名和keystore(sha1值)生成安全码
* demo里面定义的步骤
* 一、获取 access_token
* 二、生成预支付订单,需要用到第一步的access_token,得到的是prepayId
* 三、调起微信支付
* 四、处理支付结果
* 这个时候一看.感觉微信支付很难.但是我们看到demo里面这样的一句话`注意:不能hardcode在客户端,建议genPackage这个过程由服务器端完成`,所以,其实我们的微信支付,一、二步骤为了安全起见应该交给Server
* 实际开发,只需关心3,4步就可以
* 三、调起微信支付
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
/**
* @author Administrator
* 支付的时候真正关心的数据
* 这个对象是我自己封装的.和微信支付的sdk没有关系
*/
public
class
WXPayData {
private
String sign_method;
private
String timestamp;
private
String noncestr;
private
String partnerid;
private
String app_signature;
private
String prepayid;
private
String package1;
private
String appid;
}
//核心支付方法
private
void
sendPayReq(WXPayData info) {
api = WXAPIFactory.createWXAPI(
this
, info.getAppid());
PayReq req =
new
PayReq();
req.appId = info.getAppid();
req.partnerId = info.getPartnerid();
req.prepayId = info.getPrepayid();
//预支付id
req.nonceStr = info.getNoncestr();
//32位内的随机串,防重发
req.timeStamp = String.valueOf(info.getTimestamp());
//时间戳,为 1970 年 1 月 1 日 00:00 到请求发起时间的秒数
req.packageValue = info.getPackage1();
req.sign = info.getApp_signature();
// 在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信
api.sendReq(req);
}
|
* 四、处理支付结果:微信支付支付的回调是在`net.sourceforge.simcpux.wxapi.WXPayEntryActivity.class`里面
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
|
@Override
public
void
onResp(BaseResp resp) {
Log.d(TAG,
"onPayFinish, errCode = "
+ resp.errCode);
if
(resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
AlertDialog.Builder builder =
new
AlertDialog.Builder(
this
);
builder.setTitle(R.string.app_tip);
builder.setMessage(getString(R.string.pay_result_callback_msg, String.valueOf(resp.errCode)));
builder.show();
}
}
|
安全码策略
> 安全码的组成规则为:Android签名证书的sha1值+“;”+packagename(即:数字签名+分号+包名)
* 作用:确定apk的唯一性
最后
以上就是时尚吐司为你收集整理的Android就业面试技巧系列-技术篇11 (支付相关)的全部内容,希望文章能够帮你解决Android就业面试技巧系列-技术篇11 (支付相关)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复