編輯:關於Android編程
一說到支付寶,相信沒有人不知道,生活中付款,轉賬都會用到。
今天來詳細介紹下在android中如何集成支付寶支付到自己的APP中去。讓APP能夠擁有方便,快捷的支付功能。
准備工作:
商戶在b.alipay.com裡進行產品簽約
商戶或者開發者到b.alipay.com進行產品簽約,獲取商戶的PID。
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程序
經過以上步驟,開發者可以在當前文件夾中(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命令行操作。
PKCS8處理後的私鑰文件示例:
-----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-----
公鑰文件示例:
-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQWiDVZ7XYxa4CQsZoB3n7bfxLDkeGKjyQPt2FUtm4TWX9OYrd523iw6UUqnQ+Evfw88JgRnhyXadp+vnPKP7unormYQAfsM/CxzrfMoVdtwSiGtIJB4pfyRXjA+KL8nIa2hdQy5nLfgPVGZN4WidfUY/QpkddCVXnZ4bAUaQjXQIDAQAB -----END PUBLIC KEY-----
登錄支付寶官方網站b.alipay.com,點擊導航欄中“我的商家服務”,點擊“查詢PID、Key”,在“合作伙伴密鑰管理”下(根據不同的產品選擇對應的入口),點擊“RSA加密”後的“添加密鑰”,把自己的公鑰復制進去
注意:上傳的公鑰是一行格式,不允許有注釋、空格、換行等! 點擊“確認上傳”,提示:上傳成功,說明已經成功上傳。// 商戶PID public static final String PARTNER = ""; // 商戶收款賬號 public static final String SELLER = ""; // 商戶私鑰,pkcs8格式 public static final String RSA_PRIVATE = "";
public class Pay { // 商戶PID public static final String PARTNER = ""; // 商戶收款賬號 public static final String SELLER = ""; // 商戶私鑰,pkcs8格式 public static final String RSA_PRIVATE = ""; private static final int SDK_PAY_FLAG = 1; private Activity activity; public Pay(Activity activity) { this.activity = activity; } /** * call alipay sdk pay. 調用SDK支付 * */ public void pay(String name, String msg, String orderno, String money, final Handler handler) { // 訂單 String orderInfo = getOrderInfo(name, msg, orderno, money); // 對訂單做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(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(); } /** * create the order info. 創建訂單信息 * */ public String getOrderInfo(String subject, String body, String orderno, String price) { // 簽約合作者身份ID 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\""; // 設置未付款交易的超時時間 // 默認30分鐘,一旦超時,該筆交易就會自動被關閉。 // 取值范圍:1m~15d。 // m-分鐘,h-小時,d-天,1c-當天(無論交易何時創建,都在0點關閉)。 // 該參數數值不接受小數點,如1.5h,可轉換為90m。 orderInfo += "&it_b_pay=\"30m\""; // extern_token為經過快登授權獲取到的alipay_open_id,帶上此參數用戶將使用授權的賬戶進行支付 // orderInfo += "&extern_token=" + "\"" + extern_token + "\""; // 支付寶處理完請求後,當前頁面跳轉到商戶指定頁面的路徑,可空 orderInfo += "&return_url=\"m.alipay.com\""; // 調用銀行卡支付,需配置此參數,參與簽名, 固定值 (需要簽約《無線銀行卡快捷支付》才能使用) // orderInfo += "&paymethod=\"expressGateway\""; return orderInfo; } /** * get the out_trade_no for an order. 生成商戶訂單號,該值在商戶端應保持唯一(可自定義格式規范) * */ 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; } /** * sign the order info. 對訂單信息進行簽名 * * @param content * 待簽名訂單信息 */ public String sign(String content) { return SignUtils.sign(content, RSA_PRIVATE); } /** * get the sign type we use. 獲取簽名方式 * */ public String getSignType() { return "sign_type=\"RSA\""; } }其中public void pay(String name, String msg, String orderno, String money,final Handler handler) 方法是調用支付是用到的,傳的參數為商戶的名字,商品計費名稱,訂單號和價格,最後一個Handler handler參數是用來接收支付回調發送消息的。 支付的線程必須異步調用。
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 resultInfo = payResult.getResult(); String resultStatus = payResult.getResultStatus(); if (TextUtils.equals(resultStatus, "9000")) { Toast.makeText(AppActivity.this, "支付成功", Toast.LENGTH_SHORT).show(); } else { // “8000”代表支付結果因為支付渠道原因或者系統原因還在等待支付結果確認,最終交易是否成功以服務端異步通知為准(小概率狀態) if (TextUtils.equals(resultStatus, "8000")) { Toast.makeText(AppActivity.this, "支付結果確認中", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(AppActivity.this, "支付失敗", Toast.LENGTH_LONG).show(); } } break; } } } }; }
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; } }公鑰私鑰一定要傳正確才能簽名成功。 另外的Base64.java和PayResult.java兩個類就不用做修改了。 常見的支付錯誤碼如下: 在商戶應用工程的AndroidManifest.xml文件裡面添加聲明:
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("商戶名稱", "商品計費名稱", "1231321321", "1", handler); } });
0x00 序隨著移動安全越來越火,各種調試工具也都層出不窮,但因為環境和需求的不同,並沒有工具是萬能的。另外工具是死的,人是活的,如果能搞懂工具的原理再結合上
概述關於Android ColorFilter 和 Tint之間的關系一直混淆不清。兩者均是對顯示的圖片進行著色或者過濾。 ColorFilter: 色彩過濾 Tint:
1、如圖片1所示,在一個Android應用中,除了標題欄和底層的ActionBar的區域,是我們可以操縱的UI區域,那是不是說我們就不能改變除了這兩個區域的UI呢?答案是
設置adb的usb連接配置 把需要測試的手機連接入電腦,通過系統查找USB連接配置,找到廠商ID: 把ID添加進adb_usb.ini;使