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内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复