igl 5 месяцев назад
Родитель
Сommit
7eddb2041e
32 измененных файлов с 707 добавлено и 15 удалено
  1. 36 0
      vehicle-client/pom.xml
  2. 7 3
      vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/AssetClient.java
  3. 10 0
      vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/constant/TradeConstant.java
  4. 31 0
      vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/param/WithdrawParam.java
  5. 95 0
      vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/util/FastJsonUtils.java
  6. 60 0
      vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/util/JsonBuilder.java
  7. 49 0
      vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/util/MyExecuter.java
  8. 6 0
      vehicle-server/pom.xml
  9. 13 4
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/controller/AssetController.java
  10. 2 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/dao/MerchantMapper.java
  11. 11 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/dao/MerchantRelationMapper.java
  12. 10 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/dao/OmsWithdrawMapper.java
  13. 40 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/entity/MerchantRelation.java
  14. 66 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/entity/OmsWithdraw.java
  15. 29 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/handle/CustomConfig.java
  16. 53 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/handle/TradeHandle.java
  17. 3 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/AssetService.java
  18. 7 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/MerchantRelationService.java
  19. 2 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/MerchantService.java
  20. 7 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/OmsWithdrawService.java
  21. 54 7
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/AssetServiceImpl.java
  22. 26 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/MerchantRelationServiceImpl.java
  23. 5 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/MerchantServiceImpl.java
  24. 36 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/OmsWithdrawServiceImpl.java
  25. 15 0
      vehicle-server/src/main/resources/5upay-config.properties
  26. 3 1
      vehicle-server/src/main/resources/mapper/MerchantMapper.xml
  27. 3 0
      vehicle-server/src/main/webapp/META-INF/MANIFEST.MF
  28. BIN
      vehicle-server/src/main/webapp/cfca/client.pfx
  29. BIN
      vehicle-server/src/main/webapp/cfca/server.cer
  30. 15 0
      vehicle-server/src/main/webapp/cfca/smclinet.sm2
  31. BIN
      vehicle-server/src/main/webapp/cfca/smserver.cer
  32. 13 0
      vehicle-server/src/main/webapp/cfca/璇佷功鏂囦欢璇存槑.txt

+ 36 - 0
vehicle-client/pom.xml

@@ -36,5 +36,41 @@
             <artifactId>framework-wechat</artifactId>
             <version>${framework-wechat.version}</version>
         </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.8.26</version>
+        </dependency>
+        <dependency>
+            <groupId>com.upay.sdk</groupId>
+            <artifactId>upay-sdk-core</artifactId>
+            <version>2.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.upay.sdk</groupId>
+            <artifactId>upay-sdk-international</artifactId>
+            <version>2.0.0</version>
+        </dependency>
+        <!-- 加解密相关jar包 -->
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+            <version>1.69</version>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bctls-jdk15on</artifactId>
+            <version>1.69</version>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcutil-jdk15on</artifactId>
+            <version>1.69</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.83</version>
+        </dependency>
     </dependencies>
 </project>

+ 7 - 3
vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/AssetClient.java

@@ -1,14 +1,18 @@
 package com.chelvc.cloud.vehicle.client;
 
 import com.chelvc.cloud.vehicle.client.dto.MerchantAssetDTO;
+import com.chelvc.cloud.vehicle.client.param.WithdrawParam;
 import org.springframework.cloud.openfeign.FeignClient;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.cloud.openfeign.SpringQueryMap;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
 
 @FeignClient("vehicle")
 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);
 }

+ 10 - 0
vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/constant/TradeConstant.java

@@ -0,0 +1,10 @@
+package com.chelvc.cloud.vehicle.client.constant;
+
+public interface TradeConstant {
+
+    static final String PARTNER_ID = "893951545";
+
+    static final String WITHDRAW_URL = "https://apis.5upay.com/wallet/withdraw";
+
+    static final String WITHDRAW_NOTIFY_URL = "https://demo.5upay.com/sdk/onlinepay/notify";
+}

