需求:用户充值使用后的剩余金额,需要退回到用户原路。
参考文档:微信支付-开发者文档
pom.xml配置:
<!--微信支付SDK--> <dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-java</artifactId> <version>0.2.12</version> </dependency> <!--微信支付SDK--> <dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-apache-httpclient</artifactId> <version>0.4.4</version> </dependency>
配置说明:在application.yml文件中配置
wx: app_id: wx70f123456abc0000 #微信小程序appId app_secret: 012029bc88ab195f64000c0f40003ed9 #小程序秘钥 mch_id: 1000008342 #微信支付商户号 mch_serial_no: 47401236EAE7432BA123456E95F3EC483A000000 #商户API证书序列号 api_key: ABCD20225806STOPCHARGE0123WXZFSH #微信支付API密钥;apiV3秘钥 key_path: C:\apiclient_key.pem #商户API私钥路径
package com.xxxx.common.vo;
import lombok.Data;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "wx")
@Data
@ToString
public class WxPayV3Vo {
//小程序appid
private String appId;
//商户号
private String mchId;
//证书序列号
private String mchSerialNo;
//小程序秘钥
private String appSecret;
//微信支付API密钥;apiV3秘钥
private String apiKey;
//证书地址
private String keyPath;
}
不废话直接上代码
控制层:小程序传2个参数,余额和用户Id
/**
* 退款
* @param amount
* @param userId
* @return
*/
@ApiOperation(value = "退款", notes = "退款")
@GetMapping(value = "/refund")
@ResponseBody
public CommonResult<Boolean> refund(String amount,Integer userId) {
return CommonResult.success(chargeOrderStatusService.refund(amount,userId));
}
实现类
/**
* 退款
*/
@Override
public boolean refund(String amount, Integer userId) {
BigDecimal amount1 = new BigDecimal(amount);
//查询充值订单集合
List<UserRecharge> chargeOrderStatusList = selectChargeOrderData(userId);
for (UserRecharge userRecharge : chargeOrderStatusList) {
String orderId = userRecharge.getOrderId();//商户订单号
if (amount1.compareTo(BigDecimal.ZERO) <= 0) {
throw new CrmebException("退款金额不能为0,请修改退款金额");
}
//用户剩余金额
User user = queryUserMoney(userId);
//退款金额>用户剩余金额
if (amount1.compareTo(user.getNowMoney()) > 0) {
throw new CrmebException("退款金额大于剩余金额,请修改退款金额");
}
if (amount1.compareTo(user.getNowMoney()) <= 0) {
try {
//开始退款
chargeOrderStatusService.refundStart(amount1, userId, orderId);
} catch (Exception e) {
e.printStackTrace();
throw new CrmebException("微信申请退款失败!");
}
}
}
return false;
}
/**
* 查询充值订单
*
* @return
*/
private List<UserRecharge> selectChargeOrderData(Integer userId) {
LambdaQueryWrapper<UserRecharge> lqw = Wrappers.lambdaQuery();
lqw.eq(UserRecharge::getUid, userId);
lqw.orderByDesc(UserRecharge::getCreateTime);
lqw.last("LIMIT 1");
List<UserRecharge> userRechargeList = userRechargeDao.selectList(lqw);
if (userRechargeList.size() < 0) {
throw new CrmebException("没有找到充值订单信息");
}
return userRechargeList;
}
/**
* 查询用户剩余金额
*
* @return
*/
private User queryUserMoney(Integer userId) {
LambdaQueryWrapper<User> lqw = Wrappers.lambdaQuery();
lqw.eq(User::getUid, userId);
User User = userDao.selectOne(lqw);
if (ObjectUtil.isNull(User)) {
throw new CrmebException("没有找到订单信息");
}
return User;
}
/**
* 开始退款
*
* @param amount1 退款金额
* @param userId
* @param orderId
* @return
*/
@Override
public CommonResult<Object> refundStart(BigDecimal amount1, Integer userId, String orderId) {
//查询用户剩余金额
User user = queryUserMoney(userId);
try {
Config config = new RSAAutoCertificateConfig.Builder()
.merchantId(wxPayV3Bean.getMchId())
.privateKeyFromPath(wxPayV3Bean.getKeyPath())
.merchantSerialNumber(wxPayV3Bean.getMchSerialNo())
.apiV3Key(wxPayV3Bean.getApiKey())
.build();
//构造申请退款对象
RefundService service = new RefundService.Builder().config(config).build();
//请求参数
CreateRequest requestParam = new CreateRequest();
//设置退款金额
AmountReq amountReq = new AmountReq();
String amountStr = amount1.toString();//用户退款金额
Number number = Float.parseFloat(amountStr) * 100;
int oamount = number.intValue();
long refundLong = Long.valueOf(oamount);
amountReq.setRefund(refundLong);//退款金额
String nowMoneyStr = String.valueOf(user.getNowMoney());//用户剩余金额
Number number1 = Float.parseFloat(nowMoneyStr) * 100;
int oamount1 = number1.intValue();
long LongNowMoney = Long.valueOf(oamount1);
//生成商户退款单号
String formattedTime = formatTime(LocalDateTime.now(), "yyyyMMddHHmmss");
String randomNum = String.valueOf(generateRandomNumber(1000, 9999));
String StartChargeSeq = "refund_" + formattedTime + randomNum;
amountReq.setTotal(LongNowMoney);//原订单金额
amountReq.setCurrency("CNY");//货币类型(默认人民币)
requestParam.setAmount(amountReq);
requestParam.setReason("退款");
requestParam.setOutRefundNo(StartChargeSeq);
requestParam.setOutTradeNo(orderId);//商户订单号
//发起请求,申请退款
Refund refund = service.create(requestParam);
//调用成功的响应数据
System.out.println("退款调用成功的响应数据======" + refund);
if (Status.SUCCESS.equals(refund.getStatus().SUCCESS)) {
return CommonResult.success("退款成功");
}
if (Status.PROCESSING.equals(refund.getStatus().PROCESSING)) {
//根据请求返回状态修改对应订单状态
return CommonResult.success("退款中");
}
if (Status.ABNORMAL.equals(refund.getStatus().ABNORMAL)) {
//根据请求返回状态修改对应订单状态
return CommonResult.success("退款异常");
}
if (Status.CLOSED.equals(refund.getStatus().CLOSED)) {
//根据请求返回状态修改对应订单状态
return CommonResult.success("退款关闭");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}