支付寶集成文檔
一、申請移動支付權限
首先登錄【支付寶開放平臺】http://open.alipay.com/platform/home.htm,添加應用,申請移動支付權限。申請開通支付,是需要公司文件的,個人是不允許開始支付的。
二、阿里支付DEMO
自己去下載
2、配置幾個變量
這部分會對代碼中用到的幾個變量的找到方法或生成方法進行講述,部分資料引自支付寶開放平臺。
(1)PID
合作者身份ID(PID)是商戶與支付寶簽約後,商戶獲得的支付寶商戶唯一識別碼。當商戶把支付寶功能接入商戶網站時會用到PID,以便讓支付寶認證商戶。
查看PID步驟如下:
1、登錄支付寶官方網站b.alipay.com
2、點擊導航欄中“商家服務”
3、點擊“查詢PID、Key”
(2)、APPID、APP SECRET和支付寶公鑰
在https://openhome.alipay.com/platform/createApp.htm頁面,創建一個應用
完成之後:在我的應用中是可以看得到的:
然後轉到帳戶基本信息頁面:https://openhome.alipay.com/platform/keyManage.htm
在開放平臺密鑰欄,可以找到APPID,APP SECRET,和支付寶密鑰
這三個數據,都是在應用創建後,支付寶爲我們生成好的,無法更改!
(3)、生成商戶私鑰【windows生成方法】
(有關mac的生成方法,下面會再補充)
1、下載DEMO及SDK
到文檔中心,查看移動支付對應的文檔,文檔地址:http://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103563&docType=1
然後,點擊(SDK&DEMO下載)下載代碼
2、得到原始私鑰
在代碼中的DEMO/openssl/bin目錄下,有openssl.exe文件
打開openssl.exe
輸入
genrsa -out rsa_private_key.pem 1024
得到生成成功的結果,如下圖:
此時,我們可以在bin文件夾中看到一個文件名爲rsa_private_key.pem的文件
用記事本方式打開它,可以看到-----BEGIN RSA PRIVATE KEY-----開頭,-----END RSA PRIVATE KEY-----結尾的沒有換行的字符串,這個就是原始的私鑰。
但這段原始私鑰代碼中是用不到的,我們需要將它轉化爲PKCS8格式
3、轉換爲PKCS8格式
在openssl.exe中輸入:並回車
pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
得到生成功的結果,這個結果就是PKCS8格式的私鑰,如下圖:
注意,私鑰是紅框包括的那部分,是不包含BEGIN PRIVATE KEY和END PRIVATE KEY這兩行的。
右鍵點擊openssl窗口上邊邊緣,選擇編輯→標記,選中要複製的文字(如上圖),
此時繼續右鍵點擊openssl窗口上邊邊緣,選擇編輯→複製,
把複製的內容粘土進一個新的記事本中,可隨便命名,只要知道這個是PKCS8格式的私鑰即可。
(4)、生成商戶私鑰【MAC生成方法】
這裏來講一下mac端如何生成用戶私鑰的,由於mac系統是自帶openssl的,所以只需要打開終端,利用cd命令切到任意一個想存放生成Key的文件夾下:
比如,切到下載目錄下
然後運行下面的命令來生成私鑰原始密鑰
openssl genrsa -out rsa_private_key.pem 1024
然後運行下面的命令來生成轉換的PCKS8格式的命令。
openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
然後將生成的私鑰複製保存起來。
從上面的命令可以看出,與windows相比,mac上需要在前面添加openssl指定運行的是openssl命令。其它命令是完全一致的。
(5)、生成用戶公鑰及網頁填充
1、生成公鑰
同樣對於windows用戶而言,直接在openssl.exe中輸入下面的命令:
rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
同樣,如果是Mac的同學,輸入的命令應該是如下:
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
得到生成成功的結果,如下圖:
此時,我們可以在bin文件夾中看到一個文件名爲rsa_public_key.pem的文件,用記事本方式打開它,可以看到-----BEGIN
PUBLIC KEY-----開頭,
-----END PUBLIC KEY-----結尾的沒有換行的字符串,這個就是公鑰。
在生成網頁以後,複製----BEGIN PUBLIC KEY-----和-----END
PUBLIC KEY-----之間的部分,即那段純代碼,不要把----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----給複製進去了。中間的這部分就是公鑰。
2、網頁填充
然後到https://openhome.alipay.com/platform/keyManage.htm?keyType=partner(需要登錄)中,左側找到合作伙伴密鑰欄,再到右側的RSA加密中,將公鑰粘貼進去。由於,我們已經粘貼進去了,所以這裏顯示查看開發者公鑰,在沒填之前寫的是“添加開發者公鑰”
到這裏,所有的準備工作都已經結束了。下面就是配置DEMO的過程了
3、配置DEMO
在剛纔下載的sdk&demo的源碼中,打開DEMO/客戶端demo/支付寶Android
15.0.1/alipay_demo工程
路徑如下:
在PayDemoActivity中配置幾個變量:
//PID
public static final String PARTNER = "";
在這裏填上我們上面找到的PID;
// 商戶收款賬號
public static final String SELLER = "[email protected]";
然後在SELLER上寫上我們支付寶的登錄帳戶,即那個你申請移動支付的支付寶賬號
// 支付寶公鑰
public static final String RSA_PUBLIC ="";
然後在RSA_PUBLIC這裏填上支付寶公鑰
// 商戶私鑰,pkcs8格式
public static final String RSA_PRIVATE = "";
最後是填上RSA_PRIVATE對應的商戶私鑰,注意是PKCS8格式的。
私鑰這部分,注意是----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----之間的部分,即那段純代碼,不要把----BEGIN
PUBLIC KEY-----和-----END PUBLIC KEY-----給複製進去了。中間的這部分就是公鑰。
現在運行demo就直接可以支付了。
本文中對應的DEMO在文章底部給出。
4、代碼講解
通過上面的配置,demo應該就直接可以運行了,但這裏所涉及的代碼,我們再仔細看看
主要的支付與結果返回就是pay()這個函數,這裏完成了支付所需要的所有功能。代碼如下:
public void pay(View v) {
…………
// 訂單信息
String orderInfo = getOrderInfo("測試的商品", "該測試商品的詳細描述", "0.01");
// 對訂單做RSA 簽名
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();
Runnable payRunnable = new Runnable() {
@Override
public void run() {
// 構造PayTask 對象
PayTask alipay = new PayTask(PayDemoActivity.this);
// 調用支付接口,獲取支付結果
String result = alipay.pay(payInfo);
Message msg = new Message();
msg.what = SDK_PAY_FLAG;
msg.obj = result;
mHandler.sendMessage(msg);
}
};
// 必須異步調用
Thread payThread = new Thread(payRunnable);
payThread.start();
}
這裏總是分了四步來完成支付與結果接收。
第一步:構造定單信息:
String orderInfo = getOrderInfo("測試的商品", "該測試商品的詳細描述", "0.01");
主要是這句,即在getOrderInfo()函數中完成定單信息的構造:(這裏對getOrderInfo函數做的精減,更多字段及意義參考源碼)
有關paymethod的方法使用,參考:https://cshall.alipay.com/support/help_detail.htm?help_id=476935
各個字段的意義及取值參考:http://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103663&docType=1
public 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"
+ "\"";
…………
return orderInfo;
}
這裏就是通過我們的提供的商家ID,產品信息,價格等信息來構造定單及回調頁面,這裏需要非常注意的一個地方:
// 服務器異步通知頁面路徑
orderInfo += "&noify_url=" + "\"" + "http://notify.msp.hk/notify.htm"
+ "\"";
服務器異步通知頁面路徑,首先我們用支付寶支付之後,支付寶會返回給我們兩個通知,一個是同步的,就是我們點擊支付後支付寶直接反饋給我們客戶端的信息,我們可以直接拿到,根據反饋的結果可以初步判定該次交易是否成功,第二個就是服務器異步的通知,這個異步的通知是支付寶的服務器端發給我們服務器端的信息,我們在客戶端是直接獲取不了的,那支付寶的服務器怎麼知道我們服務器的路徑呢,那就是這參數的作用了,我們給支付寶服務器一個路徑,它就會在訂單狀態改變的時候給我們服務器端一個反饋,告訴服務器這次交易的狀態,如果服務器結果判定該次交易成功了,就必須返給支付寶服務器一個success,要不服務器會一直給我們異步通知,因爲它不知道該次交易是否完成了(一般情況下25小時內8次通知,頻率一般是2m
10m 10m 1h 2h 6h 15h),我們一般會在收到異步通知時,對訂單的狀態進行更新。
其它的就不講了,通過看源碼都能看得懂,比如構造訂單號啥的。
第二步:對訂單字符串做RSA簽名
爲什麼要簽名呢?當然是防止傳輸出錯了,這可是跟錢相關的,如果orderInfo傳輸過程中出錯了,那怎麼樣來校驗它是不是出錯了呢,只有通過簽名算法來了。所以這裏就需要對訂單字符串做簽名。
具體簽名算法就不講了,直接應用到項目中就行,不需要理解,如果想看看怎麼實現的,裏面有對應的源碼,可以去研究一下。
// 對訂單做RSA 簽名
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();
第四步:請求與結果返回
最後是發送請求,代碼如下:
Runnable payRunnable = new Runnable() {
@Override
public void run() {
// 構造PayTask 對象
PayTask alipay = new PayTask(PayDemoActivity.this);
// 調用支付接口,獲取支付結果
String result = alipay.pay(payInfo);
Message msg = new Message();
msg.what = SDK_PAY_FLAG;
msg.obj = result;
mHandler.sendMessage(msg);
}
};
// 必須異步調用
Thread payThread = new Thread(payRunnable);
payThread.start();
最關鍵的部分在這裏:
PayTask alipay = new PayTask(PayDemoActivity.this);
// 調用支付接口,獲取支付結果
String result = alipay.pay(payInfo);
Message msg = new Message();
msg.what = SDK_PAY_FLAG;
msg.obj = result;
mHandler.sendMessage(msg);
在String result = alipay.pay(payInfo);中,就直接獲得了支付結果;
然後通過handler將結果發送出去。
這就是同步的方式獲取支付結果的方式。