1.退款接口,
微信API文档地址https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_9.shtml
//微信退款,微信支持一个订单多次退款(上限为50),并且订单的交易完成时间不能超过一年
//退款结果,微信会回调通知
//outTradeNo 商户订单号(下单的时候,我们生成的订单))
//refundAmount 退款的金额(单位:分)
//refundReason 退款的说明
//salesId 退款单号,我们自己生成,多次退款的时候要每次不一样
public ReturnJson weChatRefundHighShop (String outTradeNo, String refundAmount, String refundReason,String salesId) throws Exception{
//可以在此查询当前退款的订单信息,校验订单是否存在、获取金额等信息.....
//订单金额
int orderMoney = 1000;
//通过加载文件的方式来读取私钥,或者也可以使用字符串的方式来加载私钥
String path = this.getClass().getClassLoader().getResources("./apiclient_key.pem").nextElement().getPath();
//加载商户私钥(私钥存储在文件)
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new FileInputStream(path));
// 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,apiV3Key:V3密钥)
AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(new WechatPay2Credentials(WX_MCH_ID, new PrivateKeySigner(WX_Serial_Number, merchantPrivateKey)),V3_key.getBytes("utf-8"));
//初始化httpClient
CloseableHttpClient builder = WechatPayHttpClientBuilder.create().withMerchant(WX_MCH_ID, WX_Serial_Number, merchantPrivateKey).withValidator(new WechatPay2Validator(verifier)).build();
//微信的退款接口
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds");、
//退款请求参数的说明
//out_trade_no 商户订单号
//out_refund_no 商户退款单号
//reason 退款的原因
//notify_url 退款结果通知的地址,此地址必须是一个公网地址
//funds_account 退款资金的来源 AVAILABLE:可用余额账户
//amount 资金信息
//refund 退款金额 单位:分
//total 退款原订单的总金额,需要我们查询我们自己的订单信息获取
//currency 币种
String requestData = "{\n" +
" \"out_trade_no\": \""+outTradeNo+"\",\n" +
" \"out_refund_no\": \""+ salesId +"\",\n" +
" \"reason\": \"优选商城退款\",\n" +
" \"notify_url\": \""+Wechat_H5_Refund+"\",\n" +
" \"funds_account\": \"AVAILABLE\",\n" +
" \"amount\": {\n" +
" \"refund\": "+refundAmount+",\n" +
" \"total\": "+ orderMoney +",\n" +
" \"currency\": \"CNY\"\n" +
" }" +
"}";
StringEntity entity = new StringEntity(requestData,"utf-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept","application/json");
CloseableHttpResponse response = builder.execute(httpPost);
JSONObject jsonResult = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
String refundEnum = jsonResult.getString("status");
return ReturnUtils.returnVal(CommonConstants.appCode.SUCCESS.get(),refundEnum);
}else {
return ReturnUtils.returnVal(CommonConstants.appCode.DATAERROR.get(),jsonResult);
}
} finally {
response.close();
}
}
2.微信回调接口的编写
//退款成功后,微信方通知的回调地址
//在这里解析验签之后,获取到微信发送的退款相关信息
//判断退款状态为成功,然后进行我们自己的业务处理
//此接口微信可能会多次调用,请注意处理
@ResponseBody
@RequestMapping(value = "/wechatRefundNotify",produces = {"application/json;charset=utf-8"})
public ResultEntity wechatRefundNotify(@RequestBody Weixin weixin) {
AesUtil aesutils = new AesUtil(this.V3_key.getBytes());
try {
String string = aesutils.decryptToString(weixin.getResource().getAssociated_data().getBytes(), weixin.getResource().getNonce().getBytes(), weixin.getResource().getCiphertext());
JSONObject jsonObject = JSONObject.parseObject(string);
//获取退款单号
String out_refund_no = jsonObject.getString("out_refund_no");
//获取退款状态 SUCCESS(退款成功) CLOSE(退款关闭) ABNORMAL(退款异常)
String refund_status = jsonObject.getString("refund_status");
if(refund_status.equals("SUCCESS")){
//这里是退款成功,进行我们自己的业务处理,然后告诉微信我们收到了,你不用再发了
return new ResultEntity("SUCCESS", "成功");
}else if(refund_status.equals("ABNORMAL")) {
//这里是退款异常了,就需要我们自己另行处理,然后提示用户
return new ResultEntity("SUCCESS", "成功");
}
} catch (Exception e) {
//异常的记录.....
}
return new ResultEntity("FAIL", "失败");
}
3.微信回调的参数及说明
//微信退款回调的通知参数
public class Weixin {
private String create_time;
private String summary;
private String resiyrce_type;
private WeixinReturnEntities resource = new WeixinReturnEntities();
}
//微信回调的参数
public class WeixinReturnEntities {
//退款状态
private String trade_state;
//退款单号
private String out_trade_no;
private String associated_data;
private String nonce;
private String ciphertext;
}