http://blog.csdn.net/kroclin/article/details/40746779java
1、前言android
最近作的項目恰好要集成支付寶,上網找了不少資料,介紹得感受不是很全面,因此我通過這兩天的集成,順便記錄下來,學習交流。須要的朋友也能夠看看。主要集成仍是參照了官方給出的demo,再參照demo進行封裝,如今使用起來變得方便好多。並且文章裏面還提到了集成過程當中遇到的一些問題,固然最後也都解決了。安全
2、準備工做app
支付寶開放平臺上面也明確了,目前僅僅支持企業用戶申請,因此我的開發者就無法使用到。但願支付寶早日能夠開放給我的開發者。學習
支付寶的集成是相對比較麻煩,其中涉及到了不少東西要弄,要生成私鑰公鑰等等。文檔裏面也有詳細說到如何如何生成那些東西,不過就是文檔的內容量有點多了,看起來總抓不住先後,這裏我稍做整理,把android須要用到的提取出來了。測試
一、PIDui
首先說一下就是支付寶的支付是這樣的,企業用戶申請了支付寶以後,支付寶就會提供一個合做者id,就是所謂的pid,是2088開頭的16位純數字;編碼
二、支付寶帳戶url
這個就是你用於收款用的支付寶帳號,要跟申請時候同一個。spa
如下幾個要運行我附件中的「移動支付接口智能SDK版"中,\openssl\bin文件夾下面的openssl.exe生成,這個是由支付寶提供的
三、RSA私鑰:genrsa -out rsa_private_key.pem 1024
運行完命令行能夠看到bin文件夾下面會生成私鑰
![](http://static.javashuo.com/static/loading.gif)
四、RSA公鑰:rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
運行完命令行後能夠看到生成了公鑰
![](http://static.javashuo.com/static/loading.gif)
五、PKCS8編碼的私鑰:pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
運行完後,將生成的東西拷貝下來放到文本文件裏面就行。這後面要用到的!!包括begin跟end那兩句一塊兒存起來
![](http://static.javashuo.com/static/loading.gif)
3、支付過程
須要進行再封裝的主要有下面這個類,作幾點說明,AliPayParamsBO是我封裝的一個實體類,由於我把剛剛上面講到的那些PID、私鑰啊等等都放在服務端了,這樣會比較安全,就算別人反編譯了你的項目,那也看不到什麼東西,支付寶官方也是這樣建議的。測試的時候,能夠把這個AliPayParamsBO類,裝進你生成的那些參數去測試就好啦,至於OrderBO類,也是我封裝的一個類,裏面主要包含的是這個訂單相關的一些東西,好比商品名稱、商品介紹,價格等等,這些在支付過程當中都是必要的。
而須要強調一點就是,產生這個支付過程當中,我先是構造好須要請求的參數,注意一點就是我在createOrderInfo()方法中對參數進行構造,可是 sign、sign_type 兩個參數先不要參與,由於這兩個參數不須要參與簽名,等前面那些參數構造好了以後,簽完名再將sign、sign_type 兩個參數構造進去,再進行支付。
- import java.io.UnsupportedEncodingException;
- import java.net.URLEncoder;
-
- import android.os.Handler;
- import android.os.Message;
-
- import com.alipay.android.app.sdk.AliPay;
- import com.common.ui.BaseActivity;
- import com.common.utils.CLog;
- import com.onecity.cs.bo.AliPayParamsBO;
- import com.onecity.cs.bo.OrderBO;
-
- public class AlipayUtil {
-
- private static final String TAG = "PayActivity";
- public static final int RQF_PAY = 1;
- public static final int RQF_LOGIN = 2;
-
-
- public static void pay(final BaseActivity activity, AliPayParamsBO aliPayBO, OrderBO orderBO, final Handler handler){
- try {
- String info = createOrderInfo(orderBO, aliPayBO);
- String sign = Rsa.sign(info, aliPayBO.getPrivate_key_pkcs8());
- sign = URLEncoder.encode(sign, "utf-8");
- info += "&sign=\"" + sign + "\"&" + getSignType();
- CLog.log("ExternalPartner", "start pay");
-
- CLog.log(TAG, "info = " + info);
-
- final String orderInfo = info;
- new Thread() {
- public void run() {
- AliPay alipay = new AliPay(activity, handler);
-
-
-
-
- String result = alipay.pay(orderInfo);
- CLog.log(TAG, "result = " + result);
- Message msg = handler.obtainMessage();
- msg.what = RQF_PAY;
- msg.obj = result;
- handler.sendMessage(msg);
- }
- }.start();
-
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
-
-
- private static String createOrderInfo(OrderBO orderBO, AliPayParamsBO aliPayBO)
- throws UnsupportedEncodingException {
- StringBuilder sb = new StringBuilder();
- sb.append("partner=\"");
- sb.append(aliPayBO.getPid());
- sb.append("\"&out_trade_no=\"");
- sb.append(orderBO.getOrder_sn());
- sb.append("\"&subject=\"");
- sb.append(orderBO.getSubject());
- sb.append("\"&body=\"");
- sb.append(orderBO.getBody());
- sb.append("\"&total_fee=\"");
- sb.append(
- sb.append("\"¬ify_url=\"");
-
-
- sb.append(URLEncoder.encode(aliPayBO.getNotify_url(), "utf-8"));
- sb.append("\"&service=\"mobile.securitypay.pay");
- sb.append("\"&_input_charset=\"UTF-8");
- sb.append("\"&return_url=\"");
- sb.append(URLEncoder.encode("http://m.alipay.com", "utf-8"));
- sb.append("\"&payment_type=\"1");
- sb.append("\"&seller_id=\"");
- sb.append(aliPayBO.getAccount());
-
-
-
- sb.append("\"&it_b_pay=\"1m");
- sb.append("\"");
-
- return new String(sb);
- }
-
- private static String getSignType() {
- return "sign_type=\"RSA\"";
- }
- }
遇到的問題:整個過程仍是比較順利的,一開始我是使用了4.0系統的手機進行測試,也可以正常使用。可是跑給同事手機以後,問題出現了,竟然出現了。。點擊支付的時候始終喚不起支付頁面,還報了 failure calling remote service 異常,而後就挺納悶,查了代碼發現好像沒啥問題。
立刻去打印log,看到了以下問題:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
看了以上異常信息以後個人第一反應就是難道個人私鑰弄錯了,但想一想4.0仍是沒問題的啊。後來就追查到了代碼中,就在Rsa類中的sign方法,這是支付寶給出的類,我就在異常中將異常信息打印出來,果然
![](http://static.javashuo.com/static/loading.gif)
仍是編碼問題。
- public static String sign(String content, String privateKey) {
- String charset = "UTF-8";
- try {
- PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
- Base64.decode(privateKey));
- KeyFactory keyf = KeyFactory.getInstance("RSA");
- PrivateKey priKey = keyf.generatePrivate(priPKCS8);
-
- java.security.Signature signature = java.security.Signature
- .getInstance(SIGN_ALGORITHMS);
-
- signature.initSign(priKey);
- signature.update(content.getBytes(charset));
-
- byte[] signed = signature.sign();
-
- return Base64.encode(signed);
- } catch (Exception e) {
- e.printStackTrace();
- System.out.println("Exception="+e.getMessage());
- }
-
- return null;
- }
而後我就忽然想到了上面生成的 「PKCS8編碼的私鑰」,而後將剛剛上面那個AlipayUtil類的pay方法裏面的
- String sign = Rsa.sign(info, aliPayBO.getPrivate_key_pkcs8());
簽名時用的就是 「PKCS8編碼的私鑰」(本來出問題是用到RSA私鑰),代碼中改過來了。此次就好了啦,不管4.0如下仍是以上通殺。界面以下:
![](http://static.javashuo.com/static/loading.gif)
好啦,客戶端的集成大概就是這樣,其餘相關的類是按照支付寶demo裏面的,就不要展現出來了,須要的到代碼下載裏面去下載就ok啦~