| @@ -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(), "验证码未填写"); | |||
| } | |||
| @@ -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<String,Object> createOrder( HttpServletRequest request){ | |||
| logger.debug("[" + getIpAddr() + "] TtOrderCallbackController::createOrder"); | |||
| Map<String,Object> resultMap = new HashMap<>(); | |||
| String body = ((BodyReaderHttpServletRequestWrapper) request).getBody(); | |||
| logger.info("抖音支付通知-----body{}"+body); | |||
| try { | |||
| Map<String, Object> 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<String, Object> pMap = JSONObject.parseObject(msg, Map.class); | |||
| String appid = (String) pMap.get("appid"); | |||
| WxAppinfo appinfo = appinfoService.getByAppId(appid); | |||
| WxPayAccount payAccount = payAccountService.getById(appinfo.getPayId()); | |||
| Map<String,Object> 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<String,String> 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; | |||
| } | |||
| } | |||
| } | |||
| @@ -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) { | |||
| @@ -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 | |||
| } | |||
| @@ -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; | |||
| } | |||
| } | |||
| @@ -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; | |||
| } | |||
| @@ -140,7 +140,6 @@ public class WxMsgValidationcodeServiceImpl implements WxMsgValidationcodeServic | |||
| @Override | |||
| public ResultData hasvalidationcode(WxMsgValidationcode record) { | |||
| List<WxMsgValidationcode> wxmsgvalidationcodelist = wxMsgValidationcodeMapper.findList(record); | |||
| Date currentdate = new Date(); | |||
| wxmsgvalidationcodelist = wxmsgvalidationcodelist.stream().filter(validationcode -> | |||
| @@ -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; | |||
| } | |||
| @@ -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<WxRefundOrder> 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<WxRefundOrder> 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()); | |||
| @@ -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<String, String> 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); | |||
| } | |||
| } | |||