微商城支付开发(二)

微信支付功能(代码开发)

上一篇文章已经告诉大家如何配置来获取微信提供的参数。在这里再问问自己是否拿到以下参数:

          1.开发者IDAppID

    2.商户ID

             3.支付key(需要加密的MD5)

PS(已通过微信认证的公众号,必须通过ICP备案域名(否则会报支付失败))

以下图了解一下大概流程就行了,能完全掌握更好。

微信内网页支付时序图


如果都拿到了就开始把支付的代码嵌入到项目中来调起支付接口(眼睛擦干净点啊,下面的参数都是有规则滴 区分大小写,我就是在这里卡了我很久,enmmmmmmmp不知该讲不讲唉)

在这里感谢提供文章帮助我的大神,就不一一道谢了微笑

涉及到相关帮助文章或者下载地址

1、https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455784140(PS:由于微信支付时调试,不能用浏览器打开微信路径,会提示要求你在微信浏览器打开该路径,所以去下载微信web开发者工具)

2、https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=3_1  (微信支付开发文档,好好看看这里面的支付相关规则)

3、https://blog.csdn.net/xb12369/article/details/50512633    (微信支付,body不是UTF-8)

4、https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_102&index=2#     (统一下单API)

5、https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1                 微信支付接口签名校验工具)


流程如下:

1.在用户点击下单后,创建完订单成功后,返回到JS里面进行跳转时,路径为以下:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=xxxxxxxxxxxxxxxx&redirect_uri=http://m.xxxxxxx.com/xxxxxx/xxxxxx/selectpay.html?ord_id="+ret.body.ord_id+"&response_type=code&scope=snsapi_base&state=STATE&connect_redirect=1#wechat_redirect

具体而言,这一步是用来获取code,但必须用户同意网页授权后才能得到code值(为什么要code后面再来解释)在微信中打开这个授权链接,会进入到如下图所示页面:

  单击取消或允许按钮,都会进入到上面设置的回调页面。如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数redirect_uri?state=STATE
  【code说明 】:
  code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
  【参数说明】:

参数

是否必须

说明

appid

公众号的唯一标识

redirect_uri

授权后重定向的回调链接地址

response_type

返回类型,请填写code

scope

应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)

state

重定向后会带上state参数,开发者可以填写任意参数值

#wechat_redirect

直接在微信打开链接,可以不填此参数。做页面302重定向时候,必须带此参数


分解路径:

appid:填写开发者ID

redirect_uri:重定向页面,跳转到你需要进行支付的页面

ord_id:订单ID需要查询

可自己参考

https://www.cnblogs.com/goflee/p/3484561.html

这时候已经拿到code了,还有其他参数。我的重定向是selectpay.html。


2.在selectpay.html页面  js里面获取code还有其他参数(根据自己代码去写)

        

 ajaxGetJson({
        url:"json.html?formatId=byypOrderSelectPayTrade",
        data:{"ord_id":URLParams.get("ord_id")},
        success:function(ret){
            if(ret.head.code == "0000"){
            	$("#selectpay").html(template("tpl-selectpay",ret.body));
				getWXUserOpenId();
            }else{
                jDialog.confirm("支付数据加载失败!",function(r){
                    if(r){
                        myLocationReload();
                    }else{
                        location.href = './ucenter/myorder.html';
                    }
                },false,"重试","返回订单");
            }
        }
    });

将数据绑定好在来获取code相关参数

//获取用户的openId
    function getWXUserOpenId(){
    	var access_code = getQueryString('code');
    	if(access_code != null){
    		code = access_code;
    	}
   	}
   	
   	//获取微信url回调参数
   	function getQueryString(name) {  
          var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");  
          var r = location.search.substr(1).match(reg);  
          if (r != null)  
              return unescape(decodeURI(r[2]));  
          return null;  
    } 

code在用户点击支付时会提交到后台去。