+ 31 - 0
vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/param/WithdrawParam.java

@@ -0,0 +1,31 @@
+package com.chelvc.cloud.vehicle.client.param;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WithdrawParam implements Serializable {
+
+    /**
+     * 类型:1-用户;2-商家
+     */
+    private Integer type;
+
+    /**
+     * 金额
+     */
+    private BigDecimal amount;
+
+    /**
+     * 商家id (用户提现不用传)
+     */
+    private Long merchantId;
+}

+ 95 - 0
vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/util/FastJsonUtils.java

@@ -0,0 +1,95 @@
+package com.chelvc.cloud.vehicle.client.util;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.upay.sdk.Constants;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+public abstract class FastJsonUtils {
+    static final Logger LOGGER = LoggerFactory.getLogger(FastJsonUtils.class);
+
+    public static JSONObject convert(InputStream inputStream) {
+        byte[] buffer = new byte[1024];
+        int len = 0;
+        try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+            while ((len = inputStream.read(buffer, 0, buffer.length)) != -1) {
+                out.write(buffer, 0, len);
+            }
+            byte[] bytes = out.toByteArray();
+            String jsonStr = new String(bytes, Constants.CHARSET);
+            JSONObject jsonObject = JSONObject.parseObject(jsonStr);
+            return jsonObject;
+        } catch (IOException e) {
+            LOGGER.info("", e);
+        }
+        return null;
+    }
+
+    /**
+     * 对 JSON 对象中的数据按键名 a-z 排序,并递归处理嵌套的 JSON 数据,最终拼接键值
+     *
+     * @param json         需要处理的 JSON 对象
+     * @param excludeField 排序排队的字段
+     * @return hmacSourceResult 通过入参返回排序后的拼接字符串
+     */
+
+    public static void generateHmacSource(JSONObject json, String[] excludeField, StringBuilder hmacSourceResult) {
+        // 如果 excludeField 为 null,则初始化为空数组
+        if (excludeField == null) {
+            excludeField = new String[0];
+        }
+
+        Set<String> keys = json.keySet();
+        List<String> list = new ArrayList<String>(keys);
+
+        Collections.sort(list);
+        for (String key : list) {
+            boolean exclude = false;
+            for (String field : excludeField) {
+                if (key.equals(field)) {
+                    exclude = true;
+                    break;
+                }
+            }
+            if (exclude) {
+                continue;
+            }
+            Object obj = json.get(key);
+            if (obj == null) {
+                LOGGER.warn("value is null for key:[{}],json:[{}]", key, json.toJSONString());
+                continue;
+            }
+            if (obj instanceof JSONObject) {
+                //如果值为对像时,递归调用
+                generateHmacSource((JSONObject) obj, excludeField, hmacSourceResult);
+            } else if (obj instanceof JSONArray) {
+                // 如果值是 JSONArray,处理数组中的每个元素
+                JSONArray array = (JSONArray) obj;
+                for (Object element : array) {
+                    if (element instanceof JSONObject) {
+                        // 如果元素是 JSONObject,递归调用
+                        generateHmacSource((JSONObject) element, excludeField, hmacSourceResult);
+                    } else if (StringUtils.isNotBlank(element.toString())) {
+                        // 如果是普通值,直接拼接到结果中
+                        hmacSourceResult.append(element.toString()).append("#");
+                    }
+                }
+            } else {
+                if (StringUtils.isNotBlank(obj.toString())) {
+                    hmacSourceResult.append(obj).append("#");
+                }
+            }
+        }
+    }
+
+}

+ 60 - 0
vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/util/JsonBuilder.java

