zoukankan      html  css  js  c++  java
  • Android—基于微信开放平台v3SDK,开发微信支付填坑。

    接触微信支付之前听说过这是一个坑,,,心里已经有了准备。。。我以为我没准跳坑出不来了,没有想到我填上了,调用成功之后我感觉公司所有的同事都是漂亮的,隔着北京的大雾霾我仿佛看见了太阳~~~好了,装逼结束。。。进入正题

    开发准备:

    1.在微信开放平台申请账号

    2.成功后创建应用,就是填一些看似很官方很正经的资料了。。。(说审核7天左右,没有意外的情况下你的app第二天就审核成功了是不是很开心,有了appid,是不是就可以调用微   信支付了????-------想多了,真的)

    3.微信支付是需要额外申请的:需要资料审核,账户验证,协议签署等步骤,(我记得,,资料审核要填写的东西好多,,,好多,,,账户验证就是你审核成功后微信会发送邮件到你   注册时登记的邮箱账号,其中含有随机金额用于账户验证,协议签署,略,太简单)一定要好好阅读你邮件的任何信息,因为有的细节错了,,,你可能填坑很久。。。。。。

    正式开发阶段:

    问题1:

    调用官方的SDK发现只能成功的调起一次微信,再次支付的时候怎么也调用不起来了

    解决:

    似乎不是什么正经方法:在手机设置中管理应用程序,清除微信数据,缓存,,再来一遍,绝对可以调起来(当然还是只是一次。。。。)

    继续:

    我认为要用微信支付嘛,,就只看了调用支付接口的文档:

    后来发现需要的参数prepayid是怎么也找不到啊,,后来才发现这个prepayid是先调用”统一下单“这个接口时候温馨反过来的东西,但是官方的SDK中并没有统一下单的代码。坑吗???

    所以要先看统一下单文档了 

    1.使用自己的APP调用的时候把官网down下来的SDK中WXPayEntryActivity拷贝到自己的项目,所在包的名字最后一定是.wxapi(我连包一起拷了。。。。)

    2.在项目清单文件中填写:

     

     3.SDK中的AppRegister拷贝下来,,,里面换成你自己的appid,然后在项目清单中也注册一下。

     

     

    4.重点来了,,就是你APP要调微信支付的activity,我这还叫PayActivity

     要调起微信支付页面,要在这个activity中,将你的app注册到微信

     

    接下来先调用统一下单获取prepayid,参数,微信人家要xml格式的!我们就得发送xml格式的!

     

    好了调用的时候把这个方法的返回值当参数传,,等待微信返回success吧!。。

     我遇见的错误:签名错误

    我的原因是大意了 ConfigUtil.NOTIFY_URL这个参数写的空字符串

    还有是因为debug版运行的,没有打包运行

    返回成功之后,可以调用支付接口了

    不要忘了这一步去跳转界面,,,,,

    没有跳转到微信支付可能是你由运行的debug版本,,,,没有打包。。。。。

    问题:支付成功或者失败后不能跳转到支付结果界面,就是官方demo中的WXPayEntryActivity类

    解决:这个类必选在你的包名+.wxapi包下,必须是你的包名+.wxapi包下 你的包名+.wxapi包下 你的包名+.wxapi包下 重要的事说好多遍。。

    下面是我的PayActivity完整代码:

    package com.example.taijiapp.ui;
    
    import java.io.StringReader;
    import java.net.InetAddress;
    import java.net.NetworkInterface;
    import java.net.SocketException;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Map;
    import java.util.Random;
    
    import org.apache.http.NameValuePair;
    import org.apache.http.message.BasicNameValuePair;
    import org.xmlpull.v1.XmlPullParser;
    
    import com.example.taijiapp.R;
    import com.example.taijiapp.util.Constants;
    import com.example.taijiapp.util.MD5;
    import com.example.taijiapp.util.T;
    import com.example.taijiapp.util.Util;
    import com.example.taijiapp.utils.ConfigUtil;
    import com.tencent.mm.sdk.modelpay.PayReq;
    import com.tencent.mm.sdk.openapi.IWXAPI;
    import com.tencent.mm.sdk.openapi.WXAPIFactory;
    
    import android.app.Activity;
    import android.app.ProgressDialog;
    import android.content.Context;
    import android.net.wifi.WifiInfo;
    import android.net.wifi.WifiManager;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.util.Log;
    import android.util.Xml;
    import android.view.View;
    import android.widget.Button;
    
    public class PayActivity extends Activity {
    	PayReq req;
    	private IWXAPI msgApi;
    	Map<String, String> resultunifiedorder;
    	StringBuffer sb;
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.pay);
    		req = new PayReq();
    		sb = new StringBuffer();
    		msgApi = WXAPIFactory.createWXAPI(this, Constants.APP_ID);
    		/**
    		 * 将app注册到微信
    		 */
    		boolean registerApp = msgApi.registerApp(Constants.APP_ID);
    		T.show(this, "注册========"+registerApp+"");
    		Button appayBtn = (Button) findViewById(R.id.appay_btn);
    		Button check_pay_btn = (Button) findViewById(R.id.check_pay_btn);
    		appayBtn.setOnClickListener(new View.OnClickListener() {
    
    			@Override
    			public void onClick(View v) {
    				GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
    				getPrepayId.execute();
    			}
    		});
    		/**
    		 * 将该app注册到微信
    		 */
    		check_pay_btn.setOnClickListener(new View.OnClickListener() {
    
    			@Override
    			public void onClick(View v) {
    				genPayReq();
    				sendPayReq();
    				
    			}
    		});
    //		// 生成签名参数
    //		Button appay_pre_btn = (Button) findViewById(R.id.appay_pre_btn);
    //		appay_pre_btn.setOnClickListener(new View.OnClickListener() {
    //
    //			@Override
    //			public void onClick(View v) {
    //				genPayReq();
    //			}
    //		});
    	}
    	/**
    	 * 生成签名
    	 */
    
    	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(Constants.KEY);
    		Log.e("拼接=====", sb.toString());
    		String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
    		Log.e("orion生成签名===", packageSign);
    		return packageSign;
    	}
    
    	/**
    	 * 签名工具 不含商户密钥 -暂时不用 = * 编码格式 UTF-8 = * @return
    	 */
    	public static String createSignNoKey(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('&');
    		}
    		String signStr = sb.toString();
    		String subStr = signStr.substring(0, signStr.length() - 1);
    		// 注意sign转为大写
    		return MD5.getMessageDigest(subStr.getBytes()).toUpperCase();
    	}
    
    	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.KEY);
    
    		this.sb.append("sign str
    " + sb.toString() + "
    
    ");
    		String appSign = MD5.getMessageDigest(sb.toString().getBytes());
    		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 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
    " + result.get("prepay_id") + "
    
    ");
    
    			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;
    		}
    	}
    
    	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;
    
    	}
        /**
         * 生成随机数
         * @return
         */
    	private String genNonceStr() {
    		Random random = new Random();
    		return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
    	}
        /**
         * 时间戳
         * @return
         */
    	private long genTimeStamp() {
    		return System.currentTimeMillis() / 1000;
    	}
        /**
         * 随机数
         * @return
         */
    	private String genOutTradNo() {
    		Random random = new Random();
    		return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
    	}
        /**
         * 获取设备的ip地址
         * @return
         */
    	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;
    	}
        /**
         * 转化成Ip地址的格式
         * @param i
         * @return
         */
    	private String intToIp(int i) {
    
    		return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF) + "." + (i >> 24 & 0xFF);
    	}
    
    	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", "APPtest"));
    			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", "100"));
    			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;
    		}
    	}
    
    	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
    " + req.sign + "
    
    ");
    		Log.e("orion==genPayReq===============", signParams.toString());
    
    	}
    
    	private void sendPayReq() {
    		boolean sendReq = msgApi.sendReq(req);
    		T.show(this, "微信跳转====="+sendReq+"");
    	}
    
    }
    

    里面没有的类,,,,呐: http://download.csdn.net/detail/meijuanyou/9571223  自己下载一下拷贝一下。。。

    参考博客      https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1

     备忘,希望能给大家带来帮助。。。

     

     

     

  • 相关阅读:
    Webkit CSS properties
    轻量级前端MVVM框架avalon
    ExtJS4 源码解析(一)带项目分析
    web app开发利器
    运用webkit绘制渲染页面原理解决iscroll4闪动的问题
    吐槽:基于PhoneGap开发移动项目
    轻量级前端MVVM框架avalon
    轻量级前端MVVM框架avalon
    WinDbg 命令三部曲:(一)WinDbg 命令手册
    Unit Testing with NSubstitute
  • 原文地址:https://www.cnblogs.com/yunfang/p/6078208.html
Copyright © 2011-2022 走看看