var appId = "";  
	var timeStamp = "";    
	var nonceStr = "";  
	var signType = "";   
	var paySign = "";  
	var code = "";
	var openId = "";
	var pg = "";
	var trade_no = "";
    $(document).on("click","#go-pay-btn",function(){
    	if(code != ""){
	    		ajaxGetJson({
	            url:"json.html?formateId=generateByypGoodsPayment",
	            data:{"ord_id":URLParams.get("ord_id"),"code":code},
	            error: function(textStatus){alert('系统错误~');},  
	            success:function(msg){
	                /*if(msg.head.code == "0000"){
	                    location.href = "./paysuccess.html?ord_id="+URLParams.get("ord_id");
	                }else{
	                    location.href = "./payfail.html?ord_id="+URLParams.get("ord_id");
	                }*/
	                if(msg.head.code == "0000"){
		                if(msg!=null){
		                		
		                		 appId = msg.body.appid;  
								 timeStamp = msg.body.timestamp;    
								 nonceStr = msg.body.nonceStr;  
								 signType = msg.body.signType;   
								 paySign = msg.body.sign;  
								 pg = msg.body.package;
								 trade_no = msg.body.out_trade_no;
		                		
		                       //唤起微信支付  
						       if(appId!=''){
						           pay();  
						       }
		                 }  
	                }else{
	                    location.href = "./payfail.html?ord_id="+URLParams.get("ord_id");
	                }
	           	}
	        })
    	}else{
    		alert("授权失败,请联系技术人员!");
    	}
    });


	//唤起微信支付  
	function pay(){    
	    if (typeof WeixinJSBridge == "undefined"){    
	       if( document.addEventListener ){    
	           document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);    
	       }else if (document.attachEvent){    
	           document.attachEvent('WeixinJSBridgeReady', onBridgeReady);     
	           document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);    
	       }    
	    }else{    
	       onBridgeReady();    
	    }     
	}    
	
		//开始支付  
	function onBridgeReady(){    
	    WeixinJSBridge.invoke(    
	        'getBrandWCPayRequest', {    
	            "appId" : appId,     //公众号名称,由商户传入         
	            "timeStamp": timeStamp+"",         //时间戳,自1970年以来的秒数         
	            "nonceStr" : nonceStr, //随机串         
	            "package" : pg,         
	            "signType" : signType,         //微信签名方式:         
	            "paySign" : paySign,    //微信签名 
	        },
	        function(res){         
	            if(res.err_msg == "get_brand_wcpay_request:ok" ) {    
	                //alert("支付成功");  // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。     
	                //回到用户订单列表  
	                //location.href = "./yppaynotice.html";
	                //location.href = "./paysuccess.html?ord_id="+URLParams.get("ord_id");
	                updateByypOrderInfo(URLParams.get("ord_id"),trade_no);
	            }else if (res.err_msg == "get_brand_wcpay_request:cancel")  {  
	                //alert("支付过程中用户取消");  
	                location.href = "./sensorweb/mall/ucenter/mybyyporder.htmlmyorder.html?ord_status=11";
	            }else{  
	               //支付失败  
	               alert(JSON.stringify(res));
	               alert(res.err_msg)  
	            }       
	        }    
	    );     
	 }   
	

    3.再控制器里面生成微支付需要的参数返回在js页面(话不多说直接贴代码)

//log.info("微信生成支付码开始");
		//		String user_id = MemUserConstant.getUserId(ctx);
		String ord_id=ctx.getPostString("ord_id");//1.获取传入数据	得到商品详情
		String code=ctx.getPostString("code");//code
		//out_trade_no商户订单号 以下是组成是由规则的,查看微信开发文档,基本上要是数字
		SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
		String randomDate =  format.format(new Date());
		int randomNum = (int) (Math.random() * 1000000);
		String out_trade_no = ("190008"+randomDate+randomNum).toString();
		System.out.println("商户号是:"+out_trade_no);
		
		Map<String, String> jsonObject = new HashMap<String,String>();
		WxConfig wxConfig = new WxConfig();
		//根据用户授权后 页面传入code到后台   获取openId	
		String openid = HttpXmlUtils.getOpenId(code);
		System.out.println("openid是:"+openid);
		
        //getSumTotal 微信的价格单位是分(x100),所以intValue 不存在精度丢失的问题  
