Delphi XE7 Android
應用接入支付寶SDK的方法
1 應用場景和准備工作:
- 采用XE系列開發的android apps。
- apps中需要集成支付寶的支付能力。
- 支付到指定的商家(一般就是軟件開發商自己啦),商家需要事先在支付寶的開放平台申請開通【支付寶無線快捷支付】,具體請百度。
- 開通【無線快捷支付】后,支付寶應該返回給商家如下幾個重要參數:
l PARTNER(商戶ID): 一個16為的字符串,應該都是數字。
l SELLER(商戶名):多數是商戶的郵件地址。
l RSA_PRIVATE(商戶私鑰 ): 一個848位的字符串,采用pkcs8編碼過。
l RSA_PRIVATE(商戶私鑰 ): 一個848位的字符串。
l RSA_PUBLIC(商戶公鑰):一個218位的經過pkcs8編碼的字符串。這個公鑰並沒有用到,是支付寶后台用的。
- 5. 以上幾個參數,都是支付寶再審核通過后,通過郵件發送給商家的,其中RSA的兩個公私鑰,需要商戶自己根據手冊自行生成並上傳和保存,具體這一步請務必參考支付寶開放平台的說明。
2 XE7中的開發准備工作:
- 下載一個java2op.exe,備用。
- 建立一個android的應用。
- copy支付寶sdk的三個jar包到工程目錄(最好和你的pas文件一個目錄,最好也把java2op這個文件copy到這里。
- 在IDE右邊的ProjectManager中,添加支付寶SDK(android)的三個jar包,如右圖。細心的朋友可能發現多了一個jar包:signutils.jar,這個不是支付寶(alipay)sdk帶的,是我自己加上的,用途我們稍后再說。
- 打開一個CMD命令行窗口。
- 從命令行里,CD到你的工程目錄,有jar包的地方,執行如下命令:
i. java2op -jar alipaysdk.jar -unit alipaysdk
ii. java2op -jar alipaysecsdk.jar -unit alipaysecsdk
iii. javs2op -jar alipayutdid.jar -unit alipayutdid
- 如果一切順利,在當前目錄應該發現新增的這三個pas文件。如圖:
3 XE7中的代碼工作:
- 請按照支付寶SDK的要求,在androidmanifest.template.xml文件總,增加sdk中的activity的引用,如圖:
- 具體這個xml在什么位置,以及這個activity的字符串從何處得來,我就不費力解釋了,相信大家都知道。
- 在支付寶SDK的接入手冊中,針對混淆部分的要求,可以忽略,不用關心。
- 在適當的pas文件中,增加對之前生成的三個pas的引用(附帶幾個要用到的單元,也一並加上吧),如圖:
- 注意:在編譯的時候,這三個pas文件,會報錯,幾乎都是某個"property a"重復定義的問題,請直接手動把每個報錯的‘a’都改為‘aaaaa’,隨便什么即可,刪除也行。
- 開始加入最關鍵的代碼,例如我們要在一個按鈕下開始支付,支付的商品名稱、描述和價格,我們可以用三個edit來作為測試輸入,這里就不截圖描述了,過程如下:
iv.
在pas某個位置,聲明三個常量或者屬性備用,這三個屬性就是之前支付寶返回的參數。
v. 在所謂的【支付按鈕】的事件里,寫如下代碼:
procedure TForm3.Button1Click(Sender: TObject); var PayTask: JPayTask; PayClass: JPayTaskClass; JOrderInfo: JString; OrderInfo,Sign: String; begin PayClass := TJPayTask.JavaClass; PayTask := PayClass.init(MainActivity); OrderInfo := Self.getOrderInfo('abcd','body','0.01'); sign := Self.Sign(OrderInfo); OrderInfo := OrderInfo + '&sign="'+sign+'"'; OrderInfo := OrderInfo + '&sign_type="RSA"'; Self.Memo1.Lines.Text := OrderInfo; //調試用,你懂的。 JOrderInfo := StringToJString(OrderInfo); PayTask.pay(JOrderInfo); end; |
vi. getOrderInfo: 這個函數文檔后面會有,是按照支付寶的要求,對訂單信息進行格式化處理的,這個函數中調用了一個getTradeNo,是自定義的,也就是生成訂單號的,保證不重復即可,隨便寫。
vii. Sign函數:這個函數就用到了之前在前面看到的signutils.jar這個包,原本支付寶的sdk是沒有這包的,這個包是我自己用java編寫並加入到項目中的,原因就是:支付寶sdk要求,需要對訂單信息進行rsa簽名,這個簽名過程比較復雜,熟悉java的,可以下載java的demo來看一下,我嘗試用delphi下的一些工具和第三方組件,但都失敗了,可能是我還不是很熟悉吧,我就把java中的函數封裝到這個jar中,供delphi來調用,很好用,文檔的后面也會有這個函數的代碼,但具體今后每個開發者用什么方法來給訂單做sign的簽名,只能大家各自想辦法了。文檔中,我會鏈接這個jar給大家。
viii. 如果一切正常,應該可以看到支付寶的界面了,至於調試過程中出現的各種錯誤,只能百度。
ix. 系統繁忙,請稍后重試:ALI64: 這個錯誤幾乎都是訂單信息格式不對,或者支付寶返回的各種參數沒有用對,還有可能是沒有開通無線快捷支付。
x. 系統繁忙,請稍后重試:ALI10:這個錯誤主要是sign簽名不對。
- 附錄代碼:
function TForm3.getOrderInfo(subject, body, price: string): string; var s: string; begin // 簽約合作者身份ID s := 'partner="' + PARTNER + '"'; // 簽約賣家支付寶賬號 s := s + '&seller_id="' + SELLER + '"'; // 商戶網站唯一訂單號 s := s+ '&out_trade_no="' + getOutTradeNo + '"'; // 商品名稱 s := s + '&subject="' + subject + '"'; // 商品詳情 s := s + '&body="' + body + '"'; // 商品金額 s := s + '&total_fee="' + price + '"'; // 服務器異步通知頁面路徑 s := s + '¬ify_url="' + 'http://你的業務后台地址,一定要寫,要合法"'; // 服務接口名稱, 固定值 s := s + '&service="mobile.securitypay.pay"'; // 支付類型, 固定值 s := s + '&payment_type="1"'; // 參數編碼, 固定值 s := s + '&_input_charset="utf-8"'; // 設置未付款交易的超時時間 // 默認30分鍾,一旦超時,該筆交易就會自動被關閉。 // 取值范圍:1m~15d。 // m-分鍾,h-小時,d-天,1c-當天(無論交易何時創建,都在0點關閉)。 // 該參數數值不接受小數點,如1.5h,可轉換為90m。 s := s + '&it_b_pay="30m"';
// extern_token為經過快登授權獲取到的alipay_open_id,帶上此參數用戶將使用授權的賬戶進行支付 // orderInfo += "&extern_token=" + "\"" + extern_token + "\"";
// 支付寶處理完請求后,當前頁面跳轉到商戶指定頁面的路徑,可空 s := s + '&return_url="m.alipay.com"';
// 調用銀行卡支付,需配置此參數,參與簽名, 固定值 (需要簽約《無線銀行卡快捷支付》才能使用) // orderInfo += "&paymethod=\"expressGateway\""; Result := s;
end; |
function TForm3.getOutTradeNo: string; var G: TGuid; S: string; begin G := TGuid.NewGuid; S := G.ToString; S := S.Substring(0,15); Result := 'abcdefghijklmn'; end; |
function TForm3.Sign(const Orders: string): string; var SignClass: JSignUtilsClass; Js,jpri: JString; begin Result := ''; try Js := StringToJString(Orders); JPri := StringToJString(RSA_PRIVATE); SignClass := TJSignUtils.JavaClass; SignClass.init; js := SignClass.sign(js,jpri); //js := SignClass.DoURLEncode(js); Result := JStringToString(js); finally end; |
其他:
4 真實業務場景的考慮
按照支付寶或者微信支付的開發手冊的說法,一個標准的客戶端接入支付業務模型應該是這樣的,我忽略時序圖,只用文字描述:
- 用戶登錄客戶端,選擇商品,然后點擊客戶端支付。
- 客戶端收集商品信息,然后調用自己業務平台的預付款接口。
- 業務平台根據客戶端提交的商品信息,生成自己的訂單號等內容,並按照第三方支付的要求對訂單信息進行拼裝組合,並編碼和簽名。
- 業務平台返回簽名后的訂單信息給客戶端。
- 客戶端根據這個簽名信息,呼出客戶端的第三方支付系統,完成支付。