微信支付遇到了无数的坑,总算是一个个解决了,官方文档真是让人郁闷到死,不多说,直接上代码。
一.生成预支付订单
private StringBuffer strbuffer; private Mapresultunifiedorder;
private final IWXAPI msgApi = WXAPIFactory.createWXAPI(this, null);
1.1准备工作
strbuffer=new StringBuffer(); msgApi.registerApp(Constants.APP_ID); GetPrepayIdTask getPrepayId = new GetPrepayIdTask(); getPrepayId.execute();
1.2GetPrepayIdTask
//1.获取预支付订单编号 private class GetPrepayIdTask extends AsyncTask> { private ProgressDialog dialog; @Override protected void onPreExecute() { dialog = ProgressDialog.show(EShopWEIXIN_EPAYActivity.this, "提示", "正在获取预支付订单..."); } @Override protected void onPostExecute(Map result) { if (dialog != null) { dialog.dismiss(); } resultunifiedorder=result; if(result.get("return_code").contentEquals("SUCCESS") ){//预支付成功 genPayReq();//2生成签名参数 } strbuffer.append("prepay_id\n"+result.get("prepay_id")+"\n\n"); } @Override protected void onCancelled() { super.onCancelled(); } @Override protected Map doInBackground(Void... params) { String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder"); String entity = genProductArgs();//生成预支付订单请求 Log.e("orion",entity); byte[] buf = WXUtil.httpPost(url, entity);//提交预支付订单 String content = new String(buf); Log.e("orion", content); Map xml=decodeXml(content); return xml; } }
1.3生成预支付订单请求
private String genProductArgs() { StringBuffer xml = new StringBuffer(); try { String nonceStr = genNonceStr(); String strIP=genWifiIp();//获取手机ip xml.append(""); ListpackageParams = new LinkedList (); packageParams.add(new BasicNameValuePair("appid", Constants.APP_ID));//应用ID packageParams.add(new BasicNameValuePair("body", "e"));//商品描述e路通-保险支付 packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));//商户号 packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));//随机字符串nonceStr packageParams.add(new BasicNameValuePair("notify_url", "http://wxpay.wxutil.com/pub_v2/pay/notify.v2.php"));//通知地址 packageParams.add(new BasicNameValuePair("out_trade_no", "15036257092394985"));//商户订单号 packageParams.add(new BasicNameValuePair("spbill_create_ip", strIP));//用户端实际ip packageParams.add(new BasicNameValuePair("total_fee", "1"));//订单总金额,单位为分 packageParams.add(new BasicNameValuePair("trade_type", "APP"));//支付类型 String sign = genPackageSign(packageParams); packageParams.add(new BasicNameValuePair("sign", sign)); String xmlstring = toXml(packageParams); // xmlstring = new String(xmlstring.getBytes(), "ISO-8859-1"); return xmlstring;//String(xmlstring.getBytes("UTF-8"), "ISO8859-1"),body使用中文xml要转码 } catch (Exception e) { return null; } }
1.4随机数
private String genNonceStr() { Random random = new Random(); return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)) .getBytes()); }
1.5通过wifi获取用户手机IP
private String genWifiIp() { //获取wifi管理服务 WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE); //判断wifi是否开启 if (!wifiManager.isWifiEnabled()) { wifiManager.setWifiEnabled(true); } WifiInfo wifiInfo = wifiManager.getConnectionInfo(); int ipAddress = wifiInfo.getIpAddress(); String ip = intToIp(ipAddress); return ip; } private String intToIp(int i) { return (i & 0xFF ) + "." + ((i >> 8 ) & 0xFF) + "." + ((i >> 16 ) & 0xFF) + "." + ( i >> 24 & 0xFF) ; }
1.6商户订单号(只要唯一就可以)
private String genOutTradNo() { Random rand = new Random(); int randNum = rand.nextInt(9999); String randStr = String.format("%04d", randNum); String orderseq = String.valueOf(System.currentTimeMillis())+randStr; return orderseq; }
1.7sign预支付签名
private String genPackageSign(Listparams) { 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(Constants.API_KEY); String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase(); Log.e("orion",packageSign); return packageSign; }
1.8提交数据的格式化
private String toXml(Listparams) { StringBuilder sb = new StringBuilder(); sb.append(" " ); 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(""); Log.e("orion",sb.toString()); return sb.toString(); }
1.9WXUtil文件
2.0返回数据格式化
public MapdecodeXml(String content) { try { Map xml = new HashMap (); 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; }
二、调起微信支付
1.1调起genPayReq()开始微信支付;
private void genPayReq() { PayReq req= new PayReq(); req.appId = Constants.APP_ID; req.partnerId = Constants.MCH_ID; req.prepayId = resultunifiedorder.get("prepay_id"); req.packageValue = "prepay_id="+resultunifiedorder.get("prepay_id"); req.nonceStr = genNonceStr(); req.timeStamp = String.valueOf(genTimeStamp()); ListsignParams = new LinkedList (); 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); strbuffer.append("sign\n"+req.sign+"\n\n");
msgApi.registerApp(Constants.APP_ID);msgApi.sendReq(req); Log. e( "orion", signParams.toString());}
1.2时间戳
private long genTimeStamp() { return System.currentTimeMillis() / 1000; }
1.3sign二次签名
private String genAppSign(Listparams) { 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(Constants.API_KEY); this.strbuffer.append("sign str\n"+sb.toString()+"\n\n"); String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase(); Log.e("orion",appSign); return appSign; }
三、支付结果
参照微信SDK Sample,在net.sourceforge.simcpux.wxapi包路径中实现WXPayEntryActivity类
(包名或类名不一致会造成无法回调)在WXPayEntryActivity类中实现onResp函数,支付完成后,
微信APP会返回到商户APP并回调onResp函数,开发者需要在该函数中接收通知,判断返回错误码,
如果支付成功则去后台查询支付结果再展示用户实际支付结果。注意一定不能以客户端返回作为用户支付的结果,
应以服务器端的接收的支付通知或查询API返回的结果为准。
package cn.com.siyuan.eshop.wxapi; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.widget.Toast; import com.tencent.mm.sdk.constants.ConstantsAPI; import com.tencent.mm.sdk.modelbase.BaseReq; import com.tencent.mm.sdk.modelbase.BaseResp; import com.tencent.mm.sdk.openapi.IWXAPI; import com.tencent.mm.sdk.openapi.IWXAPIEventHandler; import com.tencent.mm.sdk.openapi.WXAPIFactory; import cn.com.siyuan.eshop.utils.Util; import cn.com.siyuan.eshop.weixinepay.Constants; import cn.com.siyuan.rbeshop.R; public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler{ private static final String TAG = "MicroMsg.SDKSample.WXPayEntryActivity"; private IWXAPI api; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.pay_result); api = WXAPIFactory.createWXAPI(this, Constants.APP_ID); api.handleIntent(getIntent(), this); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); api.handleIntent(intent, this); } @Override public void onReq(BaseReq req) { } @Override public void onResp(BaseResp resp) { Log.d(TAG, "onPayFinish, errCode = " + resp.errCode); if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) { if(resp.errCode==0){ Toast.makeText(WXPayEntryActivity.this,"支付成功!",Toast.LENGTH_LONG).show(); }else if(resp.errCode==-1){ Toast.makeText(WXPayEntryActivity.this,"支付失败!",Toast.LENGTH_LONG).show(); }else if(resp.errCode==-2){ Toast.makeText(WXPayEntryActivity.this,"用户取消支付!支付失败!",Toast.LENGTH_LONG).show(); } Util.isPay=resp.errCode; finish(); } } }