Java中怎么实现微信退款功能

这期内容当中小编将会给大家带来有关Java中怎么实现微信退款功能,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

一、下载证书并导入到系统

微信支付接口中,涉及资金回滚的接口会使用到商户证书,包括退款、撤销接口。商家在申请微信支付成功后,可以按照以下路径下载:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->证书下载。

Java中怎么实现微信退款功能

Java中怎么实现微信退款功能

下载的时候需要手机验证及登录密码。下载后找到apiclient_cert.p12这个证书,双击导入,导入的时候提示输入密码,这个密码就是商户ID,且必须是在自己的商户平台下载的证书。否则会出现密码错误的提示:

Java中怎么实现微信退款功能

导入正确的提示:

Java中怎么实现微信退款功能

二、编写代码

首先初始化退款接口中的请求参数,如微信订单号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);

Map<String,String>getMap=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<Object,Object>parameters=newTreeMap<Object,Object>();
parameters.put("appid",appid);
parameters.put("mch_id",mch_id);
parameters.put("nonce_str",nonce_str);
parameters.put("transaction_id",transaction_id);
parameters.put("out_trade_no",out_trade_no);
parameters.put("out_refund_no",out_refund_no);
parameters.put("total_fee",total_fee);
parameters.put("refund_fee",refund_fee);
parameters.put("op_user_id",op_user_id);


Stringsign=DictionarySort.createSign(parameters);
setSign(sign);//把签名数据设置到Sign这个属性中

}

MobiMessage实现json数据类型和xml数据之间的转换。

publicclassMobiMessage{

publicstaticMap<String,String>xml2map(HttpServletRequestrequest)throwsIOException,DocumentException{
Map<String,String>map=newHashMap<String,String>();
SAXReaderreader=newSAXReader();
InputStreaminputStream=request.getInputStream();
Documentdocument=reader.read(inputStream);
Elementroot=document.getRootElement();
List<Element>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<String,String>parseXml(Stringxml)throwsException{
Map<String,String>map=newHashMap<String,String>();
Documentdocument=DocumentHelper.parseText(xml);
Elementroot=document.getRootElement();
List<Element>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("<![CDATA[");
writer.write(text);
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中怎么实现微信退款功能了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注恰卡编程网行业资讯频道。

发布于 2021-06-13 23:18:50
收藏
分享
海报
0 条评论
180
上一篇:Spring Data的JDBC的作用是什么 下一篇:Spring中Ioc的原理是什么
目录

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码