1. 程式人生 > >公眾號微信支付java開發,微信支付簽名錯誤,或者一直請求回撥方法問題

公眾號微信支付java開發,微信支付簽名錯誤,或者一直請求回撥方法問題

本編為原創,如需轉載,請註明出處。

微信支付開發過程中,如果沒有遇到簽名錯誤這個問題或者一直請求回撥方法問題,那麼感覺你開發了一個假對接,網上也有許多列子,以及官網也有微信團隊demo,但是還是有解決不了的各種簽名問題,demo需要手動修改因為他的加密方式會不盡如人意,還有排序問題。好了,話不多說,直接進入步驟中。

注意:如果遇到簽名錯誤,一定要檢視引數順序

          比較坑的是,

1:官網商戶key填寫的時候提示你8位數還是6位數以上的數字加字母組成就可以,但是你必須在設定完之後,再次修改成32位加密字串!!!

2:回撥地址,如果你是http://www.xxx.cn/txxxr/wxpay/wxpay.do的方式,你的地址需要寫成http://www.xxx.cn/txxxr/wxpay/      !!!

好了,以上兩個問題如果都沒問題了,那麼我們進入正式程式碼開發。(具體工具類以及全部程式碼,會在本文的末尾中。)

在此只介紹重點步驟,開發可以在demo中修改我的路徑以及自己的邏輯就可以。


controller方法:

package cn.teacher.wxpay.controller;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import cn.teacher.weiXin.dao.BasWxUserForStuDao;
import cn.teacher.wxpay.sdk.WXPay;
import cn.teacher.wxpay.sdk.WXPayUtil;
import cn.teacher.wxpay.util.WXPayConfigImpl;

@Controller
@RequestMapping("wxpay")
public class WXPayController {
	private WXPay wxpay;
    private WXPayConfigImpl config;
    private String out_trade_no;
    
    @Autowired
	private BasWxUserForStuDao basWxUserForStuDao;
    