@@ -0,0 +1,60 @@
+package com.chelvc.cloud.vehicle.client.util;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.upay.sdk.Constants;
+import com.upay.sdk.core.CipherWrapper;
+import com.upay.sdk.core.Environment;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+@Slf4j
+public class JsonBuilder {
+
+    String partnerId = "";
+
+    public String getMerchantId() {
+        return merchantId;
+    }
+
+    String merchantId = "";
+
+    public String getPartnerId() {
+        return partnerId;
+    }
+
+    public JSONObject getRawDataJson() {
+        return rawDataJson;
+    }
+
+    JSONObject rawDataJson = null;
+
+
+    public JsonBuilder(String merchantId, String partnerId, JSONObject rawDataJson) {
+        this.merchantId = merchantId;
+        this.partnerId = partnerId;
+        this.rawDataJson = rawDataJson;
+    }
+
+
+    /**
+     * 构建请求参数 签名+加密
+     */
+    public JSONObject buildRequestParam() {
+        JSONObject json = rawDataJson;
+        //生成签名数据 此处不会对数据进行散列运算 会在加密时对数据进行处理
+
+        StringBuilder hmacSourceResult = new StringBuilder();
+        FastJsonUtils.generateHmacSource(json, null, hmacSourceResult);
+
+
+        json.put(Constants.HMAC, hmacSourceResult.toString().getBytes(Environment.DEFAULT_CHARSET));
+
+        if (StringUtils.isNotBlank(partnerId)) {
+            return CipherWrapper.bothEncryptWrap(merchantId, partnerId, json);
+        }
+        return CipherWrapper.bothEncryptWrap(merchantId, json);
+    }
+
+
+}

+ 49 - 0
vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/util/MyExecuter.java

@@ -0,0 +1,49 @@
+package com.chelvc.cloud.vehicle.client.util;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.parser.Feature;
+import com.upay.sdk.Constants;
+import com.upay.sdk.HttpClientUtils;
+import com.upay.sdk.core.CipherWrapper;
+import com.upay.sdk.exception.UnknownException;
+import com.upay.sdk.executer.Executer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MyExecuter extends Executer {
+    static final Logger LOGGER = LoggerFactory.getLogger(MyExecuter.class);
+
+    public JSONObject ApiRequest(JsonBuilder jsonBuilder, String apiUrl) {
+        try {
+            JSONObject requestData = jsonBuilder.buildRequestParam();
+
+            LOGGER.debug("API requestData:[" + requestData.toJSONString() + "]");
+            //接口同步应答报文
+            String responseStr = HttpClientUtils.post3(apiUrl, requestData);
+            LOGGER.info("API responseStr :{}", responseStr);
+
+            JSONObject responseData = JSONObject.parseObject(responseStr, new Feature[]{Feature.SortFeidFastMatch});
+            if (Constants.ERROR.equals(responseData.getString(Constants.STATUS))) {
+                //如果接口直接返回ERROR时,不需要解密
+                return responseData;
+            }
+
+            //解密
+            responseData = CipherWrapper.bothDecryptWrap(responseData);
+            if (Constants.ERROR.equals(responseData.getString(Constants.STATUS))) {
+                //解密后报文,如果status=ERROR时,不需要验签
+                return responseData;
+            }
+
+            //验签
+            super.bothVerifyHmacOrder(responseData);
+
+            LOGGER.info("API responseData :{}", responseStr);
+            return responseData;
+
+        } catch (Exception exception) {
+            LOGGER.error("API request exception", exception);
+            throw new UnknownException(exception);
+        }
+    }
+}

+ 6 - 0
vehicle-server/pom.xml

@@ -62,5 +62,11 @@
             <artifactId>lock4j-redis-template-spring-boot-starter</artifactId>
             <version>2.2.4</version>
         </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.83</version>
+        </dependency>
     </dependencies>
 </project>

+ 13 - 4
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/controller/AssetController.java

@@ -1,13 +1,12 @@
 package com.chelvc.cloud.vehicle.server.controller;
 
 import com.chelvc.cloud.vehicle.client.dto.MerchantAssetDTO;
+import com.chelvc.cloud.vehicle.client.param.WithdrawParam;
 import com.chelvc.cloud.vehicle.server.service.AssetService;
