拿到支付宝接口的andriod demo后有点无语,集成一个支付服务而已,要在十几个java类之间引用来引用去,这样不仅容易导致应用本身代码结构的复杂化,调试起来也很累,于是操刀改造之:
该删的删,该改写的改写,MobileSecurePayer之外的内容全部整合到MobileSecurePayerHelper之中。
|
/*
* Copyright (C) 2010 The MobileSecurePay Project
* All right reserved.
* author: shiqun.shi@alipay.com
*modify: fangle
*/
package
com.alipay.android;
import
java.io.BufferedReader;
import
java.io.File;
import
java.io.FileOutputStream;
import
java.io.IOException;
import
java.io.InputStream;
import
java.io.InputStreamReader;
import
java.io.OutputStream;
import
java.net.HttpURLConnection;
import
java.net.URL;
import
java.security.KeyFactory;
import
java.security.PrivateKey;
import
java.security.PublicKey;
import
java.security.Signature;
import
java.security.spec.PKCS8EncodedKeySpec;
import
java.security.spec.X509EncodedKeySpec;
import
java.util.ArrayList;
import
java.util.List;
import
javax.crypto.Cipher;
import
org.apache.http.client.entity.UrlEncodedFormEntity;
import
org.apache.http.message.BasicNameValuePair;
import
org.json.JSONException;
import
org.json.JSONObject;
import
android.content.Context;
import
android.content.Intent;
import
android.content.pm.PackageInfo;
import
android.net.Uri;
import
android.os.Handler;
import
android.os.Message;
import
android.util.Base64;
public
class
MobileSecurePayHelper {
static
final
String TAG =
"MobileSecurePayHelper"
;
public
static
final
String PARTNER =
""
;
public
static
final
String SELLER =
""
;
public
static
final
String RSA_PRIVATE =
""
;
public
static
final
String RSA_ALIPAY_PUBLIC =
""
;
Context mContext =
null
;
Handler mHandler =
null
;
String mUrl =
null
;
String mPath =
null
;
public
static
String Stream2String(InputStream is) {
BufferedReader reader =
new
BufferedReader(
new
InputStreamReader(is));
StringBuilder sb =
new
StringBuilder();
String line =
null
;
try
{
while
((line = reader.readLine()) !=
null
)
sb.append(line);
is.close();
}
catch
(IOException e) {
e.printStackTrace();
}
return
sb.toString();
}
public
static
JSONObject string2JSON(String str, String split) {
JSONObject json =
new
JSONObject();
try
{
String[] arrStr = str.split(split);
for
(
int
i =
0
; i < arrStr.length; i++) {
String[] arrKeyValue = arrStr[i].split(
"="
);
json.put(arrKeyValue[
0
],
arrStr[i].substring(arrKeyValue[
0
].length() +
1
));
}
}
catch
(Exception e) {
e.printStackTrace();
}
return
json;
}
public
static
String SendAndWaitResponse(String strReqData, String strUrl) {
String strResponse =
null
;
ArrayList<BasicNameValuePair> pairs =
new
ArrayList<BasicNameValuePair>();
pairs.add(
new
BasicNameValuePair(
"requestData"
, strReqData));
HttpURLConnection conn =
null
;
UrlEncodedFormEntity p_entity;
try
{
p_entity =
new
UrlEncodedFormEntity(pairs,
"utf-8"
);
URL url =
new
URL(strUrl);
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(
30
*
1000
);
conn.setReadTimeout(
30
*
1000
);
conn.setDoOutput(
true
);
conn.addRequestProperty(
"Content-type"
,
"application/x-www-form-urlencoded;charset=utf-8"
);
conn.connect();
OutputStream os = conn.getOutputStream();
p_entity.writeTo(os);
os.flush();
InputStream content = conn.getInputStream();
strResponse = Stream2String(content);
}
catch
(IOException e) {
e.printStackTrace();
}
finally
{
conn.disconnect();
}
return
strResponse;
}
public
static
boolean
urlDownloadToFile(Context context, String strurl,
String path) {
boolean
bRet =
false
;
try
{
URL url =
new
URL(strurl);
HttpURLConnection conn =
null
;
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(
30
*
1000
);
conn.setReadTimeout(
30
*
1000
);
conn.setDoInput(
true
);
conn.connect();
InputStream is = conn.getInputStream();
File file =
new
File(path);
file.createNewFile();
FileOutputStream fos =
new
FileOutputStream(file);
byte
[] temp =
new
byte
[
1024
];
int
i =
0
;
while
((i = is.read(temp)) >
0
)
fos.write(temp,
0
, i);
fos.close();
is.close();
bRet =
true
;
}
catch
(IOException e) {
e.printStackTrace();
}
return
bRet;
}
public
static
String RsaEncode(String content, String key) {
try
{
X509EncodedKeySpec x509 =
new
X509EncodedKeySpec(Base64.decode(key,
Base64.DEFAULT));
KeyFactory kf = KeyFactory.getInstance(
"RSA"
);
PublicKey pubKey = kf.generatePublic(x509);
Cipher cipher = Cipher.getInstance(
"RSA/ECB/PKCS1Padding"
);
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte
plaintext[] = content.getBytes(
"UTF-8"
);
byte
[] output = cipher.doFinal(plaintext);
return
new
String(Base64.encode(output, Base64.DEFAULT));
}
catch
(Exception e) {
e.printStackTrace();
}
return
null
;
}
public
static
String RsaSign(String content, String privateKey) {
try
{
PKCS8EncodedKeySpec pkcs8 =
new
PKCS8EncodedKeySpec(Base64.decode(
privateKey, Base64.DEFAULT));
KeyFactory kf = KeyFactory.getInstance(
"RSA"
);
PrivateKey priKey = kf.generatePrivate(pkcs8);
Signature signature = Signature.getInstance(
"SHA1WithRSA"
);
signature.initSign(priKey);
signature.update(content.getBytes(
"utf-8"
));
byte
[] signed = signature.sign();
return
new
String(Base64.encode(signed, Base64.DEFAULT));
}
catch
(Exception e) {
e.printStackTrace();
}
return
null
;
}
public
static
boolean
RsaCheck(String content, String sign, String publicKey) {
try
{
KeyFactory keyFactory = KeyFactory.getInstance(
"RSA"
);
byte
[] encodedKey = Base64.decode(publicKey, Base64.DEFAULT);
PublicKey pubKey = keyFactory
.generatePublic(
new
X509EncodedKeySpec(encodedKey));
Signature signature = Signature.getInstance(
"SHA1WithRSA"
);
signature.initVerify(pubKey);
signature.update(content.getBytes(
"utf-8"
));
boolean
bverify = signature.verify(Base64.decode(sign,
Base64.DEFAULT));
return
bverify;
}
catch
(Exception e) {
e.printStackTrace();
}
return
false
;
}
public
MobileSecurePayHelper(Context context, Handler handler) {
mContext = context;
mHandler = handler;
}
public
boolean
detectService() {
boolean
isExist =
false
;
List<PackageInfo> pkgList = mContext.getPackageManager()
.getInstalledPackages(
0
);
for
(
int
i =
0
; i < pkgList.size(); i++) {
if
(pkgList.get(i).packageName
.equalsIgnoreCase(
"com.alipay.android.app"
))
isExist =
true
;
}
return
isExist;
}
public
void
downloadAliMSP() {
JSONObject Resp =
null
;
try
{
JSONObject req =
new
JSONObject();
req.put(
"action"
,
"update"
);
JSONObject data =
new
JSONObject();
data.put(
"platform"
,
"android"
);
data.put(
"version"
,
"2.2.3"
);
data.put(
"partner"
,
""
);
req.put(
"data"
, data);
Resp =
new
JSONObject(SendAndWaitResponse(req.toString(),
mUrl = Resp.getString(
"updateUrl"
);
}
catch
(JSONException e) {
e.printStackTrace();
return
;
}
new
Thread(
new
Runnable() {
public
void
run() {
mPath = mContext.getCacheDir().getAbsolutePath() +
"/temp.apk"
;
urlDownloadToFile(mContext, mUrl, mPath);
Message msg =
new
Message();
msg.what =
2
;
mHandler.sendMessage(msg);
}
}).start();
}
public
void
installAliMSP() {
if
(mPath ==
null
)
return
;
try
{
Runtime.getRuntime().exec(
"chmod 777 "
+ mPath);
}
catch
(IOException e) {
e.printStackTrace();
}
Intent intent =
new
Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
"application/vnd.android.package-archive"
);
mContext.startActivity(intent);
}
}
|
集成很简单,一个OnClickListener负责调用支付服务,一个Handler负责处理支付过程中的相应事件:
|
private
Handler m_mspHandler =
new
Handler() {
public
void
handleMessage(Message m) {
// 1:支付返回
// 2:支付组件下载完成
TextView tv = (TextView) findViewById(R.id.order_tips);
Button bt = (Button) findViewById(R.id.order_ok);
ProgressBar pb = (ProgressBar) findViewById(R.id.order_wait);
switch
(m.what) {
case
1
:
String ret = (String) m.obj;
String memo =
"memo={"
;
int
start = ret.indexOf(memo) + memo.length();
int
end = ret.indexOf(
"};result="
);
memo = ret.substring(start, end);
m_tips += memo;
if
(memo.indexOf(
"付款成功"
) >=
0
)
m_tips +=
"\r\n请注意查看短信,您将收到二维码凭证"
;
tv.setText(m_tips);
bt.setVisibility(
0
);
pb.setVisibility(
4
);
break
;
case
2
:
m_tips +=
"安全支付组件下载完成,开始安装...\r\n"
;
tv.setText(m_tips);
m_mspHelper.installAliMSP();
bt.setVisibility(
0
);
pb.setVisibility(
4
);
break
;
}
}
};
private
OnClickListener m_orderButtonListener =
new
OnClickListener() {
public
void
onClick(View v) {
String mobile = m_mobileEdt.getText().toString();
m_tips =
""
;
TextView tv = (TextView) findViewById(R.id.order_tips);
Button bt = (Button) findViewById(R.id.order_ok);
ProgressBar pb = (ProgressBar) findViewById(R.id.order_wait);
if
(mobile.length() !=
11
) {
m_tips +=
"无效的收货号码\r\n"
;
tv.setText(m_tips);
return
;
}
if
(!m_date.after(m_today)) {
m_tips +=
"订货日期不能早于明天\r\n"
;
tv.setText(m_tips);
return
;
}
"MakeOrder"
);
request.addProperty(
"Uname"
, m_intent.getStringExtra(
"userid"
));
request.addProperty(
"ProductId"
,
m_intent.getStringExtra(
"item_PID"
));
request.addProperty(
"Sum"
,
"1"
);
request.addProperty(
"PayAmount"
,
m_intent.getStringExtra(
"item_price"
));
request.addProperty(
"SMSMobile"
, mobile);
request.addProperty(
"ExpireDate"
,
String.format(
"%04d-%02d-%02d"
, m_date.get(
1
),
m_date.get(
2
) +
1
, m_date.get(
5
)));
// 显示等待条,提交订单信息
m_tips +=
"正在创建订单,请稍候...\r\n"
;
tv.setText(m_tips);
bt.setVisibility(
4
);
pb.setVisibility(
0
);
HttpTransportSE httpTransport =
new
HttpTransportSE(
SoapSerializationEnvelope envelope =
new
SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.dotNet =
true
;
envelope.bodyOut = request;
String respond;
try
{
httpTransport.call(request.getNamespace() + request.getName(),
envelope);
if
(envelope.getResponse() !=
null
)
respond = envelope.getResponse().toString();
else
respond =
"false,null"
;
}
catch
(Exception ex) {
respond =
"false,"
+ ex.getMessage();
}
if
(respond.substring(
0
,
5
).equals(
"false"
)) {
m_tips +=
"创建订单失败:"
+ respond.substring(
6
) +
"\r\n"
;
tv.setText(m_tips);
bt.setVisibility(
0
);
pb.setVisibility(
4
);
return
;
}
String msgs[] = respond.split(
"[,]"
);
String order;
m_tips +=
"创建订单成功,开始支付...\r\n"
;
tv.setText(m_tips);
if
(!m_mspHelper.detectService()) {
m_tips +=
"未安装安全支付组件,开始下载...\r\n"
;
tv.setText(m_tips);
m_mspHelper.downloadAliMSP();
return
;
}
order = String.format(
"partner=\"%s\""
,
MobileSecurePayHelper.PARTNER);
order += String.format(
"&seller=\"%s\""
,
MobileSecurePayHelper.SELLER);
order += String.format(
"&out_trade_no=\"%s\""
, msgs[
1
]);
order += String.format(
"&subject=\"%s\""
,
m_intent.getStringExtra(
"item_type"
));
order += String.format(
"&body=\"%s\""
,
m_intent.getStringExtra(
"item_name"
));
order += String.format(
"&total_fee=\"%s\""
,
m_intent.getStringExtra(
"item_price"
));
order += String.format(
"?ify_url=\"%s\""
,
String sign = URLEncoder.encode(MobileSecurePayHelper.RsaSign(
order, MobileSecurePayHelper.RSA_PRIVATE));
order += String.format(
"&sign=\"%s\""
, sign);
order += String.format(
"&sign_type=\"%s\""
,
"RSA"
);
com.alipay.android.MobileSecurePayer msp =
new
com.alipay.android.MobileSecurePayer();
if
(!msp.pay(order, m_mspHandler,
1
, OrderingActivity.
this
)) {
m_tips +=
"调用安全支付功能失败\r\n"
;
tv.setText(m_tips);
bt.setVisibility(
0
);
pb.setVisibility(
4
);
return
;
}
}
};
|