微信开发------------公众号支付统一下单整个流程

版权声明:本文为博主原创文章,未经博主允许不得转载。你想转载请附加连接哦 https://blog.csdn.net/dmw412724/article/details/82770939

申请微信支付在这里:https://blog.csdn.net/dmw412724/article/details/82735906

微信支付后台搭建(阅读本文的基础):https://blog.csdn.net/dmw412724/article/details/90053811

一。后台统一下单

private static Map<String, String> testOrder() throws Exception{
		/**
		 * 统一下单所需数据
		 */
		Map<String, String> reqData = new HashMap<>();
		reqData.put("out_trade_no", "101");
		reqData.put("total_fee", "101");
		reqData.put("notify_url", "http://www.baidu.com");
		reqData.put("body", "请支付");
		reqData.put("spbill_create_ip", "192.168.0.100");
		reqData.put("openid", "oxaaaaaaaa");
		reqData.put("trade_type", "JSAPI");
		/**
		 * 发送请求
		 */
		WXPayConfigImpl config = new WXPayConfigImpl();//沙箱
		WXPay pay = new WXPay(config);
		Map<String, String> map = pay.unifiedOrder(reqData);
		System.out.println(map);
		/**
		 * 判断http成功且结果成功
		 */
		if ("SUCCESS".equals(map.get("return_code")) && "SUCCESS".equals(map.get("result_code"))){
			Map<String, String> data = new HashMap<>();
			//取出下面的值
			data.put("appId", map.get("appid"));
			data.put("timeStamp", Long.toString(WXPayUtil.getCurrentTimestamp()));
			data.put("package", "prepay_id="+map.get("prepay_id"));//取出里面的预订单id
			data.put("nonceStr", WXPayUtil.generateNonceStr());
			data.put("signType", WXPayConstants.MD5);
			//重新加密并塞到data里
			data.put("paySign", WXPayUtil.generateSignature(data, config.getKey()));
			return data;//把这个返回到前台
		}
		return null;
	}

最终拿到数据应该得到了这几个东西:

appId,

timeStamp,

nonceStr,

package,

signType,

paySign

然后把这个map传递到前台就行了.因为这六个正好是前台所需要的

 

二. 前台

两种写法.一种是使用微信jssdk.一种是直接使用微信内置浏览器对象.它俩什么关系?应该是jssdk里引用了微信内置浏览器对象吧.

使用微信内置浏览器对象就意味着必须在微信里才能使用.这并不是在其他应用里唤醒微信并打开微信支付 .

1.jssdk写法.

这个是在使用jssdk需要进行初始化验签保证安全.这个大家都清楚.如果不懂,那么去看另外一种方法吧.

wx.config({
				    //debug: true,
				appId: "", 
				timestamp: "", 
				nonceStr: "", 
				signature: "",
				jsApiList: ["chooseWXPay"] 
			});	

你还要引入一个js.微信的js

 <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

验完后调用这个就行了.

 wx.chooseWXPay({
	appId: data.body.appId,
	timestamp: data.body.timeStamp,
        nonceStr: data.body.nonceStr,
	package: data.body.package, 
	signType: data.body.signType, 
	paySign: data.body.paySign,								
	success: function (res) {
		alert("成功");	
	},
	fail: function(res) {
		alert('fail--'+JSON.stringify(res))
	},
	complete: function(res) {
		alert('complete--'+JSON.stringify(res))
	}
									
})  

这个里面.data.body.xxx就是后台返回的值

不管怎样,都会走complete方法.

如果用户确认支付了,会走success方法.

如果调用api错误了.那么会走fail方法.

2.微信内置对象写法

WeixinJSBridge.invoke(
     'getBrandWCPayRequest',
      {
        "appId":data.body.appId,     //公众号名称,由商户传入     
        "timeStamp":data.body.timeStamp,         //时间戳,自1970年以来的秒数     
        "nonceStr":data.body.nonceStr, //随机串     
        "package":data.body.package,     
        "signType":data.body.signType,         //微信签名方式:     
        "paySign":data.body.paySign //微信签名 
     },
     function(res){
      if(res.err_msg == "get_brand_wcpay_request:ok" ){
      		// 使用以上方式判断前端返回,微信团队郑重提示:
            //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
       }
   }
);   

这个里面.data.body.xxx就是上面那1.6里说的那个map里面的值.

3.一些返回fail的坑?

1.对于安卓来说,不管什么都是fail.所以请使用ios来调试,ios会告诉你到底怎么回事.

2.微信支付授权目录要配置正确(我目前是没有这个问题的).timeStamp是要大写的,但如果你用了我的工具类,也是不会出现这样的问题的..

3.客户端ip要真实.

4.如果使用jssdk写法.请引入jweixin-1.0.0.js

5.如果ios调试没有问题,而安卓有问题(或部分机型有问题?),那么你应该使用的是jssdk,你引入的那个jweixin-1.0.0.js放在了下面,应该把这条js放到最上面来引用.

三.回调

public String notifyUrlByWx(HttpServletRequest request) throws Exception {
        String notifyData = WebUtils.getPostBody(request);//获取输入流xml字符串
		Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData); // 转换成map
		if (WXPayUtil.isSignatureValid(notifyMap, WxPayConfig.KEY)) {
			// 签名正确
			// 进行处理。
			// 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功			
			String resultCode = notifyMap.get("result_code");
			if (resultCode.equals("SUCCESS")){
				//处理业务逻辑
                
                //返回
				return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";

				
			}else{
				//如果支付失败
			}
		} else {
			// 签名错误,如果数据里没有sign字段,也认为是签名错误
		}
		return "error";
	}

猜你喜欢

转载自blog.csdn.net/dmw412724/article/details/82770939