微信支付對帳單下載

以上是官網文檔說明:java

下面是根據文檔 梳理下思路:git

/**
關於簽名的算法,api提供的原文是:

1.簽名算法

簽名生成的通用步驟以下:

第一步,設全部發送或者接收到的數據爲集合M,將集合M內非空參數值的參數按照參數名ASCII碼從小到大排序(字典序),使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串stringA。

特別注意如下重要規則:
 參數名ASCII碼從小到大排序(字典序);
 若是參數的值爲空不參與簽名;
   參數名區分大小寫;
 驗證調用返回或微信主動通知簽名時,傳送的sign參數不參與簽名,將生成的簽名與該sign值做校驗。
 微信接口可能增長字段,驗證簽名時必須支持增長的擴展字段

第二步,在stringA最後拼接上key=(API密鑰的值)獲得stringSignTemp字符串,並對stringSignTemp進行MD5運算,再將獲得的字符串全部字符轉換爲大寫,獲得sign值signValue。

舉例:

假設傳送的參數以下:

appid: wx8888888888888888

mch_id: 1900000109

device_info: 013467007045764

body: test

nonce_str: 5K8264ILTKCH16CQ2502SI8ZNMTM67VS

第一步:對參數按照key=value的格式,並按照參數名ASCII字典序排序以下:

stringA="appid=wx8888888888888888&body=test&device_info=013467007045764&mch_id=1900000109&nonce_str=5K8264ILTKCH16CQ2502SI8ZNMTM67VS";

第二步:拼接API密鑰:

stringSignTemp="stringA&key=332F17B766FC787203EBE9D6E40457A1"

sign=MD5(stringSignTemp).toUpperCase()="332F17B766FC787203EBE9D6E40457A1"

*/

 微信支付簽名算法sign:算法

String keywx = "9e4b63793722c61a555696be897d61f8";
	/**
	 * 微信支付簽名算法sign
	 * 建立md5摘要,規則是:按參數名稱a-z排序,遇到空值的參數不參加簽名。
                 建立簽名 簽名 sign 	 
	 */
	protected void  createSign(SortedMap<Object,Object> parameters) {
		StringBuffer sb = new StringBuffer();
		//parameters 參數集合值
		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+ "&" );
			}
		}
		//key就是微信支付帳戶密鑰
		sb.append("key=" + keywx);
		//sb.append("key=" + this.getKey());
		System.out.println("字符串拼接後是:"+sb.toString());  
		//字體編碼 生成MD5的時候,須要統一編碼,這裏微信api要求是UTF-8
		String enc = getCharacterEncoding(this.request, this.response);
		//生成MD5簽名驗證 注意轉換成大寫  在此是小寫
		String sign = MD5Util.MD5Encode(sb.toString(), enc).toUpperCase();
		
		this.setParameter("sign", sign);
		
		//debug信息
		this.setDebugInfo(sb.toString() + " => sign:" + sign);
		return ;
	}
		/**
	*設置debug信息
	*/
	protected void setDebugInfo(String debugInfo) {
		this.debugInfo = debugInfo;
	}
	/**
	 * 設置參數值
	 * @param parameter 參數名稱
	 * @param parameterValue 參數值
	 */
	public void setParameter(String parameter, String parameterValue) {
		String v = "";
		if(null != parameterValue) {
			v = parameterValue.trim();
		}
		this.parameters.put(parameter, v);
	}
	/**
	 * 獲取編碼字符集
	 * @param request
	 * @param response
	 * @return String
	 */
	public static String getCharacterEncoding(HttpServletRequest request,
			HttpServletResponse response) {
		
		if(null == request || null == response) {
			return "gbk";
		}
		
		String enc = request.getCharacterEncoding();
		if(null == enc || "".equals(enc)) {
			enc = response.getCharacterEncoding();
		}
		
		if(null == enc || "".equals(enc)) {
			enc = "gbk";
		}
		
		return enc;
	}

 MD5Util方法:數據庫

 

public class MD5Util {

	private static String byteArrayToHexString(byte b[]) {
		StringBuffer resultSb = new StringBuffer();
		for (int i = 0; i < b.length; i++)
			resultSb.append(byteToHexString(b[i]));

		return resultSb.toString();
	}

