首页 > 代码库 > Android应用集成支付宝接口的简化

Android应用集成支付宝接口的简化

拿到支付宝接口的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 = http://www.mamicode.com/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 pairs = new ArrayList();

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 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 = http://www.mamicode.com/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(),

"https://msp.alipay.com/x.htm"));

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);

intent.setDataAndType(Uri.parse("file://" + mPath),

"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;

}

SoapObject request = new SoapObject("http://airtimes.cn/",

"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(

"http://www.android-study.com/serv.asmx");

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\"",

"http://www.android-study.com/alipay.aspx");

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;

}

}

};

<iframe id="google_ads_frame2" vspace="0" height="250" marginHeight="0" src="http://googleads.g.doubleclick.net/pagead/ads?client=ca-pub-3447371224873639&output=html&h=250&slotname=8660799060&adk=1970350646&w=300&lmt=1400811521&flash=0&url=http%3A%2F%2Fwww.cnblogs.com%2Fxiaochao1234%2Fp%2F3746061.html&dt=1400811522401&shv=r20140515&cbv=r20140417&saldr=sb&correlator=1400811522303&frm=20&ga_vid=1304086684.1400769066&ga_sid=1400806953&ga_hid=225245089&ga_fc=1&u_tz=480&u_his=187&u_java=1&u_h=768&u_w=1364&u_ah=740&u_aw=1364&u_cd=16&u_nplug=0&u_nmime=0&dff=verdana&dfs=16&adx=0&ady=11970&biw=314&bih=74&eid=317150304&oid=3&rx=0&eae=0&docm=9&vis=0&fu=0&ifi=2&xpc=nUf61FZn08&p=http%3A//www.cnblogs.com&dtd=58" frameBorder="0" width="300" allowTransparency="true" name="google_ads_frame2" marginWidth="0" scrolling="no" hspace="0"></iframe><iframe id="google_ads_frame3" vspace="0" height="250" marginHeight="0" src="http://googleads.g.doubleclick.net/pagead/ads?client=ca-pub-3447371224873639&output=html&h=250&slotname=8660799060&adk=1970350646&w=300&lmt=1400811521&flash=0&url=http%3A%2F%2Fwww.cnblogs.com%2Fxiaochao1234%2Fp%2F3746061.html&dt=1400811522466&shv=r20140515&cbv=r20140417&saldr=sb&prev_slotnames=8660799060&correlator=1400811522303&frm=20&ga_vid=1304086684.1400769066&ga_sid=1400806953&ga_hid=225245089&ga_fc=1&u_tz=480&u_his=187&u_java=1&u_h=768&u_w=1364&u_ah=740&u_aw=1364&u_cd=16&u_nplug=0&u_nmime=0&dff=verdana&dfs=16&adx=306&ady=12220&biw=314&bih=74&eid=317150304&oid=3&rx=0&eae=0&docm=9&vis=0&fu=0&ifi=3&xpc=TQiWABMnlQ&p=http%3A//www.cnblogs.com&dtd=73" frameBorder="0" width="300" allowTransparency="true" name="google_ads_frame3" marginWidth="0" scrolling="no" hspace="0"></iframe>