Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 集成支付寶支付詳解

Android 集成支付寶支付詳解

編輯:關於Android編程

一說到支付寶,相信沒有人不知道,生活中付款,轉賬都會用到。

今天來詳細介紹下在android中如何集成支付寶支付到自己的APP中去。讓APP能夠擁有方便,快捷的支付功能。

准備工作:

商戶在b.alipay.com裡進行產品簽約
RSA私鑰及公鑰生成
上傳RSA公鑰,簽名驗證
接口調用
一.商戶在b.alipay.com裡進行產品簽約

 

商戶或者開發者到b.alipay.com進行產品簽約,獲取商戶的PID。

\

\

 
二.RSA私鑰及公鑰生成
  生成方式一(推薦):使用支付寶提供的一鍵生成工具:   Windwos:點擊下載 MAC OSX:點擊下載
解壓打開文件夾,直接運行“支付寶RAS密鑰生成器SHAwithRSA1024_V1.0.bat”(WINDOWS)或“SHAwithRSA1024_V1.0.command”(MACOSX),點擊“生成RSA密鑰”,會自動生成公私鑰,然後點擊“打開文件位置”,即可找到工具自動生成的密鑰。     生成方式二:也可以使用OpenSSL工具命令生成
首先進入OpenSSL工具,再輸入以下命令。  
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-----

 

三.上傳RSA公鑰,簽名驗證

登錄支付寶官方網站b.alipay.com,點擊導航欄中“我的商家服務”,點擊“查詢PID、Key”,在“合作伙伴密鑰管理”下(根據不同的產品選擇對應的入口),點擊“RSA加密”後的“添加密鑰”,把自己的公鑰復制進去

\

\

  注意:上傳的公鑰是一行格式,不允許有注釋、空格、換行等! 點擊“確認上傳”,提示:上傳成功,說明已經成功上傳。   \    
四.接口調用
首先,導入需要的支付寶SDK資源放入商戶應用工程的libs目錄下   \   右鍵 Build Path,將libs目錄下的alipaySDK-20150602.jar導入,選中Order and Export,勾選alipaySDK-20151014.jar   \     拷貝sdk提供的類到工程下:   \   這幾個類也很簡單,不需要做打的修改,只改動pay.java裡面的就好了  
// 商戶PID
public static final String PARTNER = "";
// 商戶收款賬號
public static final String SELLER = "";
// 商戶私鑰,pkcs8格式
public static final String RSA_PRIVATE = "";

添加上對應的參數,java私鑰一定要是pkcs8格式的。    
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參數是用來接收支付回調發送消息的。   支付的線程必須異步調用

// 服務器異步通知頁面路徑 orderInfo += "?ify_url=" + "\"" + "notify_URL" + "\""; 這裡要填寫真實的回到地址,是支付寶回調通知服務器的。   orderInfo += "&it_b_pay=\"30m\""; 交易的超時時間默認30分鐘,可以自己設置。 其余地方不用太大改動。    
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;
			}
			}
		}
	};

}

這裡是模擬調用支付,點擊按鈕開始跳轉支付,handler收到消息後判斷支付狀態。9000為支付成功,8000為支付確認中,其余支付失敗。   支付時出現偶爾出現java.security.spec.InvalidKeySpecException: java.lang.RuntimeException錯誤,需要調整一下RSA簽名私鑰,SignUtils 類   把KeyFactory keyf = KeyFactory.getInstance("RSA"); 改成KeyFactory keyf = KeyFactory.getInstance("RSA", "BC");  
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文件裡面添加聲明:  



 





特別注意事項: \
  測試場景一定注意,安裝支付寶錢包則直接跳轉app支付,沒安裝則進入H5網頁支付。   未安裝支付寶錢包測試如下:   \\\\\    
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);

			}
		});

傳入參數是我任意填寫的。   點擊“支付按鈕”,開始支付,未安裝支付寶錢包,會自動跳轉H5網頁支付,第一次會輸入手機號獲取驗證碼,自動記錄。再次進入時直接到確認付款頁面,支付中途取消返回結果碼為6001。

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved