微信app支付 java後臺接Android

阿門阿前那棵葡萄樹發表於2018-07-27

抽時間整理一下之前專案中的微信app支付,以備以後需要,如果對你可以有點幫助是最好不過的;

直接上程式碼:

public class WeChatAppConfig {
	
	 /**
	    * 預支付請求地址
	    */
	   public static final String  PrepayUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
	 
	   /**
	    * 查詢訂單地址
	    */
	   public static final String  OrderUrl = "https://api.mch.weixin.qq.com/pay/orderquery";
	 
	   /**
	    * 關閉訂單地址
	    */
	   public static final String  CloseOrderUrl = "https://api.mch.weixin.qq.com/pay/closeorder";
	 
	   /**
	    * 申請退款地址
	    */
	   public static final String  RefundUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund";
	 
	   /**
	    * 查詢退款地址
	    */
	   public static final String  RefundQueryUrl = "https://api.mch.weixin.qq.com/pay/refundquery";
	 
	   /**
	    * 下載賬單地址
	    */
	   public static final String  DownloadBillUrl = "https://api.mch.weixin.qq.com/pay/downloadbill";
	 
	   /**
	    * 商戶APPID
	    */
	   public static final String  AppId = "此處是商戶appid";
	 
	   /**
	    * 商戶賬戶 獲取支付能力後,從郵件中得到
	    */
	   public static final String  MchId = "此處是mchid";
	 
	   /**
	    * 商戶祕鑰  32位,在微信商戶平臺中設定 api安全下的設定金鑰(不是開放平臺 )  注意!!! 注意!!!!
	    */
	   public static final String  AppSercret = "此處是商戶金鑰";
	 
	   /**
	    * sign type
	    */
	   public static final String  Sign = "MD5";
	   
	   /**
	    * 伺服器非同步通知頁面路徑
	    */
	  public static String notify_url = "http://catering.saimark.xusage.com/catering/a/****** (為後臺url)";
	 
	   /**
	    * 頁面跳轉同步通知頁面路徑
	    */
	   public static String return_url = "此處為後臺url";
	 
	   /**
	    * 退款通知地址
	    */
	   public static String refund_notify_url = "此處為後臺url";
	 
	   /**
	    * 退款需要證照檔案,證照檔案的地址
	    */
	   public static String refund_file_path = "此處為後臺url";
	 
	   /**
	    * 商品名稱
	    */
	   public static String subject =  "subject(自己按需要更改,也可以傳值進入)";
	 
	   /**
	    * 商品描述
	    */
	   public static String body = "微信支付(自己按需要更改,也可以傳值進入)";
	 
	/*   private static  Properties properties;
	 
	   public static synchronized Properties getProperties(){
	      if(properties == null){
	         String path = System.getenv(RSystemConfig.KEY_WEB_HOME_CONF) + "/weichart.properties";
	         properties = PropertiesUtil.getInstance().getProperties(path);
	      }
	      return properties;
*/

}

HttpClientUtil:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyStore;
import java.util.Map;

import javax.net.ssl.SSLContext;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class HttpClientUtil {

	public static String post(String url, Map<String, String> headMap, Map<String, String> params) {
		try {
			HttpClient httpclient = new HttpClient();
			httpclient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
			PostMethod httpPost = new PostMethod(url);
			if (null != headMap) {
				for (String key : headMap.keySet()) {
					httpPost.setRequestHeader(key, headMap.get(key));
				}
			}

			if (null != params) {
				for (String pkey : params.keySet()) {
					httpPost.addParameter(pkey, params.get(pkey));
				}
			}
			httpclient.executeMethod(httpPost);

			BufferedReader reader = new BufferedReader(new InputStreamReader(httpPost.getResponseBodyAsStream()));
			StringBuffer stringBuffer = new StringBuffer();
			String str = "";
			while ((str = reader.readLine()) != null) {
				stringBuffer.append(str);
			}
			reader.close();
			return stringBuffer.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static String postHttplient(String url, String xmlInfo) {
		try {
			HttpClient httpclient = new HttpClient();
			httpclient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
			PostMethod httpPost = new PostMethod(url);
			httpPost.setRequestEntity(new StringRequestEntity(xmlInfo));
			httpclient.executeMethod(httpPost);

			BufferedReader reader = new BufferedReader(new InputStreamReader(httpPost.getResponseBodyAsStream()));
			StringBuffer stringBuffer = new StringBuffer();
			String str = "";
			while ((str = reader.readLine()) != null) {
				stringBuffer.append(str);
			}
			reader.close();
			return stringBuffer.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 需要加密執行的
	 * 
	 * @param url
	 * @param xmlInfo
	 * @return
	 * @throws Exception
	 */
	public static String postHttplientNeedSSL(String url, String xmlInfo, String cretPath, String mrchId)
			throws Exception {
		// 選擇初始化金鑰檔案格式
		KeyStore keyStore = KeyStore.getInstance("PKCS12");
		// 得到金鑰檔案流
		FileInputStream instream = new FileInputStream(new File(cretPath));
		try {
			// 用商戶的ID 來解讀檔案
			keyStore.load(instream, mrchId.toCharArray());
		} finally {
			instream.close();
		}
		// 用商戶的ID 來載入
		SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mrchId.toCharArray()).build();
		// Allow TLSv1 protocol only
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
				SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
		// 用最新的httpclient 載入金鑰
		CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
		StringBuffer ret = new StringBuffer();
		try {
			HttpPost httpPost = new HttpPost(url);
			httpPost.setEntity(new StringEntity(xmlInfo));
			CloseableHttpResponse response = httpclient.execute(httpPost);
			try {
				HttpEntity entity = response.getEntity();
				if (entity != null) {
					BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
					String text;
					while ((text = bufferedReader.readLine()) != null) {
						ret.append(text);
					}
				}
				EntityUtils.consume(entity);
			} finally {
				response.close();
			}
		} finally {
			httpclient.close();
		}
		return ret.toString();
	}

	public static String postHtpps(String urlStr, String xmlInfo) {
		try {
			URL url = new URL(urlStr);
			URLConnection con = url.openConnection();
			con.setDoOutput(true);
			//con.setRequestProperty("Pragma:", "no-cache");
			con.setRequestProperty("Cache-Control", "no-cache");
			con.setRequestProperty("Content-Type", "text/xml;charset=utf-8");
			OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream(), "utf-8");
			out.write(xmlInfo);
			out.flush();
			out.close();
			BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
			StringBuffer lines = new StringBuffer();
			String line = "";
			for (line = br.readLine(); line != null; line = br.readLine()) {
				lines.append(line);
			}
			return lines.toString();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

}

WeiMd5:

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class WeiMd5 {

	// 全域性陣列
    private final static String[] strDigits = { "0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

    // 返回形式為數字跟字串
    private static String byteToArrayString(byte bByte) {
        int iRet = bByte;
        // System.out.println("iRet="+iRet);
        if (iRet < 0) {
            iRet += 256;
        }
        int iD1 = iRet / 16;
        int iD2 = iRet % 16;
        return strDigits[iD1] + strDigits[iD2];
    }


    // 轉換位元組陣列為16進位制字串
    private static String byteToString(byte[] bByte) {
        StringBuffer sBuffer = new StringBuffer();
        for (int i = 0; i < bByte.length; i++) {
            sBuffer.append(byteToArrayString(bByte[i]));
        }
        return sBuffer.toString();
    }

    public static String encode(String strObj) {
        String resultString = null;
        try {
            resultString = new String(strObj);
            MessageDigest md = MessageDigest.getInstance("MD5");
            // md.digest() 該函式返回值為存放雜湊值結果的byte陣列
            try{
               resultString = byteToString(md.digest(strObj.getBytes("UTF-8")));
            }catch(UnsupportedEncodingException e){
               // TODO Auto-generated catch block
               e.printStackTrace();
            }
        } catch (NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        }
        return resultString;
    }
	
}

WeiChartUtil:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import xusage.xcharge.support.xentity.RechargeUpdateFromWechatAppNotify;


public class WeiChartUtil {

	   /**
	    * 返回狀態碼
	    */
	   public static final String ReturnCode = "return_code";

	   /**
	    * 返回資訊
	    */
	   public static final String ReturnMsg = "return_msg";

	   /**
	    * 業務結果
	    */
	   public static final String ResultCode = "result_code";

	   /**
	    * 預支付交易會話標識
	    */
	   public static final String PrepayId = "prepay_id";
	   /**
	    * 得到微信預付單的返回ID
	    * @param orderId  商戶自己的訂單號
	    * @param totalFee  總金額  (分)
	    * @return
	    */
	   public static Map<String, String> getPreyId(String orderId,
	                                  String totalFee,String schoolLabel){
	      Map<String, String> reqMap = new HashMap<String, String>();
	      reqMap.put("appid", WeChatAppConfig.AppId);
	      reqMap.put("mch_id", WeChatAppConfig.MchId);
	      reqMap.put("nonce_str", getRandomString());

	      reqMap.put("body", schoolLabel+"_"+ WeChatAppConfig.body);
	      //reqMap.put("detail", WeChatAppConfig.subject); //非必填
	      //reqMap.put("attach", "附加資料"); //非必填
	      reqMap.put("out_trade_no", orderId); //商戶系統內部的訂單號,
	      reqMap.put("total_fee", changeToFen(Double.valueOf(totalFee))); //訂單總金額,單位為分
	      reqMap.put("spbill_create_ip", getHostIp()); //使用者端實際ip
	      Date date = new Date();
	      //reqMap.put("time_start", String.valueOf(date.getTime()/1000)); //交易起始時間 非必填
	      // reqMap.put("time_expire", "172.16.40.18"); //交易結束時間  非必填
	      // reqMap.put("goods_tag", "172.16.40.18"); //商品標記 非必填
	      reqMap.put("notify_url", WeChatAppConfig.notify_url); //通知地址
	      reqMap.put("trade_type", "APP"); //交易型別
	      //reqMap.put("limit_pay", "no_credit"); //指定支付方式,no_credit 指定不能使用信用卡支  非必填
	      reqMap.put("sign", getSign(reqMap));

	      String reqStr = creatXml(reqMap);
	      String retStr = HttpClientUtil.postHtpps(WeChatAppConfig.PrepayUrl, reqStr);
	      return getInfoByXml(retStr);
	   }

	   /**
	    * 關閉訂單
	    * @param orderId  商戶自己的訂單號
	    * @return
	    */
	   public static Map<String, String> closeOrder(String orderId){
	      Map<String, String> reqMap = new HashMap<String, String>();
	      reqMap.put("appid", WeChatAppConfig.AppId);
	      reqMap.put("mch_id", WeChatAppConfig.MchId);
	      reqMap.put("nonce_str", getRandomString());
	      reqMap.put("out_trade_no", orderId); //商戶系統內部的訂單號,
	      reqMap.put("sign", getSign(reqMap));

	      String reqStr = creatXml(reqMap);
	      String retStr = HttpClientUtil.postHtpps(WeChatAppConfig.CloseOrderUrl, reqStr);
	      return getInfoByXml(retStr);
	   }


	   /**
	    * 查詢訂單
	    * @param orderId 商戶自己的訂單號
	    * @return
	    */
	   public static Map<String, String> getOrder(String orderId){
	      Map<String, String> reqMap = new HashMap<String, String>();
	      reqMap.put("appid", WeChatAppConfig.AppId);
	      reqMap.put("mch_id", WeChatAppConfig.MchId);
	      reqMap.put("nonce_str", getRandomString());
	      reqMap.put("out_trade_no", orderId); //商戶系統內部的訂單號,
	      reqMap.put("sign", getSign(reqMap));

	      String reqStr = creatXml(reqMap);
	      String retStr = HttpClientUtil.postHtpps(WeChatAppConfig.OrderUrl, reqStr);
	      //return retStr;
	      return getInfoByXml(retStr);
	   }


	   /**
	    * 退款
	    * @param orderId  商戶訂單號
	    * @param refundId  退款單號
	    * @param totralFee 總金額(分)
	    * @param refundFee 退款金額(分)
	    * @param opUserId 操作員ID
	    * @return
	    */
	   public static Map<String, String> refundWei(String orderId,String refundId,String totralFee,String refundFee,String opUserId){
	      Map<String, String> reqMap = new HashMap<String, String>();
	      reqMap.put("appid", WeChatAppConfig.AppId);
	      reqMap.put("mch_id", WeChatAppConfig.MchId);
	      reqMap.put("nonce_str", getRandomString());
	      reqMap.put("out_trade_no", orderId); //商戶系統內部的訂單號,
	      reqMap.put("out_refund_no", refundId); //商戶退款單號
	      reqMap.put("total_fee", totralFee); //總金額
	      reqMap.put("refund_fee", refundFee); //退款金額
	      reqMap.put("op_user_id", opUserId); //操作員
	      reqMap.put("sign", getSign(reqMap));

	      String reqStr = creatXml(reqMap);
	      String retStr = "";
	      try{
	         retStr = HttpClientUtil.postHttplientNeedSSL(WeChatAppConfig.RefundUrl, reqStr, WeChatAppConfig.refund_file_path, WeChatAppConfig.MchId);
	      }catch(Exception e){
	         e.printStackTrace();
	         return null;
	      }
	      return getInfoByXml(retStr);
	   }


	   /**
	    * 退款查詢
	    * @param refundId  退款單號
	    * @return
	    */
	   public static Map<String, String> getRefundWeiInfo(String refundId){
	      Map<String, String> reqMap = new HashMap<String, String>();
	      reqMap.put("appid", WeChatAppConfig.AppId);
	      reqMap.put("mch_id", WeChatAppConfig.MchId);
	      reqMap.put("nonce_str", getRandomString());
	      reqMap.put("out_refund_no", refundId); //商戶退款單號
	      reqMap.put("sign", getSign(reqMap));

	      String reqStr = creatXml(reqMap);
	      String retStr = HttpClientUtil.postHtpps(WeChatAppConfig.RefundQueryUrl, reqStr);
	      return getInfoByXml(retStr);
	   }

	   /**這個方法 可以自己寫,以前我使用的是我公司封裝的類,後來很多人找我要JAR包,所以我改成了這樣,方便部分人直接使用程式碼,我自己未測試,不過應該問題不大,歡迎使用有問題的找我。
	    * 傳入map  生成頭為XML的xml字串,例:<xml><key>123</key></xml>
	    * @param reqMap
	    * @return
	    */
	   public static String creatXml(Map<String, String> reqMap){
	      Set<String> set = reqMap.keySet();
	      StringBuffer b = new StringBuffer();
	      b.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
	      b.append("<xml>");
	      for(String key : set){
	         b.append("<"+key+">").append(reqMap.get(key)).append("</"+key+">");
	      }
	      b.append("</xml>");
	      return b.toString();
	   }

	   /**
	    * 得到加密值
	    * @param map
	    * @return
	    */
	   public static String getSign(Map<String, String> map){
	      String[] keys = map.keySet().toArray(new String[0]);
	      Arrays.sort(keys);
	      StringBuffer reqStr = new StringBuffer();
	      for(String key : keys){
	         String v = map.get(key);
	         if(v != null && !v.equals("")){
	            reqStr.append(key).append("=").append(v).append("&");
	         }
	      }
	      reqStr.append("key").append("=").append(WeChatAppConfig.AppSercret);

	      return WeiMd5.encode(reqStr.toString()).toUpperCase();
	   }

	   /**
	    * 得到10 位的時間戳
	    * 如果在JAVA上轉換為時間要在後面補上三個0 
	    * @return
	    */
	   public static String getTenTimes(){
	      String t = new Date().getTime()+"";
	      t = t.substring(0, t.length()-3);
	      return t;
	   }

	   /**
	    * 得到隨機字串
	    * @param length
	    * @return
	    */
	   public static String getRandomString(){
	      int length = 32;
	      String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
	      Random random = new Random();
	      StringBuffer sb = new StringBuffer();

	      for(int i = 0; i < length; ++i){
	         int number = random.nextInt(62);//[0,62)  
	         sb.append(str.charAt(number));
	      }
	      return sb.toString();
	   }

	   /**
	    * 得到本地機器的IP
	    * @return
	    */
	   private static String getHostIp(){
	      String ip = "";
	      try{
	         ip = InetAddress.getLocalHost().getHostAddress();
	      }catch(UnknownHostException e){
	         e.printStackTrace();
	      }
	      return ip;
	   }
	   /**
	    * 將xml解析成map
	    * @param xmlStr
	    * @return
	    */
	   public static Map<String, String> getInfoByXml(String xmlStr){
	      try{
	         Map<String, String> m = new HashMap<String, String>();
	         Document d = DocumentHelper.parseText(xmlStr);
	         Element root = d.getRootElement();
	         for ( Iterator<?> i = root.elementIterator(); i.hasNext(); ) {
	            Element element = (Element) i.next();
	            String name = element.getName();
	            if(!element.isTextOnly()){
	               //不是字串 跳過。確定了微信放回的xml只有根目錄
	               continue;
	            }else{
	               m.put(name, element.getTextTrim());
	            }
	         }
	         //對返回結果做校驗.去除sign 欄位再去加密
	         String retSign = m.get("sign");
	         m.remove("sign");
	         String rightSing = getSign(m);
	         if(rightSing.equals(retSign)){
	        	m.put("sign", retSign);
	            return m;
	         }
	      }catch(DocumentException e){
	         e.printStackTrace();
	      }
	      return null;
	}

	   /**
	    * 將金額轉換成分
	    * @param fee 元格式的
	    * @return 分
	    */
	   public static String changeToFen(Double fee){
	      String priceStr = "";
	      if(fee != null){
	          int p = (int)(fee * 100); //價格變為分
	          priceStr = Integer.toString(p);
	      }
	      return priceStr;
	   }
	   

	   /**
	     * 接收微信的非同步通知
	     * 
	     * @throws IOException
	     */
	    public static String reciverWx(HttpServletRequest request) throws IOException
	    {
	        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();
	        return sb.toString();
	    }
	    
	    /**
	     * 驗證回撥簽名
	     * @return
	     */
	   /* public static boolean isTenpaySign(Map<String, String> map) {
	       String signFromAPIResponse = map.get("sign");
	       if (signFromAPIResponse == null || signFromAPIResponse.equals("")) {
	    	   LOGGER.error("API返回的資料簽名資料不存在,有可能被第三方篡改!!!");
	    	   return false;
	       }
	       LOGGER.info("伺服器回包裡面的簽名是:" + signFromAPIResponse);
	     //將API返回的資料根據用簽名演算法進行計算新的簽名,用來跟API返回的簽名進行比較
	     //算出簽名
	       String resultSign = "";
	       map.remove("sign");
	       String tobesign = getSign(map);
    	   try{
    		   resultSign = WeiMd5.encode(tobesign).toUpperCase();
    	   }catch (Exception e) {
    		   resultSign = WeiMd5.encode(tobesign).toUpperCase();
    	   }
    	   LOGGER.info("微信回撥;再次驗證簽名正確與否生成的簽名:{}", resultSign);
	       String tenpaySign = signFromAPIResponse.toUpperCase();
	       return tenpaySign.equals(resultSign);

	    } */
	    private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(WeiChartUtil.class);

}

至此,如果配置好config資料後 不出意外就可以得到prepayid了;

Android端需要的資料為: appid  partnerid  prepayid  noncestr  package  timestamp;

這時有幾個地方需要注意:

1. 獲取prepayid後 返回給Android端的是需要二次簽名的;也就是說再次獲取通過WeiChartUtil.getSign()獲取簽名,傳入只包含這6個引數的map(也要注意這6個引數名的大小寫,微信端定義好的);

2.package 現在預設值為 “Sign=WXPay” ;

3.timestamp 為十位的時間戳 ,自己做下處理,去掉後三位即可; 不過看到有說timestamp和noncestr在Android端可以那邊自己做;反正我是一併處理返回過去了;

好了;後臺支付的介面至此結束,接下來就是Android端的對接了;

 

接下來是支付完成後,微信會請求事先再WeChatAppConfig中配置好的回撥url;

這裡我就只放處理的程式碼了:

			String sb = WeiChartUtil.reciverWx(request);
			//解析xml成map  
			Map<String, String> xmlMap = new HashMap<String, String>();  
			xmlMap = WeiChartUtil.getInfoByXml(sb);  //此方法裡已經驗證過是否是微信返回的簽名
			//判斷簽名是否正確  
			if(xmlMap != null) {  
				//------------------------------  
				//處理業務開始  
				//------------------------------  
				String resXml = "";  
				if("SUCCESS".equals((String)xmlMap.get("result_code"))){  
					// 這裡是支付成功  
					//////////執行自己的業務邏輯////////////////  
					String mch_id = (String)xmlMap.get("mch_id");  
					String openid = (String)xmlMap.get("openid");  
					String is_subscribe = (String)xmlMap.get("is_subscribe");  
					String out_trade_no = (String)xmlMap.get("out_trade_no");    //這個就是我們內部傳給微信的訂單號
					String total_fee = (String)xmlMap.get("total_fee");  
					LOGGER.info("is_subscribe:{}, out_trade_no: {}, total_fee: {},mch_id: {}, openid: {}",is_subscribe,out_trade_no,total_fee,mch_id,openid);  
					
					
					//////////執行自己的業務邏輯////////////////  
					LOGGER.info("支付成功");  
					//通知微信.非同步確認成功.必寫.不然會一直通知後臺.九次之後就認為交易失敗了.  通知頻率為15/15/30/180/1800/1800/1800/1800/3600 
					resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"  
							+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";  
					result.setResXml("SUCCESS");
				} else {  
					result.setResXml("FAIL");
					LOGGER.info("支付失敗,錯誤資訊:" + xmlMap.get("err_code"));  
					resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"  
							+ "<return_msg><![CDATA[報文為空]]></return_msg>" + "</xml> ";  
				}  
				//------------------------------  
				//處理業務完畢  
				//------------------------------  
				BufferedOutputStream out = new BufferedOutputStream(  
						response.getOutputStream());  
				out.write(resXml.getBytes());
				out.flush();  
				out.close();  
			} else{  
				result.setResXml("FAIL");
				LOGGER.info("通知簽名驗證失敗");  
			}  

再接收到回撥時候,最好是要對簽名做下再次認證的,因為我圖方便,將再次認證就放在getInfoByXml()方法裡的,這個是可以直接拿來用的,如果覺得想分離出來手動處理下吧,再WeiChatUtils中最下邊也有現成的註釋掉的方法;

如果專案需要做單筆交易查詢再次認證;呼叫相應的方法即可;傳入自己資料庫中訂單的id去查詢(out_trade_no:商戶系統內部的訂單號)

好啦;微信app支付到此結束; 希望對你能有幫助 

相關文章