Ver Fonte

首信易提现回调

igl há 3 meses atrás
pai
commit
3955bab0c3

+ 6 - 2
vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/AssetClient.java

@@ -1,6 +1,7 @@
 package com.chelvc.cloud.vehicle.client;
 
 import com.chelvc.cloud.vehicle.client.dto.MerchantAssetDTO;
+import com.chelvc.cloud.vehicle.client.param.WithdrawNotifyParam;
 import com.chelvc.cloud.vehicle.client.param.WithdrawParam;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.cloud.openfeign.SpringQueryMap;
@@ -13,6 +14,9 @@ public interface AssetClient {
     @GetMapping("/asset/merchant")
     MerchantAssetDTO getMerchantAsset(@RequestParam("merchantId") Long merchantId);
 
-    @PutMapping(value = "/asset/withdraw", consumes = MediaType.APPLICATION_JSON_VALUE)
-    void withdraw(@SpringQueryMap WithdrawParam param);
+    @PutMapping(value = "/asset/withdraw")
+    void withdraw(@RequestBody WithdrawParam param);
+
+    @PostMapping(value = "/asset/withdraw/notify")
+    void withdrawNotify(@RequestBody WithdrawNotifyParam param);
 }

+ 67 - 0
vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/param/WithdrawNotifyParam.java

@@ -0,0 +1,67 @@
+package com.chelvc.cloud.vehicle.client.param;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 提现回调参数
+ */
+@Data
+public class WithdrawNotifyParam implements Serializable {
+
+    private static final long serialVersionUID = 3682560818657891605L;
+
+    /**
+     * 商户编号
+     */
+    private String merchantId;
+    /**
+     * 提现流水号
+     */
+    private String orderId;
+    /**
+     * 订单编号
+     */
+    private String requestId;
+    /**
+     * 服务商编号
+     */
+    private String partnerId;
+    /**
+     * 提现金额:分
+     */
+    private String withdrawAmount;
+    /**
+     * 提现状态:SUCCESS 成功;FAIL 失败
+     */
+    private String withdrawStatus;
+    /**
+     * 错误信息
+     */
+    private String errorMessage;
+    /**
+     * 到账金额
+     */
+    private String receivedAmount;
+    /**
+     * 账户名称
+     */
+    private String accountName;
+    /**
+     * 账户号
+     */
+    private String bankCardNumberDec;
+    /**
+     * 开户行
+     */
+    private String bankCode;
+    /**
+     * 账户类型:PUBLIC 对公;PRIVATE 对私
+     */
+    private String accountType;
+    /**
+     * 参数签名
+     */
+    private String hmac;
+}

+ 11 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/controller/AssetController.java

@@ -1,6 +1,7 @@
 package com.chelvc.cloud.vehicle.server.controller;
 
 import com.chelvc.cloud.vehicle.client.dto.MerchantAssetDTO;
+import com.chelvc.cloud.vehicle.client.param.WithdrawNotifyParam;
 import com.chelvc.cloud.vehicle.client.param.WithdrawParam;
 import com.chelvc.cloud.vehicle.server.service.AssetService;
 import com.chelvc.framework.base.context.SessionContextHolder;
@@ -28,4 +29,14 @@ public class AssetController {
     public void withdraw(@RequestBody WithdrawParam param) {
         this.assetService.withdraw(param);
     }
+
+    /**
+     * 提现回调接口
+     *
+     * @param param
+     */
+    @PostMapping("/asset/withdraw/notify")
+    public void withdrawNotify(@RequestBody WithdrawNotifyParam param) {
+        this.assetService.withdrawNotify(param);
+    }
 }

+ 10 - 1
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/dao/AssetMapper.java

@@ -12,5 +12,14 @@ import java.time.LocalDateTime;
 public interface AssetMapper extends BaseMapper<Asset> {
 
     @Update("update asset set frozen = frozen - #{payAmount}, total = total + #{platformRealityAmount}, update_time = #{now} where user_id = #{userId} and type = 0")
-    void updatePlatformAsset(BigDecimal platformRealityAmount, BigDecimal payAmount, LocalDateTime now, Long userId);
+    int updatePlatformAsset(BigDecimal platformRealityAmount, BigDecimal payAmount, LocalDateTime now, Long userId);
+
+    @Update("update asset set total = total - #{amount}, frozen = frozen + #{amount}, update_time = #{now} where user_id = #{userId} and type = #{type}")
+    int updateFrozenAmount(BigDecimal amount, LocalDateTime now, Long userId, Integer type);
+
+    @Update("update asset set total = total + #{amount}, frozen = frozen - #{amount}, update_time = #{now} where user_id = #{userId} and type = #{type}")
+    int backFrozen(BigDecimal amount, Long userId, Integer type, LocalDateTime now);
+
+    @Update("update asset set frozen = frozen - #{amount}, update_time = #{now} where user_id = #{userId} and type = #{type}")
+    int deductFrozen(BigDecimal amount, Long userId, Integer type, LocalDateTime now);
 }

