src/main/java/cc/mrbird/febs/common/properties/XcxProperties.java
@@ -18,5 +18,11 @@ private String wecharPaynotifyUrl; //测试支付的开关,true:支付0.01元 private Boolean debug; //支付证书地址 private String certLocalPath; //微信商户号 private String wecharpayMchid; //支付秘钥 private String wecharpaySecret; } src/main/java/cc/mrbird/febs/mall/controller/ApiMallOrderController.java
@@ -89,6 +89,12 @@ return new FebsResponse().success().message("删除成功"); } @ApiOperation(value = "用户退款", notes = "用户退款") @PostMapping(value = "/refundOrder/{id}") public FebsResponse refundOrder(@PathVariable("id") Long id) { return mallOrderInfoService.refundOrder(id); } @ApiOperation(value = "提交退款申请", notes = "提交退款申请") @PostMapping(value = "/applyRefund") public FebsResponse applyRefund(@RequestBody AddRefundDto addRefundDto) { src/main/java/cc/mrbird/febs/mall/entity/MallRefundEntity.java
New file @@ -0,0 +1,26 @@ package cc.mrbird.febs.mall.entity; import cc.mrbird.febs.common.entity.BaseEntity; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.math.BigDecimal; @Data @TableName("mall_refund") public class MallRefundEntity extends BaseEntity { //退款编号 private String refundNo; //退款人ID private Long memberId; //退款订单ID private Long orderId; //退款方式 1:微信 2:支付宝 3:其他 private Integer type; //退款状态 1:成功 2:失败 3:退款中 private Integer state; //退款金额 private BigDecimal amount; } src/main/java/cc/mrbird/febs/mall/mapper/MallRefundMapper.java
New file @@ -0,0 +1,7 @@ package cc.mrbird.febs.mall.mapper; import cc.mrbird.febs.mall.entity.MallRefundEntity; import com.baomidou.mybatisplus.core.mapper.BaseMapper; public interface MallRefundMapper extends BaseMapper<MallRefundEntity> { } src/main/java/cc/mrbird/febs/mall/service/IApiMallOrderInfoService.java
@@ -1,5 +1,6 @@ package cc.mrbird.febs.mall.service; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.mall.dto.*; import cc.mrbird.febs.mall.entity.MallOrderInfo; import cc.mrbird.febs.mall.vo.OrderDetailVo; @@ -32,4 +33,6 @@ void autoCancelOrder(Long id); void goodsComment(ApiAddCommentDtos addCommentDtos); FebsResponse refundOrder(Long id); } src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java
@@ -1,7 +1,9 @@ package cc.mrbird.febs.mall.service.impl; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.common.enumerates.*; import cc.mrbird.febs.common.exception.FebsException; import cc.mrbird.febs.common.properties.XcxProperties; import cc.mrbird.febs.common.utils.*; import cc.mrbird.febs.mall.conversion.MallGoodsCommentConversion; import cc.mrbird.febs.mall.conversion.MallOrderInfoConversion; @@ -16,18 +18,22 @@ import cc.mrbird.febs.pay.model.BrandWCPayRequestData; import cc.mrbird.febs.pay.service.IPayService; import cc.mrbird.febs.pay.service.IXcxPayService; import cc.mrbird.febs.pay.util.WeixinServiceUtil; import cc.mrbird.febs.rabbit.producter.AgentProducer; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUnit; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SecureUtil; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -62,6 +68,7 @@ private final IPayService payService; private final IXcxPayService iXcxPayService; private final IMallAchieveService mallAchieveService; private final MallRefundMapper mallRefundMapper; @Override @Transactional(rollbackFor = Exception.class) @@ -560,4 +567,100 @@ } } @Autowired private WeixinServiceUtil weixinServiceUtil; private final XcxProperties xcxProperties = SpringContextHolder.getBean(XcxProperties.class); @Override @Transactional public FebsResponse refundOrder(Long id) { MallMember member = LoginUserUtil.getLoginUser(); MallOrderInfo mallOrderInfo = this.baseMapper.selectById(id); if(ObjectUtil.isEmpty(mallOrderInfo)){ return new FebsResponse().fail().message("订单不存在"); } Integer status = mallOrderInfo.getStatus(); if(OrderStatusEnum.WAIT_SHIPPING.getValue() != status){ return new FebsResponse().fail().message("订单不是待发货状态"); } Integer deliveryState = mallOrderInfo.getDeliveryState(); if(1 != deliveryState){ return new FebsResponse().fail().message("订单不是待配送状态"); } QueryWrapper<MallRefundEntity> objectQueryWrapper = new QueryWrapper<>(); objectQueryWrapper.eq("member_id",member.getId()); objectQueryWrapper.eq("order_id",mallOrderInfo.getId()); MallRefundEntity mallRefund = mallRefundMapper.selectOne(objectQueryWrapper); MallRefundEntity mallRefundEntity = new MallRefundEntity(); if(ObjectUtil.isEmpty(mallRefund)){ mallRefundEntity.setRefundNo(mallOrderInfo.getOrderNo()+"_r"); mallRefundEntity.setMemberId(member.getId()); mallRefundEntity.setOrderId(mallOrderInfo.getId()); mallRefundEntity.setType(1); mallRefundEntity.setState(3); mallRefundEntity.setAmount(mallOrderInfo.getAmount()); mallRefundMapper.insert(mallRefundEntity); } if(mallRefund.getState() == 1){ return new FebsResponse().fail().message("订单已退款"); } if(mallRefund.getState() == 3){ return new FebsResponse().fail().message("订单退款中"); } if(mallRefund.getState() == 2){ mallRefundEntity.setId(mallRefund.getId()); mallRefundEntity.setRefundNo(mallRefund.getRefundNo()); mallRefundEntity.setMemberId(mallRefund.getMemberId()); mallRefundEntity.setOrderId(mallRefund.getOrderId()); mallRefundEntity.setType(mallRefund.getType()); mallRefundEntity.setState(3); mallRefundEntity.setAmount(mallRefund.getAmount()); mallRefundMapper.updateById(mallRefundEntity); } //退款订单编号 String orderNo = mallOrderInfo.getOrderNo(); //退款退款编号 String refundNo = mallRefundEntity.getRefundNo(); //退款订单金额 BigDecimal orderAmount = mallOrderInfo.getAmount(); BigDecimal aa = new BigDecimal(100); int orderMoney = orderAmount.multiply(aa).intValue(); //退款退款金额 BigDecimal refundAmount = mallRefundEntity.getAmount(); BigDecimal bb = new BigDecimal(100); int refundMoney = refundAmount.multiply(bb).intValue(); Boolean flag = false; Boolean debug = xcxProperties.getDebug(); if (debug) { boolean b = weixinServiceUtil.comRefund(orderNo, refundNo, 1, 1, null); flag = b; } else { log.info("开始调用退款接口。。。退款编号为{}", refundNo); boolean b = weixinServiceUtil.comRefund(orderNo, refundNo, orderMoney, refundMoney, null); flag = b; } /** * 更新退款表 * 更新订单表 */ Long refundId = mallRefundEntity.getId(); MallRefundEntity mallRefundOld = mallRefundMapper.selectById(refundId); MallOrderInfo mallOrderInfoOld = this.baseMapper.selectByOrderNo(orderNo); if(flag){ mallRefundOld.setState(1); mallRefundMapper.updateById(mallRefundOld); mallOrderInfoOld.setStatus(OrderStatusEnum.REFUNDED.getValue()); this.baseMapper.updateById(mallOrderInfoOld); }else{ mallRefundOld.setState(2); mallRefundMapper.updateById(mallRefundOld); return new FebsResponse().fail().message("退款失败,请联系客服人员"); } return new FebsResponse().success().message("退款成功"); } } src/main/java/cc/mrbird/febs/pay/util/WeixinServiceUtil.java
@@ -3,10 +3,9 @@ import cc.mrbird.febs.common.exception.FebsException; import cc.mrbird.febs.common.properties.XcxProperties; import cc.mrbird.febs.common.utils.SpringContextHolder; import cc.mrbird.febs.pay.model.BrandWCPayRequestData; import cc.mrbird.febs.pay.model.JsApiPayBusiness; import cc.mrbird.febs.pay.model.JsApiPayReqData; import cc.mrbird.febs.pay.model.JsApiPayResData; import cc.mrbird.febs.pay.model.*; import cc.mrbird.febs.pay.service.impl.RefundService; import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -46,9 +45,9 @@ JsApiPayBusiness jsApiPayBusiness = new JsApiPayBusiness(); String idAddr = getIpAddr(WebUtil.getRequest()); String mchID = WechatConfigure.WECHARPAY_MCHID; String paySecret = WechatConfigure.WECHARPAY_SECRET; String appId = WechatConfigure.MINIPROGRAM_APPID; String mchID = xcxProperties.getWecharpayMchid(); String paySecret = xcxProperties.getWecharpaySecret(); String appId = xcxProperties.getXcxAppid(); JsApiPayReqData jsApiPayReqData = new JsApiPayReqData( appId, mchID, paySecret, notifyUrl, desc, @@ -81,48 +80,48 @@ * @param opUserID 操作员id,默认为商户号 * @return */ // public boolean comRefund(String outTradeNo, String outRefundNo,int totalFee, // int refundFee, String opUserID){ // LogUtil.info("#---outTradeNo:{}#---outRefundNo:{}#---totalFee:{}#---refundFee:{}", // outTradeNo,outRefundNo,totalFee,refundFee); // BusParameterSettings mchID = busParameterSettingsDao.selectCompanyParamByCode(AppConstance.WECHARPAY_MCHID, HostInterceptor.getCompanyId()); // if(opUserID==null){ // opUserID=mchID.getParamValue(); // } // RefundResData result=null; // boolean flag=false; // try { // JsApiPayBusiness jsApiPayBusiness = new JsApiPayBusiness(); // Long companyId=HostInterceptor.getCompanyId(); // BusParameterSettings paySecret = busParameterSettingsDao.selectCompanyParamByCode(AppConstance.WECHARPAY_SECRET, companyId); // BusParameterSettings appId = busParameterSettingsDao.selectCompanyParamByCode(AppConstance.MINIPROGRAM_APPID, companyId); // BusParameterSettings certLocalPath = busParameterSettingsDao.selectCompanyParamByCode(AppConstance.WECHARPAY_CERTLOCAL_PATH, companyId); // // RefundReqData refundReqData=new RefundReqData(mchID.getParamValue(),appId.getParamValue(),paySecret.getParamValue(), outTradeNo, outRefundNo, totalFee, refundFee,opUserID); // RefundService refundService=new RefundService(); // HttpsRequest2 request2= (HttpsRequest2) refundService.getServiceRequest(); // request2.setCertLocalPath(certLocalPath.getParamValue()); // request2.setMchId(mchID.getParamValue()); // // result = jsApiPayBusiness.refundComOrder(refundService, refundReqData); // LogUtil.info("#退款,企业付款到个人---result:{}",result); // //如果返回余额不足时 // if (StringUtils.equals(AppConstance.REFUND_FAIL_NOTENOUGH, result.getErr_code())) { // LogUtil.info("#退款失败,{}!", "商户余额不足"); // throw new GlobleException("退款失败,请联系管理员!"); // } // } catch (Exception e) { // LogUtil.error("#企业付款到个人异常#退款#outTradeNo:{}#opUserID:{}", e, outTradeNo,opUserID); // } // // if (result.getResult_code().equals(WechatConfigure.SUCCESS)) { // flag=true; // }else{ // flag=false; // throw new GlobleException(result.getErr_code_des()); // } // return flag; // } public boolean comRefund(String outTradeNo, String outRefundNo,int totalFee, int refundFee, String opUserID){ log.info("#---outTradeNo:{}#---outRefundNo:{}#---totalFee:{}#---refundFee:{}", outTradeNo,outRefundNo,totalFee,refundFee); String mchID = xcxProperties.getWecharpayMchid(); if(opUserID==null){ opUserID=mchID; } RefundResData result=null; boolean flag=false; try { JsApiPayBusiness jsApiPayBusiness = new JsApiPayBusiness(); String paySecret = xcxProperties.getWecharpaySecret(); String appId = xcxProperties.getXcxAppid(); String certLocalPath = xcxProperties.getCertLocalPath(); RefundReqData refundReqData=new RefundReqData(mchID,appId,paySecret, outTradeNo, outRefundNo, totalFee, refundFee,opUserID); RefundService refundService=new RefundService(); HttpsRequest2 request2= (HttpsRequest2) refundService.getServiceRequest(); request2.setCertLocalPath(certLocalPath); request2.setMchId(mchID); result = jsApiPayBusiness.refundComOrder(refundService, refundReqData); log.info("#退款,企业付款到个人---result:{}",result); //如果返回余额不足时,商户余额不足时微信返回状态码(退款失败时) if (StrUtil.equals("NOTENOUGH", result.getErr_code())) { log.info("#退款失败,{}!", "商户余额不足"); flag=false; } } catch (Exception e) { log.error("#企业付款到个人异常#退款#outTradeNo:{}#opUserID:{}", e, outTradeNo,opUserID); flag=false; } if (result.getResult_code().equals("SUCCESS")) { flag=true; }else{ flag=false; } return flag; } /**@Description 支付获取远程设备的ip @date 2017年6月27日 src/main/resources/application-dev.yml
@@ -69,3 +69,6 @@ xcx_secret: 71403646f666f9b9dca308d4f357765c debug: true wecharPaynotifyUrl: http://groupbuy.csxuncong.com/api/xcxPay/wxpayCallback certLocalPath: /home/xuncongCert/apiclient_cert.p12 wecharpayMchid: 1605533690 wecharpaySecret: CSxc168888CSxc168888CSxc168888xc src/main/resources/application-prod.yml
@@ -63,5 +63,8 @@ wechar_login_url: https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code xcx_appid: wx5cc58f796224af61 xcx_secret: 71403646f666f9b9dca308d4f357765c debug: false debug: true wecharPaynotifyUrl: http://groupbuy.csxuncong.com/api/xcxPay/wxpayCallback certLocalPath: /home/xuncongCert/apiclient_cert.p12 wecharpayMchid: 1605533690 wecharpaySecret: CSxc168888CSxc168888CSxc168888xc src/main/resources/application-test.yml
@@ -65,3 +65,6 @@ xcx_secret: 71403646f666f9b9dca308d4f357765c debug: true wecharPaynotifyUrl: http://groupbuy.csxuncong.com/api/xcxPay/wxpayCallback certLocalPath: /home/xuncongCert/apiclient_cert.p12 wecharpayMchid: 1605533690 wecharpaySecret: CSxc168888CSxc168888CSxc168888xc