用户使用移动的终端完成对所购买商品或者服务的支付功能;分为近场支付(蓝牙支付,刷卡,滴卡),和远程支付(网上支付,短信支付)
都是比较安全.都是大公司的产品.而且这个和金钱之前挂钩;
支付不难.因为是第三方平台的东西.
在客户端使用第三方平台的api调用插件完成支付-->调用第三方平台jar包里面的方法(集成过程),这一步才用到支付宝sdk
支付方法需要的支付参数
MainActivity
1
2
3
4
5
6
7
8
9
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
public
class
MainActivity
extends
Activity {
private
Button btn_zfb;
/**
* 支付宝通过hanlder机制发送支付结果出来,这个过程我们理解为"同步返回".因为只要支付宝支付成功.客户端就可以通过handler收到消息
*/
private
Handler handler =
new
Handler() {
public
void
handleMessage(android.os.Message msg) {
/*
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;
}
*/
};
};
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initListener();
}
private
void
initView() {
btn_zfb = (Button) findViewById(R.id.btn1);
}
private
void
initListener() {
/**
* 支付宝支付
*/
btn_zfb.setOnClickListener(
new
OnClickListener() {
@Override
public
void
onClick(View v) {
//1. 选择商品,把**支付数据**post到后台server-->发送一个请求
final
String goodInfoJsonString =
"{\"goodInfos\":[{\"goodCounts\":\"1\",\"goodExtInfo\":{},\"goodIDs\":\"965\",\"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\":\"3800\",\"payTicketCount\":\"1\",\"payType\":\"1\"}],\"payPass\":\"\",\"returnUrl\":\"\",\"totalPrice\":\"3800\"},\"processPath\":\"1\",\"sessionKey\":\"chfrlczgtomqsiurzzyo\",\"userID\":\"200394160\"}"
;
//2.把支付数据post到后台server-->发送一个请求
new
Thread(
new
Runnable() {
@Override
public
void
run() {
// TODO
try
{
DefaultHttpClient httpClient =
new
DefaultHttpClient();
HttpPost post =
new
HttpPost(
"http://mobileif.maizuo.com/version3/orderform/order?version=2"
);
post.addHeader(
"Content-Type"
,
"application/json"
);
post.setEntity(
new
StringEntity(goodInfoJsonString));
HttpResponse response = httpClient.execute(post);
if
(response.getStatusLine().getStatusCode() ==
200
) {
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity);
System.out.println(result);
//-->bean-->getAlipayVerifyKey();
//3.在客户端使用第三方平台的api调用插件完成支付
//获取Alipay对象,构造参数为当前Activity和Handler实例对象
//mHandler就是一会处理我们支付结果的hanlder
AliPay alipay =
new
AliPay(MainActivity.
this
, handler);
//调用pay方法,将订单信息传入
String orderInfo =
"_input_charset=\"UTF-8\"&body=\"卖座网电子影票\"&it_b_pay=\"1h\"¬ify_url=\"http%3A%2F%2Fpay.maizuo.com%2FmobileBack.htm\"&out_trade_no=\"201503283783092428\"&partner=\"2088411628331920\"&payment_type=\"1\"&seller_id=\"2088411628331920\"&service=\"mobile.securitypay.pay\"&subject=\"海岸影城(2D通兑票1张)\"&total_fee=\"38.00\"&sign=\"KDhXG0I8T1VZCgg3tfmYbnhF91I6marCQ0yWgmIe1ZGJ9z6MHFwwV7O156%2FkTecKikrIwRnrPNOI%0Ac8h6bUPRX9DIoHF3Yamj1NCi%2B5j0e16uRy5VtyhLFPx608stqjLlaepBsRZYPblyikuts67W9IJ%2B%0AyNrrG8cZ6ltgulZTFH4%3D\"&sign_type=\"RSA\""
;
//支付串码
String payResult = alipay.pay(orderInfo);
}
}
catch
(Exception e) {
e.printStackTrace();
}
}
}).start();
}
});
}
// “00” – 银联正式环境
// “01” – 银联测试环境,该环境中不发生真实交易
String serverMode =
"00"
;
/**
* 银联支付
*/
public
void
uupay(View v) {
//通过支付请求.拿到支付串码
String tn =
"201503281059506568548"
;
//发起支付请求
int
ret = UPPayAssistEx.startPay(MainActivity.
this
,
null
,
null
, tn, serverMode);
if
(ret == UPPayAssistEx.PLUGIN_NOT_FOUND) {
//安装Asset中提供的UPPayPlugin.apk
// 此处可根据实际情况,添加相应的处理逻辑
UPPayAssistEx.installUPPayPlugin(
this
);
}
}
/**
* uupay处理支付结果
*/
protected
void
onActivityResult(
int
requestCode,
int
resultCode, Intent data) {
if
(data ==
null
) {
return
;
}
String str = data.getExtras().getString(
"pay_result"
);
String msg =
""
;
/*
* 支付控件返回字符串:success、fail、cancel 分别代表支付成功,支付失败,支付取消
*/
if
(str.equalsIgnoreCase(
"success"
)) {
msg =
"支付成功!"
;
}
else
if
(str.equalsIgnoreCase(
"fail"
)) {
msg =
"支付失败!"
;
}
else
if
(str.equalsIgnoreCase(
"cancel"
)) {
msg =
"用户取消了支付"
;
}
//下面就是进行用户提示
Toast.makeText(getApplicationContext(), msg,
0
).show();
}
}
|
RSA密钥生成命令
关键方法:
//通过支付请求.拿到支付串码 String tn = "201503281059506568548"; //发起支付请求 int ret = UPPayAssistEx.startPay(MainActivity.this, null, null, tn, serverMode); if (ret == UPPayAssistEx.PLUGIN_NOT_FOUND) { //安装Asset中提供的UPPayPlugin.apk // 此处可根据实际情况,添加相应的处理逻辑 UPPayAssistEx.installUPPayPlugin(this); }
处理支付结果:在onactivityForResult中处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
@Override
protected
void
onActivityResult(
int
requestCode,
int
resultCode, Intent data) {
initData();
if
(data ==
null
) {
return
;
}
String uupayResult = data.getExtras().getString(
"pay_result"
);
Logger.i(TAG,
"pay_result:"
+ uupayResult);
if
(uupayResult !=
null
&& !
""
.equals(uupayResult)) {
Logger.i(TAG,
"pay_result:"
+ uupayResult);
Message msg =
new
Message();
if
(uupayResult.equalsIgnoreCase(
"success"
)) {
msg.what = UUPAYSUCCESS;
}
else
if
(uupayResult.equalsIgnoreCase(
"fail"
)) {
msg.what = UUPAYFAIL;
}
/*else if (uupayResult.equalsIgnoreCase("cancel")) {
msg = "用户取消了支付";
}*/
handler.sendMessage(msg);
}
super
.onActivityResult(requestCode, resultCode, data);
}
|
微信
关键方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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);
}
|
处理支付结果:在WXPayEntryActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
errCode = resp.errCode;
Logger.i(TAG,
"微信支付结果:"
+ String.valueOf(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();*/
}
Message msg =
new
Message();
if
(errCode ==
0
) {
msg.what = PayActivity.WEIXINPAYSUCCESS;
}
else
{
msg.what = PayActivity.WEIXINPAYFAIL;
}
PayActivity.instance.handler.sendMessage(msg);
finish();
|
安全码:
数字签名+";"+包名; 输入“安全码”。安全码的组成规则为:Android签名证书的sha1值+“;”+packagename(即:数字签名+分号+包名),例如: BB:0D:AC:74:D3:21:E1:43:67:71:9B:62:91:AF:A1:66:6E:44:5D:75;com.baidumap.dem
1
2
3
4
5
6
7
8
9
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
|
public
class
PayDemoActivity
extends
FragmentActivity {
// 商户PID
public
static
final
String PARTNER =
"2016012501118845"
;
// 商户收款账号
public
static
final
String SELLER =
"6225757524716173"
;
// 商户私钥,pkcs8格式
public
static
final
String RSA_PRIVATE =
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALTam792ATycFFDXWg6VEQofa3lT4qWkmcyXLnbSZVHV/brDdDNfeHMJWwvsvuJYNxEDZOYL/AA7/WuBLI+KklXhFUnu/NjQWmXzndiQI15Mfq+2TDh1Cf9H7ypUHah8RrcTwaM9H1/SWP7f2o2QOucB2Y/bI4Faq3ISwONXztTvAgMBAAECgYEAjK4cRwOhFKeIehX6XKuB9LDaJielfxoZ9PaI0y74V38w/q15X1jdVgaqBw2ismjSdO6B9xzNatU/XPe/VO0CxHFZ3/5Qhc/b724MsTxGyVC8TMI/oHMgAlVE3cR4/fwj0fhsYUYbSy9yCTqyinpdLZcNkUpMBJaeaM4jQJZvaSECQQDm7TrKPyJ1mgkKZADco+/HzcX1OnLvGtjFnSxD4LUShFfpYW5bWthy+869Jt9iIbOVDkvrfANMKhOuk0sEany/AkEAyH2SUFJUA1r+csi6WDf694npi6gtY0MhcNgGmoVr3g1daWf3cbx81VUE9y4ffqH91mdxWlVMVsCQetNYywdD0QJAAKQsA5/FQrpYyBSbBAHYip+BqzqsUwmqDHJxSwb2ucRwUg+ZNNu9uiQE4PWYrTcWvpU5lL/VaoK7Z0K1dJ+vFQJBAKV78F7X9XxniQqZYCYc3sufS+P4Rq5d5KZNyPWWFvjLs0SjifyZBbjYWibkLR7K+sgTzd4v9bjNbPPUqr+6GWECQAk6JYzWuS8D7ns/JEbI1fuUzm2U8/Q2R60dq7EFtbw+Po1dxZzUJ+V5JhW9exvhrr7lVII/0aB8nv/LUE+2XCo="
;
// 支付宝公钥
public
static
final
String RSA_PUBLIC =
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOaTXyiUeJHkrIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsraprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUrCmZYI/FCEa3/cNMW0QIDAQAB"
;
private
static
final
int
SDK_PAY_FLAG =
1
;
private
static
final
int
SDK_CHECK_FLAG =
2
;
private
Handler mHandler =
new
Handler() {
public
void
handleMessage(Message msg) {
switch
(msg.what) {
case
SDK_PAY_FLAG: {
PayResult payResult =
new
PayResult((String) msg.obj);
/**
* 同步返回的结果必须放置到服务端进行验证(验证的规则请看https://doc.open.alipay.com/doc2/
* detail.htm?spm=0.0.0.0.xdvAU6&treeId=59&articleId=103665&
* docType=1) 建议商户依赖异步通知
*/
String resultInfo = payResult.getResult();
// 同步返回需要验证的信息
String resultStatus = payResult.getResultStatus();
// 判断resultStatus 为“9000”则代表支付成功,具体状态码代表含义可参考接口文档
if
(TextUtils.equals(resultStatus,
"9000"
)) {
Toast.makeText(PayDemoActivity.
this
,
"支付成功"
,
Toast.LENGTH_SHORT).show();
}
else
{
// 判断resultStatus 为非"9000"则代表可能支付失败
// "8000"代表支付结果因为支付渠道原因或者系统原因还在等待支付结果确认,最终交易是否成功以服务端异步通知为准(小概率状态)
if
(TextUtils.equals(resultStatus,
"8000"
)) {
Toast.makeText(PayDemoActivity.
this
,
"支付结果确认中"
,
Toast.LENGTH_SHORT).show();
}
else
{
// 其他值就可以判断为支付失败,包括用户主动取消支付,或者系统返回的错误
Toast.makeText(PayDemoActivity.
this
,
"支付失败"
,
Toast.LENGTH_SHORT).show();
}
}
break
;
}
case
SDK_CHECK_FLAG: {
Toast.makeText(PayDemoActivity.
this
,
"检查结果为:"
+ msg.obj,
Toast.LENGTH_SHORT).show();
break
;
}
default
:
break
;
}
};
};
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.pay_main);
}
/**
* call alipay sdk pay. 调用SDK支付
*
*/
public
void
pay(View v) {
if
(TextUtils.isEmpty(PARTNER) || TextUtils.isEmpty(RSA_PRIVATE)
|| TextUtils.isEmpty(SELLER)) {
new
AlertDialog.Builder(
this
)
.setTitle(
"警告"
)
.setMessage(
"需要配置PARTNER | RSA_PRIVATE| SELLER"
)
.setPositiveButton(
"确定"
,
new
DialogInterface.OnClickListener() {
public
void
onClick(
DialogInterface dialoginterface,
int
i) {
//
finish();
}
}).show();
return
;
}
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();
System.out.println(
"payInfo==========="
+ payInfo);
Runnable payRunnable =
new
Runnable() {
@Override
public
void
run() {
// 构造PayTask 对象
PayTask alipay =
new
PayTask(PayDemoActivity.
this
);
// 调用支付接口,获取支付结果
String result = alipay.pay(payInfo,
true
);
Message msg =
new
Message();
msg.what = SDK_PAY_FLAG;
msg.obj = result;
mHandler.sendMessage(msg);
}
};
// 必须异步调用
Thread payThread =
new
Thread(payRunnable);
payThread.start();
}
/**
* check whether the device has authentication alipay account.
* 查询终端设备是否存在支付宝认证账户
*
*/
public
void
check(View v) {
Runnable checkRunnable =
new
Runnable() {
@Override
public
void
run() {
// 构造PayTask 对象
PayTask payTask =
new
PayTask(PayDemoActivity.
this
);
// 调用查询接口,获取查询结果
boolean
isExist = payTask.checkAccountIfExist();
Message msg =
new
Message();
msg.what = SDK_CHECK_FLAG;
msg.obj = isExist;
mHandler.sendMessage(msg);
}
};
Thread checkThread =
new
Thread(checkRunnable);
checkThread.start();
}
/**
* get the sdk version. 获取SDK版本号
*
*/
public
void
getSDKVersion() {
PayTask payTask =
new
PayTask(
this
);
String version = payTask.getVersion();
Toast.makeText(
this
, version, Toast.LENGTH_SHORT).show();
}
/**
* 原生的H5(手机网页版支付切natvie支付) 【对应页面网页支付按钮】
*
* @param v
*/
public
void
h5Pay(View v) {
Intent intent =
new
Intent(
this
, H5PayDemoActivity.
class
);
Bundle extras =
new
Bundle();
/**
* url是测试的网站,在app内部打开页面是基于webview打开的,demo中的webview是H5PayDemoActivity,
* demo中拦截url进行支付的逻辑是在H5PayDemoActivity中shouldOverrideUrlLoading方法实现,
* 商户可以根据自己的需求来实现
*/
String url =
"http://m.taobao.com"
;
// url可以是一号店或者美团等第三方的购物wap站点,在该网站的支付过程中,支付宝sdk完成拦截支付
extras.putString(
"url"
, url);
intent.putExtras(extras);
startActivity(intent);
}
/**
* create the order info. 创建订单信息
*
*/
private
String getOrderInfo(String subject, String body, String price) {
// 签约合作者身份ID
String orderInfo =
"partner="
+
"\""
+ PARTNER +
"\""
;
// 签约卖家支付宝账号
orderInfo +=
"&seller_id="
+
"\""
+ SELLER +
"\""
;
// 商户网站唯一订单号
orderInfo +=
"&out_trade_no="
+
"\""
+ getOutTradeNo() +
"\""
;
// 商品名称
orderInfo +=
"&subject="
+
"\""
+ subject +
"\""
;
// 商品详情
orderInfo +=
"&body="
+
"\""
+ body +
"\""
;
// 商品金额
orderInfo +=
"&total_fee="
+
"\""
+ price +
"\""
;
// 服务器异步通知页面路径
orderInfo +=
"¬ify_url="
+
"\""
+
"http://notify.msp.hk/notify.htm"
+
"\""
;
// 服务接口名称, 固定值
orderInfo +=
"&service=\"mobile.securitypay.pay\""
;
// 支付类型, 固定值
orderInfo +=
"&payment_type=\"1\""
;
// 参数编码, 固定值
orderInfo +=
"&_input_charset=\"utf-8\""
;
// 设置未付款交易的超时时间
// 默认30分钟,一旦超时,该笔交易就会自动被关闭。
// 取值范围:1m~15d。
// m-分钟,h-小时,d-天,1c-当天(无论交易何时创建,都在0点关闭)。
// 该参数数值不接受小数点,如1.5h,可转换为90m。
orderInfo +=
"&it_b_pay=\"30m\""
;
// extern_token为经过快登授权获取到的alipay_open_id,带上此参数用户将使用授权的账户进行支付
// orderInfo += "&extern_token=" + "\"" + extern_token + "\"";
// 支付宝处理完请求后,当前页面跳转到商户指定页面的路径,可空
orderInfo +=
"&return_url=\"m.alipay.com\""
;
// 调用银行卡支付,需配置此参数,参与签名, 固定值 (需要签约《无线银行卡快捷支付》才能使用)
// orderInfo += "&paymethod=\"expressGateway\"";
return
orderInfo;
}
/**
* get the out_trade_no for an order. 生成商户订单号,该值在商户端应保持唯一(可自定义格式规范)
*
*/
private
String getOutTradeNo() {
SimpleDateFormat format =
new
SimpleDateFormat(
"MMddHHmmss"
,
Locale.getDefault());
Date date =
new
Date();
String key = format.format(date);
Random r =
new
Random();
key = key + r.nextInt();
key = key.substring(
0
,
15
);
return
key;
}
/**
* sign the order info. 对订单信息进行签名,即加密
*
* @param content
* 待签名订单信息
*/
private
String sign(String content) {
return
SignUtils.sign(content, RSA_PRIVATE);
}
/**
* get the sign type we use. 获取签名方式
*
*/
private
String getSignType() {
return
"sign_type=\"RSA\""
;
}
}
|