微信支付核心部分,記錄在此防止再次被坑

首先導入微信jar包(官網有)

在MyApplication中初始化IWXAPI 對象

// 微信支付初始化
	static IWXAPI msgApi;

	public static IWXAPI getWXAPI() {
		return msgApi;
	}
// 微信支付初始化
		msgApi = WXAPIFactory.createWXAPI(this, null);
		msgApi.registerApp(GlobalConstant.WEIXINID);

WEIXINID是開發者賬號審覈之後取到的appid

在支付的時候app把訂單號和價錢傳給服務器,由服務與微信通信之後返回相應的訂單數據,之後將返回的數據設置到PayReq中去,並排序調用
msgApi<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">.sendReq(req);</span>
這個方法有一個boolean型的返回值,雖然微信沒有明說有啥用,不過粗略的觀察到,只要配置不對,appid,key之類的不正確都會導致返回值爲false,能正確吊起支付頁面的返回值都是true,雖然也遇到過返回了true但是支付頁面都沒顯示的情況,這種多半是服務器沒配置好或者apk簽名與微信那邊的記錄不符
以下是吊起支付的核心代碼

PayReq req = new PayReq();
	req.appId = object.optString("appid");
	req.partnerId = object.optString("mch_id");
	req.prepayId = object.optString("prepay_id");
	req.nonceStr = object.optString("nonce_str");
	req.timeStamp = gettimes();
	req.packageValue = "Sign=WXPay";
	req.extData = getIntent().getStringExtra("OrderId"); // optional
	// 在支付之前,如果應用沒有註冊到微信,應該先調用IWXMsg.registerApp將應用註冊到微信
	List<NameValuePair> params = new ArrayList<NameValuePair>();
	params.add(new BasicNameValuePair("appid", req.appId));
	params.add(new BasicNameValuePair("noncestr", req.nonceStr));
	params.add(new BasicNameValuePair("package", req.packageValue));
	params.add(new BasicNameValuePair("partnerid", req.partnerId));
	params.add(new BasicNameValuePair("prepayid", req.prepayId));
	params.add(new BasicNameValuePair("timestamp", req.timeStamp));

	req.sign = genAppSign(params);
	boolean isok = api.sendReq(req);


req.timeStamp的值是一個10位數的隨機數,沒有嚴格要求,微信有說明,好像是爲了避免併發的情況

我取的是隨機數

private String gettimes() {
		String str = "";
		for (int i = 0; i < 10; i++) {
			str += (int) (10 * (Math.random())) + "";
		}
		return str;
	}



req.sign的值爲,正確排序微信返回來的那幾個值之後用MD5加密的key

加密算法:

private String genAppSign(List<NameValuePair> params) {
		StringBuilder sb = new StringBuilder();

		for (int i = 0; i < params.size(); i++) {
			sb.append(params.get(i).getName());
			sb.append('=');
			sb.append(params.get(i).getValue());
			sb.append('&');
		}
		sb.append("key=");
		sb.append(GlobalConstant.WEIXIN_KEY);
		System.out.println("str=" + sb.toString());
		String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
		Log.w("orion", appSign);
		return appSign;
	}

WEIXIN_KEY是申請到微信開發者賬號之後再次申請到的“支付能力”在拿到appid下面有個選項是獲取支付能力,需求再申請一個微信商戶賬號,然後安裝祕鑰什麼的,最後自己設置一個32位的key,服務器端和app都需要用到,具體做法參見http://help.ecmoban.com/article-2085.html

MD5加密方法來自微信demo

public class MD5 {

	private MD5() {
	}

	public final static String getMessageDigest(byte[] buffer) {
		char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
		try {
			MessageDigest mdTemp = MessageDigest.getInstance("MD5");
			mdTemp.update(buffer);
			byte[] md = mdTemp.digest();
			int j = md.length;
			char str[] = new char[j * 2];
			int k = 0;
			for (int i = 0; i < j; i++) {
				byte byte0 = md[i];
				str[k++] = hexDigits[byte0 >>> 4 & 0xf];
				str[k++] = hexDigits[byte0 & 0xf];
			}
			return new String(str);
		} catch (Exception e) {
			return null;
		}
	}
}
同時項目中的包名下面必須有一個包名爲wxapi的包存在,裏面必須有一個Activity名爲WXPayEntryActivity,並且extends Activity implements IWXAPIEventHandler

在@Override
public void onResp(BaseResp resp) {

方法中處理微信支付的回調,如果沒有這個activity可能導致支付失敗
不過微信支付的成功與否還是以服務器爲準,微信也是這麼說的

處理方法:

if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX && resp.errCode == 0) {
	//成功
} else {
	AlertDialog.Builder builder = new AlertDialog.Builder(this);
	builder.setMessage("支付失敗");
	builder.setOnCancelListener(new OnCancelListener() {

		@Override
		public void onCancel(DialogInterface dialog) {
			finish();
		}
	});
	builder.show();
}
調用微信支付的activity在聲明的時候需要加入以下內容:


<intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />

                <data android:scheme="你的appid" />
            </intent-filter>

支付回調的聲明:

<activity
            android:name=".wxapi.WXPayEntryActivity"
            android:configChanges="keyboardHidden|orientation|screenSize"
            android:exported="true"
            android:screenOrientation="portrait"
            android:theme="@android:style/Theme.Translucent.NoTitleBar" />



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章