1. 程式人生 > >Java開發SSM框架微信退款

Java開發SSM框架微信退款

這篇文章是Java微信退款的教程,退款之前使用者需要先進行支付,支付之後才可以使用退款。做到退款的同學應該已經是完成了支付了,我寫的退款和支付的流程很相似只是所需的引數有所不同。

        String outTradeNo = request.getParameter("outTradeNo");// 獲取商戶訂單號

		Integer totalFee = Integer.parseInt(request.getParameter("totalFee"));// 獲取支付金額

		Map<String, String> getMap = new HashMap<String, String>();
		// 獲得當前目錄
		String path = request.getSession().getServletContext().getRealPath("/");

		Date now = new Date();
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");// 可以方便地修改日期格式
		String outRefundNo = "NO" + dateFormat.format(now);

提供的引數有訂單號這個是支付成功之後生成的唯一號碼,然後是獲取到使用者支付的金額這兩個引數都是由支付之後的訂單上面獲得的。下面那個path則是儲存微信安全證書檔案的位置,這裡提一下要實現微信退款和微信企業轉賬功能是需要到微信商戶平臺去下載安全證書的,然後把證書放在專案的WEB-INF/目錄下即可。

        RefundReqData refundReqData = new RefundReqData();
		refundReqData.setAppid(Configure.getAppID());
		refundReqData.setMch_id(Configure.getMch_id());
		refundReqData.setNonce_str(RandomStringGenerator.getRandomStringByLength(32));
		refundReqData.setOut_trade_no(outTradeNo);
		refundReqData.setOut_refund_no(outRefundNo);
		refundReqData.setTotal_fee(totalFee);
		refundReqData.setRefund_fee(refundFee);
		refundReqData.setOp_user_id(Configure.getMch_id());
		refundReqData.setNotify_url("https://weixin.qq.com/notify/");
        String sign = Signature.getSign(refundReqData);// 生成簽名
		refundReqData.setSign(sign);

獲取到需要的引數之後呢,我在這裡使用了一個退款的實體類把這些引數儲存到了我的實體類裡面方便後面的簽名加密。

ArrayList<String> list = new ArrayList<String>();
        @SuppressWarnings("rawtypes")
		Class cls = o.getClass();
        Field[] fields = cls.getDeclaredFields();
        for (Field f : fields) {
            f.setAccessible(true);
            if (f.get(o) != null && f.get(o) != "") {
            	String name = f.getName();
            	XStreamAlias anno = f.getAnnotation(XStreamAlias.class);
            	if(anno != null)
            		name = anno.value();
                list.add(name + "=" + f.get(o) + "&");
            }
        }
        int size = list.size();
        String [] arrayToSort = list.toArray(new String[size]);
        Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < size; i ++) {
            sb.append(arrayToSort[i]);
        }
        String result = sb.toString();
        result += "key=" + Configure.getKey();
        System.out.println("簽名資料:"+result);
        result = MD5Util.MD5Encode(result,"utf-8").toUpperCase();
        return result;

這個是我簽名加密的方法,把資料加密之後會成為一個很長的字串,但是官方提供的退款介面是沒辦法解析你這個超長字串的資料的,所以我們要把這個字串變成官方介面認識的資料格式也就是xml格式。

private static XStream xstream = new XStream(new XppDriver() {
	        public HierarchicalStreamWriter createWriter(Writer out) {
	            return new PrettyPrintWriter(out) {
	                // 對所有xml節點的轉換都增加CDATA標記
	                boolean cdata = true;
	 
	                //@SuppressWarnings("unchecked")
	                public void startNode(String name, Class clazz) {
	                    super.startNode(name, clazz);
	                }
	 
	                protected void writeText(QuickWriter writer, String text) {
	                    if (cdata) {
	                        writer.write("<![CDATA[");
	                        writer.write(text);
	                        writer.write("]]>");
	                    } else {
	                        writer.write(text);
	                    }
	                }
	            };
	        }
	    });

這一段程式碼是我把字串格式的資料轉換成xml格式的方法。再把xml格式的資料儲存在一個字串裡面,這個時候我們開始向官方介面傳送資料。

	public String httpsRequest(String url, String xmlObj, String path) throws Exception {
		// 載入證書
		initCert(path);

		String result = null;

		HttpPost httpPost = new HttpPost(url);

		// 得指明使用UTF-8編碼,否則到API伺服器XML的中文不能被成功識別
		StringEntity postEntity = new StringEntity(xmlObj, "UTF-8");
		httpPost.addHeader("Content-Type", "text/xml");
		httpPost.setEntity(postEntity);

		// 設定請求器的配置
		httpPost.setConfig(requestConfig);

		try {
			HttpResponse response = httpClient.execute(httpPost);

			HttpEntity entity = response.getEntity();

			result = EntityUtils.toString(entity, "UTF-8");

		} catch (ConnectionPoolTimeoutException e) {
			e.printStackTrace();
		} catch (ConnectTimeoutException e) {
			e.printStackTrace();

		} catch (SocketTimeoutException e) {
			e.printStackTrace();

		} catch (Exception e) {
			e.printStackTrace();

		} finally {
			httpPost.abort();
		}

		return result;
	}

通過Https往API post xml資料。

RefundRequest refundRequest = new RefundRequest();
			String result = refundRequest.httpsRequest("https://api.mch.weixin.qq.com/secapi/pay/refund", info, path);

			getMap = MobiMessage.parseXml(new String(result.toString().getBytes(), "utf-8"));
			System.out.println(getMap + "............getMap");
			json.put("return_msg", getMap.get("return_msg"));
			json.put("return_code", getMap.get("return_code"));
			json.put("outTradeNo", outTradeNo);

這一段就是給介面傳送資料的程式碼(官方api介面,xml資料,證書的位置),然後我們接受介面返回的資訊通過返回的return_msg和return_code來判斷是否退款成功。

好了,微信退款就是這樣完全可以照著程式碼把流程讀出來很清晰明瞭也很簡單,程式碼能力稍強的都看得懂,我主要是給大家提供一個思路。如果有同學沒看懂也沒關係下面是該專案的原始碼地址大家可以去下載退款的原始碼都在裡面:https://download.csdn.net/download/qq_37756682/10521165

大家有任何的疑問建議歡迎在部落格下方評論留言,謝謝!