写这个博客之前我不懂不吐槽一下微信官方的技术文档写得太烂,支付demo直接无语,好吧吐槽完毕回归主题之前做微信支付时遇到了不少麻烦,今天特地写一篇博客,希望能给大家带来帮助,首先你要去在微信开放平台注册相关账户那些就不说了下载官方的框架 导入到自己项目中
好现在代码开始 定义微信的两个类
private PayReq req;
private IWXAPI msgApi; private StringBuffer sb;
实例化对象
msgApi = WXAPIFactory.createWXAPI(this, Constant.APP_ID);
req = new PayReq();
//注册appid
msgApi.registerApp(Constant.APP_ID); sb=new StringBuffer();
/***
* 微信支付
*/
private void weixinPay(){
//生成prepay_id
GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
getPrepayId.execute();
}
GetprepayIdTask类代码
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 void onPostExecute(Map<String,String> result) {
sb.append("prepay_id\n"+result.get("prepay_id")+"\n\n");
Log.e("prepay_id",sb.toString());
if (sb==null){
Toast.makeText(PayActivity.this,"支付异常",Toast.LENGTH_LONG).show();
}
resultunifiedorder=result;
//生成签名参数
genPayReq();
msgApi.sendReq(req);
if (dialog != null) {
dialog.dismiss();
}
}
@Override
protected void onCancelled() {
super.onCancelled();
}
@Override
protected Map<String,String> doInBackground(Void... params) {
String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
String entity = genProductArgs();
byte[] buf = Util.httpPost(url, entity);
String content = new String(buf);
Log.e("orion", "----"+content);
Map<String,String> xml=decodeXml(content);
return xml;
}
}
GetprepayIdTask中的genProductArgs()方法
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", Constant.APP_ID));//AppId
packageParams.add(new BasicNameValuePair("body", "你的订单"));//支付时描述内容,不支持中文不过被我改了
packageParams.add(new BasicNameValuePair("mch_id", Constant.MCH_ID));//商户号
packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));//MD5加密
packageParams.add(new BasicNameValuePair("notify_url", "服务器异步通知地址"));//服务器通知地址
packageParams.add(new BasicNameValuePair("out_trade_no","你的订单号"));//订单号genOutTradNo()
packageParams.add(new BasicNameValuePair("spbill_create_ip","127.0.0.1"));//不动不知道干嘛用的
packageParams.add(new BasicNameValuePair("total_fee",(int) (0.01*100)+""));//价格只支持int类型单位分
packageParams.add(new BasicNameValuePair("trade_type", "APP"));//这个不动是区别是什么平台
String sign = genPackageSign(packageParams);
packageParams.add(new BasicNameValuePair("sign", sign));
Log.e("微信支付价格",to.format(totalcount*100));
String xmlstring =toXml(packageParams);
return new String(xmlstring.toString().getBytes(), "ISO8859-1");//解决body不能写中文的bug
} catch (Exception e) {
Log.e("支付", "----genProductArgs fail, ex = " + e.getMessage());
return null;
}
}
GetprepayIdTask中的decodeXml方法
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;
}
genPayReq()方法生成签名
/***
* 生成参数签名
*/
private void genPayReq() {
req.appId = Constant.APP_ID;
req.partnerId = Constant.MCH_ID;
req.prepayId = resultunifiedorder.get("prepay_id");
req.packageValue = "prepay_id="+resultunifiedorder.get("prepay_id");
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");
Log.e("orion", "----"+signParams.toString());
}
genPayReq() 中的genNoncestr()方法
private String genNonceStr() {
Random random = new Random();
return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
}
genPayReq() 中的genAppsingn()方法Appkey是微信商户平台自己设置的
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());
Log.e("orion","----"+appSign);
return appSign;
}
Util类里面的http请求因为安卓5.0抛弃掉了httpclient 要想使用HttpClient需要在Bulid.gradle做配置请看下面
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;
}
}
想要在Android studio里面是用HttpClient 需要在build.gradle配置
android {
useLibrary 'org.apache.http.legacy'
}
项目源码:http://download.csdn.net/detail/liufatao/9692044