+import com.chelvc.framework.base.context.SessionContextHolder;
 import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 @RestController
 @RequiredArgsConstructor(onConstructor = @__(@Autowired))
@@ -19,4 +18,14 @@ public class AssetController {
     public MerchantAssetDTO getMerchantAsset(@RequestParam("merchantId") Long merchantId) {
         return this.assetService.getMerchantAsset(merchantId);
     }
+
+    /**
+     * 提现接口
+     *
+     * @param param
+     */
+    @PutMapping("/asset/withdraw")
+    public void withdraw(@RequestBody WithdrawParam param) {
+        this.assetService.withdraw(param);
+    }
 }

+ 2 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/dao/MerchantMapper.java

@@ -185,4 +185,6 @@ public interface MerchantMapper extends BaseMapper<Merchant> {
      */
     Map<String,Object> getAddMerchantReport(@Param("year") Integer year,
                                              @Param("month") Integer month,@Param("day") Integer day);
+
+    MerchantDTO queryCheck(@Param("id") Long id, @Param("userId") Long userId);
 }

+ 11 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/dao/MerchantRelationMapper.java

@@ -0,0 +1,11 @@
+package com.chelvc.cloud.vehicle.server.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.chelvc.cloud.vehicle.server.entity.MerchantRelation;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface MerchantRelationMapper extends BaseMapper<MerchantRelation> {
+
+
+}

+ 10 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/dao/OmsWithdrawMapper.java

@@ -0,0 +1,10 @@
+package com.chelvc.cloud.vehicle.server.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.chelvc.cloud.vehicle.server.entity.OmsWithdraw;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface OmsWithdrawMapper extends BaseMapper<OmsWithdraw> {
+
+}

+ 40 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/entity/MerchantRelation.java

@@ -0,0 +1,40 @@
+package com.chelvc.cloud.vehicle.server.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.chelvc.framework.database.entity.Entity;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+import lombok.experimental.SuperBuilder;
+
+
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString(callSuper = true)
+@TableName(autoResultMap = true)
+public class MerchantRelation implements Entity<Long> {
+
+    private static final long serialVersionUID = -2573290665569937880L;
+    /**
+     * 主键
+     */
+    @TableId(type = IdType.ASSIGN_ID)
+    private Long id;
+
+    private Long userId;
+
+    /**
+     * 类型:1-用户;2-商家
+     */
+    private Integer type;
+
+    /**
+     * 首信易商户id
+     */
+    private String sxyMerchantId;
+}

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

@@ -0,0 +1,66 @@
+package com.chelvc.cloud.vehicle.server.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.chelvc.framework.database.entity.ModifyEntity;
+import lombok.*;
+import lombok.experimental.SuperBuilder;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 提现 oms_withdraw
+ *
+ * @author liude
+ * @date 2023-11-08
+ */
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString(callSuper = true)
+@EqualsAndHashCode(callSuper = true)
+@TableName(autoResultMap = true)
+public class OmsWithdraw extends ModifyEntity<Long>
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 订单id */
+    @TableId(type = IdType.ASSIGN_ID)
+    private Long id;
+
+    /** 用户id */
+    private Long userId;
+
+    /** 类型:0-平台; 1-用户;2-商家 */
+    private Integer type;
+
+    /** 提现渠道:1-首信易 */
+    private Integer channel;
+
+    /** 提现金额 */
+    private BigDecimal amount;
+
+    /** 应付金额(实际支付金额) */
+    private BigDecimal payAmount;
+
+    /** 状态:0-体现中;1-成功;2-失败;3-拒绝 */
+    private Integer status;
+
+    /**
+     * 提现时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+
+    /**
+     * 备注
+     */
+    private String remark;
+}

+ 29 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/handle/CustomConfig.java

@@ -0,0 +1,29 @@
+package com.chelvc.cloud.vehicle.server.handle;
+
+import com.upay.sdk.ConfigurationUtils;
+import org.apache.commons.configuration.MapConfiguration;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.util.HashMap;
+import java.util.Map;
+
+@Configuration
+public class CustomConfig {
+
+    @PostConstruct
+    public void init(){
+        Map<String, Object> map = new HashMap<>();
+        map.put("http.content.type.v3", "application/vnd.5upay-v3.0+json");
+        map.put("http.content.type.v4", "application/vnd.5upay-v4.0+json");
+        map.put("893951545.client.private.key.path", "F:/workspace/after/car/vehicle/vehicle-server/src/main/webapp/cfca/client.pfx");
+        map.put("893951545.client.private.key.password", "123456");
+        map.put("onlinepay.query.url", "https://apis.5upay.com/onlinePay/query");
+        map.put("ehking.sdk.net.client.defaultConnectTimeout", "30000");
+        map.put("ehking.sdk.net.client.defaultReadTimeout", "30000");
+        //必须在sdk调用前初始化
+        ConfigurationUtils.setConfigSource(new MapConfiguration(map));
+        System.setProperty("jdk.tls.disabledAlgorithms","");
+    }
+}

+ 53 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/handle/TradeHandle.java

@@ -0,0 +1,53 @@
+package com.chelvc.cloud.vehicle.server.handle;
+
+import com.alibaba.fastjson.JSONObject;
+import com.chelvc.cloud.vehicle.client.util.JsonBuilder;
+import com.chelvc.cloud.vehicle.client.util.MyExecuter;
+import com.upay.sdk.ConfigurationUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.configuration.MapConfiguration;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Slf4j
+public class TradeHandle {
+
+    public static void handle(String jsonData, String apiUrl, String merchantId, String partnerId){
+        JSONObject rawDataJson = JSONObject.parseObject(jsonData);
+        log.info("接口地址:{}", apiUrl);
+        log.info("请求报文json: {}: ", rawDataJson.toJSONString());
+        JsonBuilder jsonSupport = new JsonBuilder(merchantId, partnerId, rawDataJson);
+        MyExecuter myExecuter = new MyExecuter();
+        JSONObject rawRespJsonData = myExecuter.ApiRequest(jsonSupport, apiUrl);
+        log.info("应答报文json: {}: ", rawRespJsonData.toJSONString());
+    }
+
+    public static void main(String[] args) {
+
+        Map<String, Object> map = new HashMap<>();
+        map.put("http.content.type.v3", "application/vnd.5upay-v3.0+json");
+        map.put("http.content.type.v4", "application/vnd.5upay-v4.0+json");
+        map.put("893951545.client.private.key.path", "F:/workspace/after/car/vehicle/vehicle-server/src/main/webapp/cfca/client.pfx");
+        map.put("893951545.client.private.key.password", "123456");
+        map.put("onlinepay.query.url", "https://apis.5upay.com/onlinePay/query");
+        map.put("ehking.sdk.net.client.defaultConnectTimeout", "30000");
+        map.put("ehking.sdk.net.client.defaultReadTimeout", "30000");
+        //必须在sdk调用前初始化
+        ConfigurationUtils.setConfigSource(new MapConfiguration(map));
+        System.setProperty("jdk.tls.disabledAlgorithms","");
+
+        String merchantId = "893951545";
+        String partnerId = null;
+
+        String apiUrl = "https://apis.5upay.com/wallet/withdraw";
+        String rawJsonData = "{\n" +
+                "\"merchantId\": \"893951545\",\n" +
+                "\"requestId\": \"1527231168976\",\n" +
+                "\"withdrawAmount\": \"10000\",\n" +
+                "\"notifyUrl\": \"https://demo.5upay.com/sdk/onlinepay/notify\",\n" +
+                "\"remark\": \"备注\",\n" +
+                "}";
+        handle(rawJsonData, apiUrl, merchantId, partnerId);
+    }
+}

+ 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.WithdrawParam;
 import com.chelvc.cloud.vehicle.server.entity.Asset;
 
 import java.math.BigDecimal;
@@ -28,4 +29,6 @@ public interface AssetService {
     void updatePlatformAsset(BigDecimal platformRealityAmount, BigDecimal payAmount);
 
     MerchantAssetDTO getMerchantAsset(Long merchantId);
+
+    void withdraw(WithdrawParam param);
 }

+ 7 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/MerchantRelationService.java

@@ -0,0 +1,7 @@
+package com.chelvc.cloud.vehicle.server.service;
+
+import com.chelvc.cloud.vehicle.server.entity.MerchantRelation;
+
+public interface MerchantRelationService {
+    MerchantRelation queryByUserIdAndType(Long userId, Integer type);
+}

+ 2 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/MerchantService.java

@@ -233,4 +233,6 @@ public interface MerchantService extends IService<Merchant> {
      * @return
      */
     Map<String,Object> getMerchantReportCount(ReportModifyParam param);
+
+    MerchantDTO queryCheck(Long merchantId, Long userId);
 }

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

@@ -0,0 +1,7 @@
+package com.chelvc.cloud.vehicle.server.service;
+
+import java.math.BigDecimal;
+
+public interface OmsWithdrawService {
+    Long createWithdraw(Long userId, Integer type, BigDecimal amount, Integer channel);
+}

+ 54 - 7
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/AssetServiceImpl.java

@@ -1,18 +1,19 @@
 package com.chelvc.cloud.vehicle.server.service.impl;
 
+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.dto.MerchantAssetDTO;
-import com.chelvc.cloud.vehicle.client.dto.MerchantTeamDTO;
-import com.chelvc.cloud.vehicle.client.dto.OrderDTO;
-import com.chelvc.cloud.vehicle.client.dto.WalletDTO;
+import com.chelvc.cloud.vehicle.client.constant.TradeConstant;
+import com.chelvc.cloud.vehicle.client.dto.*;
+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.service.AssetService;
-import com.chelvc.cloud.vehicle.server.service.BalanceDetailService;
-import com.chelvc.cloud.vehicle.server.service.OmsOrderService;
+import com.chelvc.cloud.vehicle.server.entity.MerchantRelation;
+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 lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -21,12 +22,16 @@ import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
+import java.util.HashMap;
 
 @Service
 @RequiredArgsConstructor(onConstructor = @__({@Autowired,@Lazy}))
 public class AssetServiceImpl extends ServiceImpl<AssetMapper, Asset> implements AssetService {
     private final BalanceDetailService balanceDetailService;
     private final OmsOrderService orderService;
+    private final MerchantService merchantService;
+    private final MerchantRelationService merchantRelationService;
+    private final OmsWithdrawService withdrawService;
 
     @Override
     public Asset queryAsset(Long userId, Integer type) {
@@ -113,4 +118,46 @@ public class AssetServiceImpl extends ServiceImpl<AssetMapper, Asset> implements
         dto.setMerchantTeamDTO(merchantTeamDTO);
         return dto;
     }
+
+    @Override
+    public void withdraw(WithdrawParam param) {
+        Integer type = param.getType();
+        BigDecimal amount = param.getAmount();
+        Long userId = SessionContextHolder.getId();
+        if(type == null || (type != 1 && type != 2)){
+            throw new ResourceUnavailableException("提现类型错误");
+        }
+        if(type == 2){
+            //商家体现
+            Long merchantId = param.getMerchantId();
+            MerchantDTO merchantDTO = merchantService.queryCheck(merchantId, userId);
+            if(merchantDTO == null){
+                throw new ResourceUnavailableException("该账户下商家不存在");
+            }
+            userId = merchantId;
+        }
+        Asset asset = queryAsset(userId, type);
+        BigDecimal total = asset.getTotal();
+        if(amount.compareTo(total) > 0){
+            throw new ResourceUnavailableException("账户余额不足");
+        }
+        //查询首信易商户号
+        MerchantRelation merchantRelation = merchantRelationService.queryByUserIdAndType(userId, type);
+        if(merchantRelation == null){
+            throw new ResourceUnavailableException("请联系管理员开通商户号");
+        }
+        //生成提现订单
+        Long withdrawId = withdrawService.createWithdraw(userId, 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();
+        TradeHandle.handle(gson.toJson(map), TradeConstant.WITHDRAW_URL, sxyMerchantId, TradeConstant.PARTNER_ID);
+    }
 }

+ 26 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/MerchantRelationServiceImpl.java

@@ -0,0 +1,26 @@
+package com.chelvc.cloud.vehicle.server.service.impl;
+
+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.server.dao.MerchantRelationMapper;
+import com.chelvc.cloud.vehicle.server.entity.MerchantRelation;
+import com.chelvc.cloud.vehicle.server.service.MerchantRelationService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor(onConstructor = @__({@Autowired,@Lazy}))
+public class MerchantRelationServiceImpl extends ServiceImpl<MerchantRelationMapper,
+        MerchantRelation> implements MerchantRelationService {
+
+    @Override
+    public MerchantRelation queryByUserIdAndType(Long userId, Integer type) {
+        LambdaQueryWrapper<MerchantRelation> wrapper = Wrappers.lambdaQuery();
+        wrapper.eq(MerchantRelation::getUserId, userId);
+        wrapper.eq(MerchantRelation::getType, type);
+        return baseMapper.selectOne(wrapper);
+    }
+}

+ 5 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/MerchantServiceImpl.java

@@ -555,4 +555,9 @@ public class MerchantServiceImpl extends ServiceImpl<MerchantMapper, Merchant> i
         return this.baseMapper.getAddMerchantReport(param.getYear(),month,day);
     }
 
