微信支付
1:去微信開放平臺註冊應用
https://open.weixin.qq.com/cgi-bin/index?t=home/index&lang=zh_CN&token=2c0fee9c43e1eb8f9febcc7cb73abf598e2d4011
這裏需要注意的是:
包名正確(重要)
簽名正確(重要)
微信提供的簽名生成工具
把包名添加上去就可以獲取簽名
注意:把要獲取簽名的應用安裝在手機上
https://res.wx.qq.com/open/zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android2.apk
創建移動應用併成功之後會收到騰訊發來的郵件:
通過郵件你能獲得重要的參數:
(1):AppID
(2):微信支付商戶號
(4):前往商戶平臺完成入駐
(4):API祕鑰(自己設置即可,注意一定要32位字母加數字的組合)記得保存好祕鑰,以後要使用
開發前的準備
先了解下交互時序圖,統一下單API、支付結果通知API和查詢訂單API等都涉及簽名過程,調用都必須在商戶服務器端完成。如圖8.6所示。
安卓sdk下載
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=11_1
微信開放平臺
https://open.weixin.qq.com/
微信android開發手冊
https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317784&token=&lang=zh_CN
微信app開發步驟
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5
開始接入微信支付
1.在項目中引入微信開發包
2.在AndroidManifest.xml中添加相應的權限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
3.在MainActivity中註冊到爲微信
配置debug簽名
創建應用需要填寫應用簽名,配置在debug下直接用的正式的key,這樣就不用每次打包才能調起微信客戶端
signingConfigs {
debug {
storeFile file("你的keystore路徑")
storePassword "xxx"
keyAlias "xxx"
keyPassword "xxx"
}
release {
storeFile file("你的keystore路徑")
storePassword "xxx"
keyAlias "xxx"
keyPassword "xxx"
}
}
3.在MainActivity中註冊到爲微信
api= WXAPIFactory.createWXAPI(this,ConfigUtil.Wechat_Appid,true);
api.registerApp(ConfigUtil.Wechat_Appid);
4.在點擊的時候向微信發送請求
case R.id.wechat_pay:
PayReq request = new PayReq();
request.appId = ConfigUtil.Wechat_Appid;
request.partnerId = "1327244301";
request.prepayId= "wx2016092009564343e737275f0904349502";
request.packageValue = "Sign=WXPay";
request.nonceStr= "70vhVHnJj6ph7mf9";
request.timeStamp= "1474336603";
request.sign= "815BC8D5508FD90F7A978856B2174E21";
api.sendReq(request);
break;
5.配置回調
[1]在微信管理後臺中配置的包名下新建wxapi包
[2]在wxapi包下新建WXPayEntryActivity的類(注意這個類的位置和名稱不能改變)
[3]WXPayEntryActivity類實現IWXAPIEventHandler繼承Activity,該佈局文件自己定義即可
[4]在AndroidManifest.xml中註冊activity
<activity
android:name=".wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop"/>
[5]在WXPayEntryActivity類中onCreate中註冊微信
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
api = WXAPIFactory.createWXAPI(this, ConfigUtil.Wechat_Appid);
api.handleIntent(getIntent(), this);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
[6]實現onResp
public void onResp(BaseResp baseResp) {
Log.d(TAG, "onPayFinish, errCode = " + baseResp.errCode);
if (baseResp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("標題");
builder.setMessage(String.valueOf(baseResp.errCode));
builder.show();
}
}
baseResp.errCode是返回的錯誤碼
注意:WXPayEntryActivity類必須叫這個名必須在wxapi包下
微信調不起來:
檢查簽名是否正確
包名是否與微信後臺配置的一致
檢查是否添加權限
檢查代碼 是否在初始化時註冊微信 是否正確發送請求
微信支付調用起來沒有回調:
查看包名是否正確
類名是否正確
在AndroidManifest.xml是否註冊activity
解決方法:
實在掉不起來微信(包名正確簽名正確)就重新安裝微信客戶端 和重新安裝 測試項目
預支付訂單和sign最好在服務器中完成,但若是就想在客戶端做怎麼弄呢?爲方便,那麼我這裏就直接給出代碼,可供大家參考:
/**
*該類用於在客戶端處理吊起微信支付前,生成prepay_id和sign的方式舉例,
* 但建議在服務器端處理prepay_id和sign
**/
public class PayActivity extends Activity {
// appid
// 請同時修改 androidmanifest.xml裏面,.PayActivity裏的屬性<data
// android:scheme=""/>爲新設置的appid
public static String APP_ID;
// 商戶號
public static String MCH_ID ;
// API密鑰,在商戶平臺設置
public static String API_KEY ;
private String body;
private String total;
PayReq req;
final IWXAPI msgApi = WXAPIFactory.createWXAPI(this, null);
Map<String, String> resultunifiedorder;
StringBuffer sb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
APP_ID= getIntent().getStringExtra("appid");
MCH_ID=getIntent().getStringExtra("partnerid");
API_KEY=getIntent().getStringExtra("apikey");
body=getIntent().getStringExtra("body");
req = new PayReq();
sb = new StringBuffer();
msgApi.registerApp(APP_ID);
// 生成prepay_id
GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
getPrepayId.execute();
}
private class GetPrepayIdTask extends AsyncTask<Void, Void, Map<String, String>> {
private ProgressDialog dialog;
@Override
protected void onPreExecute() {
dialog = ProgressDialog.show(PayActivity.this, getString(R.string.app_tip), getString(R.string.getting_prepayid));
}
@Override
protected Map<String, String> doInBackground(Void... params) {
String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
String entity = genProductArgs();
Log.e("orion", entity);
byte[] buf = Util.httpPost(url, entity); //執行與獲取預付款訂單請求,並獲得訂單byte
String content = new String(buf);
Log.e("orion", content);
Map<String, String> map = decodeXml(content);
return map;
}
@Override
protected void onPostExecute(Map<String, String> result) {
if (dialog != null) {
dialog.dismiss();
}
sb.append("prepay_id\n" + result.get("prepay_id") + "\n\n");
resultunifiedorder = result;
if (result.get("prepay_id") != null) {
genPayReq(); //吊起支付請求
} else {
Toast.makeText(getApplicationContext(), "調用微信支付失敗!", Toast.LENGTH_SHORT).show();
}
}
}
public Map<String, String> decodeXml(String content) {
try {
Map<String, String> xml = new HashMap<String, String>();
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new StringReader(content));
int event = parser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String nodeName = parser.getName();
switch (event) {
case XmlPullParser.START_DOCUMENT:
break;
case XmlPullParser.START_TAG:
if ("xml".equals(nodeName) == false) {
// 實例化student對象
xml.put(nodeName, parser.nextText());
}
break;
case XmlPullParser.END_TAG:
break;
}
event = parser.next();
}
return xml;
} catch (Exception e) {
Log.e("orion", e.toString());
}
return null;
}
private String genNonceStr() {
Random random = new Random();
return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
}
private long genTimeStamp() {
return System.currentTimeMillis() / 1000;
}
private String genOutTradNo() {
Random random = new Random();
String out_trade_no = MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
return out_trade_no;
}
private String genProductArgs() {
StringBuffer xml = new StringBuffer();
try {
String nonceStr = genNonceStr();
xml.append("</xml>");
List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
packageParams.add(new BasicNameValuePair("appid", APP_ID));
packageParams.add(new BasicNameValuePair("body", body));//物品
packageParams.add(new BasicNameValuePair("mch_id", MCH_ID));
packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
packageParams.add(new BasicNameValuePair("notify_url", "http://baidu.com"));
packageParams.add(new BasicNameValuePair("out_trade_no", genOutTradNo()));
packageParams.add(new BasicNameValuePair("spbill_create_ip", getPhoneIp()));
packageParams.add(new BasicNameValuePair("total_fee", getIntent().getStringExtra("total_fee")));//金額
packageParams.add(new BasicNameValuePair("trade_type", "APP"));
String sign = genPackageSign(packageParams);
packageParams.add(new BasicNameValuePair("sign", sign));
String xmlstring = toXml(packageParams);
return new String(xmlstring.getBytes(), "ISO8859-1");
// return xmlstring;
} catch (Exception e) {
// Log.e(TAG, "genProductArgs fail, ex = " + e.getMessage());
return null;
}
}
private void genPayReq() {
req.appId = APP_ID;
req.partnerId = MCH_ID;
req.prepayId = resultunifiedorder.get("prepay_id");
req.packageValue = "Sign=WXPay";
req.nonceStr = genNonceStr();
req.timeStamp = String.valueOf(genTimeStamp());
List<NameValuePair> signParams = new LinkedList<NameValuePair>();
signParams.add(new BasicNameValuePair("appid", req.appId));
signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
signParams.add(new BasicNameValuePair("package", req.packageValue));
signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));
req.sign = genAppSign(signParams);
sb.append("sign\n" + req.sign + "\n\n");
sendPayReq();
Log.e("orion", signParams.toString());
}
/**
* 獲取預支付訂單時需要生成的PackageSign簽名
*/
private String genPackageSign(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(API_KEY);
String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
Log.e("orion", packageSign);
return packageSign;
}
//吊起支付時需要生成的AppSign簽名
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(API_KEY);
this.sb.append("sign str\n" + sb.toString() + "\n\n");
String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
Log.e("orion", appSign);
return appSign;
}
private String toXml(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
sb.append("<xml>");
for (int i = 0; i < params.size(); i++) {
sb.append("<" + params.get(i).getName() + ">");
sb.append(params.get(i).getValue());
sb.append("</" + params.get(i).getName() + ">");
}
sb.append("</xml>");
Log.e("orion", sb.toString());
return sb.toString();
}
// 發起微信支付
private void sendPayReq() {
msgApi.registerApp(APP_ID);
msgApi.sendReq(req);
}
public static String getPhoneIp() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
return inetAddress.getHostAddress().toString();
}
}
}
} catch (Exception e) {
}
return "127.0.0.1";
}
}
其中Util中涉及的代碼如下:
public static byte[] httpPost(String url, String entity) {
if (url == null || url.length() == 0) {
Log.e(TAG, "httpPost, url is null");
return null;
}
HttpClient httpClient = getNewHttpClient();
HttpPost httpPost = new HttpPost(url);
try {
httpPost.setEntity(new StringEntity(entity));
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
HttpResponse resp = httpClient.execute(httpPost);
if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
Log.e(TAG, "httpGet fail, status code = " + resp.getStatusLine().getStatusCode());
return null;
}
return EntityUtils.toByteArray(resp.getEntity());
} catch (Exception e) {
Log.e(TAG, "httpPost exception, e = " + e.getMessage());
e.printStackTrace();
return null;
}
}
其他文檔:
微信支付集成及爬坑:代碼詳談
集成微信登錄 :http://www.jianshu.com/p/d95e4343e231
Android實現點擊支付按鈕,彈起自定義輸入法進行密碼輸入: 點我哦!
微信掃一掃揭祕: 猛戳這裏!