這期內容當中小編將會給大家帶來有關Java中怎么實現微信退款功能,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
一、下載證書并導入到系統
微信支付接口中,涉及資金回滾的接口會使用到商戶證書,包括退款、撤銷接口。商家在申請微信支付成功后,可以按照以下路徑下載:微信商戶平臺()-->賬戶設置-->API安全-->證書下載。
下載的時候需要手機驗證及登錄密碼。下載后找到.p12這個證書,雙擊導入,導入的時候提示輸入密碼,這個密碼就是商戶ID,且必須是在自己的商戶平臺下載的證書。否則會出現密碼錯誤的提示:
導入正確的提示:
二、編寫代碼
首先初始化退款接口中的請求參數微信訂單系統微信訂單系統,如微信訂單號(和商戶訂單號只需要知道一個)、訂單金額等;其次調用中的方法解析成需要的類型;最后調用類的方法觸發請求。
/** ?*?處理退款請求 ?*?@param?request ?*?@return ?*?@throws?Exception ?*/ ?@RequestMapping("/refund") ?@ResponseBody ?public?JsonApi?refund(HttpServletRequest?request)?throws?Exception?{ ??//獲得當前目錄 ??String?path?=?request.getSession().getServletContext().getRealPath("/"); ??LogUtils.trace(path); ? ??Date?now?=?new?Date(); ??SimpleDateFormat?dateFormat?=?new?SimpleDateFormat("yyyyMMddHHmmss");//可以方便地修改日期格式 ??String?outRefundNo?=?"NO"?+?dateFormat.format(?now?); ? ??//獲得退款的傳入參數 ??String?transactionID?=?"4008202001201609012791655620"; ??String?outTradeNo?=?"20160901141024"; ??Integer?totalFee?=?1; ??Integer?refundFee?=?totalFee; ? ??RefundReqData?refundReqData?=?new?RefundReqData(transactionID,outTradeNo,outRefundNo,totalFee,refundFee); ? ??String?info?=?MobiMessage.RefundReqData2xml(refundReqData).replaceAll("__",?"_"); ??LogUtils.trace(info); ? ??try?{ ???RefundRequest?refundRequest?=?new?RefundRequest(); ???String?result?=?refundRequest.httpsRequest(WxConfigure.REFUND_API,?info,?path); ???LogUtils.trace(result); ? ???Map?getMap?=?MobiMessage.parseXml(new?String(result.toString().getBytes(),?"utf-8")); ???if("SUCCESS".equals(getMap.get("return_code"))?&&?"SUCCESS".equals(getMap.get("return_msg"))){ ????return?new?JsonApi(); ???}else{ ????//返回錯誤描述 ????return?new?JsonApi(getMap.get("err_code_des")); ???} ??}catch(Exception?e){ ???e.printStackTrace(); ???return?new?JsonApi(); ??} }
初始化退款接口需要的數據,隱藏了get和set方法。
public?class?RefundReqData?{ ? ?//每個字段具體的意思請查看API文檔 ?private?String?appid?=?""; ?private?String?mch_id?=?""; ?private?String?nonce_str?=?""; ?private?String?sign?=?""; ?private?String?transaction_id?=?""; ?private?String?out_trade_no?=?""; ?private?String?out_refund_no?=?""; ?private?int?total_fee?=?0; ?private?int?refund_fee?=?0; ?private?String?op_user_id?=?""; ? ?/** ??*?請求退款服務 ??*?@param?transactionID?是微信系統為每一筆支付交易分配的訂單號,通過這個訂單號可以標識這筆交易,它由支付訂單API支付成功時返回的數據里面獲取到。建議優先使用 ??*?@param?outTradeNo?商戶系統內部的訂單號,transaction_id?、out_trade_no?二選一,如果同時存在優先級:transaction_id>out_trade_no ??*?@param?outRefundNo?商戶系統內部的退款單號,商戶系統內部唯一,同一退款單號多次請求只退一筆 ??*?@param?totalFee?訂單總金額,單位為分 ??*?@param?refundFee?退款總金額,單位為分 ??*/ ?public?RefundReqData(String?transactionID,String?outTradeNo,String?outRefundNo,int?totalFee,int?refundFee){ ? ??//微信分配的公眾號ID(開通公眾號之后可以獲取到) ??setAppid(WxConfigure.AppId); ? ??//微信支付分配的商戶號ID(開通公眾號的微信支付功能之后可以獲取到) ??setMch_id(WxConfigure.Mch_id); ? ??//transaction_id是微信系統為每一筆支付交易分配的訂單號,通過這個訂單號可以標識這筆交易,它由支付訂單API支付成功時返回的數據里面獲取到。 ??setTransaction_id(transactionID); ? ??//商戶系統自己生成的唯一的訂單號 ??setOut_trade_no(outTradeNo); ? ??setOut_refund_no(outRefundNo); ? ??setTotal_fee(totalFee); ? ??setRefund_fee(refundFee); ? ??setOp_user_id(WxConfigure.Mch_id); ? ??//隨機字符串,不長于32?位 ??setNonce_str(StringUtil.generateRandomString(16)); ? ? ??//根據API給的簽名規則進行簽名 ??SortedMap
實現json數據類型和xml數據之間的轉換。
public?class?MobiMessage?{ ? ?public?static?Map?xml2map(HttpServletRequest?request)?throws?IOException,?DocumentException?{ ??Map ?map?=?new?HashMap (); ??SAXReader?reader?=?new?SAXReader(); ??InputStream?inputStream?=?request.getInputStream(); ??Document?document?=?reader.read(inputStream); ??Element?root?=?document.getRootElement(); ??List ?list?=?root.elements(); ??for(Element?e:list){ ???map.put(e.getName(),?e.getText()); ??} ??inputStream.close(); ??return?map; ?} ? ? ?//訂單轉換成xml ?public?static?String?JsApiReqData2xml(JsApiReqData?jsApiReqData){ ??/*XStream?xStream?=?new?XStream(); ??xStream.alias("xml",productInfo.getClass()); ??return?xStream.toXML(productInfo);*/ ??MobiMessage.xstream.alias("xml",jsApiReqData.getClass()); ??return?MobiMessage.xstream.toXML(jsApiReqData); ?} ? ?public?static?String?RefundReqData2xml(RefundReqData?refundReqData){ ??/*XStream?xStream?=?new?XStream(); ??xStream.alias("xml",productInfo.getClass()); ??return?xStream.toXML(productInfo);*/ ??MobiMessage.xstream.alias("xml",refundReqData.getClass()); ??return?MobiMessage.xstream.toXML(refundReqData); ?} ? ?public?static?String?class2xml(Object?object){ ? ??return?""; ?} ?public?static?Map ?parseXml(String?xml)?throws?Exception?{ ??Map ?map?=?new?HashMap (); ??Document?document?=?DocumentHelper.parseText(xml); ??Element?root?=?document.getRootElement(); ??List ?elementList?=?root.elements(); ??for?(Element?e?:?elementList) ???map.put(e.getName(),?e.getText()); ??return?map; ?} ? ?//擴展xstream,使其支持CDATA塊 ?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(""); ?????}?else?{ ??????writer.write(text); ?????} ????} ???}; ??} ?}); ? ? }
類中方法加載證書到系統中,其中證書地址如下:
public?static?String?certLocalPath?=?"/WEB-INF/cert/apiclient_cert.p12";
類中方法調用微信接口,觸發請求。
public?class?RefundRequest?{ ? ?//連接超時時間,默認10秒 ?private?int?socketTimeout?=?10000; ? ?//傳輸超時時間,默認30秒 ?private?int?connectTimeout?=?30000; ? ?//請求器的配置 ?private?RequestConfig?requestConfig; ? ?//HTTP請求器 ?private?CloseableHttpClient?httpClient; ? ?/** ??*?加載證書 ??*?@param?path ??*?@throws?IOException ??*?@throws?KeyStoreException ??*?@throws?UnrecoverableKeyException ??*?@throws?NoSuchAlgorithmException ??*?@throws?KeyManagementException ??*/ ?private?void?initCert(String?path)?throws?IOException,?KeyStoreException,?UnrecoverableKeyException,?NoSuchAlgorithmException,?KeyManagementException?{ ??//拼接證書的路徑 ??path?=?path?+?WxConfigure.certLocalPath; ??KeyStore?keyStore?=?KeyStore.getInstance("PKCS12"); ? ??//加載本地的證書進行https加密傳輸 ??FileInputStream?instream?=?new?FileInputStream(new?File(path)); ??try?{ ???keyStore.load(instream,?WxConfigure.Mch_id.toCharArray());?//加載證書密碼,默認為商戶ID ??}?catch?(CertificateException?e)?{ ???e.printStackTrace(); ??}?catch?(NoSuchAlgorithmException?e)?{ ???e.printStackTrace(); ??}?finally?{ ???instream.close(); ??} ? ??//?Trust?own?CA?and?all?self-signed?certs ??SSLContext?sslcontext?=?SSLContexts.custom() ????.loadKeyMaterial(keyStore,?WxConfigure.Mch_id.toCharArray())??//加載證書密碼,默認為商戶ID ????.build(); ??//?Allow?TLSv1?protocol?only ??SSLConnectionSocketFactory?sslsf?=?new?SSLConnectionSocketFactory( ????sslcontext, ????new?String[]{"TLSv1"}, ????null, ????SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); ? ??httpClient?=?HttpClients.custom() ????.setSSLSocketFactory(sslsf) ????.build(); ? ??//根據默認超時限制初始化requestConfig ??requestConfig?=?RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build(); ? ?} ? ? ?/** ??*?通過Https往API?post?xml數據 ??*?@param?url?API地址 ??*?@param?xmlObj?要提交的XML數據對象 ??*?@param?path?當前目錄,用于加載證書 ??*?@return ??*?@throws?IOException ??*?@throws?KeyStoreException ??*?@throws?UnrecoverableKeyException ??*?@throws?NoSuchAlgorithmException ??*?@throws?KeyManagementException ??*/ ?public?String?httpsRequest(String?url,?String?xmlObj,?String?path)?throws?IOException,?KeyStoreException,?UnrecoverableKeyException,?NoSuchAlgorithmException,?KeyManagementException?{ ??//加載證書 ??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)?{ ???LogUtils.trace("http?get?throw?ConnectionPoolTimeoutException(wait?time?out)"); ? ??}?catch?(ConnectTimeoutException?e)?{ ???LogUtils.trace("http?get?throw?ConnectTimeoutException"); ? ??}?catch?(SocketTimeoutException?e)?{ ????LogUtils.trace("http?get?throw?SocketTimeoutException"); ? ??}?catch?(Exception?e)?{ ????LogUtils.trace("http?get?throw?Exception"); ? ??}?finally?{ ???httpPost.abort(); ??} ? ??return?result; ?} }
上述就是小編為大家分享的Java中怎么實現微信退款功能了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:部分文章信息來源于網絡以及網友投稿,本站只負責對文章進行整理、排版、編輯,出于傳遞更多信息之目的,并不意味著贊同其觀點或證實其內容的真實性,如本站文章和轉稿涉及版權等問題,請作者在及時聯系本站,我們會盡快為您處理。