+    @Override
+    public MerchantDTO queryCheck(Long merchantId, Long userId) {
+        return this.baseMapper.queryCheck(merchantId, userId);
+    }
+
 }

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

@@ -0,0 +1,36 @@
+package com.chelvc.cloud.vehicle.server.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.chelvc.cloud.vehicle.server.dao.OmsWithdrawMapper;
+import com.chelvc.cloud.vehicle.server.entity.OmsWithdraw;
+import com.chelvc.cloud.vehicle.server.service.OmsWithdrawService;
+import com.chelvc.framework.common.exception.ResourceUnavailableException;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Service
+@RequiredArgsConstructor(onConstructor = @__({@Autowired,@Lazy}))
+public class OmsWithdrawServiceImpl extends ServiceImpl<OmsWithdrawMapper,
+        OmsWithdraw> implements OmsWithdrawService {
+
+    @Override
+    public Long createWithdraw(Long userId, Integer type, BigDecimal amount, Integer channel) {
+        OmsWithdraw withdraw = new OmsWithdraw();
+        withdraw.setAmount(amount);
+        withdraw.setChannel(channel);
+        withdraw.setStatus(0);
+        withdraw.setUserId(userId);
+        withdraw.setType(type);
+        withdraw.setCreateTime(new Date());
+        int i = baseMapper.insert(withdraw);
+        if(i != 1){
+            throw new ResourceUnavailableException("提现申请失败");
+        }
+        return withdraw.getId();
+    }
+}

+ 15 - 0
vehicle-server/src/main/resources/5upay-config.properties

@@ -0,0 +1,15 @@
+
+wallet.withdraw.url=https://apis.5upay.com/wallet/withdraw
+wallet.withdraw.query.url=https://apis.5upay.com/wallet/withdrawQuery
+wallet.withdraw.certificate.url=https://apis.5upay.com/wallet/withdrawCertificate
+wallet.withdraw.certificate.partner.url=https://apis.5upay.com/wallet/withdrawCertificatePartner
+
+ehking.sdk.net.client.defaultConnectTimeout=30000
+ehking.sdk.net.client.defaultReadTimeout=30000
+
+
+http.content.type.v3=application/vnd.5upay-v3.0+json
+
+#商户私钥证书,正式商用时,请更新为商户的实际证书
+893951545.client.private.key.path=F:\\workspace\\after\\car\\vehicle\\vehicle-server\\src\\main\\webapp\\cfca\\client.pfx
+893951545.client.private.key.password=123456

