需要些的文章有點(diǎn)多,時(shí)間太少奇徒,我就先隨便寫寫捷沸,后面有空閑在優(yōu)化。
開始 小程序js 頁(yè)面我就不放了 就一個(gè)按鈕自己寫測(cè)試
//申請(qǐng)退款
sqtk: function (e) {
var that = this;
var that = this;
var outRefundNo = "1165166525";
var openId = "o7Rrj5M-METpuTV8mNxv6_6gn1sw";
var tradeNo = "85511613375";
var amount = "0.01";
console.log('申請(qǐng)退款' + e.currentTarget.dataset.wmddid)
wx.showModal({
title: '提示',
content: '申請(qǐng)退款么',
success: function (res) {
if (res.confirm) {
wx.request({
url: 'http://**/app/refund',
method: 'POST',
data: {
openId: openId,
tradeNo: tradeNo,
amount: amount,
outRefundNo: outRefundNo,
refundAmount: amount
}, //參數(shù)為鍵值對(duì)字符串
header: {
//設(shè)置參數(shù)內(nèi)容類型為x-www-form-urlencoded
"Accept": "*/*", 'Content-Type': 'application/json'
},
success: function (e) {
var data = e.data.wxPayResponse;
}
})
} else if (res.cancel) {
console.log('用戶點(diǎn)擊取消')
}
}
})
}
服務(wù)端接口
AppWxPayController.java
退款申請(qǐng)+回調(diào)
@PostMapping("refund")
@ApiOperation("微信退款申請(qǐng)")
public R refund(@RequestBody PayParam payParam){
WxPayEntity wxPayEntity=wxPayService.refund(payParam);
return R.ok().put("wxPayResponse", wxPayEntity);
}
@PostMapping("refundNotifyUrl")
@ApiOperation("微信退款回調(diào)")
public String refundNotifyUrl(HttpServletRequest request){
String xmlString = WxPayUtils.getXmlString(request);
logger.info("----微信退款回調(diào)接收到的數(shù)據(jù)如下:---" + xmlString);
return wxPayService.refundAsyncNotify(xmlString);
}
service+實(shí)現(xiàn)類 WxPayService.java
/** 微信申請(qǐng)退款
* <p>Title: refund</p>
* <p>Description: </p>
* @return
*/
WxPayEntity refund(PayParam payParam);
/**
* 微信退款異步通知
* @param notifyData 異步通知內(nèi)容
* @return
*/
String refundAsyncNotify(String notifyData);
WxPayServiceImpl.java
/* (non-Javadoc)
* <p>Title: refund</p>
* <p>Description: 退款申請(qǐng)</p>
* @param payParam
* @return
* @see com.alpha.modules.wxpay.service.WxPayService#refund(com.alpha.modules.wxpay.form.PayParam)
*/
@Override
public WxPayEntity refund(PayParam payParam) {
WxRefundResponse response = null;
try {
//組請(qǐng)求參數(shù)
WxRefundRequest request = new WxRefundRequest();
request.setAppid(WxConfigure.getAppID());
request.setMchId(WxConfigure.getMch_id());
request.setNonceStr(WxPayUtils.getRandomStr(32));
request.setSignType("MD5");
request.setOutTradeNo(payParam.getTradeNo());
request.setOutRefundNo(payParam.getOutRefundNo());
request.setTotalFee(WxPayUtils.yuanToFen(payParam.getAmount()));
request.setRefundFee(WxPayUtils.yuanToFen(payParam.getRefundAmount()));
request.setNotifyUrl(WxConfigure.getRefundNotifyUrl());
request.setSign(WxPayUtils.signByMD5(request, WxConfigure.getKey()));
Retrofit retrofit=null;
try {
OkHttpClient client=initCert();// 加載證書
retrofit = new Retrofit.Builder()
.baseUrl("https://api.mch.weixin.qq.com")
.addConverterFactory(SimpleXmlConverterFactory.create())
.client(client)
.build();
} catch (Exception e) {
e.printStackTrace();
}
String xml = WxPayUtils.objToXML(request);
RequestBody requestBody = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml);
Call<WxRefundResponse> call = retrofit.create(WxPayApi.class).REFUND_RESPONSE_CALL(requestBody);
Response<WxRefundResponse> retrofitResponse = call.execute();
response = retrofitResponse.body();
if(!response.getReturnCode().equals("SUCCESS")) {
throw new RuntimeException("【微信退款】發(fā)起退款, returnCode != SUCCESS, returnMsg = " + response.getReturnMsg());
}
if (!response.getResultCode().equals("SUCCESS")) {
throw new RuntimeException("【微信退款】發(fā)起退款, resultCode != SUCCESS, err_code = " + response.getErrCode() + " err_code_des=" + response.getErrCodeDes());
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return buildWxRefundResponse(response);
}
/**
* 加載證書
*
*/
private static OkHttpClient initCert() throws Exception {
// 證書密碼厂财,默認(rèn)為商戶ID
String key = WxConfigure.getMch_id();
// 證書的路徑
String path = WxConfigure.getCertPath();
// 指定讀取證書格式為PKCS12
KeyStore keyStore = KeyStore.getInstance("PKCS12");
// 讀取本機(jī)存放的PKCS12證書文件
FileInputStream instream = new FileInputStream(new File(path));
try {
// 指定PKCS12的密碼(商戶ID)
keyStore.load(instream, key.toCharArray());
} finally {
instream.close();
}
SSLContext sslcontext = SSLContexts
.custom()
.loadKeyMaterial(keyStore, key.toCharArray())
.build();
// 設(shè)置OkHttpClient的SSLSocketFactory
return new OkHttpClient.Builder()
.addInterceptor(chain -> {
// 請(qǐng)求頭
Request request = chain.request().newBuilder()
.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
.addHeader("Accept-Encoding", "gzip, deflate")
.addHeader("Connection", "keep-alive")
.addHeader("Accept", "*/*")
.build();
return chain.proceed(request);
})
// 超時(shí)時(shí)間
.readTimeout(5, TimeUnit.MINUTES)
.connectTimeout(5, TimeUnit.MINUTES)
// HTTPS
.sslSocketFactory(sslcontext.getSocketFactory())
// Hostname domain.com not verified
.hostnameVerifier((s, sslSession) -> true)
.build();
}
private WxPayEntity buildWxRefundResponse(WxRefundResponse wxRefundResponse) {
String timeStamps = String.valueOf(System.currentTimeMillis() / 1000L); //微信接口時(shí)間戳為10位字符串
WxPayEntity wxPayEntity = new WxPayEntity();
try {
wxPayEntity.setTimeStamp(timeStamps);
wxPayEntity.setNonceStr(WxPayUtils.getRandomStr(32));
wxPayEntity.setAppid(WxConfigure.getAppID());
wxPayEntity.setSignType("MD5");
} catch (Exception e) {
e.printStackTrace();
}
logger.info("【微信退款】退款申請(qǐng)通知:"+wxPayEntity.getOutTradeNo()+"退款申請(qǐng)成功");
return wxPayEntity;
}
/* (non-Javadoc)
* <p>Title: refundAsyncNotify</p>
* <p>Description: 退款回調(diào)通知</p>
* @param notifyData
* @return
* @see com.alpha.modules.wxpay.service.WxPayService#refundAsyncNotify(java.lang.String)
*/
@Override
public String refundAsyncNotify(String notifyData) {
WxRefundNotifyResponse wxRefundNotifyResponse = (WxRefundNotifyResponse) WxPayUtils.xmlToObj(notifyData, WxRefundNotifyResponse.class);
try {
if(!wxRefundNotifyResponse.getReturnCode().equals("SUCCESS")) {
throw new RuntimeException("【微信退款】退款成功通知, returnCode != SUCCESS, returnMsg = " + wxRefundNotifyResponse.getReturnMsg());
}
if(StringUtils.isNoneBlank(wxRefundNotifyResponse.getReqInfo())){
String reqInfo=AESUtils.decode(notifyData, WxConfigure.getKey());
WxRefundNotifyReqinfo wxRefundNotifyReqinfo= (WxRefundNotifyReqinfo) WxPayUtils.xmlToObj(reqInfo,WxRefundNotifyReqinfo.class);
if(wxRefundNotifyReqinfo.getRefundStatus().equals("SUCCESS")){
//查詢transaction_id 是否為空 為空就修改訂單狀態(tài)
}
logger.info("【微信退款】退款成功通知:"+wxRefundNotifyReqinfo.getOutTradeNo()+"退款成功");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return WxPayUtils.returnXML(wxRefundNotifyResponse.getReturnCode());
}
這里有個(gè)坑芋簿,就是解碼是256位的,而正常的是128位璃饱,需要替換2個(gè)jre的jar包
問題還沒完与斤,因?yàn)槟承﹪?guó)家的進(jìn)口管制限制,Java發(fā)布的運(yùn)行環(huán)境包中的加解密有一定的限制荚恶。比如默認(rèn)不允許256位密鑰的AES加解密撩穿,解決方法就是修改策略文件, 從官方網(wǎng)站下載JCE無(wú)限制權(quán)限策略文件谒撼,注意自己JDK的版本別下錯(cuò)了食寡。將local_policy.jar和US_export_policy.jar這兩個(gè)文件替換%JRE_HOME%\lib\security和%JDK_HOME%\jre\lib\security下原來(lái)的文件,注意先備份原文件廓潜。
官方網(wǎng)站提供了JCE無(wú)限制權(quán)限策略文件的下載:
JDK6的下載地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
JDK7的下載地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
JDK8的下載地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
下載后解壓抵皱,可以看到local_policy.jar和US_export_policy.jar以及readme.txt。
然后后面一篇放實(shí)體類吧 我就不文字描述了辩蛋。
下一篇:[微信支付實(shí)體類補(bǔ)發(fā)]
(http://www.reibang.com/p/fd73ea49040e)