Jelajahi Sumber

会员退款

chao 3 tahun lalu
induk
melakukan
35f21abdeb

+ 21 - 2
src/main/java/com/caimei365/order/controller/PayNonOrderApi.java

@@ -157,7 +157,7 @@ public class PayNonOrderApi {
      *               userType      用户类型(银联支付使用)企业:ENTERPRISE,个人:USER
      * }
      */
-    @ApiOperation("升级超级会员-银联线上支付(旧:/PayOrder/secondHandPay[UNIONPAY])")
+    @ApiOperation("升级超级会员-银联线上支付")
     @PostMapping("/vip/union")
     public ResponseJson<JSONObject> paySuperVipByUnionPay(PayVipDto payVipDto, @RequestHeader HttpHeaders headers){
         if (null == payVipDto.getVipRecordId()) {
@@ -178,7 +178,7 @@ public class PayNonOrderApi {
     /**
      * 升级超级会员-支付回调
      */
-    @ApiOperation("升级超级会员-支付回调(旧:/PayOrder/secondHandPayCallBack)")
+    @ApiOperation("升级超级会员-支付回调")
     @GetMapping("/vip/callback")
     public String paymentSuperVipCallback(String data) throws NoSuchAlgorithmException, InvalidKeySpecException {
         if (StringUtils.isBlank(data)) {
@@ -186,4 +186,23 @@ public class PayNonOrderApi {
         }
         return payNonOrderService.paymentSuperVipCallback(data);
     }
+
+    /**
+     * 升级超级会员-线上退款
+     * @param payVipDto {
+     *               vipRecordId   会员购买记录Id
+     *               code          退款口令
+     * }
+     */
+    @ApiOperation("升级超级会员-线上退款)")
+    @PostMapping("/vip/online/refund")
+    public ResponseJson<JSONObject> superVipOnlineRefund(PayVipDto payVipDto) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        if (null == payVipDto.getVipRecordId()) {
+            return ResponseJson.error("会员购买记录Id不能为空!", null);
+        }
+        if (StringUtils.isEmpty(payVipDto.getCode()) || !"SVIP".equals(payVipDto.getCode())) {
+            return ResponseJson.error("退款口令code不正确!", null);
+        }
+        return payNonOrderService.superVipOnlineRefund(payVipDto);
+    }
 }

+ 5 - 0
src/main/java/com/caimei365/order/mapper/OrderCommonMapper.java

@@ -44,6 +44,11 @@ public interface OrderCommonMapper {
      * @param orderId 订单Id
      */
     List<DiscernReceiptVo> getDiscernReceipt(Integer orderId, String shopOrderId);
+    /**
+     * 超级会员支付记录
+     * @param vipRecordId 购买记录Id
+     */
+    DiscernReceiptVo getVipDiscernReceipt(Integer vipRecordId);
     /**
      * 获取返佣款
      * @param shopOrderId 子订单Id

+ 4 - 0
src/main/java/com/caimei365/order/model/vo/DiscernReceiptVo.java

@@ -69,4 +69,8 @@ public class DiscernReceiptVo implements Serializable {
      * 单次收款金额
      */
     private Double associateAmount;
+    /**
+     * 米花科技平台唯一流水号
+     */
+    private String mbOrderId;
 }

+ 8 - 0
src/main/java/com/caimei365/order/service/PayNonOrderService.java

@@ -81,4 +81,12 @@ public interface PayNonOrderService {
      * 升级超级会员-支付回调
      */
     String paymentSuperVipCallback(String data) throws NoSuchAlgorithmException, InvalidKeySpecException;
+    /**
+     * 升级超级会员-线上退款
+     * @param payVipDto {
+     *               vipRecordId   会员购买记录Id
+     *               code          退款口令
+     * }
+     */
+    ResponseJson<JSONObject> superVipOnlineRefund(PayVipDto payVipDto) throws NoSuchAlgorithmException, InvalidKeySpecException;
 }

+ 64 - 11
src/main/java/com/caimei365/order/service/impl/PayNonOrderServiceImpl.java

@@ -3,6 +3,7 @@ package com.caimei365.order.service.impl;
 import com.alibaba.fastjson.JSONObject;
 import com.caimei365.order.components.WeChatService;
 import com.caimei365.order.mapper.BaseMapper;
+import com.caimei365.order.mapper.OrderCommonMapper;
 import com.caimei365.order.mapper.PayOrderMapper;
 import com.caimei365.order.model.ResponseJson;
 import com.caimei365.order.model.bo.PayParamBo;
@@ -13,6 +14,7 @@ import com.caimei365.order.model.po.DiscernReceiptPo;
 import com.caimei365.order.model.po.OrderReceiptRelationPo;
 import com.caimei365.order.model.po.SplitAccountPo;
 import com.caimei365.order.model.po.UserVipPo;
+import com.caimei365.order.model.vo.DiscernReceiptVo;
 import com.caimei365.order.model.vo.OrderPayLinkVo;
 import com.caimei365.order.service.PayNonOrderService;
 import com.caimei365.order.utils.MathUtil;
@@ -26,7 +28,6 @@ import org.springframework.http.HttpHeaders;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
-import java.math.BigDecimal;
 import java.security.NoSuchAlgorithmException;
 import java.security.spec.InvalidKeySpecException;
 import java.text.SimpleDateFormat;
@@ -46,6 +47,8 @@ public class PayNonOrderServiceImpl implements PayNonOrderService {
     @Resource
     private PayOrderMapper payOrderMapper;
     @Resource
+    private OrderCommonMapper orderCommonMapper;
+    @Resource
     private WeChatService weChatService;
     @Value("${pay.second-notify-url}")
     private String secondHandUrl;
@@ -540,14 +543,22 @@ public class PayNonOrderServiceImpl implements PayNonOrderService {
         // 附加数据,支付时若有传输则原样返回(vipId,payType,userId,recordId),下单时为空,则不返回该数据
         String attach = json.getString("attach");
         String[] split = attach.split(",");
-        // 会员套餐Id
-        Integer vipId = Integer.valueOf(split[0]);
-        // 用户Id
-        Integer userId = Integer.valueOf(split[1]);
-        // 购买历史记录Id
-        Integer recordId = Integer.valueOf(split[2]);
-        // 支付方式
-        String payType = split[3];
+        int vipId = 0;
+        int userId = 0;
+        int recordId = 0;
+        int payType = 0;
+        try {
+            // 会员套餐Id
+            vipId = Integer.parseInt(split[0]);
+            // 用户Id
+            userId = Integer.parseInt(split[1]);
+            // 购买历史记录Id
+            recordId = Integer.valueOf(split[2]);
+            // 支付方式
+            payType = Integer.valueOf(split[3]);
+        } catch (NumberFormatException e) {
+            log.info("【升级超级会员异步回调】>>>>>>>>>>>>>>获取回调参数解析失败!");
+        }
         //超级会员数据库修改
         UserVipPo userVip = new UserVipPo();
         UserVipPo dbUserVip = payOrderMapper.getUserVipInfo(userId);
@@ -580,12 +591,12 @@ public class PayNonOrderServiceImpl implements PayNonOrderService {
         record.setBeginTime(beginTime);
         record.setEndTime(cal.getTime());
         record.setPayWay(1);
-        record.setPayType(Integer.valueOf(payType));
+        record.setPayType(payType);
         record.setPayTime(new Date());
         payOrderMapper.updateVipPackageRecord(record);
         // 修改支付链接状态
         OrderPayLinkVo orderPayLink = payOrderMapper.getVipPayLink(recordId, amount);
-        if (null != orderPayLink && ("12".equals(payType) || "17".equals(payType))) {
+        if (null != orderPayLink && (12 == payType || 17 == payType)) {
             orderPayLink.setPayStatus(1);
             payOrderMapper.updateOrderPayLinkStatus(orderPayLink);
         }
@@ -626,4 +637,46 @@ public class PayNonOrderServiceImpl implements PayNonOrderService {
         payOrderMapper.updateSplitAccountByPay(mbOrderId);
         return "SUCCESS";
     }
+
+    /**
+     * 升级超级会员-线上退款
+     *
+     * @param payVipDto {
+     *                  vipRecordId   会员购买记录Id
+     *                  code          退款口令
+     *                  }
+     */
+    @Override
+    public ResponseJson<JSONObject> superVipOnlineRefund(PayVipDto payVipDto) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        // 超级会员支付记录
+        DiscernReceiptVo discernReceipt = orderCommonMapper.getVipDiscernReceipt(payVipDto.getVipRecordId());
+        JSONObject json = new JSONObject();
+        json.put("merAccount", PayUtil.merAccount);
+        // 当前时间戳
+        long time = System.currentTimeMillis() / 1000;
+        json.put("time", time);
+        //商户退款流水号,由商户自行生成,必须唯一
+        String merchantRefundNo = payVipDto.getCode() + payVipDto.getVipRecordId() + "##" + discernReceipt.getId();
+        json.put("merchantRefundNo", merchantRefundNo);
+        //退款金额,单位分,必须大于0
+        double refundAmt = MathUtil.mul(discernReceipt.getAssociateAmount(), 100).doubleValue();
+        json.put("refundAmt", refundAmt);
+        //退款原因
+        String refundCause = "用户主动退款";
+        json.put("refundCause", refundCause);
+        //平台交易订单号
+        json.put("mbOrderId", discernReceipt.getMbOrderId());
+        String sign = PayUtil.getPaySign(json, PayUtil.merKey);
+        json.put("sign", sign);
+        String data = PayUtil.privateKeyEncrypt(json, PayUtil.merKey);
+        JSONObject result = PayUtil.httpPost("https://platform.mhxxkj.com/paygateway/mbrefund/orderRefund/v1", PayUtil.merAccount, data);
+        String code = result.getString("code");
+        if (!"000000".equals(code)) {
+            String msg = result.getString("msg");
+            log.info("【线上退款】失败>>>>>>>msg:" + msg);
+            return ResponseJson.error(result);
+        }
+        log.info("【线上退款】成功>>>>>>>vipRecordId:" + payVipDto.getVipRecordId());
+        return ResponseJson.success(result);
+    }
 }

+ 9 - 1
src/main/java/com/caimei365/order/utils/PayUtil.java

@@ -100,7 +100,15 @@ public class PayUtil {
         String responseBody	= HttpClient4Utils.sendHttpRequest(url, paramMap, "UTF-8", false);
         return JSON.parseObject(responseBody);
     }
-
+    //post请求
+    public static JSONObject httpPost(String url, String merAccount, String data) {
+        //请求参数为如下:merAccount、data
+        Map<String, String> paramMap	= new HashMap<String, String>();
+        paramMap.put("data", data);
+        paramMap.put("merAccount", merAccount);
+        String responseBody	= HttpClient4Utils.sendHttpRequest(url, paramMap, "UTF-8", true);
+        return JSON.parseObject(responseBody);
+    }
     /**
      * 公钥解密
      */

+ 19 - 0
src/main/resources/mapper/OrderCommonMapper.xml

@@ -132,6 +132,25 @@
         AND cror.delFlag = '0' AND cdr.delFlag = '0' AND cdr.receiptStatus = '3' AND cdr.payType != '16' AND cdr.receiptStatus IN(2,3)
         ORDER BY cdr.receiptDate DESC
     </select>
+    <select id="getVipDiscernReceipt" resultType="com.caimei365.order.model.vo.DiscernReceiptVo">
+        SELECT
+            cdr.id,
+            cdr.payWay,
+            cdr.payType,
+            cdr.receiptType,
+            cdr.receiptStatus,
+            cdr.receiptAmount,
+            cdr.confirmType,
+            cdr.receiptDate,
+            cdr.confirmDate,
+            cdr.reviewDate,
+            cdr.updateDate,
+            cdr.delFlag,
+            cror.mbOrderId,
+            cror.associateAmount
+        FROM cm_receipt_order_relation cror LEFT JOIN cm_discern_receipt cdr ON cror.receiptID = cdr.id
+        WHERE vipRecordId = #{vipRecordId} AND cror.relationType = '3' AND cror.delFlag = '0' AND cdr.delFlag = '0'
+    </select>
     <select id="getRebateAmountByShopOrder" resultType="java.lang.Double">
         SELECT
         receiptAmount