拿到支付宝接口的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 ; } } }; |