//        int total_fees = (trans.getTotal().intValue() - userBonus - userYqh)*100;  
        int total_fee = 1;//一分钱测试  
        https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1    (统一下单开发文档,参数规则)
        //String detail = "{goods_id:商品编码,wxpay_goods_id:1001,goods_name:充电宝,quantity: 1,price: 528800}";	//测试数据格式
        String wxPayResult = WxPayUnifiedResult.getWxPayUnifiedResult("111","2222","3333",out_trade_no, total_fee, "119.123.66.183",openid);
        Map<String, String> oppidObj =  WXPayUtil.xmlStr2Map(wxPayResult);//将xml字符串解析为map
        //1.生成签名后,这里需要得到状态是否成功,如果不成功则提示信息(等测试通过后在来设置)
        //2.再检查是否有sing签名
        
        //log.info("生成签名:"+wxPayResult);
        String timestamp = String.valueOf(new Date().getTime()/1000);  
        String nonceStr = oppidObj.get("nonce_str").toString();
        System.out.println(nonceStr);
        String prepay_id = oppidObj.get("prepay_id").toString();  //需要获得prepay_id(能得到它,离成功越来越近了)
        System.out.println(prepay_id);
        
        //参数:开始生成签名  
        SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();  
        parameters.put("appId", wxConfig.getAppid());  //区分大小写的,
        parameters.put("timeStamp", timestamp);  
        parameters.put("signType", "MD5");  
        parameters.put("nonceStr", nonceStr);  
        parameters.put("package", "prepay_id="+prepay_id);
        String sign = WXSignUtils.createSign(parameters); 

        System.out.println("预支付id相关参数是:"+jsonObject.toString());  
		
		Map<String,Object> body = new HashMap<String,Object>();
		body.put("appid", wxConfig.getAppid());
		body.put("timestamp", timestamp);
		body.put("signType", "MD5");
		body.put("nonceStr", nonceStr);
		body.put("package", "prepay_id="+prepay_id);
		body.put("sign", sign);
		body.put("prepay_id", prepay_id);
		body.put("out_trade_no", out_trade_no);
		
		RsjConstant.setSuccess(ctx, body);//5.返回数据

注意事项:

        这里要看清楚了,生成签名时key是区分大小写的,生成签名时key是区分大小写的,生成签名时key是区分大小写的,重要的事情要说3遍。否则会提示你参数有误(本人就被这个坑了很久哭哭


以下是一些公共类,也给你们贴出来

WxConfig.java

// 应用APPID【appid】
	public String appid;

	// 微信支付商户号【mch_id】
	public String mch_id;

	// 回调地址
	public String notify_url;

	public String getAppid() {
		return "wxb550b5eda3fa1234";
	}

	public void setAppid(String appid) {
		this.appid = appid;
	}

	public String getMch_id() {
		return "1498876564";
	}

	public void setMch_id(String mch_id) {
		this.mch_id = mch_id;
	}

	public String getNotify_url() {
		return "http://m.buysensor.com/sensor/mall/yppaynotice.do";支付成功回调方法,成功后微信会调用这个方法,要在控制器里面写一个方法
	}

	public void setNotify_url(String notify_url) {
		this.notify_url = notify_url;
	}

HttpXmlUtil.java

    页面上获取code就是用在这里来获取用户openId(可以先用main方法来测试 是否可以得到)

//根据提供的code查询得到openId
    public static String getOpenId(String code) throws ServletException, IOException {
    	String appid = "wxb550be2d43a48142";	//开发者ID
    	String secret = "df2dtt2rw3e4fghha11073b4dfca559c";		//开发者密码(如果忘记密码了就重置就好了)
    	//这个路径可以改动,只要是微信有的接口都行
    	String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+appid+"&secret="+secret+"&code="+code+"&grant_type=authorization_code";
    	//第一次请求 获取access_token 和 openid
//    	System.out.println(requestUrl);
    	String oppid = null;
		try {
			oppid = new HttpXmlUtils().doGet(requestUrl);
		} catch (Exception e) {
			e.printStackTrace();
		}
    	JSONObject oppidObj =JSONObject.fromObject(oppid);	//根据不同的返回结果,读取不同key
    	String openid = (String) oppidObj.get("openid");
		return openid;
    }
/** 
     * post请求并得到返回结果 
     * @param requestUrl 
     * @param requestMethod 
     * @param output 
     * @return 
     */  
    public static String httpsRequest(String requestUrl, String requestMethod, String output) {  
        try{  
            URL url = new URL(requestUrl);  
            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();  
            connection.setDoOutput(true);  
            connection.setDoInput(true);  
            connection.setUseCaches(false);  
            connection.setRequestMethod(requestMethod);  
            if (null != output) {  
                OutputStream outputStream = connection.getOutputStream();  
                outputStream.write(output.getBytes("UTF-8"));  
                outputStream.close();  
            }  
            // 从输入流读取返回内容  
            InputStream inputStream = connection.getInputStream();  
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
            String str = null;  
            StringBuffer buffer = new StringBuffer();  
            while ((str = bufferedReader.readLine()) != null) {  
                buffer.append(str);  
            }  
            bufferedReader.close();  
            inputStreamReader.close();  
            inputStream.close();  
            inputStream = null;  
            connection.disconnect();  
            return buffer.toString();  
        }catch(Exception ex){  
            ex.printStackTrace();  
        }  
  
        return "";  
    }  
    
    
    /**
     * 微信htpp传输,并返回数据
    */
    public String doGet(String url) throws Exception {
       
        URL localURL = new URL(url);
        
        URLConnection connection = openConnection(localURL);
        HttpURLConnection httpURLConnection = (HttpURLConnection)connection;
        
        httpURLConnection.setRequestProperty("Accept-Charset", charset);
        httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        
        InputStream inputStream = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader reader = null;
        StringBuffer resultBuffer = new StringBuffer();
        String tempLine = null;
        
        if (httpURLConnection.getResponseCode() >= 300) {
            throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode());
        }
        
        try {
            inputStream = httpURLConnection.getInputStream();
            inputStreamReader = new InputStreamReader(inputStream,"UTF-8");
            reader = new BufferedReader(inputStreamReader);
            
            while ((tempLine = reader.readLine()) != null) {
                resultBuffer.append(tempLine);
            }
            
        } finally {
            
            if (reader != null) {
                reader.close();
            }
            
            if (inputStreamReader != null) {
                inputStreamReader.close();
            }
            
            if (inputStream != null) {
                inputStream.close();
            }
            
        }

        return resultBuffer.toString();
    }
    
    private URLConnection openConnection(URL localURL) throws IOException {
    	URLConnection connection;
    	if (proxyHost != null && proxyPort != null) {
    		Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
    		connection = localURL.openConnection(proxy);
    	} else {
    		connection = localURL.openConnection();
    	}
    	return connection;
    }
