满满的都是坑,因为服务器偷懒让客服端写统一下单,服务器只给了通知的url。微信的支付demo并没有统一下单的代码。
读此文前先阅读 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
一步步的来 先根据统一下单的参数介绍工具:
1. 获取到当前的ip:
- <span style="font-size:14px;">public String getLocalIpAddress() {
- 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()) {
- return inetAddress.getHostAddress().toString();
- }
- }
- }
- } catch (SocketException ex) {
- }
- return null;
- }
- private String getWifiIp() {
- //获取wifi服务
- WifiManager wifiManager = (WifiManager) getSystemService(Context.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);
- }
- </span>
2.随机订单号生成 test 你们可根据自己生成随机数:
- <span style="font-size:14px;">private String genOutTradNo() {
- Random random = new Random();
- return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
- }</span>
3.签名工具:
- <span style="font-size:14px;">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(Constants.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;
- }</span>
差不多了 现在我们需要生成传递的参数 参数要求是xml 格式的:
- <span style="font-size:14px;">private String genProductArgs() {
- StringBuffer xml = new StringBuffer();
- String ip = getWifiIp();
- if (ip == "" && ip == "") {
- ip = getLocalIpAddress();
- }
- try {
- String nonceStr = genNonceStr();
- xml.append("</xml>");
- List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
- packageParams.add(new BasicNameValuePair("appid", Constants.APP_ID));
- packageParams.add(new BasicNameValuePair("body", "APP pay test"));
- packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));
- packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
- packageParams.add(new BasicNameValuePair("notify_url",ConfigUtil.NOTIFY_URL));
- packageParams.add(new BasicNameValuePair("out_trade_no",genOutTradNo()));
- packageParams.add(new BasicNameValuePair("spbill_create_ip",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);
- return xmlstring;
- } catch (Exception e) {
- Log.e("TAG", "fail, ex = " + e.getMessage());
- return null;
- }
- }</span>
其中 toxml:
- <span style="font-size:14px;">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();
- }</span>
得到传递的参数,根据文档指示,我们需要用post去吊连接URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder:
- <span style="font-size:14px;"> 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) {
- if (dialog != null) {
- dialog.dismiss();
- }
- sb.append("prepay_id\n"+result.get("prepay_id")+"\n\n");
- resultunifiedorder=result;
- }
- @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();
- Log.e("orion",entity);
- byte[] buf = Util.httpPost(url, entity);
- String content = new String(buf);
- Log.e("orion", content);
- Map<String,String> xml=decodeXml(content);
- return xml;
- }
- }</span>
其中decodexml就是:
- <span style="font-size:14px;">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;
- }</span>
下单完成,第二部就是给微信支付传递调起微信支付的参数(具体参数看文档说明):
- <span style="font-size:14px;">private void genPayReq() {
- 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());
- 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());
- }</span>
第三部,调微信支付:
- <span style="font-size:14px;">private void sendPayReq() {
- msgApi.registerApp(Constants.APP_ID);
- msgApi.sendReq(req);
- }</span>
其中:
- <span style="font-size:14px;">Constants.APP_ID</span>
- <span style="font-size:14px;"> req.partnerId = Constants.MCH_ID;</span>
- <span style="font-size:14px;">ConfigUtil.NOTIFY_URL</span>
签名两次,然后用的api——key是商户平台api安全里面自定义的。
对了 还有个获取时间工具
- <span style="font-size:14px;">private long genTimeStamp() {
- return System.currentTimeMillis() / 1000;
- }</span>
下载链接 http://download.csdn.net/detail/meijuanyou/9571223