    @RequestMapping(value="/wxpay_memberManagement")
    public  String memberManagement(HttpServletRequest request,Model model){
    	String openid ="ogcMwwuHoHeMG5Mp_cPkmYYdY6CU";
    	return "memberManagement";
    }
    @RequestMapping(value="/wxpay_packageInfo")
    public  String packageInfo(HttpServletRequest request){
    	return "packageInfo";
    }
    
    
    public WXPayController() throws Exception {
        config = WXPayConfigImpl.getInstance();
        wxpay = new WXPay(config);
        out_trade_no = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
    }
    
    
    /**
     * 掃碼支付  下單
	 * @throws Exception 
     */
	@RequestMapping(value = "/wxpay_unifiedOrder", produces = "application/json;charset=UTF-8")//這一步必須有!!
	@Transactional
    public @ResponseBody String doUnifiedOrder(String bodyname,String fee) throws Exception {//bodyname例如:騰訊支付中心,fee為價格
		JSONObject result = new JSONObject();
		Map<String, String> resdata = new HashMap<String, String>();
		//獲取到使用者的openid
		String openid ="ogcMwwuHoHeMG5Mp_cPkmYYdY6CU";
		 Map<String, String> data = new HashMap<String, String>();
	        data.put("body", bodyname);
	        data.put("out_trade_no", out_trade_no);//生成的訂單編號
	        data.put("fee_type", "CNY");
	        data.put("total_fee", fee);
	        data.put("spbill_create_ip", "58.87.76.30");//請求ip地址
	        data.put("notify_url", "http://xxx.mmath.cn/teacher/uploadwx/paytest");//請求成功返回路徑
	        data.put("trade_type", "JSAPI");//公眾號支付型別
	        data.put("openid", openid);
	        try {
	        	//統一下單,得到prepay_id
	            Map<String, String> r = wxpay.unifiedOrder(data);
	            //得到帶預支付prepay_id
	            String prepay_id= r.get("prepay_id");
	            //拼接組成新的sign並加密
	            String timestamp = String.valueOf(new Date().getTime()/1000);
	            String stringA =""+"appId="+config.getAppID()+"&nonceStr="+r.get("nonce_str") +"&package=prepay_id="+prepay_id+"&signType=MD5"+"&timeStamp=" + timestamp + "&key="+config.getKey();
	            String sign=WXPayUtil.MD5(stringA).toUpperCase();
	            //返回頁面資料供呼叫H5使用 
	            result.put("appId", config.getAppID());//appid
	            result.put("timeStamp", timestamp);//時間戳精確到秒
	            result.put("nonceStr", r.get("nonce_str"));//訂單編號
	            result.put("paySign", sign);//sign
	            result.put("signType", "MD5");//加密方式
	            result.put("packageStr", "prepay_id=" + prepay_id);  //預支付id
	            result.put("flag", true);//支付方法狀態
		
//可以在此處新增一個臨時的訂單步驟,狀態為支付中,在回撥介面中修改支付狀態為支付成功或者失敗 } catch (Exception e) { e.printStackTrace(); } return JSON.toJSONString(result); } }


頁面jsp程式碼

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<% String path = request.getContextPath(); %>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>個人中心</title>
<script type="text/javascript" src="<%=path %>/js/jquery.js"></script>
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<body>
<div>
	<div style=" width: 100%;">
		<ul >
			<li style="width: 80%;float: left;"><p><strong id="bodyname">99元套餐</strong></p><p>六年級下學期下載</p></li>
			<li style="width: 20%;float: left;"><p><input type="button" value="結算" onclick="pay();" style="background-color: yellow;"></li>
			<li style="width: 100%;float: left;" >
			<input name="tab" type="checkbox" value="" onclick="money();"/>趙小小
			<input  name="tab" type="checkbox" value=""  onclick="money();"/>陳大
			<input  name="tab" type="checkbox" value=""  onclick="money();"/>辰辰
			   合計¥<strong id="m">0</strong> </li>
		</ul>		
	</div>
</div>
<script type="text/javascript">
var prepay_id ,paySign,appId ,timeStamp, nonceStr,packageStr ,signType ;
/**
 * 點選支付按鈕進行方法呼叫
 */
function pay(){
var fee="20";
var bodyname="XXX支付介面";
    var url = "http://XXX.mmath.cn/teacher/wxpay/wxpay_unifiedOrder";
    $.ajax({
    type:"post",
    url:url,
    data: "bodyname="+bodyname+"&fee="+fee,
    success:function(data) {
     if(data.flag){
         appId = data.appId;
         paySign = data.paySign;
         timeStamp = data.timeStamp;
         nonceStr = data.nonceStr;
         packageStr = data.packageStr;
         signType = data.signType;
         callpay();
        }else{
         alert("統一下單失敗");
        }
    }
});
}
/*
 * 呼叫支付h5頁面
 */
function onBridgeReady(){
    WeixinJSBridge.invoke(
        'getBrandWCPayRequest', {
             "appId":appId,     //公眾號名稱,由商戶傳入
             "timeStamp":timeStamp, //時間戳,自1970年以來的秒數
             "nonceStr":nonceStr , //隨機串
             "package":packageStr,  //預支付交易會話標識
             "signType":signType,     //微信簽名方式
             "paySign":paySign         //微信簽名
         },
         function(res){
          if(res.err_msg == "get_brand_wcpay_request:ok" ) {
         alert('支付成功');
     }else if(res.err_msg == "get_brand_wcpay_request:cancel"){
         alert('支付取消');
     }else if(res.err_msg == "get_brand_wcpay_request:fail" ){
        alert('支付失敗');
     } //使用以上方式判斷前端返回,微信團隊鄭重提示:res.err_msg將在使用者支付成功後返回    ok,但並不保證它絕對可靠。
         }
    );
}
/**
 * 判斷是否進入支付步驟
 */
function callpay(){
    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();
    }
}

</script>
</body>
</html>

其餘的檔案以及工具類

由於上次上傳的檔案沒有宣告以下內容,導致碼農下載完資源後看到個官方demo基本一致,直接棄置不用,所以在此特別宣告。如果介意,不要下載。

(本文專案是在微信官方demo的基礎上進行修改開發的,所以類名方法名和框架結構和官方demo基本一致,但是部分內容會進行修改,請下載前仔細閱讀)

http://download.csdn.net/download/qq_37581708/10198124

好吧,我不知道怎麼弄成免費的,你們可以聯絡我,我私發給你們,或者留下你的QQ~

下面是最後一步處理:回撥介面

/**
	 * 支付成功後,接收微信返回的回撥方法
	 */
	@RequestMapping(value="/order", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public void order(HttpServletRequest request, HttpServletResponse response) throws Exception{
		String msg = "success";
        response.setContentType("text/xml");     
        String resXml = "";
	BufferedReader reader = null;
        reader = request.getReader();
        String line = "";
        String xmlString = null;
        StringBuffer inputString = new StringBuffer();
        while ((line = reader.readLine()) != null) {
            inputString.append(line);
        }
        xmlString = inputString.toString();
        request.getReader().close();
        Document doc = null;
        try {
            // 下面的是通過解析xml字串的
            doc = DocumentHelper.parseText(xmlString); // 將字串轉為XML
            Element rootElt = doc.getRootElement(); // 獲取根節點
            Element recordEle = (Element)rootElt;
            String result_code = recordEle.elementTextTrim("result_code");
            String return_code = recordEle.elementTextTrim("return_code");
            String out_trade_no = recordEle.elementTextTrim("out_trade_no");
            String stuNo =out_trade_no.split("_ms_")[1];
		//在此處開始進行資料庫訂單記錄狀態插入與修改
            if(return_code.indexOf("SUCCESS")!=-1){ 
            	if(result_code.indexOf("SUCCESS")!=-1){
            		//支付成功
            		wXPayService.updateOrder(out_trade_no, "1",stuNo);
            	}else{
            		//支付失敗
            		wXPayService.updateOrder(out_trade_no, "2","1");
            	}
		//這一步非常重要:返回給微信成功通知,否則會一直回撥。
            	resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                BufferedOutputStream out = new BufferedOutputStream(
                        response.getOutputStream());
                out.write(resXml.getBytes());
                out.flush();
                out.close();
                response.getWriter().println(msg);
            }
            
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }