Java中怎么实现微信退款功能
这期内容当中小编将会给大家带来有关Java中怎么实现微信退款功能,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
一、下载证书并导入到系统
微信支付接口中,涉及资金回滚的接口会使用到商户证书,包括退款、撤销接口。商家在申请微信支付成功后,可以按照以下路径下载:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->证书下载。
下载的时候需要手机验证及登录密码。下载后找到apiclient_cert.p12这个证书,双击导入,导入的时候提示输入密码,这个密码就是商户ID,且必须是在自己的商户平台下载的证书。否则会出现密码错误的提示:
导入正确的提示:
二、编写代码
首先初始化退款接口中的请求参数,如微信订单号transaction_id(和商户订单号只需要知道一个)、订单金额total_fee等;其次调用MobiMessage中的RefundResData2xml方法解析成需要的类型;最后调用RefundRequest类的httpsRequest方法触发请求。
/** *处理退款请求 *@paramrequest *@return *@throwsException */ @RequestMapping("/refund") @ResponseBody publicJsonApirefund(HttpServletRequestrequest)throwsException{ //获得当前目录 Stringpath=request.getSession().getServletContext().getRealPath("/"); LogUtils.trace(path); Datenow=newDate(); SimpleDateFormatdateFormat=newSimpleDateFormat("yyyyMMddHHmmss");//可以方便地修改日期格式 StringoutRefundNo="NO"+dateFormat.format(now); //获得退款的传入参数 StringtransactionID="4008202001201609012791655620"; StringoutTradeNo="20160901141024"; IntegertotalFee=1; IntegerrefundFee=totalFee; RefundReqDatarefundReqData=newRefundReqData(transactionID,outTradeNo,outRefundNo,totalFee,refundFee); Stringinfo=MobiMessage.RefundReqData2xml(refundReqData).replaceAll("__","_"); LogUtils.trace(info); try{ RefundRequestrefundRequest=newRefundRequest(); Stringresult=refundRequest.httpsRequest(WxConfigure.REFUND_API,info,path); LogUtils.trace(result); MapgetMap=MobiMessage.parseXml(newString(result.toString().getBytes(),"utf-8")); if("SUCCESS".equals(getMap.get("return_code"))&&"SUCCESS".equals(getMap.get("return_msg"))){ returnnewJsonApi(); }else{ //返回错误描述 returnnewJsonApi(getMap.get("err_code_des")); } }catch(Exceptione){ e.printStackTrace(); returnnewJsonApi(); } }
初始化退款接口需要的数据,隐藏了get和set方法。
publicclassRefundReqData{ //每个字段具体的意思请查看API文档 privateStringappid=""; privateStringmch_id=""; privateStringnonce_str=""; privateStringsign=""; privateStringtransaction_id=""; privateStringout_trade_no=""; privateStringout_refund_no=""; privateinttotal_fee=0; privateintrefund_fee=0; privateStringop_user_id=""; /** *请求退款服务 *@paramtransactionID是微信系统为每一笔支付交易分配的订单号,通过这个订单号可以标识这笔交易,它由支付订单API支付成功时返回的数据里面获取到。建议优先使用 *@paramoutTradeNo商户系统内部的订单号,transaction_id、out_trade_no二选一,如果同时存在优先级:transaction_id>out_trade_no *@paramoutRefundNo商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔 *@paramtotalFee订单总金额,单位为分 *@paramrefundFee退款总金额,单位为分 */ publicRefundReqData(StringtransactionID,StringoutTradeNo,StringoutRefundNo,inttotalFee,intrefundFee){ //微信分配的公众号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
MobiMessage实现json数据类型和xml数据之间的转换。
publicclassMobiMessage{ publicstaticMapxml2map(HttpServletRequestrequest)throwsIOException,DocumentException{ Map map=newHashMap (); SAXReaderreader=newSAXReader(); InputStreaminputStream=request.getInputStream(); Documentdocument=reader.read(inputStream); Elementroot=document.getRootElement(); List list=root.elements(); for(Elemente:list){ map.put(e.getName(),e.getText()); } inputStream.close(); returnmap; } //订单转换成xml publicstaticStringJsApiReqData2xml(JsApiReqDatajsApiReqData){ /*XStreamxStream=newXStream(); xStream.alias("xml",productInfo.getClass()); returnxStream.toXML(productInfo);*/ MobiMessage.xstream.alias("xml",jsApiReqData.getClass()); returnMobiMessage.xstream.toXML(jsApiReqData); } publicstaticStringRefundReqData2xml(RefundReqDatarefundReqData){ /*XStreamxStream=newXStream(); xStream.alias("xml",productInfo.getClass()); returnxStream.toXML(productInfo);*/ MobiMessage.xstream.alias("xml",refundReqData.getClass()); returnMobiMessage.xstream.toXML(refundReqData); } publicstaticStringclass2xml(Objectobject){ return""; } publicstaticMap parseXml(Stringxml)throwsException{ Map map=newHashMap (); Documentdocument=DocumentHelper.parseText(xml); Elementroot=document.getRootElement(); List elementList=root.elements(); for(Elemente:elementList) map.put(e.getName(),e.getText()); returnmap; } //扩展xstream,使其支持CDATA块 privatestaticXStreamxstream=newXStream(newXppDriver(){ publicHierarchicalStreamWritercreateWriter(Writerout){ returnnewPrettyPrintWriter(out){ //对所有xml节点的转换都增加CDATA标记 booleancdata=true; //@SuppressWarnings("unchecked") publicvoidstartNode(Stringname,Classclazz){ super.startNode(name,clazz); } protectedvoidwriteText(QuickWriterwriter,Stringtext){ if(cdata){ writer.write(""); }else{ writer.write(text); } } }; } }); }
RefundRequest类中initCert方法加载证书到系统中,其中证书地址如下:
publicstaticStringcertLocalPath="/WEB-INF/cert/apiclient_cert.p12";
RefundRequest类中httpsRequest方法调用微信接口,触发请求。
publicclassRefundRequest{ //连接超时时间,默认10秒 privateintsocketTimeout=10000; //传输超时时间,默认30秒 privateintconnectTimeout=30000; //请求器的配置 privateRequestConfigrequestConfig; //HTTP请求器 privateCloseableHttpClienthttpClient; /** *加载证书 *@parampath *@throwsIOException *@throwsKeyStoreException *@throwsUnrecoverableKeyException *@throwsNoSuchAlgorithmException *@throwsKeyManagementException */ privatevoidinitCert(Stringpath)throwsIOException,KeyStoreException,UnrecoverableKeyException,NoSuchAlgorithmException,KeyManagementException{ //拼接证书的路径 path=path+WxConfigure.certLocalPath; KeyStorekeyStore=KeyStore.getInstance("PKCS12"); //加载本地的证书进行https加密传输 FileInputStreaminstream=newFileInputStream(newFile(path)); try{ keyStore.load(instream,WxConfigure.Mch_id.toCharArray());//加载证书密码,默认为商户ID }catch(CertificateExceptione){ e.printStackTrace(); }catch(NoSuchAlgorithmExceptione){ e.printStackTrace(); }finally{ instream.close(); } //TrustownCAandallself-signedcerts SSLContextsslcontext=SSLContexts.custom() .loadKeyMaterial(keyStore,WxConfigure.Mch_id.toCharArray())//加载证书密码,默认为商户ID .build(); //AllowTLSv1protocolonly SSLConnectionSocketFactorysslsf=newSSLConnectionSocketFactory( sslcontext, newString[]{"TLSv1"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); httpClient=HttpClients.custom() .setSSLSocketFactory(sslsf) .build(); //根据默认超时限制初始化requestConfig requestConfig=RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build(); } /** *通过Https往APIpostxml数据 *@paramurlAPI地址 *@paramxmlObj要提交的XML数据对象 *@parampath当前目录,用于加载证书 *@return *@throwsIOException *@throwsKeyStoreException *@throwsUnrecoverableKeyException *@throwsNoSuchAlgorithmException *@throwsKeyManagementException */ publicStringhttpsRequest(Stringurl,StringxmlObj,Stringpath)throwsIOException,KeyStoreException,UnrecoverableKeyException,NoSuchAlgorithmException,KeyManagementException{ //加载证书 initCert(path); Stringresult=null; HttpPosthttpPost=newHttpPost(url); //得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别 StringEntitypostEntity=newStringEntity(xmlObj,"UTF-8"); httpPost.addHeader("Content-Type","text/xml"); httpPost.setEntity(postEntity); //设置请求器的配置 httpPost.setConfig(requestConfig); try{ HttpResponseresponse=httpClient.execute(httpPost); HttpEntityentity=response.getEntity(); result=EntityUtils.toString(entity,"UTF-8"); }catch(ConnectionPoolTimeoutExceptione){ LogUtils.trace("httpgetthrowConnectionPoolTimeoutException(waittimeout)"); }catch(ConnectTimeoutExceptione){ LogUtils.trace("httpgetthrowConnectTimeoutException"); }catch(SocketTimeoutExceptione){ LogUtils.trace("httpgetthrowSocketTimeoutException"); }catch(Exceptione){ LogUtils.trace("httpgetthrowException"); }finally{ httpPost.abort(); } returnresult; } }
上述就是小编为大家分享的Java中怎么实现微信退款功能了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注恰卡编程网行业资讯频道。
推荐阅读
-
java fileinputstream中文乱码如何解决
javafileinputstream中文乱码如何解决今天小编给...
-
java实现点赞功能
-
java实现简单点赞功能
-
java实现收藏功能
-
java输入空行结束问题怎么解决
-
Java线程中常用的操作有哪些
-
java输入时怎么通过回车来结束输入
java输入时怎么通过回车来结束输入这篇文章主要介绍“java输入...
-
Java数据结构之线索化二叉树怎么实现
Java数据结构之线索化二叉树怎么实现这篇文章主要介绍“Java数...
-
Java中的泛型怎么理解
Java中的泛型怎么理解本篇内容介绍了“Java中的泛型怎么理解”...
-
Java字符串编码解码性能怎么提升
Java字符串编码解码性能怎么提升这篇“Java字符串编码解码性能...