+ 3 - 1
vehicle-server/src/main/resources/mapper/MerchantMapper.xml

@@ -426,7 +426,9 @@
 
     </select>
 
-
+    <select id="queryCheck" resultType="com.chelvc.cloud.vehicle.client.dto.MerchantDTO">
+        select * from merchant where id = #{id} and user_id = #{userId}
+    </select>
 
 
 </mapper>

+ 3 - 0
vehicle-server/src/main/webapp/META-INF/MANIFEST.MF

@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path: 
+

BIN
vehicle-server/src/main/webapp/cfca/client.pfx


BIN
vehicle-server/src/main/webapp/cfca/server.cer


+ 15 - 0
vehicle-server/src/main/webapp/cfca/smclinet.sm2

@@ -0,0 +1,15 @@
+MIIDKgIBATBHBgoqgRzPVQYBBAIBBgcqgRzPVQFoBDC+23Ce+5hxJvc3SnCCopj+cI3lfEMPSNv9
+HC5W0dtQdX6XUhlPetyHlD2h8seiJrowggLaBgoqgRzPVQYBBAIBBIICyjCCAsYwggJqoAMCAQIC
+BRN5IxhyMAwGCCqBHM9VAYN1BQAwJTELMAkGA1UEBhMCQ04xFjAUBgNVBAoMDUNGQ0EgU00yIE9D
+QTEwHhcNMjIwNzA2MDczNjIxWhcNMjMwMjE1MDc0NzI3WjCBqzELMAkGA1UEBhMCQ04xFjAUBgNV
+BAoMDUNGQ0EgU00yIE9DQTExEDAOBgNVBAsMB1BheUVhc2UxGTAXBgNVBAsMEE9yZ2FuaXphdGlv
+bmFsLTExVzBVBgNVBAMMTlBheUVhc2VA6aaW5L+h5piT5rWL6K+V5ZWG5oi3LeaKgOacr+aUr+aM
+gemDqOa1i+ivlTJAWjY0NTUxNTE1NDQ4MTUxNTI2NTE0NjhAMTBZMBMGByqGSM49AgEGCCqBHM9V
+AYItA0IABJ+rpS6y1H6JdJtxyBUFdyQj332ANjtD9oha5IfJIZU+syGWDQCo4o37rDPAljEntbUD
+By6aMr3sOYhZGxmgbdGjgf0wgfowHwYDVR0jBBgwFoAUXJNYIFokc1YQG2RQEOzpp8oHQREwCQYD
+VR0TBAIwADBIBgNVHSAEQTA/MD0GCGCBHIbvKgEBMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cu
+Y2ZjYS5jb20uY24vdXMvdXMtMTQuaHRtMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly9jcmwuY2Zj
+YS5jb20uY24vU00yL2NybDY4MzUuY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUY+bnDzmYSLVU
+rk0qwou3niv/g+kwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMAwGCCqBHM9VAYN1BQAD
+SAAwRQIhAObZTy9L7ArMbV2DQzqqM2DUYwWtBrN3Jt1dzcByppjSAiAW+t4GhAeVRrNIEpjfr7po
+cdHqaCNKE6SMwYLxNVZbdQ==

BIN
vehicle-server/src/main/webapp/cfca/smserver.cer


+ 13 - 0
vehicle-server/src/main/webapp/cfca/璇佷功鏂囦欢璇存槑.txt

@@ -0,0 +1,13 @@
+国际算法:
+server.cer  首信生产环境公钥证书
+client.pfx   demo测试商户私钥证书
+
+国密算法:
+smserver.cer  首信生产环境公钥证书
+smclient.pfx   demo测试商户私钥证书
+
+
+注:
+1、商户系统上线时,首信生产环境公钥证书不变, 商户私钥证书需要更换成商户自己的证书;
+2、sdk2.0及以上版,配置文件中无需配置首信公钥证书;
+