From 4d471935e146fc48eba202687470240f64f10686 Mon Sep 17 00:00:00 2001 From: xhxu Date: Mon, 22 Nov 2021 15:28:09 +0800 Subject: [PATCH] update refund --- .../WxMsgValidationcodeController.java | 6 - .../controller/callback/TtPayController.java | 148 ++++++++++++++++++ .../iformall/douyin/pay/DouYinPayHelper.java | 49 ++++++ .../pay/orderQuery/QueryRefundResult.java | 11 ++ .../douyin/pay/preOrder/CreateRefund.java | 58 +++++++ .../pay/preOrder/CreateRefundResult.java | 12 ++ .../impl/WxMsgValidationcodeServiceImpl.java | 1 - .../service/impl/WxOrderServiceImpl.java | 5 - .../impl/WxRefundOrderServiceImpl.java | 32 ++-- .../refund/douyin/TtRefundAdapterService.java | 131 ++++++++++++++++ 10 files changed, 428 insertions(+), 25 deletions(-) create mode 100644 mallinkCallback/src/main/java/com/iformall/controller/callback/TtPayController.java create mode 100644 mallinkService/src/main/java/com/iformall/douyin/pay/orderQuery/QueryRefundResult.java create mode 100644 mallinkService/src/main/java/com/iformall/douyin/pay/preOrder/CreateRefund.java create mode 100644 mallinkService/src/main/java/com/iformall/douyin/pay/preOrder/CreateRefundResult.java create mode 100644 mallinkService/src/main/java/com/iformall/service/pay/service/refund/douyin/TtRefundAdapterService.java diff --git a/mallinkCApi/src/main/java/com/iformall/controller/WxMsgValidationcodeController.java b/mallinkCApi/src/main/java/com/iformall/controller/WxMsgValidationcodeController.java index 8a7086adc..eae21c8f2 100644 --- a/mallinkCApi/src/main/java/com/iformall/controller/WxMsgValidationcodeController.java +++ b/mallinkCApi/src/main/java/com/iformall/controller/WxMsgValidationcodeController.java @@ -53,9 +53,6 @@ public class WxMsgValidationcodeController extends BaseController { if(!phone.matches("^1[0-9]{10}$")){ return new ResultData(ErrorCode.SYS_PARAMETER_ERROR.getCode(),"手机号格式不正确"); } - if(type == null){ - type = 1; - } WxMsgValidationcode wxMsgValidationcode = new WxMsgValidationcode(); wxMsgValidationcode.updateTenantInfo(getTenantInfo()); wxMsgValidationcode.setPhone(phone); @@ -78,9 +75,6 @@ public class WxMsgValidationcodeController extends BaseController { if(!phone.matches("^1[0-9]{10}$")){ return new ResultData(ErrorCode.SYS_PARAMETER_ERROR.getCode(),"手机号格式不正确"); } - if(type == null){ - type = 1; - } if (StringUtils.isBlank(code)) { return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "验证码未填写"); } diff --git a/mallinkCallback/src/main/java/com/iformall/controller/callback/TtPayController.java b/mallinkCallback/src/main/java/com/iformall/controller/callback/TtPayController.java new file mode 100644 index 000000000..c93899a0b --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/controller/callback/TtPayController.java @@ -0,0 +1,148 @@ +package com.iformall.controller.callback; + +import com.alibaba.fastjson.JSONObject; +import com.iformall.common.ErrorCode; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxAppinfo; +import com.iformall.domain.po.WxPayAccount; +import com.iformall.domain.po.WxPayOrder; +import com.iformall.douyin.pay.DouYinPayHelper; +import com.iformall.enums.EnumPayStatus; +import com.iformall.enums.EnumPayWay; +import com.iformall.interceptor.BodyReaderHttpServletRequestWrapper; +import com.iformall.service.WxAppinfoService; +import com.iformall.service.WxPayAccountService; +import com.iformall.service.WxPayOrderService; +import com.iformall.service.WxRefundOrderService; +import com.iformall.service.order.OrderFactory; +import com.iformall.service.order.entity.WxComposeOrder; +import com.iformall.service.pay.PayServiceFactory; +import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/ttPay/notify") +public class TtPayController extends BaseController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + + @Autowired + private WxAppinfoService appinfoService; + + @Autowired + private WxPayAccountService payAccountService; + + @Autowired + private WxRefundOrderService wxRefundOrderService; + + @Autowired + private WxPayOrderService wxPayOrderService; + + @Autowired + private OrderFactory orderFactory; + + @Autowired + private PayServiceFactory payServiceFactory; + + /** + * timestamp number Unix 时间戳,10 位,整型数 + * nonce string 随机数 + * msg string 订单信息的 json 字符串 + * type string 回调类型标记,支付成功回调为"payment" + * msg_signature String 签名 + * + * appid string 小程序 id + * cp_orderno string 开发者传入订单号 + * way string way 字段中标识了支付渠道:2-支付宝,1-微信,3-银行卡 + * cp_extra string 预下单时开发者传入字段 + * + * @return 支付通知 + */ + @PostMapping(value = "/orderPay") + @ResponseBody + public Map createOrder( HttpServletRequest request){ + logger.debug("[" + getIpAddr() + "] TtOrderCallbackController::createOrder"); + Map resultMap = new HashMap<>(); + + String body = ((BodyReaderHttpServletRequestWrapper) request).getBody(); + logger.info("抖音支付通知-----body{}"+body); + try { + + Map parameterMap = JSONObject.parseObject(body, Map.class); + + String timestamp = (String) parameterMap.get("timestamp"); + String nonce = (String) parameterMap.get("nonce"); +// {"appid":"tt9da4eb19029c2bb301","cp_orderno":"557490321114062848","cp_extra":"","way":"2","channel_no":"2021052622001418391405536769","channel_gateway_no":"12105260162116189897","payment_order_no":"2021052622001418391405536769","out_channel_order_no":"","total_amount":100} + String msg = (String) parameterMap.get("msg"); + String type = (String) parameterMap.get("type"); + String msgSignature = (String) parameterMap.get("msg_signature"); + + Map pMap = JSONObject.parseObject(msg, Map.class); + String appid = (String) pMap.get("appid"); + WxAppinfo appinfo = appinfoService.getByAppId(appid); + WxPayAccount payAccount = payAccountService.getById(appinfo.getPayId()); + Map paramMap = new HashMap<>(); + paramMap.put("token",payAccount.getNotifyToken()); + paramMap.put("timestamp",timestamp); + paramMap.put("nonce",nonce); + paramMap.put("msg",msg); + String sign = DouYinPayHelper.getTTBackSign(paramMap, "SHA1"); + if(!msgSignature.equalsIgnoreCase(sign)){ + resultMap.put("err_tips","error"); + return resultMap; + } + if("payment".equals(type)){//支付回调 + String cp_orderno = (String) pMap.get("cp_orderno");//开发者传入订单号 + String way = (String) pMap.get("way");//2-支付宝,1-微信 + if (!StringUtils.isNotBlank(cp_orderno)) { + try { + Long payOrderId = Long.valueOf(cp_orderno); + WxPayOrder wxpayOrder = wxPayOrderService.getById(payOrderId, appinfo.getTenantId()); + PayQueryAdapterResult queryResult = payServiceFactory.getPayAdapterService(wxpayOrder.getPayVendor()).queryPayStatus(wxpayOrder, appinfo, payAccount); + if (EnumPayStatus.PAY_STATUS_SUCCESS.getCode() == queryResult.getCode()) { + WxComposeOrder composeOrder = orderFactory.getOrderAdapterService(wxpayOrder.getComposeOrder()).getComposeOrder(wxpayOrder.getOrderId(), wxpayOrder.getTenantId()); + wxPayOrderService.handleSuccessOrder(wxpayOrder, composeOrder, queryResult, true,false); + } + } catch (NumberFormatException e) { + logger.error("payOrderId参数不正确: " + paramMap.toString() + ", e:" + e.getMessage()); + } + } + + resultMap.put("err_no",0); + resultMap.put("err_tips","success"); + }else if("refund".equals(type)){//退款回调 + String cp_refundno = (String) pMap.get("cp_refundno"); + String status = (String) pMap.get("status"); + String refund_amount = (String) pMap.get("refund_amount"); + + Map map = new HashMap<>(); + map.put("appid",appid); + map.put("cp_refundno",cp_refundno); + map.put("status",status); + map.put("refund_amount",refund_amount); + wxRefundOrderService.notify(map, EnumPayWay.PAY_WAY_TT); + resultMap.put("err_no",0); + resultMap.put("err_tips","success"); + } + + return resultMap; + } catch (Exception e){ + e.printStackTrace(); + resultMap.put("err_tips","error"); + return resultMap; + } + } +} diff --git a/mallinkService/src/main/java/com/iformall/douyin/pay/DouYinPayHelper.java b/mallinkService/src/main/java/com/iformall/douyin/pay/DouYinPayHelper.java index 9be13de44..3c8cbf6cc 100644 --- a/mallinkService/src/main/java/com/iformall/douyin/pay/DouYinPayHelper.java +++ b/mallinkService/src/main/java/com/iformall/douyin/pay/DouYinPayHelper.java @@ -8,6 +8,7 @@ import java.util.*; import com.iformall.common.ErrorCode; import com.iformall.douyin.pay.enums.AppAddSubMerchantUrlType; import com.iformall.douyin.pay.orderQuery.QueryMerchantResult; +import com.iformall.douyin.pay.orderQuery.QueryRefundResult; import com.iformall.douyin.pay.orderQuery.QuerySettleResult; import com.iformall.douyin.pay.preOrder.*; import com.iformall.enums.EnumPayStatus; @@ -203,6 +204,54 @@ public class DouYinPayHelper { throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), "订单查询抖音支付状态失败"+payOrderNo); } + //退款 + public static CreateRefundResult createRefund(CreateRefund createRefund) { + Map map = createRefund.toRequestMap(); + String response = doPost("https://developer.toutiao.com/api/apps/ecpay/v1/create_refund", map); + log.info("退款 request:"+map.toString()+" response:"+response); + JSONObject jsonObject = JSON.parseObject(response); + Integer code = jsonObject.getInteger("err_no"); + if (null != code && code.intValue() == 0 ) { + CreateRefundResult result = new CreateRefundResult(); + result.setSuccess(true); + result.setRefundNo(jsonObject.getString("refund_no")); + return result; + }else { + log.error("createRefund reponse error. request: "+JSON.toJSONString(createRefund.toRequestMap())+" response:"+response); + CreateRefundResult result = new CreateRefundResult(); + result.setSuccess(false); + result.setMsg("createRefund reponse error."+jsonObject.getString("err_tips")); + return result; + } + } + + + //退款查询 + public static QueryRefundResult refundQuery(String appId, String salt, String outRefundNo, String thirdParytyId) { + Map map = new HashMap(); + map.put("app_id",appId); + map.put("salt",salt); + map.put("out_refund_no",outRefundNo); +// map.put("sign",createSign(map, secrect)); + map.put("sign",getSign(map)); + map.remove("salt"); + String response = doPost("POST https://developer.toutiao.com/api/apps/ecpay/v1/query_refund", map); + log.info("查询退款结果 request:"+map.toString()+" response:"+response); + JSONObject jsonObject = JSON.parseObject(response); + Integer code = jsonObject.getInteger("err_no"); + if (null != code && code.intValue() == 0 ) { + JSONObject info = jsonObject.getJSONObject("refundInfo"); + QueryRefundResult result = new QueryRefundResult(); + result.setRefundNo(info.getString("refund_no")); + result.setRefundAmount(info.getInteger("refund_amount")); + result.setRefundStatus(info.getString("refund_status")); + return result; + }else { + log.info("refundQuery reponse error. request: "+JSON.toJSONString(map)+" response:"+response); + throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "退款查询状态异常"); + } + } + //小程序开发者为分账方进件 //POST https://developer.toutiao.com/api/apps/ecpay/saas/app_add_sub_merchant public static AppAddSubMerchantResult appAddSubMerchant(AppAddSubMerchant appAddSubMerchant) { diff --git a/mallinkService/src/main/java/com/iformall/douyin/pay/orderQuery/QueryRefundResult.java b/mallinkService/src/main/java/com/iformall/douyin/pay/orderQuery/QueryRefundResult.java new file mode 100644 index 000000000..c4f7c4586 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/douyin/pay/orderQuery/QueryRefundResult.java @@ -0,0 +1,11 @@ +package com.iformall.douyin.pay.orderQuery; + +import lombok.Data; + +@Data +public class QueryRefundResult { + + private String refundNo;//担保支付侧的退款单号 + private Integer refundAmount;//退款金额,单位[分] + private String refundStatus;//退款状态,成功-SUCCESS;失败-FAIL +} diff --git a/mallinkService/src/main/java/com/iformall/douyin/pay/preOrder/CreateRefund.java b/mallinkService/src/main/java/com/iformall/douyin/pay/preOrder/CreateRefund.java new file mode 100644 index 000000000..4794f78f3 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/douyin/pay/preOrder/CreateRefund.java @@ -0,0 +1,58 @@ +package com.iformall.douyin.pay.preOrder; + +import com.iformall.douyin.pay.DouYinPayHelper; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +@Data +public class CreateRefund { + + private String appId;//小程序 AppID + private String sercrect;//密钥 + private String salt;// + private String outOrderNo;//开发者侧的订单号, 同一小程序下不可重复 + private String outRefundNo;//商户分配退款号 + private String reason;//退款原因 + private Integer refundAmount;//退款金额 + private String cpExtra;//开发者自定义字段,回调原样回传 【非必填】 + private String notifyUrl;//商户自定义回调地址 【非必填】 + private String thirdpartyId;//第三方平台服务商 id,非服务商模式留空 【非必填】 + private Integer disableMsg;//是否屏蔽担保支付的推送消息,1-屏蔽 0-非屏蔽,接入 POI 必传 【非必填】 + private String msgPage;//担保支付消息跳转页 【非必填】 + private Integer allSettle;//是否为分账后退款,1-分账后退款;0-分账前退款。分账后退款会扣减可提现金额,请保证余额充足【非必填】 + + public Map toRequestMap() { + Map map = new HashMap(); + map.put("app_id", appId); + map.put("salt",salt); + map.put("out_order_no", outOrderNo); + map.put("out_refund_no", outRefundNo); + map.put("reason", reason); + map.put("refund_amount", refundAmount); + if(StringUtils.isNotBlank(cpExtra)){ + map.put("cp_extra", cpExtra); + } + if(StringUtils.isNotBlank(notifyUrl)){ + map.put("notify_url", notifyUrl); + } + if(StringUtils.isNotBlank(thirdpartyId)){ + map.put("thirdparty_id", thirdpartyId); + } + if(disableMsg != null){ + map.put("disable_msg", disableMsg); + } + if(StringUtils.isNotBlank(msgPage)){ + map.put("msg_page", msgPage); + } + if(allSettle != null){ + map.put("all_settle", allSettle); + } + + map.put("sign", DouYinPayHelper.getSign(map)); + map.remove("salt"); + return map; + } +} diff --git a/mallinkService/src/main/java/com/iformall/douyin/pay/preOrder/CreateRefundResult.java b/mallinkService/src/main/java/com/iformall/douyin/pay/preOrder/CreateRefundResult.java new file mode 100644 index 000000000..3b3dfea51 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/douyin/pay/preOrder/CreateRefundResult.java @@ -0,0 +1,12 @@ +package com.iformall.douyin.pay.preOrder; + +import lombok.Data; + +@Data +public class CreateRefundResult { + + private boolean success; + private String msg; + private String refundNo; + +} diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxMsgValidationcodeServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxMsgValidationcodeServiceImpl.java index fcc5ae62a..b5cc683eb 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxMsgValidationcodeServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxMsgValidationcodeServiceImpl.java @@ -140,7 +140,6 @@ public class WxMsgValidationcodeServiceImpl implements WxMsgValidationcodeServic @Override public ResultData hasvalidationcode(WxMsgValidationcode record) { - List wxmsgvalidationcodelist = wxMsgValidationcodeMapper.findList(record); Date currentdate = new Date(); wxmsgvalidationcodelist = wxmsgvalidationcodelist.stream().filter(validationcode -> diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java index 4aa0094a1..8d624923c 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java @@ -2267,11 +2267,6 @@ public class WxOrderServiceImpl implements WxOrderService { logger.error("couponOrder失败:" + e.getMessage(),e); throw new MallinkException(ErrorCode.COUPON_ORDER_SAVE_ERR.getCode(),"["+coupon.getTitle()+"]保存券订单错误."+e.getMessage()); } - try { - - } catch (Exception e) { - logger.error("同步订单失败:" + e.getMessage(),e); - } return record; } diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxRefundOrderServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxRefundOrderServiceImpl.java index 9a261c837..35b9c89e1 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxRefundOrderServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxRefundOrderServiceImpl.java @@ -22,6 +22,7 @@ import com.iformall.service.WxRefundOrderService; import com.iformall.service.helper.WxPayOrderServiceHelper; import com.iformall.service.order.OrderFactory; import com.iformall.service.pay.PayServiceFactory; +import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; import com.iformall.service.pay.service.refund.entity.RefundAdapterResult; import com.iformall.service.pay.service.refund.entity.RefundNotifyAdapterResult; import com.iformall.utils.BeanUtils; @@ -196,9 +197,13 @@ public class WxRefundOrderServiceImpl implements WxRefundOrderService { if (null == payAccount) { throw new MallinkException(ErrorCode.PAY_ORDER_QUERY_ERROR.getCode(), "payAccount为空[payId:"+appInfo.getPayId()+"]"); } - int status = WxPayOrderServiceHelper.wxOrderPayStatus(payOrder, appInfo, payAccount); - if (EnumPayStatus.PAY_STATUS_SUCCESS.getCode() != status) { - return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(),"该订单查询微信支付状态为未支付成功,无法退款。"); + try { + PayQueryAdapterResult queryResult = payServiceFactory.getPayAdapterService(payOrder.getPayVendor()).queryPayStatus(payOrder, appInfo, payAccount); + if(EnumPayStatus.PAY_STATUS_SUCCESS.getCode() != queryResult.getCode()){ + return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(),"该订单查询支付状态为未支付成功,无法退款。"); + } + } catch (Exception e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR); } final IdWorker idWorker = IdWorker.get(); @@ -213,6 +218,7 @@ public class WxRefundOrderServiceImpl implements WxRefundOrderService { rOrder.setOrderNumber(wxOrder.getOrderNumber()); // 退款订单填写支付订单orderNumber rOrder.setProductId(wxOrder.getProductId()); rOrder.setType(EnumOrderType.COUPON.getCode()); + rOrder.setPayVendor(wxOrder.getPayVendor()); rOrder.setCUserId(wxOrder.getCUserId()); if (payType == EnumPayType.PAY_B_REFUND) { rOrder.setDetail("["+bUserId+"]B端管理员操作退款"); //B端发起退款后存B端用户ID在此 @@ -264,17 +270,24 @@ public class WxRefundOrderServiceImpl implements WxRefundOrderService { } } - - WxRefundOrder record = new WxRefundOrder(); + record.updateTenantInfo(wxCouponOrder); record.setPayOrderNo(String.valueOf(payOrder.getId())); record.setOrderId(rOrder.getId()); + + // check 是否有退款订单 + List refundList = wxRefundOrderMapper.findList(record); + if (refundList.size() > 0) { + logger.error("退款订单已存在, 无法再提交退款申请"); + throw new MallinkException(ErrorCode.REFUND_ORDER_EXIST.getCode(), "退款订单已存在, 无法再提交退款申请"); + } + + // 创建退款订单 Long refundId = idWorker.nextId(); //String out_refund_id = String.valueOf(refundId); record.setId(refundId); - record.updateTenantInfo(wxCouponOrder); record.setCreateTime(currentDate); record.setUpdateTime(currentDate); // 微信内部订单号 @@ -297,13 +310,6 @@ public class WxRefundOrderServiceImpl implements WxRefundOrderService { throw new MallinkException(ErrorCode.DB_FAIL); } - // check 是否有退款订单 - List refundList = wxRefundOrderMapper.findList(record); - if (refundList.size() > 0) { - logger.error("退款订单已存在, 无法再提交退款申请"); - throw new MallinkException(ErrorCode.REFUND_ORDER_EXIST.getCode(), "退款订单已存在, 无法再提交退款申请"); - } - RefundAdapterResult refundResult = payServiceFactory.getRefundPayAdapterService(payOrder.getPayVendor()).refund(payAccount, appInfo, record, payOrder, payType); if (refundResult.isSuccess()) { record.setRefundOrderStatus(EnumRefundStatus.REFUND_REQ_SUCCESS.getCode()); diff --git a/mallinkService/src/main/java/com/iformall/service/pay/service/refund/douyin/TtRefundAdapterService.java b/mallinkService/src/main/java/com/iformall/service/pay/service/refund/douyin/TtRefundAdapterService.java new file mode 100644 index 000000000..047cf7218 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/service/pay/service/refund/douyin/TtRefundAdapterService.java @@ -0,0 +1,131 @@ +package com.iformall.service.pay.service.refund.douyin; + + +import com.iformall.common.ErrorCode; +import com.iformall.domain.po.WxAppinfo; +import com.iformall.domain.po.WxPayAccount; +import com.iformall.domain.po.WxPayOrder; +import com.iformall.domain.po.WxRefundOrder; +import com.iformall.douyin.pay.DouYinPayHelper; +import com.iformall.douyin.pay.orderQuery.QueryRefundResult; +import com.iformall.douyin.pay.preOrder.CreateRefund; +import com.iformall.douyin.pay.preOrder.CreateRefundResult; +import com.iformall.enums.EnumPayType; +import com.iformall.enums.EnumPayWay; +import com.iformall.enums.EnumRefundStatus; +import com.iformall.exception.MallinkException; +import com.iformall.mapper.WxAppinfoMapper; +import com.iformall.mapper.WxPayAccountMapper; +import com.iformall.mapper.WxPayOrderMapper; +import com.iformall.mapper.WxRefundOrderMapper; +import com.iformall.service.pay.service.refund.RefundPayAdapterService; +import com.iformall.service.pay.service.refund.entity.RefundAdapterResult; +import com.iformall.service.pay.service.refund.entity.RefundNotifyAdapterResult; +import com.iformall.utils.XmlUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +@Slf4j +@Service +public class TtRefundAdapterService implements RefundPayAdapterService{ + + @Override + public RefundAdapterResult refund(WxPayAccount payAccount,WxAppinfo appInfo,WxRefundOrder record,WxPayOrder payOrder,EnumPayType payType) { + CreateRefund createRefund = new CreateRefund(); + createRefund.setAppId(appInfo.getAppId()); + createRefund.setSalt(payAccount.getApiKey()); + createRefund.setOutOrderNo(payOrder.getPayOrderNo()); + createRefund.setOutRefundNo(String.valueOf(record.getId())); + if (payType == EnumPayType.PAY_B_REFUND) { + createRefund.setReason("B端商户退款"); + } else if (payType == EnumPayType.PAY_ADMIN_REFUND) { + createRefund.setReason("管理端商户退款"); + } else if (payType == EnumPayType.PAY_AUTO_REFUND) { + createRefund.setReason("超期自动退款"); + } else { + createRefund.setReason("用户自己退款"); + } + createRefund.setRefundAmount(record.getRefundFee()); + + CreateRefundResult refund = DouYinPayHelper.createRefund(createRefund); + if(refund.isSuccess()){ + return new RefundAdapterResult(true, EnumRefundStatus.REFUND_REQ_SUCCESS.getCode(), "退款订单申请成功", refund); + }else{ + return new RefundAdapterResult(false,EnumRefundStatus.REFUND_REQ_FAIL.getCode(),refund.getMsg(),refund); + } + } + + @Override + public RefundAdapterResult queryRefund(WxAppinfo appInfo,WxPayAccount payAccount, WxRefundOrder record) { + QueryRefundResult queryRefundResult = DouYinPayHelper.refundQuery(appInfo.getAppId(), payAccount.getApiKey(), String.valueOf(record.getId()), null); + if(queryRefundResult != null){ + if("SUCCESS".equals(queryRefundResult.getRefundStatus())){ + return new RefundAdapterResult(true,0,"退款",queryRefundResult); + }else{ + return new RefundAdapterResult(false,ErrorCode.REFUND_ORDER_ERROR.getCode(),"退款失败",queryRefundResult); + } + }else{ + throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR); + } + } + + @Autowired + WxAppinfoMapper wxAppinfoMapper; + @Autowired + WxPayAccountMapper wxPayAccountMapper; + @Autowired + WxPayOrderMapper wxPayOrderMapper; + @Autowired + WxRefundOrderMapper wxRefundOrderMapper; + + + private RefundNotifyAdapterResult notifyErrorResult(String msg) { + SortedMap resultMap = new TreeMap(); + resultMap.put("return_code", "FAIL"); + resultMap.put("return_msg", msg); + return new RefundNotifyAdapterResult(false,ErrorCode.REFUND_ORDER_ERROR.getCode(),msg,XmlUtil.getRequestXml(resultMap)); + } + + private RefundNotifyAdapterResult notifySuccessResult(String transactionId,String refundId,WxRefundOrder refundOrder) { + SortedMap resultMap = new TreeMap(); + resultMap.put("return_code", "SUCCESS"); + resultMap.put("return_msg", "OK"); + return new RefundNotifyAdapterResult(transactionId, refundId,refundOrder,XmlUtil.getRequestXml(resultMap)); + } + + + @Override + public RefundNotifyAdapterResult notify(Map paramMap, EnumPayWay payWay) { + String appId = paramMap.get("appid"); + WxAppinfo appinfo = wxAppinfoMapper.findByAppId(appId); + if (appinfo == null) { + log.error("未找到appid信息:" + appId); + throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND); + } + WxPayAccount payAccount = wxPayAccountMapper.selectById(appinfo.getPayId()); + if (payAccount == null) { + log.error("未找到mch_id信息:" + appId); + throw new MallinkException(ErrorCode.MCH_INFO_NOT_FOUND); + } + if (!"SUCCESS".equals(paramMap.get("status"))) { + log.warn("notify refund, wxpay status not success, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); + return notifyErrorResult("订单状态码非SUCCESS"); + } + String refundno = paramMap.get("cp_refundno"); + Long refundOrderId = Long.valueOf(refundno); + WxRefundOrder refundOrder = wxRefundOrderMapper.selectById(refundOrderId); + // 验证退款金额 + if (!paramMap.get("refund_amount").equals(refundOrder.getRefundFee().toString())) { + log.warn("notify refund, wxpay check refund_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); + return notifyErrorResult("退款总金额不一致"); + } + log.info("notify refund, wxpay checksign success, paramMap:{}, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); + return notifySuccessResult(refundOrder.getPayOrderNo(), paramMap.get("cp_refundno"), refundOrder); + } + +}