+ 3 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/entity/OmsWithdraw.java

@@ -34,6 +34,9 @@ public class OmsWithdraw extends ModifyEntity<Long>
     /** 用户id */
     private Long userId;
 
+    /** 外部订单号 */
+    private String outOrderId;
+
     /** 类型:0-平台; 1-用户;2-商家 */
     private Integer type;
 

+ 2 - 1
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/handle/TradeHandle.java

@@ -13,7 +13,7 @@ import java.util.Map;
 @Slf4j
 public class TradeHandle {
 
-    public static void handle(String jsonData, String apiUrl, String merchantId, String partnerId){
+    public static JSONObject handle(String jsonData, String apiUrl, String merchantId, String partnerId){
         JSONObject rawDataJson = JSONObject.parseObject(jsonData);
         log.info("接口地址:{}", apiUrl);
         log.info("请求报文json: {}: ", rawDataJson.toJSONString());
@@ -21,6 +21,7 @@ public class TradeHandle {
         MyExecuter myExecuter = new MyExecuter();
         JSONObject rawRespJsonData = myExecuter.ApiRequest(jsonSupport, apiUrl);
         log.info("应答报文json: {}: ", rawRespJsonData.toJSONString());
+        return rawRespJsonData;
     }
 
     public static void main(String[] args) {

+ 3 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/AssetService.java

@@ -1,6 +1,7 @@
 package com.chelvc.cloud.vehicle.server.service;
 
 import com.chelvc.cloud.vehicle.client.dto.MerchantAssetDTO;
+import com.chelvc.cloud.vehicle.client.param.WithdrawNotifyParam;
 import com.chelvc.cloud.vehicle.client.param.WithdrawParam;
 import com.chelvc.cloud.vehicle.server.entity.Asset;
 
@@ -31,4 +32,6 @@ public interface AssetService {
     MerchantAssetDTO getMerchantAsset(Long merchantId);
 
     void withdraw(WithdrawParam param);
+
+    void withdrawNotify(WithdrawNotifyParam param);
 }

+ 8 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/OmsWithdrawService.java

@@ -1,7 +1,15 @@
 package com.chelvc.cloud.vehicle.server.service;
 
+import com.chelvc.cloud.vehicle.server.entity.OmsWithdraw;
+
 import java.math.BigDecimal;
 
 public interface OmsWithdrawService {
     Long createWithdraw(Long userId, Integer type, BigDecimal amount, Integer channel);
+
+    int updateStatusById(Long id, Integer status);
+
+    OmsWithdraw queryById(Long id);
+
+    int updateByNotify(Long id, String outOrderId, Integer status);
 }

+ 67 - 12
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/AssetServiceImpl.java

@@ -1,27 +1,35 @@
 package com.chelvc.cloud.vehicle.server.service.impl;
 
+import com.alibaba.fastjson.JSONObject;
 import com.alibaba.nacos.shaded.com.google.gson.Gson;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.chelvc.cloud.vehicle.client.constant.PlatformConstant;
+import com.chelvc.cloud.vehicle.client.constant.ReserveStatus;
 import com.chelvc.cloud.vehicle.client.constant.TradeConstant;
 import com.chelvc.cloud.vehicle.client.dto.*;
+import com.chelvc.cloud.vehicle.client.param.WithdrawNotifyParam;
 import com.chelvc.cloud.vehicle.client.param.WithdrawParam;
 import com.chelvc.cloud.vehicle.server.dao.AssetMapper;
 import com.chelvc.cloud.vehicle.server.entity.Asset;
 import com.chelvc.cloud.vehicle.server.entity.MerchantRelation;
+import com.chelvc.cloud.vehicle.server.entity.OmsWithdraw;
 import com.chelvc.cloud.vehicle.server.handle.TradeHandle;
 import com.chelvc.cloud.vehicle.server.service.*;
 import com.chelvc.framework.base.context.SessionContextHolder;
 import com.chelvc.framework.common.exception.ResourceUnavailableException;
+import com.chelvc.framework.common.function.Executor;
+import com.chelvc.framework.database.context.DatabaseContextHolder;
 import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
+import java.util.Date;
 import java.util.HashMap;
 
 @Service
@@ -146,18 +154,65 @@ public class AssetServiceImpl extends ServiceImpl<AssetMapper, Asset> implements
         if(merchantRelation == null){
             throw new ResourceUnavailableException("请联系管理员开通商户号");
         }
-        //生成提现订单
-        Long withdrawId = withdrawService.createWithdraw(userId, type, amount, 1);
+        Long finalUserId = userId;
+        DatabaseContextHolder.transactional((Executor) () -> {
+            //生成提现订单
+            Long withdrawId = withdrawService.createWithdraw(finalUserId, type, amount, 1);
+            String sxyMerchantId = merchantRelation.getSxyMerchantId();
+            //生成提现参数
+            HashMap<String, Object> map = new HashMap<>();
+            map.put("merchantId", sxyMerchantId);
+            map.put("requestId", withdrawId);
+            map.put("withdrawAmount", amount.multiply(new BigDecimal("100")));
+            map.put("notifyUrl", TradeConstant.WITHDRAW_NOTIFY_URL);
+            map.put("remark", "");
+            Gson gson = new Gson();
+            JSONObject json = TradeHandle.handle(gson.toJson(map),
+                    TradeConstant.WITHDRAW_URL, sxyMerchantId, TradeConstant.PARTNER_ID);
+            String status = json.getString("status");
+            if(!"SUCCESS".equals(status)){
+                //提现申请失败
+                withdrawService.updateStatusById(withdrawId, 2);
+                return;
+            }
+            //冻结金额
+            int i = baseMapper.updateFrozenAmount(amount, LocalDateTime.now(), finalUserId, type);
+            if(i != 1){
+                withdrawService.updateStatusById(withdrawId, 2);
+                throw new ResourceUnavailableException("提现申请失败");
+            }
+        });
+    }
 
-        String sxyMerchantId = merchantRelation.getSxyMerchantId();
-        //生成提现参数
-        HashMap<String, Object> map = new HashMap<>();
-        map.put("merchantId", sxyMerchantId);
-        map.put("requestId", withdrawId);
-        map.put("withdrawAmount", amount.multiply(new BigDecimal("100")));
-        map.put("notifyUrl", TradeConstant.WITHDRAW_NOTIFY_URL);
-        map.put("remark", "");
-        Gson gson = new Gson();
-        TradeHandle.handle(gson.toJson(map), TradeConstant.WITHDRAW_URL, sxyMerchantId, TradeConstant.PARTNER_ID);
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void withdrawNotify(WithdrawNotifyParam param) {
+        String requestId = param.getRequestId();
+        Long id = Long.parseLong(requestId);
+        OmsWithdraw withdraw = withdrawService.queryById(id);
+        if(withdraw == null){
+            return;
+        }
+        String withdrawAmount = param.getWithdrawAmount();
+        BigDecimal amount = withdraw.getAmount();
+        if(amount.compareTo(new BigDecimal(withdrawAmount)) != 0){
+            //金额不一致
+            return;
+        }
+        String withdrawStatus = param.getWithdrawStatus();
+        int status = 2;
+        if("SUCCESS".equals(withdrawStatus)){
+            status = 1;
+        }
+        //更新提现订单状态和外部订单号
+        int i = withdrawService.updateByNotify(id, param.getOrderId(), status);
+        if(i == 1){
+            if(status == 2){
+                //失败解冻金额
+                baseMapper.backFrozen(amount, withdraw.getUserId(), withdraw.getType(), LocalDateTime.now());
+            } else {
+                baseMapper.deductFrozen(amount, withdraw.getUserId(),withdraw.getType(), LocalDateTime.now());
+            }
+        }
     }
 }

+ 25 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/OmsWithdrawServiceImpl.java

@@ -1,5 +1,7 @@
 package com.chelvc.cloud.vehicle.server.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.chelvc.cloud.vehicle.server.dao.OmsWithdrawMapper;
 import com.chelvc.cloud.vehicle.server.entity.OmsWithdraw;
@@ -33,4 +35,27 @@ public class OmsWithdrawServiceImpl extends ServiceImpl<OmsWithdrawMapper,
         }
         return withdraw.getId();
     }
+
+    @Override
+    public int updateStatusById(Long id, Integer status) {
+        UpdateWrapper<OmsWithdraw> update = Wrappers.update();
+        update.set("status", status);
+        update.eq("id", id);
+        return baseMapper.update(null, update);
+    }
+
+    @Override
+    public OmsWithdraw queryById(Long id) {
+        return baseMapper.selectById(id);
+    }
+
+    @Override
+    public int updateByNotify(Long id, String outOrderId, Integer status) {
+        UpdateWrapper<OmsWithdraw> update = Wrappers.update();
+        update.set("status", status);
+        update.set("out_order_id", outOrderId);
+        update.set("update_time", new Date());
+        update.eq("id", id);
+        return baseMapper.update(null, update);
+    }
 }