依赖
<!-- 微信支付apiv3版本 -->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.14</version>
</dependency>
微信支付工具类
package com.github.devcude.comp.plaza.mall.plat.util.core;
import com.github.devcude.comp.plaza.mall.plat.configuration.core.WxPayConfig;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAPublicKeyConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.refund.RefundService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* 微信普通商户支付工具类
*
* @ClassName WXPayUtil
* @Description TODO
* @Author orison
* @Date 2024-08-12 17:09
* @Version 1.0
**/
@Component
@Slf4j
public class WXPayGeneralUtil implements ApplicationContextAware {
@Autowired
WxPayConfig wxPayConfig;
/**
* 公钥路径
* 【微信推出了平台证书的替代公钥方案,两者使用场景完全相同,但公钥不会过期,后续新申请的商户号将使用公钥进行验签与敏感信息加密。
* 微信支付公钥使用介绍:https://pay.weixin.qq.com/docs/merchant/products/platform-certificate/wxp-pub-key-guide.html
* 平台证书切换微信支付公钥指引:https://pay.weixin.qq.com/docs/merchant/products/platform-certificate/update-pub-key.html
* 新申请的商户不能再用平台证书,请申请公钥】
*/
/**
* 项目名
*/
public static JsapiService service;//jsapi支付服务
public static JsapiServiceExtension jsapiServiceExtension; //jsapi支付服务增强接口(强烈推荐)
public static NotificationConfig notificationConfig;//回调配置
public static RefundService refundService;//退款服务
public JsapiServiceExtension getJsapiServiceExtension() {
Config config = new RSAPublicKeyConfig.Builder()
.merchantId(wxPayConfig.getMerchantId())
.privateKeyFromPath(wxPayConfig.getPrivateKeyPath())
.publicKeyFromPath(wxPayConfig.getPublicKeyPath())
.publicKeyId(wxPayConfig.getPublicKeyId())
.merchantSerialNumber(wxPayConfig.getMerchantSerialNumber())
.apiV3Key(wxPayConfig.getApiV3Key())
.build();
return new JsapiServiceExtension.Builder().config(config).build();
}
public NotificationConfig getNotificationConfig() {
Config config = new RSAPublicKeyConfig.Builder()
.merchantId(wxPayConfig.getMerchantId())
.privateKeyFromPath(wxPayConfig.getPrivateKeyPath())
.publicKeyFromPath(wxPayConfig.getPublicKeyPath())
.publicKeyId(wxPayConfig.getPublicKeyId())
.merchantSerialNumber(wxPayConfig.getMerchantSerialNumber())
.apiV3Key(wxPayConfig.getApiV3Key())
.build();
return (NotificationConfig) config;
}
public RefundService getRefundService() {
Config config = new RSAPublicKeyConfig.Builder()
.merchantId(wxPayConfig.getMerchantId())
.privateKeyFromPath(wxPayConfig.getPrivateKeyPath())
.publicKeyFromPath(wxPayConfig.getPublicKeyPath())
.publicKeyId(wxPayConfig.getPublicKeyId())
.merchantSerialNumber(wxPayConfig.getMerchantSerialNumber())
.apiV3Key(wxPayConfig.getApiV3Key())
.build();
return new RefundService.Builder().config(config).build();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
}
// /**
// * 根据退款单号查询退款单信息
// * 参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/query-by-out-refund-no.html
// *
// * @param outRefundNo
// * @return
// */
// public static Result queryRefund(String outRefundNo) {
// try {
// QueryByOutRefundNoRequest request = new QueryByOutRefundNoRequest();
// request.setOutRefundNo(outRefundNo);
// Refund refund = refundService.queryByOutRefundNo(request);
status
可选取值:
SUCCESS: 退款成功
CLOSED: 退款关闭
PROCESSING: 退款处理中
ABNORMAL: 退款异常
// return Result.success(refund);
// } catch (ServiceException e) {
// log.error("普通商户-根据退款单号查询退款单信息异常", e);
// return Result.fail(e.getErrorMessage());
// }
// }
//
// /**
// * 关闭订单
// * 参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/close-order.html
// *
// * @param outTradeNo
// * @return
// */
// public static Result closeOrder(String outTradeNo) {
// try {
// CloseOrderRequest request = new CloseOrderRequest();
// request.setMchid(merchantId);
// request.setOutTradeNo(outTradeNo);
// service.closeOrder(request);
// return Result.success();
// } catch (ServiceException e) {
// log.error("普通商户-关闭订单异常", e);
// return Result.fail(e.getErrorMessage());
// }
// }
//
// /**
// * 根据系统业务单号查询订单
// * (用于防止订单支付后微信没有回调支付接口,导致订单还是处于待支付,解决方案如:定时任务查询当天处于待支付订单)
// * 参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/query-by-out-trade-no.html
// *
// * @param outTradeNo trade_state
// * 【交易状态】 交易状态,枚举值:
// * * SUCCESS:支付成功
// * * REFUND:转入退款
// * * NOTPAY:未支付
// * * CLOSED:已关闭
// * * REVOKED:已撤销(仅付款码支付会返回)
// * * USERPAYING:用户支付中(仅付款码支付会返回)
// * * PAYERROR:支付失败(仅付款码支付会返回)
// */
// public static Result queryOrderByOutTradeNo(String outTradeNo) {
// try {
// QueryOrderByOutTradeNoRequest query = new QueryOrderByOutTradeNoRequest();
// query.setMchid(merchantId);
// query.setOutTradeNo(outTradeNo);
// Transaction transaction = service.queryOrderByOutTradeNo(query);
// return Result.success(transaction);
// } catch (ServiceException e) {
// log.error("普通商户-根据系统业务号查询订单异常", e);
// return Result.fail(e.getErrorMessage());
// }
// }
//
//
// /**
// * 微信支付单号查询订单
// * 参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/query-by-wx-trade-no.html
// *
// * @param transactionId 【微信支付订单号】 微信支付系统生成的订单号
// * @return
// */
// public static Transaction queryOrderByTransactionId(String transactionId) {
// QueryOrderByIdRequest request = new QueryOrderByIdRequest();
// request.setMchid(merchantId);
// request.setTransactionId(transactionId);
// return service.queryOrderById(request);
// }
//
//
// /**
// * 退款
// * 参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/create.html
// * 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上。
// * 注意:
// * 交易时间超过一年的订单无法提交退款(按支付成功时间+365天计算)
// * 微信支付退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。申请退款总金额不能超过订单金额。 一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号
// * 请求频率限制:150qps,即每秒钟正常的申请退款请求次数不超过150次
// * 每个支付订单的部分退款次数不能超过50次
// * 如果同一个用户有多笔退款,建议分不同批次进行退款,避免并发退款导致退款失败
// * 申请退款接口的返回仅代表业务的受理情况,具体退款是否成功,需要通过退款查询接口获取结果
// * 错误或无效请求频率限制:6qps,即每秒钟异常或错误的退款申请请求不超过6次
// * 一个月之前的订单申请退款频率限制为:5000/min
// * 同一笔订单多次退款的请求需相隔1分钟
// *
// * @param outTradeNo
// */
// public static Result refunds(String outTradeNo, long total, long refund, String uri) {
// try {
// String symbol = StringUtils.join(WXPayGeneralUtil.randomNum(6, 10).toArray(), ",").replace(",", "");
// String str = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()) + symbol;
// String out_refund_no = str;//商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
// CreateRequest request = new CreateRequest();
// request.setOutTradeNo(outTradeNo);
// request.setOutRefundNo(out_refund_no);
// request.setNotifyUrl(notifyUrl + contextPath + uri);
// AmountReq amountReq = new AmountReq();
// amountReq.setRefund(refund);
// amountReq.setTotal(total);
// amountReq.setCurrency("CNY");
// request.setAmount(amountReq);
// refundService.create(request);
// return Result.success("已申请退款", out_refund_no);
// } catch (ServiceException e) {
// log.error("普通商户-退款", e);
// return Result.fail(e.getErrorMessage());
// }
// }
//
// /**
// * 对退款回调预处理
// * 参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/refund-result-notice.html
// *
// * @param request
// * @param response
// * @return
// */
// public static Map refundsCallbackHandle(HttpServletRequest request, HttpServletResponse response) {
// try {
// //获取报文
// String body = IOUtils.toString(request.getInputStream(), "UTF-8");
// //随机串
// String nonceStr = request.getHeader("Wechatpay-Nonce");
// //微信传递过来的签名
// String signature = request.getHeader("Wechatpay-Signature");
// //证书序列号(微信平台)
// String serialNo = request.getHeader("Wechatpay-Serial");
// //时间戳
// String timestamp = request.getHeader("Wechatpay-Timestamp");
// // 签名方式
// String signType = request.getHeader("Wechatpay-Signature-Type");
// // 构造 RequestParam
// com.wechat.pay.java.core.notification.RequestParam requestParam = new com.wechat.pay.java.core.notification.RequestParam.Builder()
// .serialNumber(serialNo)
// .nonce(nonceStr)
// .signature(signature)
// .timestamp(timestamp)
// .signType(signType)
// .body(body)
// .build();
// // 如果已经初始化了 RSAAutoCertificateConfig,可以直接使用 config
// // 初始化 NotificationParser
// NotificationParser parser = new NotificationParser(notificationConfig);
// // 验签、解密并转换成 Transaction
// Map transaction = parser.parse(requestParam, Map.class);
// return transaction;
// } catch (Exception e) {
// e.printStackTrace();
// myWriter(response, 500);
// log.error("微信支付回调Exception", e);
// }
// return null;
// }
//
//
// /**
// * 生成指定范围的随机数字
// *
// * @param scope 需要生成的随机数字的个数
// * @param total 数字范围
// * @return
// */
// public static List<Integer> randomNum(int scope, int total) {
// List<Integer> mylist = new ArrayList<>(); // 用于储存不重复的随机数
// Random rd = new Random();
// while (mylist.size() < scope) {
// int myNum = rd.nextInt(total);
// if (!mylist.contains(myNum += 1)) { // 判断容器中是否包含指定的数字
// mylist.add(myNum); // 往集合里面添加数据。
// }
// }
// return mylist;
// }
//
// /**
// * 对支付回调预处理
// * 参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/payment-notice.html
// *
// * @param request
// * @param response
// * @return
// */
// public static Map paymentCallbackHandle(HttpServletRequest request, HttpServletResponse response) {
// try {
// //获取报文
// String body = IOUtils.toString(request.getInputStream(), "UTF-8");
// //随机串
// String nonceStr = request.getHeader("Wechatpay-Nonce");
// //微信传递过来的签名
// String signature = request.getHeader("Wechatpay-Signature");
// //证书序列号(微信平台)
// String serialNo = request.getHeader("Wechatpay-Serial");
// //时间戳
// String timestamp = request.getHeader("Wechatpay-Timestamp");
// // 签名方式
// String signType = request.getHeader("Wechatpay-Signature-Type");
// // 构造 RequestParam
// com.wechat.pay.java.core.notification.RequestParam requestParam = new com.wechat.pay.java.core.notification.RequestParam.Builder()
// .serialNumber(serialNo)
// .nonce(nonceStr)
// .signature(signature)
// .timestamp(timestamp)
// .signType(signType)
// .body(body)
// .build();
// // 如果已经初始化了 RSAAutoCertificateConfig,可以直接使用 config
// // 初始化 NotificationParser
// NotificationParser parser = new NotificationParser(notificationConfig);
// // 验签、解密并转换成 Transaction
// Map transaction = parser.parse(requestParam, Map.class);
//
// return transaction;
// } catch (Exception e) {
// e.printStackTrace();
// myWriter(response, 500);
// log.error("微信支付回调Exception", e);
// return null;
// }
// }
//
//
// private static void myWriter(HttpServletResponse response, int code) {
// try {
// // 设置HTTP应答状态码,例如200 OK
// Map map = new HashMap();
// if (code == 200) {
// response.setStatus(200);
// map.put("code", "SUCCESS");
// map.put("message", "成功");
// } else {
// response.setStatus(500);
// map.put("code", "FAIL");
// map.put("message", "失败");
// }
// response.setCharacterEncoding("UTF-8");
// response.setContentType("text/html; charset=utf-8");
// PrintWriter writer = response.getWriter();
// String resultStr = JSON.toJSONString(map);
// writer.print(resultStr);
// writer.close();
// } catch (IOException e) {
// log.error("Exception", e);
// }
// }
}
微信配置类
package com.github.devcude.comp.plaza.mall.plat.configuration.core;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author caozhen
* @ClassName WxPayConfig
* @description: 微信支付配置类
* @date 2024年01月03日
* @version: 1.0
*/
@Data
@Component
@ConfigurationProperties(prefix = "wx")
public class WxPayConfig {
//APPID
private String appId;
//mchid
private String merchantId;
//商户API私钥
private String privateKeyPath;
//商户证书序列号
private String merchantSerialNumber;
//商户APIv3密钥
private String apiV3Key;
//支付通知地址
private String payNotifyUrl;
//退款通知地址
private String refundNotifyUrl;
private String publicKeyId;
private String publicKeyPath;
}
微信配置参数
#微信
wx.secret=cd4cbd9e64cae84f7797d9260b03****
#应用id(小程序id)
wx.appId=wx0aca260a96c6****
#商户号
wx.merchantId=170064****
#商户证书序列号
wx.merchantSerialNumber=1ABCC51EB4C596CD7B9BE2669E86F11DD62F****
#商户APIv3密钥
wx.apiV3Key=jsingkleis5216498520YLGCwijn****
#公钥id
wx.publicKeyId=PUB_KEY_ID_011700648250202501080035680000****
##168环境
wx.payNotifyUrl=http://n.****.com:19594/wxPay/callBack
#退款通知地址
wx.refundNotifyUrl=http://n.****.com:19594/wxPay/refundNotify
#商户API私钥
wx.privateKeyPath=/usr/share/app/wx-cert/apiclient_key.pem
#公钥路径
wx.publicKeyPath=/usr/share/app/wx-cert/pub_key.pem
调用方法
下单
@RequestMapping
public Object order(String orderNum, HttpServletRequest httpServletRequest) {
PmUserBean pmUserBean = TokenUtil.getUser(httpServletRequest.getHeader("token"));
pmUserBean = pmUserService.find(pmUserBean.getId());
IntegralProductOrderBean integralProductOrderBean = integralProductOrderService.findByQuery(IntegralProductOrderParam.builder().num(orderNum).build());
if (null == integralProductOrderBean) {
return ResponseBean.serverError("找不到订单");
}
ProductBean productBean = productService.find(integralProductOrderBean.getProductId());
if (null == productBean) {
return ResponseBean.serverError("找不到商品");
}
String orderNo = integralProductOrderBean.getNum();
Double price = integralProductOrderBean.getPrice();
Integer totalFee = (int) (price * 100);
String desc = productBean.getName();
//totalFee = 1;
try {
JsapiServiceExtension jsapiServiceExtension = wxPayGeneralUtil.getJsapiServiceExtension();
// request.setXxx(val)设置所需参数,具体参数可见Request定义
com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest request = new PrepayRequest();
Amount amount = new Amount();
amount.setTotal(totalFee);
request.setAmount(amount);
request.setAppid(wxPayConfig.getAppId());
request.setMchid(wxPayConfig.getMerchantId());
request.setDescription(desc);
request.setNotifyUrl(wxPayConfig.getPayNotifyUrl());
request.setOutTradeNo(orderNo);
//request.setAttach(req.getOrderType());
Payer payer = new Payer();
payer.setOpenid(pmUserBean.getOpenid());
//payer.setOpenid("oITTw64LaFAsci7mRXk0pBRthpgI");
request.setPayer(payer);
// 调用下单方法,得到应答
PrepayWithRequestPaymentResponse response = jsapiServiceExtension.prepayWithRequestPayment(request);
return ResponseBean.success("下单成功").addData("res", response);
} catch (ServiceException e) {
JSONObject parse = JSONObject.parseObject(e.getResponseBody());
throw new RuntimeException(parse.getString("message"));
} catch (Exception e) {
throw new RuntimeException(e.toString());
}
}
支付回调
/**
* 对支付回调预处理
* 参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/payment-notice.html
*
* @param request
* @param response
* @return
*/
@RequestMapping
public Object callBack(HttpServletRequest request, HttpServletResponse response) {
try {
NotificationConfig notificationConfig = wxPayGeneralUtil.getNotificationConfig();
//获取报文
String body = IOUtils.toString(request.getInputStream(), "UTF-8");
//随机串
String nonceStr = request.getHeader("Wechatpay-Nonce");
//微信传递过来的签名
String signature = request.getHeader("Wechatpay-Signature");
//证书序列号(微信平台)
String serialNo = request.getHeader("Wechatpay-Serial");
//时间戳
String timestamp = request.getHeader("Wechatpay-Timestamp");
// 签名方式
String signType = request.getHeader("Wechatpay-Signature-Type");
// 构造 RequestParam
com.wechat.pay.java.core.notification.RequestParam requestParam = new com.wechat.pay.java.core.notification.RequestParam.Builder()
.serialNumber(serialNo)
.nonce(nonceStr)
.signature(signature)
.timestamp(timestamp)
.signType(signType)
.body(body)
.build();
NotificationParser parser = new NotificationParser(notificationConfig);
// 验签、解密并转换成 Transaction
Map transaction = parser.parse(requestParam, Map.class);
log.info("支付回调结果:{}", transaction);
String payStatus = (String) transaction.get("trade_state");
String orderNum = (String) transaction.get("out_trade_no");
IntegralProductOrderBean integralProductOrderBean = integralProductOrderService.findByQuery(IntegralProductOrderParam.builder().num(orderNum).build());
if (null == integralProductOrderBean) {
return ResponseBean.serverError("找不到订单");
}
log.info("支付返回状态:{}", payStatus);
if (payStatus.equals("SUCCESS")) {
return handleSuccess(integralProductOrderBean);
}
return ResponseBean.serverError("订单不存在");
} catch (Exception e) {
e.printStackTrace();
log.error("微信支付回调Exception", e);
}
return ResponseBean.serverError("支付失败");
}
退款
/**
* 发送退款申请
*/
public Object refundPay(IntegralProductOrderBean integralProductOrderParam) {
IntegralProductOrderBean integralProductOrderBean = integralProductOrderService.find(integralProductOrderParam.getId());
if (null == integralProductOrderBean) {
return ResponseBean.serverError("找不到订单");
}
//售后中
integralProductOrderBean.setStatus("refunding");
integralProductOrderBean.setRefundTime(new Date());
//退款编号
integralProductOrderBean.setRefundNum("TK" + busNumInstService.nextSeq(BbBsnmKeys.REFUND_NUM, CommonBsnmTplKeys.DATE_LENGTH_6_SEQ));
//退款处理中
integralProductOrderBean.setRefundStatus("refundHandle");
//输入退款金额
Double price = integralProductOrderBean.getPrice();
Long refundPrice = (long) (price * 100);
Double price1 = integralProductOrderBean.getPrice();
Long total = (long) (price1 * 100);
try {
RefundService refundService = wxPayGeneralUtil.getRefundService();
CreateRequest request = new CreateRequest();
request.setOutTradeNo(integralProductOrderBean.getNum());
request.setOutRefundNo(integralProductOrderBean.getRefundNum());
request.setNotifyUrl(wxPayConfig.getRefundNotifyUrl());
AmountReq amountReq = new AmountReq();
amountReq.setRefund(refundPrice);
amountReq.setTotal(total);
amountReq.setCurrency("CNY");
request.setAmount(amountReq);
refundService.create(request);
integralProductOrderService.update(integralProductOrderBean);
return ResponseBean.success("已申请退款").addData("refundNum", integralProductOrderBean.getRefundNum());
} catch (ServiceException e) {
log.error("普通商户-退款", e);
String errorMessage = e.getErrorMessage();
return ResponseBean.serverError("退款失败:" + errorMessage);
}
}
退款回调
/**
* 退款回调
*/
@RequestMapping
public Object refundNotify(HttpServletRequest request, HttpServletResponse response) {
try {
NotificationConfig notificationConfig = wxPayGeneralUtil.getNotificationConfig();
//获取报文
String body = IOUtils.toString(request.getInputStream(), "UTF-8");
//随机串
String nonceStr = request.getHeader("Wechatpay-Nonce");
//微信传递过来的签名
String signature = request.getHeader("Wechatpay-Signature");
//证书序列号(微信平台)
String serialNo = request.getHeader("Wechatpay-Serial");
//时间戳
String timestamp = request.getHeader("Wechatpay-Timestamp");
// 签名方式
String signType = request.getHeader("Wechatpay-Signature-Type");
// 构造 RequestParam
com.wechat.pay.java.core.notification.RequestParam requestParam = new com.wechat.pay.java.core.notification.RequestParam.Builder()
.serialNumber(serialNo)
.nonce(nonceStr)
.signature(signature)
.timestamp(timestamp)
.signType(signType)
.body(body)
.build();
// 如果已经初始化了 RSAAutoCertificateConfig,可以直接使用 config
// 初始化 NotificationParser
NotificationParser parser = new NotificationParser(notificationConfig);
// 验签、解密并转换成 Transaction
Map transaction = parser.parse(requestParam, Map.class);
log.info("退款信息:{}", transaction);
String refundStatus = (String) transaction.get("refund_status");
log.info("退款状态:{}", refundStatus);
String orderNum = (String) transaction.get("out_trade_no");
IntegralProductOrderBean integralProductOrderBean = integralProductOrderService.findByQuery(IntegralProductOrderParam.builder().num(orderNum).build());
if (null == integralProductOrderBean) {
return ResponseBean.serverError("找不到订单");
}
if (refundStatus.equals("SUCCESS")) {
//退款成功逻辑
}
return transaction;
} catch (Exception e) {
e.printStackTrace();
log.error("微信支付回调Exception", e);
}
return ResponseBean.serverError("退款失败");
}
微信发起提现
/**
* 商户转账到用户,提现
*
* @return
*/
@RequestMapping
public Object withdraw(WithdrawRecordParam withdrawRecordParam) {
WithdrawRecordBean withdrawRecordBean = this.withdrawRecordService.find(withdrawRecordParam);
if (withdrawRecordBean == null) {
return ResponseBean.serverError("该记录不存在!");
}
PmUserBean pmUserBean = pmUserService.find(PmUserParam.builder().id(withdrawRecordBean.getUserId()).build());
if (null == pmUserBean || StringUtils.isEmpty(pmUserBean.getOpenid())) {
return ResponseBean.serverError("找不到用户");
}
//输入退款金额
Double price = withdrawRecordBean.getPrice();
Long totalPrice = (long) (price * 100);
try {
TransferBatchService transferBatchService = wxPayGeneralUtil.getTransferBatchService();
InitiateBatchTransferRequest request = new InitiateBatchTransferRequest();
request.setAppid(wxPayConfig.getAppId());
request.setOutBatchNo(withdrawRecordBean.getNum());
request.setBatchName("提现");
request.setBatchRemark("提现");
request.setTotalAmount(totalPrice);
request.setTotalNum(1);
List<TransferDetailInput> transferDetailList = new ArrayList<>();
TransferDetailInput transferDetailInput = new TransferDetailInput();
transferDetailInput.setOutDetailNo(withdrawRecordBean.getNum());
transferDetailInput.setTransferAmount(totalPrice);
transferDetailInput.setTransferRemark("提现");
transferDetailInput.setOpenid(pmUserBean.getOpenid());//我的openid
transferDetailList.add(transferDetailInput);
request.setTransferDetailList(transferDetailList);
InitiateBatchTransferResponse response = transferBatchService.initiateBatchTransfer(request);
log.info(response.toString());
return ResponseBean.success("发起提现成功").addData("num", withdrawRecordBean.getNum());
} catch (ServiceException e) {
log.error("提现失败", e);
return ResponseBean.serverError("提现失败");
}
}
提现结果查询
@RequestMapping
public Object findWithdrawStatus(WithdrawRecordParam withdrawRecordParam) {
WithdrawRecordBean withdrawRecordBean = this.withdrawRecordService.find(withdrawRecordParam);
if (withdrawRecordBean == null) {
return ResponseBean.serverError("该记录不存在!");
}
try {
TransferBatchService transferBatchService = wxPayGeneralUtil.getTransferBatchService();
GetTransferDetailByOutNoRequest request = new GetTransferDetailByOutNoRequest();
request.setOutBatchNo(withdrawRecordBean.getNum());
request.setOutDetailNo(withdrawRecordBean.getNum());
//INIT: 初始态。 系统转账校验中
//WAIT_PAY: 待确认。待商户确认, 符合免密条件时, 系统会自动扭转为转账中
//PROCESSING:转账中。正在处理中,转账结果尚未明确
//SUCCESS:转账成功
//FAIL:转账失败。需要确认失败原因后,再决定是否重新发起对该笔明细单的转账(并非整个转账批次单)
TransferDetailEntity transferDetailByOutNo = transferBatchService.getTransferDetailByOutNo(request);
String status = transferDetailByOutNo.getDetailStatus();
if (status.equals("SUCCESS")) {
withdrawRecordBean.setStatus("success");
withdrawRecordService.update(withdrawRecordBean);
}
return ResponseBean.success("操作成功").addData("data", transferDetailByOutNo);
} catch (ServiceException e) {
log.error("提现失败", e);
return ResponseBean.serverError("操作失败");
}
}