private String charset = "utf-8";
	private Integer connectTimeout = null;
	private Integer socketTimeout = null;
	private String proxyHost = null;
	private Integer proxyPort = null;

	public static String xmlInfo(UnifiedOrder unifiedorder){
		//构造xml参数的时候,至少有10个必传参数  
		/* 
		 * <xml> 
               <appid>wx2421b1c4370ec43b</appid> 
               <attach>支付测试</attach> 
               <body>JSAPI支付测试</body> 
               <mch_id>10000100</mch_id> 
               <nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str> 
               <notify_url>http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php</notify_url> 
               <openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid> 
               <out_trade_no>1415659990</out_trade_no> 
               <spbill_create_ip>14.23.150.211</spbill_create_ip> 
               <total_fee>1</total_fee> 
               <trade_type>JSAPI</trade_type> 
               <sign>0CB01533B8C1EF103065174F50BCA001</sign> 
            </xml> 
		 */  
		if(unifiedorder!=null){  
			StringBuffer bf = new StringBuffer();  
			bf.append("<xml>");  

			bf.append("<appid><![CDATA[");  
			bf.append(unifiedorder.getAppid());  
			bf.append("]]></appid>");  
			
			bf.append("<body><![CDATA[");  
			bf.append(unifiedorder.getBody());  
			bf.append("]]></body>");  

			bf.append("<mch_id><![CDATA[");  
			bf.append(unifiedorder.getMch_id());  
			bf.append("]]></mch_id>");  

			bf.append("<nonce_str><![CDATA[");  
			bf.append(unifiedorder.getNonce_str());  
			bf.append("]]></nonce_str>");  
			
			bf.append("<notify_url><![CDATA[");  
			bf.append(unifiedorder.getNotify_url());  
			bf.append("]]></notify_url>");
			
			bf.append("<openid><![CDATA[");  
			bf.append(unifiedorder.getOpenid());  
			bf.append("]]></openid>");  
			
			bf.append("<out_trade_no><![CDATA[");  
			bf.append(unifiedorder.getOut_trade_no());  
			bf.append("]]></out_trade_no>");  
			
			bf.append("<spbill_create_ip><![CDATA[");  
			bf.append(unifiedorder.getSpbill_create_ip());  
			bf.append("]]></spbill_create_ip>");  
			
			bf.append("<total_fee><![CDATA[");  
			bf.append(unifiedorder.getTotal_fee());  
			bf.append("]]></total_fee>");  
			
			bf.append("<trade_type><![CDATA[");  
			bf.append(unifiedorder.getTrade_type());  
			bf.append("]]></trade_type>");  
			
			bf.append("<detail><![CDATA[");  
			bf.append(unifiedorder.getDetail());  
			bf.append("]]></detail>");  

			bf.append("<attach><![CDATA[");  
			bf.append(unifiedorder.getAttach());  
			bf.append("]]></attach>");  


			bf.append("<time_start><![CDATA[");  
			bf.append(unifiedorder.getTime_start());  
			bf.append("]]></time_start>");  

			bf.append("<time_expire><![CDATA[");  
			bf.append(unifiedorder.getTime_expire());  
			bf.append("]]></time_expire>");  

			bf.append("<sign><![CDATA[");  
			bf.append(unifiedorder.getSign());  
			bf.append("]]></sign>");  

			bf.append("</xml>");  
			return bf.toString();  
		}  

		return "";
	}
	

