一說到支付寶,相信沒有人不知道,生活中付款,轉帳都會用到。java
今天來詳細介紹下在Android中如何集成支付寶支付到本身的APP中去。讓APP可以擁有方便,快捷的支付功能。express
準備工做:macos
商戶在b.alipay.com裏進行產品簽約
RSA私鑰及公鑰生成
上傳RSA公鑰,簽名驗證
接口調用服務器
一.商戶在b.alipay.com裏進行產品簽約
商戶或者開發者到b.alipay.com進行產品簽約,獲取商戶的PID。app
二.RSA私鑰及公鑰生成
生成方式一(推薦):使用支付寶提供的一鍵生成工具:
Windwos:
點擊下載
MAC OSX:
點擊下載
解壓打開文件夾,直接運行「支付寶RAS密鑰生成器SHAwithRSA1024_V1.0.bat」(WINDOWS)或「SHAwithRSA1024_V1.0.command」(MACOSX),點擊「生成RSA密鑰」,會自動生成公私鑰,而後點擊「打開文件位置」,便可找到工具自動生成的密鑰。
生成方式二:也可使用OpenSSL工具命令生成
首先進入OpenSSL工具,再輸入如下命令。
- <span style="font-size:12px">OpenSSL> genrsa -out rsa_private_key.pem 1024 #生成私鑰
- OpenSSL> pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out rsa_private_key_pkcs8.pem #Java開發者須要將私鑰轉換成PKCS8格式
- OpenSSL> rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem #生成公鑰
- OpenSSL> exit #退出OpenSSL程序</span>
通過以上步驟,開發者能夠在當前文件夾中(OpenSSL運行文件夾),看到rsa_private_key.pem(RSA私鑰)、rsa_private_key_pkcs8.pem(pkcs8格式RSA私鑰)和rsa_public_key.pem(對應RSA公鑰)3個文件。開發者將私鑰保留,將公鑰提交給支付寶網關,用於驗證簽名。如下爲私鑰文件和公鑰文件示例。
注意:對於使用Java的開發者,將pkcs8在console中輸出的私鑰去除頭尾、換行和空格,做爲開發者私鑰,對於.NET和PHP的開發者來講,無需進行pkcs8命令行操做。dom
PKCS8處理後的私鑰文件示例:異步
- <span style="font-size:12px">-----BEGIN PRIVATE KEY-----
- MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAN0yqPkLXlnhM+2H/57aHsYHaHXazr9pFQun907TMvmbR04wHChVsKVgGUF1hC0FN9hfeYT5v2SXg1WJSg2tSgk7F29SpsF0I36oSLCIszxdu7ClO7c22mxEVuCjmYpJdqb6XweAZzv4Is661jXP4PdrCTHRdVTU5zR9xUByiLSVAgMBAAECgYEAhznORRonHylm9oKaygEsqQGkYdBXbnsOS6busLi6xA+iovEUdbAVIrTCG9t854z2HAgaISoRUKyztJoOtJfI1wJaQU+XL+U3JIh4jmNx/k5UzJijfvfpT7Cv3ueMtqyAGBJrkLvXjiS7O5ylaCGuB0Qz711bWGkRrVoosPM3N6ECQQD8hVQUgnHEVHZYtvFqfcoq2g/onPbSqyjdrRu35a7PvgDAZx69Mr/XggGNTgT3jJn7+2XmiGkHM1fd1Ob/3uAdAkEA4D7aE3ZgXG/PQqlm3VbE/+4MvNl8xhjqOkByBOY2ZFfWKhlRziLEPSSAh16xEJ79WgY9iti+guLRAMravGrs2QJBAOmKWYeaWKNNxiIoF7/4VDgrcpkcSf3uRB44UjFSn8kLnWBUPo6WV+x1FQBdjqRviZ4NFGIP+KqrJnFHzNgJhVUCQFzCAukMDV4PLfeQJSmna8PFz2UKva8fvTutTryyEYu+PauaX5laDjyQbc4RIEMU0Q29CRX3BA8WDYg7YPGRdTkCQQCG+pjU2FB17ZLuKRlKEdtXNV6zQFTmFc1TKhlsDTtCkWs/xwkoCfZKstuV3Uc5J4BNJDkQOGm38pDRPcUDUh2/
- -----END PRIVATE KEY-----</span>
公鑰文件示例:ide
- <span style="font-size:12px">-----BEGIN PUBLIC KEY-----
- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQWiDVZ7XYxa4CQsZoB3n7bfxLDkeGKjyQPt2FUtm4TWX9OYrd523iw6UUqnQ+Evfw88JgRnhyXadp+vnPKP7unormYQAfsM/CxzrfMoVdtwSiGtIJB4pfyRXjA+KL8nIa2hdQy5nLfgPVGZN4WidfUY/QpkddCVXnZ4bAUaQjXQIDAQAB
- -----END PUBLIC KEY-----</span>
三.上傳RSA公鑰,簽名驗證
登陸支付寶官方網站b.alipay.com,點擊導航欄中「個人商家服務」,點擊「查詢PID、Key」,在「合做夥伴密鑰管理」下(根據不一樣的產品選擇對應的入口),點擊「RSA加密」後的「添加密鑰」,把本身的公鑰複製進去工具
注意:上傳的公鑰是一行格式,不容許有註釋、空格、換行等!
點擊「確認上傳」,提示:上傳成功,說明已經成功上傳。
四.接口調用
首先,導入須要的支付寶SDK資源放入商戶應用工程的libs目錄下
右鍵 Build Path,將libs目錄下的alipaySDK-20150602.jar導入,選中Order and Export,勾選alipaySDK-20151014.jar
拷貝sdk提供的類到工程下:
這幾個類也很簡單,不須要作打的修改,只改動pay.java裏面的就行了
- <span style="font-size:12px">
- public static final String PARTNER = "";
- public static final String SELLER = "";
- public static final String RSA_PRIVATE = "";</span>
添加上對應的參數,java私鑰必定要是pkcs8格式的。
- <span style="font-size:12px">public class Pay {
-
- public static final String PARTNER = "";
-
- public static final String SELLER = "";
-
- public static final String RSA_PRIVATE = "";
- private static final int SDK_PAY_FLAG = 1;
- private Activity activity;
-
- public Pay(Activity activity) {
- this.activity = activity;
- }
-
-
- public void pay(String name, String msg, String orderno, String money,
- final Handler handler) {
-
- String orderInfo = getOrderInfo(name, msg, orderno, money);
-
- String sign = sign(orderInfo);
- try {
-
- 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 alipay = new PayTask(activity);
-
- String result = alipay.pay(payInfo);
-
- Message msg = new Message();
- msg.what = SDK_PAY_FLAG;
- msg.obj = result;
- handler.sendMessage(msg);
- }
- };
-
-
- Thread payThread = new Thread(payRunnable);
- payThread.start();
- }
-
-
- public String getOrderInfo(String subject, String body, String orderno,
- String price) {
-
-
- String orderInfo = "partner=" + "\"" + PARTNER + "\"";
-
-
- orderInfo += "&seller_id=" + "\"" + SELLER + "\"";
-
-
- orderInfo += "&out_trade_no=" + "\"" + orderno + "\"";
-
-
- orderInfo += "&subject=" + "\"" + subject + "\"";
-
-
- orderInfo += "&body=" + "\"" + body + "\"";
-
-
- orderInfo += "&total_fee=" + "\"" + price + "\"";
-
-
- orderInfo += "¬ify_url=" + "\"" + "notify_URL" + "\"";
-
-
- orderInfo += "&service=\"mobile.securitypay.pay\"";
-
-
- orderInfo += "&payment_type=\"1\"";
-
-
- orderInfo += "&_input_charset=\"utf-8\"";
-
-
-
-
-
-
- orderInfo += "&it_b_pay=\"30m\"";
-
-
-
-
-
- orderInfo += "&return_url=\"m.alipay.com\"";
-
-
-
-
- return orderInfo;
- }
-
-
- public String getOutTradeNo() {
- SimpleDateFormat format = new SimpleDateFormat("MMddHHmmss",
- Locale.getDefault());
- Date date = new Date();
- String key = format.format(date);
-
- Random r = new Random();
- key = key + r.nextInt();
- key = key.substring(0, 15);
- return key;
- }
-
-
- public String sign(String content) {
- return SignUtils.sign(content, RSA_PRIVATE);
- }
-
-
- public String getSignType() {
- return "sign_type=\"RSA\"";
- }
-
- }</span>
其中
public void pay(String name, String msg, String orderno, String money,final Handler handler) 方法是調用支付是用到的,傳的參數爲商戶的名字,商品計費名稱,訂單號和價格,最後一個Handler handler參數是用來接收支付回調發送消息的。
支付的線程必須異步調用。
// 服務器異步通知頁面路徑
orderInfo += "?ify_url=" + "\"" + "notify_URL" + "\""; 這裏要填寫真實的回到地址,是支付寶回調通知服務器的。
orderInfo += "&it_b_pay=\"30m\""; 交易的超時時間默認30分鐘,能夠本身設置。 其他地方不用太大改動。
- <span style="font-size:12px">public class AppActivity extends Activity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- Button btn_pay = (Button) findViewById(R.id.btn_pay);
- btn_pay.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- Pay pay = new Pay(AppActivity.this);
- pay.pay("商戶名稱", "商品計費名稱", "訂單號", "1", handler);
-
- }
- });
-
- }
-
- Handler handler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- switch (msg.what) {
- case 1: {
- PayResult payResult = new PayResult((String) msg.obj);
-
-
- String resultStatus = payResult.getResultStatus();
- if (TextUtils.equals(resultStatus, "9000")) {
- Toast.makeText(AppActivity.this, "支付成功",
- Toast.LENGTH_SHORT).show();
- } else {
-
- if (TextUtils.equals(resultStatus, "8000")) {
- Toast.makeText(AppActivity.this, "支付結果確認中",
- Toast.LENGTH_SHORT).show();
- } else {
- Toast.makeText(AppActivity.this, "支付失敗",
- Toast.LENGTH_LONG).show();
- }
- }
- break;
- }
- }
- }
- };
-
- }</span>
這裏是模擬調用支付,點擊按鈕開始跳轉支付,
handler收到消息後判斷支付狀態。9000爲支付成功,8000爲支付確認中,其他支付失敗。
支付時出現偶爾出現java.security.spec.InvalidKeySpecException: java.lang.RuntimeException錯誤,須要調整一下RSA簽名私鑰,SignUtils 類
把KeyFactory keyf = KeyFactory.getInstance("RSA");
改爲KeyFactory keyf = KeyFactory.getInstance("RSA", "BC");
- <span style="font-size:12px">public class SignUtils {
-
- private static final String ALGORITHM = "RSA";
-
- private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
-
- private static final String DEFAULT_CHARSET = "UTF-8";
-
- public static String sign(String content, String privateKey) {
- try {
- PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
- Base64.decode(privateKey));
- KeyFactory keyf = KeyFactory.getInstance("RSA", "BC");
- PrivateKey priKey = keyf.generatePrivate(priPKCS8);
-
- java.security.Signature signature = java.security.Signature
- .getInstance(SIGN_ALGORITHMS);
-
- signature.initSign(priKey);
- signature.update(content.getBytes(DEFAULT_CHARSET));
-
- byte[] signed = signature.sign();
-
- return Base64.encode(signed);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- return null;
- }
-
- }</span>
公鑰私鑰必定要傳正確才能簽名成功。
另外的Base64.java和PayResult.java兩個類就不用作修改了。
常見的支付錯誤碼以下:
在商戶應用工程的AndroidManifest.xml文件裏面添加聲明:
- <span style="font-size:12px">
-
-
- </span>
- <span style="font-size:12px">
-
-
-
- </span>
特別注意事項:
測試場景必定注意,安裝支付寶錢包則直接跳轉app支付,沒安裝則進入H5網頁支付。