在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" />