WxPayUnifiedResult.java

/**
	 * @param body
	 * @param detail
	 * @param attach
	 * @param out_trade_no	商户号(自定义生成   必须数字组成 30个数字内)
	 * @param total_fee
	 * @param spbill_create_ip	提交ip地址
	 * @param openid   用户ID
	 * 获得prepay_id(得到这个参数支付功能成功一半)
	 * @return
	 */
	public static String getWxPayUnifiedResult(String body,String detail,String attach,String out_trade_no,int total_fee,String spbill_create_ip,String openid){  
		WxConfig wxConfig = new WxConfig();
		try{  
			//应用APPID【appid】  
			String appid = wxConfig.getAppid();
			System.out.println("appid是:"+appid);  
			//微信支付商户号【mch_id】  
			String mch_id = wxConfig.getMch_id();  
			System.out.println("mch_id是:"+mch_id);  
			//回调地址  
			String notify_url = wxConfig.getNotify_url();
			System.out.println("回调地址是:"+notify_url);
			//随机字符串  
			String nonce = UUID.randomUUID().toString().substring(0,30);
			String nonce_str = nonce;  
			System.out.println("随机字符串是:"+nonce_str);  
			SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
			//交易起始时间  
			Date stDate = new Date();
			String time_start = format.format(stDate);
			System.out.println(time_start);  
			//交易结束时间  
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(stDate);
			calendar.add(Calendar.MINUTE, 30);	//设置为30分钟
			String time_expire = format.format(calendar.getTime());
			System.out.println(time_expire);  		
			//交易类型  
			String trade_type = "JSAPI";//JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里  

			//body = "黑色手拿包";  

			//参数:开始生成签名  
			SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();  
			parameters.put("appid", appid);  
			System.out.println("body是:"+body);  
			//body = Utf8EncodeUtils.getUTF8XMLString(body);  
			parameters.put("body", body.toString());
			parameters.put("mch_id", mch_id);  
			parameters.put("nonce_str", nonce_str);  
			parameters.put("notify_url", notify_url);  	//回调地址  
			parameters.put("openid", openid);  	//用戶ID
			parameters.put("out_trade_no", out_trade_no);  	//商户系统内部订单号
			parameters.put("spbill_create_ip", spbill_create_ip);  
			parameters.put("total_fee", total_fee);  		//现金支付金额订单现金支付金额
			parameters.put("trade_type", trade_type);  	//交易类型 JSAPI 
			//detail = Utf8EncodeUtils.getUTF8XMLString(detail);  
			System.out.println("detail是:"+detail);  
			parameters.put("detail", detail.toString());  
			parameters.put("attach", attach);  	// 商家数据包 attach 否 String(128) 123456 商家数据包,原样返回 
			parameters.put("time_start", time_start);  	
			parameters.put("time_expire", time_expire);  	//结束时间

			//开始签名  
			String sign = WXSignUtils.createSign(parameters); 
			System.out.println("签名是:"+sign);  
			//log.debug("微信支付签名:"+sign);  

			UnifiedOrder unifiedorder = new UnifiedOrder();  
			unifiedorder.setAppid(appid);  
			unifiedorder.setMch_id(mch_id);  
			unifiedorder.setNonce_str(nonce_str);  
			unifiedorder.setSign(sign);  
			unifiedorder.setBody(body);  
			unifiedorder.setDetail(detail);  
			unifiedorder.setAttach(attach);  
			unifiedorder.setOut_trade_no(out_trade_no);  
			unifiedorder.setTotal_fee(total_fee);  
			unifiedorder.setSpbill_create_ip(spbill_create_ip);  
			unifiedorder.setTime_start(time_start);  
			unifiedorder.setTime_expire(time_expire); 
			unifiedorder.setNotify_url(notify_url);  
			unifiedorder.setTrade_type(trade_type);  
			unifiedorder.setOpenid(openid);  

			//构造xml参数  
			String xmlInfo = HttpXmlUtils.xmlInfo(unifiedorder);  
			
			System.out.println("构造xml参数:"+xmlInfo);
			//System.out.println("xml参数编码:"+new String(xmlInfo.toString().getBytes("utf-8"),"iso8859-1"));

			String wxUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";    //统一访问地址

			String method = "POST";  

			String weixinPost = HttpXmlUtils.httpsRequest(wxUrl, method, xmlInfo).toString();  

			System.out.println("weixinPost:"+weixinPost);  
			//log.debug("微信支付返回:"+weixinPost);

			return weixinPost.toString(); 
		}catch(Exception ex){
			ex.printStackTrace();  

			//log.debug("微信支付:"+ex.getMessage());  
		}

		return null;  
	}  