	private static String byteToHexString(byte b) {
		int n = b;
		if (n < 0)
			n += 256;
		int d1 = n / 16;
		int d2 = n % 16;
		return hexDigits[d1] + hexDigits[d2];
	}

	public static String MD5Encode(String origin, String charsetname) {
		String resultString = null;
		try {
			resultString = new String(origin);
			MessageDigest md = MessageDigest.getInstance("MD5");
			if (charsetname == null || "".equals(charsetname))
				resultString = byteArrayToHexString(md.digest(resultString
						.getBytes()));
			else
				resultString = byteArrayToHexString(md.digest(resultString
						.getBytes(charsetname)));
		} catch (Exception exception) {
		}
		return resultString;
	}

	private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
			"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

}

 

 

參數包裝成XML格式丟給微信:api

 /**
     * 參數包裝成XML格式丟給微信
    * */
	public  String GetpayXmlRequest(String appid,String spid,String getNonce_str,String sign, String trans_time, String bill_type)
	{  
		/*
	   <xml>
		   <appid>wx8888888888888888</appid>
		   <bill_date>20160426</bill_date>
		   <bill_type>ALL</bill_type>
		   <mch_id>1900000109</mch_id>
		   <nonce_str>21df7dc9cd8616b56919f20d9f679233</nonce_str>
		   <sign>E8778F1C4C953C0BF37AA45C3BC379D0</sign>
		 </xml> 
	  */
		
		       StringBuffer sb = new StringBuffer();  
			   sb.append("<xml>");  
			   sb.append("<appid><![CDATA[");  
			   sb.append(appid);  
			   sb.append("]]></appid>");  
			
			   sb.append("<mch_id><![CDATA[");  
			   sb.append(spid);  
			   sb.append("]]></mch_id>");  
			 
			   sb.append("<nonce_str><![CDATA[");  
			   sb.append(getNonce_str);  
			   sb.append("]]></nonce_str>");  
			 
			   sb.append("<sign><![CDATA[");  
			   sb.append(sign);  
			   sb.append("]]></sign>");  
			  
			   sb.append("<bill_date><![CDATA[");  
			   sb.append(trans_time);  
			   sb.append("]]></bill_date>");  
			 
			   sb.append("<bill_type><![CDATA[");  
			   sb.append(bill_type);  
			   sb.append("]]></bill_type>");  
			 
			   sb.append("</xml>");  
			   return sb.toString();  

		        /*
		         
		        sb.append("<appid>");
		        sb.append(appid);  
		        sb.append("</appid>");
		        sb.append("<bill_date>");  
		        sb.append(trans_time);  
		        sb.append("</bill_date>");
		        sb.append("<bill_type>");  
		        sb.append(bill_type);  
		        sb.append("</bill_type>");
		        sb.append("<mch_id>");
		        sb.append(spid);
		        sb.append("</mch_id>");
		        sb.append("<nonce_str>"); 
		        sb.append(stamp);  
		        sb.append("</nonce_str>");
		        sb.append("<sign>"); 	
		        sb.append(sign); 
		        sb.append("</sign>");
		        sb.append("</xml>");  
		       return sb.toString();  
		       */

		    }  

 post發送請求數據:服務器