WXSignUtil.java

    

/** 
     * 微信支付签名算法sign(动态参数) 
     * @param characterEncoding 
     * @param parameters 
     * @return 
     */  
	 @SuppressWarnings("rawtypes")
    public static String createSign(SortedMap<Object,Object> parameters){  
        StringBuffer sb = new StringBuffer();  
		Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)  
        Iterator it = es.iterator();  
        while(it.hasNext()) {  
            Map.Entry entry = (Map.Entry)it.next();  
            String k = (String)entry.getKey();  
            Object v = entry.getValue();  
            if(null != v && !"".equals(v)   
                    && !"sign".equals(k) && !"key".equals(k)) {  
                sb.append(k + "=" + v + "&");  
            }  
        }  
        sb.append("key=" + "C5628D57CAB6C2D93DG29566ADFB1B31CB");  //这个就是商户号API证书
        System.out.println("字符串拼接后是:"+sb.toString());  
        String sign = DigestUtils.md5Hex(sb.toString()).toUpperCase();
        return sign;  
    }  

WXPayUtil.java   (org.dom4j.Document、org.dom4j.Element来接收

//xml形式的字符串转换为map集合  
    public static Map<String,String> xmlStr2Map(String xmlStr){  
    	Map<String,String> map = new HashMap<String,String>();  
		Document doc = null;  
		try {  
			doc = DocumentHelper.parseText(xmlStr); // 将字符串转为XML  
			Element rootElt = doc.getRootElement(); // 获取根节点 
			List<Element> list =  rootElt.elements();//获取根节点下所有节点  
			for (Element element : list) {  //遍历节点  
				map.put(element.getName(), element.getText()); //节点的name为map的key,text为map的value  
			}  
		} catch (DocumentException e) {  
			e.printStackTrace();  
		} catch (Exception e) {  
			e.printStackTrace();  
		}  
		return map;
    } 

最后一步,支付成功后微信就会执行你给它的回调地址,这个时候你需要接收他的消息然后回复它,不回复它他会一直发消息共8次

 /**
     * 微信支付回调页面
	 * @throws IOException 
     */
    public void byypWechatPayNotify(AreaContext ctx) throws IOException{
    	log.info("开始处理支付返回请求");
    	String resXml = "";	//反馈给微信服务器
    	String bodystr;
        try {
        	/*InputStream inputStream;
        	StringBuffer sb = new StringBuffer();
        	inputStream = ctx.getRequest().getInputStream();
        	String s;
        	BufferedReader in = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
        	while((s = in.readLine()) != null){
        		sb.append(s);
        	}
        	inputStream.close();
        	in.close();
        	bodystr= sb.toString();
        	log.info("微信支付回调返回:"+bodystr);*/
        	
            Map<String, String> map = WechatMerchantFactory.getCallbackParams(ctx.getRequest());	//微信支付系统发送的数据
        	log.info("微信支付系统发送的数据:"+map);
             //在这里还需要验证签名
        	if(!map.isEmpty()){
        		if (map.get("result_code").toString().equalsIgnoreCase("SUCCESS")) {
                    String orderId = map.get("out_trade_no");
                    System.out.println(orderId);
                    
                    //这里写成功后的业务逻辑
//                  orderService.updateConfirm(orderId);
                    //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了  
                    
                    log.info("支付成功!");
                    resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml> ";
                }else{
               	 log.info("支付失败,错误信息:"+map.get("result_code"));
                    resXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
                }
        	}
        } catch (Exception e) {
            e.printStackTrace();
            log.error("微信支付回掉异常!",e);
        }
        resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
        //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了  
        WechatMerchantFactory.writeMessageToResponse(ctx.getResponse(), resXml.toString());
        log.info("回复微信服务器成功!");
        
        Map<String,Object> body = new HashMap<String,Object>();
		body.put("body", null);
		RsjConstant.setSuccess(ctx, body);//5.返回数据
    }

WechatMerchantFactory.java

/**
     * 获取请求参数
     */
    public static Map<String, String> getCallbackParams(HttpServletRequest request)
            throws Exception {
        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        System.out.println("~~~~~~~~~~~~~~~~获取请求参数~~~~~~~~~");
        outSteam.close();
        inStream.close();
        String result = new String(outSteam.toByteArray(), "utf-8");
        System.out.println(result);
        if(result != ""){
        	return WXPayUtil.xmlToMap(result);
        }else{
        	return null;
        }
    }
    
    
    
    /**
     * 将xml参数解析为map返回出来 ,直接调用key(另一种方法)
     */
    public static SortedMap<Object, Object> getCallbackParamsTest(HttpServletRequest request) throws Exception{
    	// SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();  读取申明
    	//读取参数
        InputStream inputStream;
        StringBuffer sb = new StringBuffer();
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();

        //解析xml成map
        Map<String, String> m = new HashMap<String, String>();
        m = WXPayUtil.xmlToMap(sb.toString());

        //过滤空 设置 TreeMap
        SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
        Iterator it = m.keySet().iterator();
        while (it.hasNext()) {
            String parameter = (String) it.next();
            String parameterValue = m.get(parameter);

            String v = "";
            if (null != parameterValue) {
                v = parameterValue.trim();
            }
            packageParams.put(parameter, v);
        }
		return packageParams;
    }
    
    /**
     *  微信回调给平台,平台将消息返回给微信服务器
     */
    public static void writeMessageToResponse(HttpServletResponse response, String message) {
        PrintWriter writer = null;
        try {
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            writer = response.getWriter();
            writer.write(message);
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null)
                writer.close();
        }
    }


所有的公共方法都贴出来了,我自己在做的时候 找别人的代码都没怎么详细 缺斤少两的 方法全靠自己去找出来。

控制台的生成参数基本上已经可以了,吧参数返回出去就可以调起支付界面了。(PS:生成好的参数,一定要去检验查看参数是不是通过的)

最后返回给页面的参数模板

timestamp": "1521618904","
prepay_id": "wx20180321155336e666c3445a420336916025","
signType": "MD5","
package": "prepay_id=wx20180321155336e666c3445a420336916025","
appid": "wxb550b534224445a8142","
nonceStr": "gebFuy5LKwjQqVZa"


https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1(支付场景介绍,可以看看自己是否这样)


注意事项:再页面调起支付有问题,去查找以下地方

               1.按照我上一篇文章检查一下是否配置是否正确

               2.检查返回的参数是否正确(参数区分大小写的,不要搞错了,不然会提示你JSAPI缺少:total或者xxxx参数)

终于写完了,我也是怕忘记所以贴出来,同时也是为了其他同志们不要像我怎么苦逼的去找,心塞哦。如果还有其他方法没有贴出来,评论告诉我看到了会马上回复你的。如果对你有用的话请在评论区回复Thanks♪(・ω・)ノ嘿嘿



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值