/** 請求的參數 */
	protected SortedMap parameters;
	
    protected HttpServletRequest request;
	
	protected HttpServletResponse response;
	/** 密鑰 */
	protected String key;
	/** debug信息 */
	protected String debugInfo;
	
	/**
	*獲取密鑰
	*/
	public String getKey() {
		return key;
	}
	/**
	*設置密鑰
	*/
	public void setKey(String key) {
		this.key = key;
	}
	
	/**
	 * post發送請求數據
	 * @param urlStr
	 */
	public  void testPost(String urlStr) {  
		 BufferedReader br= null;
		 HttpURLConnection con=null;
		 OutputStreamWriter out=null;
		        try {  
		            URL url = new URL(urlStr);  
		           // URLConnection con = url.openConnection(); 
		            con = (HttpURLConnection) url.openConnection(); 
		         // 發送POST請求必須設置以下兩行
		            con.setDoOutput(true);  // POST方式
		            con.setDoInput(true);
		            con.setUseCaches(false);
		            con.setRequestMethod("POST"); 
		         // 設置通用的請求屬性
		            con.setRequestProperty("accept", "*/*");
		            con.setRequestProperty("connection", "Keep-Alive");
		            con.setRequestProperty("user-agent",
		                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
		            
//		            con.setRequestProperty("Pragma:", "no-cache");  
//		            con.setRequestProperty("Cache-Control", "no-cache");  
//		            con.setRequestProperty("Content-Type", "text/xml");  
		            
		            // 輸出流,寫數據
		             out = new OutputStreamWriter(con  
		                   .getOutputStream(),"UTF-8");    
		            
		            
		         // 發送請求參數
		            String xmlInfo = GetpayXmlRequest("wx8888888888888888","1900000109","1462240367309","56B106AFDDF1802B12DF8634C2E73B92","20160623","ALL");  
		            System.out.println("urlStr=" + urlStr);  
		            System.out.println("xmlInfo=" + xmlInfo);  
		           out.write(new String(xmlInfo.getBytes("UTF-8"))); 
		        // flush輸出流的緩衝
		            out.flush();  
		           // out.close();  
		          //讀取服務器的響應內容並顯示 定義BufferedReader輸入流來讀取URL的響應
		            br = new BufferedReader(new InputStreamReader(con  
		                    .getInputStream(),"UTF-8"));  
		           String line = "";  
		           StringBuffer buffer = new StringBuffer();
//		            for (line = br.readLine(); line != null; line = br.readLine()) {  
//		               System.out.println(line);  
//		               buffer.append(line);// 將讀到的內容添加到 buffer 中
//		               buffer.append("\n"); // 添加換行符
//
//		            } 
		            while ((line = br.readLine()) != null)
		            {   
		            buffer.append(line); // 將讀到的內容添加到 buffer 中
		            buffer.append("\n"); // 添加換行符
		            System.out.println(line);  
	                }  
		            
		            //con.getOutputStream().close();
		        } 
		        catch (MalformedURLException e) 
		        {  
		            e.printStackTrace();  
		        } 
		        catch (IOException e)
		        {  
		            e.printStackTrace();  
		        }  
		        // 使用finally塊來關閉輸入流
		        finally {
		            try {
		            	if(out!=null){
		                    out.close();
		                }

		                if (br != null) 
		                {
		                	br.close();
		                	con.disconnect();
		                }
		            } catch (Exception e2) {
		                e2.printStackTrace();
		            }
		        }

		    }  

 

/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String url = "https://api.mch.weixin.qq.com/pay/downloadbill";  
		 
		  new HttpPostTest().testPost(url);  

		    
		  //微信api提供的參數   賦值
		    String appid="wx8888888888888888"; 
		    String spid="1900000109";//       1221024001
		    String getNonce_str="1462240367309";//1462240367309  ibuaiVcKdpRxkhJA
		    String trans_time="20160623";
		    String bill_type="ALL";
		    String sign ="";
	         
		   // 獲取值
	        SortedMap<Object,Object> sparameters = new TreeMap<Object,Object>();  
	        sparameters.put("appid", appid);
	        sparameters.put("mch_id", spid); 
	        sparameters.put("nonce_str", getNonce_str);
	        sparameters.put("bill_date", trans_time);  
	        sparameters.put("bill_type", bill_type);  
	         
	        // new HttpPostTest().createSign(sparameters);
	}

 注意 以上單元測試時要先 建立生成簽名後,再把簽名的值傳到參數中去,而後進行httppost請求便可。微信

 這裏商戶號 必定都要改爲本身申請的appid 和 mch_id 這樣就會有微信返回結果數據顯示了,結果實例就不在這裏展示出來。app

  獲取到對帳信息後就是後續的業務處理了,根據不一樣的需求進行不一樣的業務處理了,主要就是解析數據格式,生成文檔,保存到本地以及導入到數據庫的邏輯操做了。post

相關文章
相關標籤/搜索