Bläddra i källkod

Merge remote-tracking branch 'origin/master'

liude 4 månader sedan
förälder
incheckning
6a122bec61
26 ändrade filer med 1248 tillägg och 44 borttagningar
  1. 6 0
      vehicle-client/pom.xml
  2. 19 0
      vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/UserAuthClient.java
  3. 34 0
      vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/constant/MerchantApplyStatus.java
  4. 1 1
      vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/constant/TradeConstant.java
  5. 109 0
      vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/dto/UserAuthDTO.java
  6. 4 0
      vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/param/MerchantApplyRecordParam.java
  7. 3 3
      vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/param/MerchantAuthModifyParam.java
  8. 52 0
      vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/param/UserAuthParam.java
  9. 19 0
      vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/util/MyExecuter.java
  10. 157 0
      vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/util/SFTPConfigModel.java
  11. 348 0
      vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/util/SFTPUtils.java
  12. 29 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/controller/UserAuthController.java
  13. 12 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/dao/UserAuthMapper.java
  14. 1 1
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/entity/MerchantAuth.java
  15. 112 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/entity/UserAuth.java
  16. 2 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/MerchantAuthService.java
  17. 11 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/MerchantRelationService.java
  18. 2 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/MerchantService.java
  19. 12 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/UserAuthService.java
  20. 41 9
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/MerchantApplyRecordServiceImpl.java
  21. 36 12
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/MerchantAuthServiceImpl.java
  22. 135 17
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/MerchantRelationServiceImpl.java
  23. 7 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/MerchantServiceImpl.java
  24. 84 0
      vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/UserAuthServiceImpl.java
  25. 0 1
      vehicle-server/src/main/resources/application.yml
  26. 12 0
      vehicle-server/src/main/resources/mapper/UserAuthMapper.xml

+ 6 - 0
vehicle-client/pom.xml

@@ -77,5 +77,11 @@
             <artifactId>fastjson</artifactId>
             <version>1.2.83</version>
         </dependency>
+
+        <dependency>
+            <groupId>com.jcraft</groupId>
+            <artifactId>jsch</artifactId>
+            <version>0.1.55</version>
+        </dependency>
     </dependencies>
 </project>

+ 19 - 0
vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/UserAuthClient.java

@@ -0,0 +1,19 @@
+package com.chelvc.cloud.vehicle.client;
+
+import com.chelvc.cloud.vehicle.client.dto.UserAuthDTO;
+import com.chelvc.cloud.vehicle.client.param.UserAuthParam;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@FeignClient("vehicle")
+public interface UserAuthClient {
+
+    @GetMapping("/user/auth")
+    UserAuthDTO getUserAuthInfo(@RequestParam("userId") Long userId);
+
+    @PutMapping(value = "/user/auth")
+    void userAuth(@RequestBody UserAuthParam param);
+}

+ 34 - 0
vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/constant/MerchantApplyStatus.java

@@ -0,0 +1,34 @@
+package com.chelvc.cloud.vehicle.client.constant;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum MerchantApplyStatus {
+    PROCESSING(1, "PROCESSING","审核中"),
+    SUCCESS(2, "SUCCESS","入网完成"),
+    PASS(3, "PASS","审核通过"),
+    NO_PASS(4, "NO_PASS","审核不通过"),
+    REFUSE(5, "REFUSE","审核拒绝"),
+    ESIGN_PROCESS(6, "ESIGN_PROCESS","待签约"),
+    ESIGN_PROCESSING(7, "ESIGN_PROCESSING","签约中"),
+    ESIGN_FAIL(8, "ESIGN_FAIL","签约失败"),
+    ESIGN_SUCCESS(9, "ESIGN_SUCCESS","签约成功"),
+    ;
+
+    private Integer status;
+
+    private String type;
+
+    private String desc;
+
+    public static Integer getStatus(String type){
+        for (MerchantApplyStatus applyStatus : MerchantApplyStatus.values()) {
+            if (applyStatus.getType().equals(type)) {
+                return applyStatus.getStatus();
+            }
+        }
+        return 0;
+    }
+}

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

@@ -20,7 +20,7 @@ public interface TradeConstant {
     /**
      * 商户入网回调地址
      */
-    static final String MERCHANT_NET_IN_NOTIFY_URL = "https://apis.5upay.com/wallet/withdraw";
+    static final String MERCHANT_NET_IN_NOTIFY_URL = "http://igl611.a1.luyouxia.net:20487/maintain/merchant/apply/notify";
 
     /**
      * 被分账方入网

+ 109 - 0
vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/dto/UserAuthDTO.java

@@ -0,0 +1,109 @@
+package com.chelvc.cloud.vehicle.client.dto;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.*;
+import lombok.experimental.SuperBuilder;
+
+import java.util.Date;
+
+@Data
+@SuperBuilder
+@AllArgsConstructor
+@ToString(callSuper = true)
+public class UserAuthDTO {
+
+    /**
+     * 主键
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 用户ID
+     */
+    private Long userId;
+
+    /**
+     * 认证状态:认证状态:0-未申请;1-审核中;2-入网完成;3-审核通过;4-审核不通过;5-审核拒绝;6-待签约;7-签约中;8-签约失败;9-签约成功;
+     */
+    private Integer status;
+
+    /**
+     * 真实姓名
+     */
+    private String userName;
+
+    /**
+     * 身份证正面照片
+     */
+    private String idCardFrontPhoto;
+
+    /**
+     * 身份证反面照片
+     */
+    private String idCardBackPhoto;
+
+    /**
+     * 银行卡照片
+     */
+    private String bankCardNo;
+
+    /**
+     * 身份证号
+     */
+    private String idCardNo;
+
+    /**
+     * 邮箱
+     */
+    private String email;
+
+    /**
+     * 电话
+     */
+    private String phone;
+
+    /**
+     * 地址
+     */
+    private String address;
+
+    /**
+     * 身份证有效期开始时间
+     */
+    private Date idCardExpirationDateStart;
+
+    /**
+     * 身份证有效期
+     */
+    private Date idCardExpirationDate;
+
+    /**
+     * 开户名称
+     */
+    private String accountName;
+
+    /**
+     * 省
+     */
+    private Integer province;
+
+    /**
+     * 市
+     */
+    private Integer city;
+
+    /**
+     * 区
+     */
+    private Integer district;
+
+    public UserAuthDTO(Integer status){
+        this.status = status;
+    }
+
+    public UserAuthDTO(){
+
+    }
+}

+ 4 - 0
vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/param/MerchantApplyRecordParam.java

@@ -10,6 +10,10 @@ public class MerchantApplyRecordParam implements Serializable {
 
     private String merchantId;
 
+    private String data;
+
+    private String encryptKey;
+
     /**
      * 请求号
      */

+ 3 - 3
vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/param/MerchantAuthModifyParam.java

@@ -224,10 +224,10 @@ public class MerchantAuthModifyParam implements Serializable {
     @NotNull(message = "银行预留手机号不能为空")
     private String reservedPhoneNo;
     /**
-     * 开户名称
+     * 营业执照名称
      */
-    @NotNull(message = "开户名称不能为空")
-    private String accountName;
+    @NotNull(message = "营业执照名称不能为空")
+    private String businessName;
     /**
      * 商家主营业务
      */

+ 52 - 0
vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/param/UserAuthParam.java

@@ -0,0 +1,52 @@
+package com.chelvc.cloud.vehicle.client.param;
+
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 用户提现认证资料
+ */
+@Data
+public class UserAuthParam {
+
+    /**
+     * 真实姓名
+     */
+    private String userName;
+
+    /**
+     * 身份证正面照片
+     */
+    private String idCardFrontPhoto;
+
+    /**
+     * 身份证反面照片
+     */
+    private String idCardBackPhoto;
+
+    /**
+     * 身份证号
+     */
+    private String idCardNo;
+
+    /**
+     * 银行卡号
+     */
+    private String bankCardNo;
+
+    /**
+     * 电话
+     */
+    private String phone;
+
+    /**
+     * 身份证有效期开始时间
+     */
+    private Date idCardExpirationDateStart;
+
+    /**
+     * 身份证有效期
+     */
+    private Date idCardExpirationDate;
+}

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

@@ -46,4 +46,23 @@ public class MyExecuter extends Executer {
             throw new UnknownException(exception);
         }
     }
+
+    public JSONObject getDecrypt(String data){
+        JSONObject responseData = JSONObject.parseObject(data, 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 :{}", data);
+        return responseData;
+    }
 }

+ 157 - 0
vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/util/SFTPConfigModel.java

@@ -0,0 +1,157 @@
+package com.chelvc.cloud.vehicle.client.util;
+
+public class SFTPConfigModel {
+    /** FTP 登录用户名*/
+    private String userName;
+    /** FTP 登录密码*/
+    private String passWord;
+    /** 私钥 */
+    private String privateKey;
+    /** FTP 服务器地址IP地址*/
+    private String host;
+    /** FTP 端口*/
+    private int port;
+    /** FTP 指定上传路径*/
+    private String uploadUrl;
+    /** FTP 指定下载路径*/
+    private String downloadUrl;
+
+    public SFTPConfigModel(String userName, String passWord, String privateKey, String host, int port, String uploadUrl, String downloadUrl) {
+        this.userName = userName;
+        this.passWord = passWord;
+        this.privateKey = privateKey;
+        this.host = host;
+        this.port = port;
+        this.uploadUrl = uploadUrl;
+        this.downloadUrl = downloadUrl;
+    }
+
+    public SFTPConfigModel(String userName, String passWord, String privateKey, String host, int port) {
+        this.userName = userName;
+        this.passWord = passWord;
+        this.privateKey = privateKey;
+        this.host = host;
+        this.port = port;
+    }
+
+    public SFTPConfigModel(String userName, String passWord, String host, int port) {
+        this.userName = userName;
+        this.passWord = passWord;
+        this.host = host;
+        this.port = port;
+    }
+
+    public SFTPConfigModel(){}
+
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getPassWord() {
+        return passWord;
+    }
+
+    public void setPassWord(String passWord) {
+        this.passWord = passWord;
+    }
+
+    public String getPrivateKey() {
+        return privateKey;
+    }
+
+    public void setPrivateKey(String privateKey) {
+        this.privateKey = privateKey;
+    }
+
+    public String getHost() {
+        return host;
+    }
+
+    public void setHost(String host) {
+        this.host = host;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public String getUploadUrl() {
+        return uploadUrl;
+    }
+
+    public void setUploadUrl(String uploadUrl) {
+        this.uploadUrl = uploadUrl;
+    }
+
+    public String getDownloadUrl() {
+        return downloadUrl;
+    }
+
+    public void setDownloadUrl(String downloadUrl) {
+        this.downloadUrl = downloadUrl;
+    }
+
+
+    // -------------------------------------------------------------------------------
+    public SFTPConfigModel userName(String userName){
+        this.userName = userName;
+        return this;
+    }
+
+    public SFTPConfigModel passWord(String passWord){
+        this.passWord = passWord;
+        return this;
+    }
+
+    public SFTPConfigModel privateKey(String privateKey){
+        this.privateKey = privateKey;
+        return this;
+    }
+
+    public SFTPConfigModel host(String host){
+        this.host = host;
+        return this;
+    }
+
+    public SFTPConfigModel port(int port){
+        this.port = port;
+        return this;
+    }
+
+    /**
+     * 默认配置
+     * @return
+     */
+    public SFTPConfigModel getDefaultConfig(){
+        this.userName = "893951545";
+        this.passWord = null;
+        this.host = "merchant-sftp.5upay.com";
+        this.port = 2822;
+        this.uploadUrl = "/serviceprovider/register/";
+        this.privateKey = "C:\\893951545.rsa";
+        return this;
+    }
+
+
+    @Override
+    public String toString() {
+        return "SFTPConfigModel{" +
+                "userName='" + userName + '\'' +
+                ", passWord='" + passWord + '\'' +
+                ", privateKey='" + privateKey + '\'' +
+                ", host='" + host + '\'' +
+                ", port=" + port +
+                ", uploadUrl='" + uploadUrl + '\'' +
+                ", downloadUrl='" + downloadUrl + '\'' +
+                '}';
+    }
+}

+ 348 - 0
vehicle-client/src/main/java/com/chelvc/cloud/vehicle/client/util/SFTPUtils.java

@@ -0,0 +1,348 @@
+package com.chelvc.cloud.vehicle.client.util;
+
+import com.chelvc.framework.base.context.RestContextHolder;
+import com.jcraft.jsch.*;
+import org.apache.poi.util.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.Resource;
+
+import java.io.*;
+import java.util.Properties;
+import java.util.Vector;
+
+public class SFTPUtils {
+    private static final Logger log = LoggerFactory.getLogger(SFTPUtils.class);
+
+    private ChannelSftp sftp;
+
+    private Session session;
+
+    /** FTP 登录用户名*/
+    private String username;
+    /** FTP 登录密码*/
+    private String password;
+    /** 私钥 */
+    private String privateKey;
+    /** FTP 服务器地址IP地址*/
+    private String host;
+    /** FTP 端口*/
+    private int port;
+
+
+    private SFTPUtils(){}
+
+    /**
+     * QY
+     * 建议使用配置构参方式,可拓展性比较强
+     * @param sftpConfigModel
+     */
+    public SFTPUtils(SFTPConfigModel sftpConfigModel){
+        this.username = sftpConfigModel.getUserName();
+        this.password = sftpConfigModel.getPassWord();
+        this.privateKey = sftpConfigModel.getPrivateKey();
+        this.host = sftpConfigModel.getHost();
+        this.port = sftpConfigModel.getPort();
+    }
+
+
+    /**
+     * 连接sftp服务器
+     *
+     * @throws Exception
+     */
+    public void login(){
+        try {
+            JSch jsch = new JSch();
+            if (privateKey != null) {
+                jsch.addIdentity(privateKey);// 设置私钥
+                log.info("sftp connect,path of private key file:{}" , privateKey);
+            }
+            log.info("sftp connect by host:{} username:{}",host,username);
+
+            session = jsch.getSession("893951545", "merchant-sftp.5upay.com", 2822);
+            log.info("Session is build");
+            if (password != null) {
+                session.setPassword(password);
+            }
+            Properties config = new Properties();
+            config.put("StrictHostKeyChecking", "no");
+            config.put("LogLevel", "DEBUG");
+            session.setConfig(config);
+            session.connect();
+            log.info("Session is connected");
+
+            Channel channel = session.openChannel("sftp");
+            channel.connect();
+            log.info("channel is connected");
+
+            sftp = (ChannelSftp) channel;
+            log.info(String.format("sftp server host:[%s] port:[%s] is connect successfull", host, port));
+        } catch (JSchException e) {
+            log.error("Cannot connect to specified sftp server : {}:{} \n Exception message is: {}", new Object[]{host, port, e.getMessage()});
+        }
+    }
+
+    /**
+     * 关闭连接 server
+     */
+    public void logout(){
+        if (sftp != null) {
+            if (sftp.isConnected()) {
+                sftp.disconnect();
+                log.info("sftp is closed already");
+            }
+        }
+        if (session != null) {
+            if (session.isConnected()) {
+                session.disconnect();
+                log.info("sshSession is closed already");
+            }
+        }
+    }
+
+    /**
+     * 将输入流的数据上传到sftp作为文件
+     *
+     * @param directory
+     *            上传到该目录
+     * @param sftpFileName
+     *            sftp端文件名
+     * @param input
+     *            输入流
+     * @throws SftpException
+     * @throws Exception
+     */
+    public void upload(String directory, String sftpFileName, InputStream input) throws SftpException {
+        try {
+            sftp.cd(directory);
+        } catch (SftpException e) {
+            log.warn("directory is not exist");
+            sftp.mkdir(directory);
+            sftp.cd(directory);
+        }
+        sftp.put(input, sftpFileName);
+        log.info("file:{} is upload successful" , sftpFileName);
+    }
+
+    /**
+     * 上传单个文件
+     *
+     * @param directory
+     *            上传到sftp目录
+     * @param uploadFile
+     *            要上传的文件,包括路径
+     * @throws FileNotFoundException
+     * @throws SftpException
+     * @throws Exception
+     */
+    public void upload(String directory, String uploadFile) throws FileNotFoundException, SftpException{
+        File file = new File(uploadFile);
+        upload(directory, file.getName(), new FileInputStream(file));
+    }
+
+    /**
+     * 将byte[]上传到sftp,作为文件。注意:从String生成byte[]是,要指定字符集。
+     *
+     * @param directory
+     *            上传到sftp目录
+     * @param sftpFileName
+     *            文件在sftp端的命名
+     * @param byteArr
+     *            要上传的字节数组
+     * @throws SftpException
+     * @throws Exception
+     */
+    public void upload(String directory, String sftpFileName, byte[] byteArr) throws SftpException{
+        upload(directory, sftpFileName, new ByteArrayInputStream(byteArr));
+    }
+
+    /**
+     * 将字符串按照指定的字符编码上传到sftp
+     *
+     * @param directory
+     *            上传到sftp目录
+     * @param sftpFileName
+     *            文件在sftp端的命名
+     * @param dataStr
+     *            待上传的数据
+     * @param charsetName
+     *            sftp上的文件,按该字符编码保存
+     * @throws UnsupportedEncodingException
+     * @throws SftpException
+     * @throws Exception
+     */
+    public void upload(String directory, String sftpFileName, String dataStr, String charsetName) throws UnsupportedEncodingException, SftpException{
+        upload(directory, sftpFileName, new ByteArrayInputStream(dataStr.getBytes(charsetName)));
+    }
+
+    /**
+     * 下载文件
+     *
+     * @param directory
+     *            下载目录
+     * @param downloadFile
+     *            下载的文件
+     * @param saveFile
+     *            存在本地的路径
+     * @throws SftpException
+     * @throws FileNotFoundException
+     * @throws Exception
+     */
+    public void download(String directory, String downloadFile, String saveFile) throws SftpException, FileNotFoundException{
+        if (directory != null && !"".equals(directory)) {
+            sftp.cd(directory);
+        }
+        File file = new File(saveFile);
+        sftp.get(downloadFile, new FileOutputStream(file));
+        log.info("file:{} is download successful" , downloadFile);
+    }
+
+    /**
+     * 下载文件
+     * @param directory 下载目录
+     * @param downloadFile 下载的文件名
+     * @return 字节数组
+     * @throws SftpException
+     * @throws IOException
+     * @throws Exception
+     */
+    public byte[] download(String directory, String downloadFile) throws SftpException, IOException{
+        if (directory != null && !"".equals(directory)) {
+            sftp.cd(directory);
+        }
+        InputStream is = sftp.get(downloadFile);
+
+        byte[] fileData = IOUtils.toByteArray(is);
+
+        log.info("file:{} is download successful" , downloadFile);
+        return fileData;
+    }
+
+    /**
+     * 删除文件
+     *
+     * @param directory
+     *            要删除文件所在目录
+     * @param deleteFile
+     *            要删除的文件
+     * @throws SftpException
+     * @throws Exception
+     */
+    public void delete(String directory, String deleteFile) throws SftpException{
+        if (isExist(directory,deleteFile)){
+            sftp.cd(directory);
+            sftp.rm(deleteFile);
+            log.info("file:{} is delete successful" , deleteFile);
+        }else {
+            log.info("file:{} is delete failure,because of file is not exist" , deleteFile);
+        }
+    }
+
+    /**
+     * 列出目录下的文件
+     *
+     * @param directory 要列出的目录
+     * @return
+     * @throws SftpException
+     */
+    public Vector<?> listFiles(String directory) throws SftpException {
+        return sftp.ls(directory);
+    }
+
+
+    /**
+     * qy
+     * 判断是否存在该文件
+     * @param directory 路径
+     * @param fileName  文件名称
+     * @return
+     * @throws SftpException
+     */
+    public boolean isExist(String directory, String fileName) throws SftpException {
+        return isExist(directory+"/"+fileName);
+    }
+
+
+    /**
+     * qy
+     * 判断是否存在该文件
+     * 文件不存在的话会抛 SftpException,e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE
+     * @param path 文件(绝对路径)
+     * @return
+     * @throws SftpException
+     *
+     */
+    public boolean isExist(String path) throws SftpException {
+        boolean flag = false;
+        try {
+            sftp.stat(path);
+            flag = true;
+        }
+        catch (SftpException e){
+            if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE){
+                log.info("path:{} is not exist" , path);
+                flag = false;
+            }
+        }
+        return flag;
+    }
+
+    /**
+     * Qy
+     * 修改文件名
+     * @param path      路径
+     * @param oldName   原始名称
+     * @param newName   修改名称
+     * @throws SftpException
+     */
+    public boolean rename(String path, String oldName, String newName) throws SftpException{
+        boolean flag = false;
+        try {
+            System.out.println(path+"/"+oldName+"------->"+path+"/"+newName);
+            sftp.rename(path+"/"+oldName,path+"/"+newName);
+            flag = true;
+            log.info("old file name:[{}] rename to new file name:[{}] successful" , oldName, newName);
+        }
+        catch (SftpException e){
+            log.warn("old file name:[{}] is not exist or new file name:[{}] is exist" , oldName, newName);
+            flag = false;
+        }
+        return flag;
+    }
+
+    public static String ftpUpload(String url, String fileName){
+        SFTPConfigModel sftpConfigModel = new SFTPConfigModel().getDefaultConfig();
+        SFTPUtils sftp = new SFTPUtils(sftpConfigModel);
+        sftp.login();
+        Resource resource = RestContextHolder.get(url, Resource.class);
+        try {
+            InputStream inputStream = resource.getInputStream();
+            sftp.upload(sftpConfigModel.getUploadUrl(), fileName, inputStream);
+        } catch (SftpException e){
+            log.error("sftp上传文件失败");
+        } catch (IOException e){
+            log.error("获取文件流失败");
+        } finally {
+            sftp.logout();
+        }
+        return sftpConfigModel.getUploadUrl() + fileName;
+    }
+
+    public static String getSuffix(String url){
+        return url.substring(url.lastIndexOf(".") + 1);
+    }
+
+    // 单元测试
+    public static void main(String[] args) throws SftpException, IOException {
+        SFTPConfigModel sftpConfigModel = new SFTPConfigModel().getDefaultConfig();
+        SFTPUtils sftp = new SFTPUtils(sftpConfigModel);
+        sftp.login();
+
+        File file = new File("F:\\ceshi.txt");
+        InputStream is = new FileInputStream(file);
+        //sftp.delete(sftpConfigModel.getUploadUrl(),"NCOMP_STHO_20201103_03_0001_CONTROL.txt");
+        sftp.upload(sftpConfigModel.getUploadUrl(), "NCOMP_STHO_20201103_03_0001_CONTROL.txt", is);
+        sftp.logout();
+    }
+}

+ 29 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/controller/UserAuthController.java

@@ -0,0 +1,29 @@
+package com.chelvc.cloud.vehicle.server.controller;
+
+import com.chelvc.cloud.vehicle.client.dto.UserAuthDTO;
+import com.chelvc.cloud.vehicle.client.param.UserAuthParam;
+import com.chelvc.cloud.vehicle.server.service.UserAuthService;
+import com.chelvc.framework.base.annotation.ResponseWrapping;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+@Validated
+@RestController
+@ResponseWrapping
+@RequiredArgsConstructor(onConstructor = @__(@Autowired))
+public class UserAuthController {
+
+    private final UserAuthService userAuthService;
+
+    @GetMapping("/user/auth")
+    UserAuthDTO getUserAuthInfo(@RequestParam("userId") Long userId){
+        return userAuthService.getUserAuthInfo(userId);
+    }
+
+    @PutMapping(value = "/user/auth")
+    void userAuth(@RequestBody UserAuthParam param){
+        userAuthService.userAuth(param);
+    }
+}

+ 12 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/dao/UserAuthMapper.java

@@ -0,0 +1,12 @@
+package com.chelvc.cloud.vehicle.server.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.chelvc.cloud.vehicle.client.dto.UserAuthDTO;
+import com.chelvc.cloud.vehicle.server.entity.UserAuth;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface UserAuthMapper extends BaseMapper<UserAuth> {
+    UserAuthDTO getUserAuthInfo(@Param("userId") Long userId);
+}

+ 1 - 1
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/entity/MerchantAuth.java

@@ -53,7 +53,7 @@ public class MerchantAuth implements Entity<Long> {
     private String reviewer; // 审核人
     private String recommendationUser; // 推荐人
     private Date reviewTime; // 审核时间
-    private String accountName; // 开户名称
+    private String businessName; // 营业执照名称
     private String bankCardNo; // 开户账号
     private String reservedPhoneNo; //银行预留手机号
 

+ 112 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/entity/UserAuth.java

@@ -0,0 +1,112 @@
+package com.chelvc.cloud.vehicle.server.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.chelvc.framework.database.entity.ModifyEntity;
+import lombok.*;
+import lombok.experimental.SuperBuilder;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString(callSuper = true)
+public class UserAuth {
+
+    /**
+     * 主键
+     */
+    @TableId(type = IdType.ASSIGN_ID)
+    private Long id;
+
+    /**
+     * 用户ID
+     */
+    private Long userId;
+
+    /**
+     * 真实姓名
+     */
+    private String userName;
+
+    /**
+     * 认证状态:0-未申请;1-审核中;2-入网完成;3-审核通过;4-审核不通过;5-审核拒绝;6-待签约;7-签约中;8-签约失败;9-签约成功;
+     */
+    private Integer status;
+
+    /**
+     * 身份证正面照片
+     */
+    private String idCardFrontPhoto;
+
+    /**
+     * 身份证反面照片
+     */
+    private String idCardBackPhoto;
+
+    /**
+     * 身份证号
+     */
+    private String idCardNo;
+
+    /**
+     * 银行卡号
+     */
+    private String bankCardNo;
+
+    /**
+     * 邮箱
+     */
+    private String email;
+
+    /**
+     * 电话
+     */
+    private String phone;
+
+    /**
+     * 地址
+     */
+    private String address;
+
+    /**
+     * 身份证有效期开始时间
+     */
+    private Date idCardExpirationDateStart;
+
+    /**
+     * 身份证有效期
+     */
+    private Date idCardExpirationDate;
+
+    /**
+     * 开户名称
+     */
+    private String accountName;
+
+    /**
+     * 省
+     */
+    private Integer province;
+
+    /**
+     * 市
+     */
+    private Integer city;
+
+    /**
+     * 区
+     */
+    private Integer district;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+}

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

@@ -51,4 +51,6 @@ public interface MerchantAuthService extends IService<MerchantAuth> {
      * @param state 0-拒绝 1-通过
      */
     void certificationAudit(Long id,String state,String message );
+
+    int updateStatus(Long userId, Integer status);
 }

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

@@ -2,11 +2,22 @@ package com.chelvc.cloud.vehicle.server.service;
 
 import com.chelvc.cloud.vehicle.server.entity.MerchantAuth;
 import com.chelvc.cloud.vehicle.server.entity.MerchantRelation;
+import com.chelvc.cloud.vehicle.server.entity.UserAuth;
 
 public interface MerchantRelationService {
     MerchantRelation queryByUserIdAndType(Long userId, Integer type);
 
+    /**
+     * 个体户开通子商户
+     * @param merchantAuth
+     */
     void registerMerchantId(MerchantAuth merchantAuth);
 
+    /**
+     * 个人开通子商户
+     * @param userAuth
+     */
+    void registerMerchantId(UserAuth userAuth);
+
     int insert(Long userId, Integer type, String sxyMerchantId);
 }

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

@@ -237,4 +237,6 @@ public interface MerchantService extends IService<Merchant> {
     MerchantDTO queryCheck(Long merchantId, Long userId);
 
     void merchantApplyNotify(MerchantApplyRecordParam param);
+
+    Merchant queryByApplicant(Long applicant);
 }

+ 12 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/UserAuthService.java

@@ -0,0 +1,12 @@
+package com.chelvc.cloud.vehicle.server.service;
+
+import com.chelvc.cloud.vehicle.client.dto.UserAuthDTO;
+import com.chelvc.cloud.vehicle.client.param.UserAuthParam;
+
+public interface UserAuthService {
+    UserAuthDTO getUserAuthInfo(Long userId);
+
+    void userAuth(UserAuthParam param);
+
+    int updateStatus(Long userId, Integer status);
+}

+ 41 - 9
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/MerchantApplyRecordServiceImpl.java

@@ -1,13 +1,19 @@
 package com.chelvc.cloud.vehicle.server.service.impl;
 
+import com.alibaba.fastjson.JSONObject;
 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.MerchantApplyStatus;
 import com.chelvc.cloud.vehicle.client.param.MerchantApplyRecordParam;
 import com.chelvc.cloud.vehicle.server.dao.MerchantApplyRecordMapper;
 import com.chelvc.cloud.vehicle.server.entity.MerchantApplyRecord;
 import com.chelvc.cloud.vehicle.server.service.MerchantApplyRecordService;
+import com.chelvc.cloud.vehicle.server.service.MerchantAuthService;
 import com.chelvc.cloud.vehicle.server.service.MerchantRelationService;
+import com.chelvc.cloud.vehicle.server.service.UserAuthService;
+import com.upay.sdk.Constants;
+import com.upay.sdk.core.CipherWrapper;
 import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -20,6 +26,8 @@ public class MerchantApplyRecordServiceImpl extends
         ServiceImpl<MerchantApplyRecordMapper, MerchantApplyRecord> implements MerchantApplyRecordService {
 
     private final MerchantRelationService merchantRelationService;
+    private final UserAuthService userAuthService;
+    private final MerchantAuthService merchantAuthService;
 
     @Override
     public int insert(MerchantApplyRecord record) {
@@ -28,19 +36,43 @@ public class MerchantApplyRecordServiceImpl extends
 
     @Override
     public void updateByNotify(MerchantApplyRecordParam param) {
-        String requestId = param.getRequestId();
+        JSONObject responseData = new JSONObject();
+        responseData.put("merchantId", param.getMerchantId());
+        responseData.put("partnerId", null);
+        responseData.put("encryptKey", param.getEncryptKey());
+        responseData.put("data", param.getData());
+        //解密
+        responseData = CipherWrapper.bothDecryptWrap(responseData);
+        String status = responseData.getString("subMerchantReviewStatus");
+        if (Constants.ERROR.equals(status)) {
+            //解密后报文,如果status=ERROR时,不需要验签
+            return;
+        }
+        String requestId = responseData.getString("requestId");
         LambdaQueryWrapper<MerchantApplyRecord> wrapper = Wrappers.lambdaQuery();
         wrapper.eq(MerchantApplyRecord::getRequestId, requestId);
         MerchantApplyRecord record = baseMapper.selectOne(wrapper);
-        record.setExamineStatus(param.getSubMerchantReviewStatus());
-        record.setCertificateSupplementUrl(param.getCertificateSupplementUrl());
-        record.setElectronicContractingUrl(param.getElectronicContractingUrl());
-        record.setMerchantReviewRemarks(param.getSubMerchantReviewRemarks());
-        record.setPostReviewRemark(param.getPostReviewRemark());
-        record.setPostReviewStatus(param.getPostReviewStatus());
-        record.setSubMerchantId(param.getSubMerchantId());
+        record.setExamineStatus(status);
+        record.setCertificateSupplementUrl(responseData.getString("certificateSupplementUrl"));
+        record.setElectronicContractingUrl(responseData.getString("electronicContractingUrl"));
+        record.setMerchantReviewRemarks(responseData.getString("merchantReviewRemarks"));
+        record.setPostReviewRemark(responseData.getString("postReviewRemark"));
+        record.setPostReviewStatus(responseData.getString("postReviewStatus"));
+        String subMerchantId = responseData.getString("subMerchantId");
+        record.setSubMerchantId(subMerchantId);
         record.setUpdateTime(new Date());
         baseMapper.updateById(record);
-        merchantRelationService.insert(record.getUserId(), record.getType(), param.getSubMerchantId());
+        Integer type = record.getType();
+        if(type == 1){
+            //更改个人认证状态
+            userAuthService.updateStatus(record.getUserId(), MerchantApplyStatus.getStatus(status));
+        }
+        if(type == 2){
+            //更改个人认证状态
+            merchantAuthService.updateStatus(record.getUserId(), MerchantApplyStatus.getStatus(status));
+        }
+        if("SUCCESS".equals(status)){
+            merchantRelationService.insert(record.getUserId(), record.getType(), subMerchantId);
+        }
     }
 }

+ 36 - 12
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/MerchantAuthServiceImpl.java

@@ -1,5 +1,8 @@
 package com.chelvc.cloud.vehicle.server.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.chelvc.cloud.user.client.UserClient;
@@ -12,13 +15,14 @@ import com.chelvc.cloud.vehicle.client.param.MerchantAuthPagingParam;
 import com.chelvc.cloud.vehicle.client.param.MerchantModifyParam;
 import com.chelvc.cloud.vehicle.server.copier.MerchantAuthCopier;
 import com.chelvc.cloud.vehicle.server.dao.MerchantAuthMapper;
-import com.chelvc.cloud.vehicle.server.entity.Merchant;
 import com.chelvc.cloud.vehicle.server.entity.MerchantAuth;
 import com.chelvc.cloud.vehicle.server.service.CategoryService;
 import com.chelvc.cloud.vehicle.server.service.MerchantAuthService;
 import com.chelvc.cloud.vehicle.server.service.MerchantRelationService;
 import com.chelvc.cloud.vehicle.server.service.MerchantService;
 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.common.model.Pagination;
 import com.chelvc.framework.common.util.AssertUtils;
 import com.chelvc.framework.common.util.StringUtils;
@@ -54,6 +58,11 @@ public class MerchantAuthServiceImpl extends ServiceImpl<MerchantAuthMapper, Mer
     @Override
     public Long addMerchantAuth(@NonNull MerchantAuthModifyParam param) {
         Long userId = SessionContextHolder.getId();
+        LambdaQueryWrapper<MerchantAuth> wrapper = Wrappers.lambdaQuery();
+        wrapper.eq(MerchantAuth::getApplicant, userId);
+        if(baseMapper.selectCount(wrapper) > 0){
+            throw new ResourceUnavailableException("审核认证已申请");
+        }
         if (StringUtils.isEmpty(param.getStoreAddress())){
             param.setStoreAddress(param.getStoreAddress());
         }
@@ -66,7 +75,7 @@ public class MerchantAuthServiceImpl extends ServiceImpl<MerchantAuthMapper, Mer
         }
         merchantAuth.setApplicationTime(new Date());
         merchantAuth.setApplicant(userId);
-        merchantAuth.setReviewStatus("2");
+        merchantAuth.setReviewStatus("1");
         this.save(merchantAuth);
         MerchantModifyParam param1 = new MerchantModifyParam();
         param1.setName(param.getStoreName());
@@ -92,7 +101,8 @@ public class MerchantAuthServiceImpl extends ServiceImpl<MerchantAuthMapper, Mer
         }else{
             this.merchantService.updateMerchant(merchant.getId(),param1);
         }
-
+        //首信易商户子商户认证
+        merchantRelationService.registerMerchantId(merchantAuth);
         return merchantAuth.getId();
     }
 
@@ -102,8 +112,12 @@ public class MerchantAuthServiceImpl extends ServiceImpl<MerchantAuthMapper, Mer
             param.setStoreAddress(param.getStoreAddress());
         }
         MerchantAuth merchantAuth = AssertUtils.nonnull(this.getById(id), "商家认证不存在");
+        String reviewStatus = merchantAuth.getReviewStatus();
+        if("2".equals(reviewStatus)){
+            throw new ResourceUnavailableException("已认证成功,不可重复认证");
+        }
         MerchantAuthCopier.INSTANCE.copying(param, merchantAuth);
-        merchantAuth.setReviewStatus("2");
+        merchantAuth.setReviewStatus("1");
         merchantAuth.setId(id);
         this.updateById(merchantAuth);
         MerchantModifyParam param1 = new MerchantModifyParam();
@@ -131,7 +145,8 @@ public class MerchantAuthServiceImpl extends ServiceImpl<MerchantAuthMapper, Mer
         }else{
             this.merchantService.updateMerchant(merchantIds.get(0),param1);
         }
-
+        //首信易商户子商户认证
+        merchantRelationService.registerMerchantId(merchantAuth);
     }
 
     @Override
@@ -179,18 +194,27 @@ public class MerchantAuthServiceImpl extends ServiceImpl<MerchantAuthMapper, Mer
     }
 
     @Override
-    public void certificationAudit(Long id, String state,String message ) {
+    public void certificationAudit(Long id, String state, String message) {
         Long userId = SessionContextHolder.getId();
         MerchantAuth merchantAuth = AssertUtils.nonnull(this.getById(id), "商家认证不存在");
         merchantAuth.setReviewStatus(state);
         merchantAuth.setReviewTime(new Date());
         merchantAuth.setReviewer(userId.toString());
         merchantAuth.setMessage(message);
-        this.updateById(merchantAuth);
-        if (StringUtils.notEmpty(state) && "1".equals(state)){
-            this.userClient.updateUserRole(merchantAuth.getApplicant());
-            //注册商家号
-            merchantRelationService.registerMerchantId(merchantAuth);
-        }
+        DatabaseContextHolder.transactional((Executor) () -> {
+            this.updateById(merchantAuth);
+            if (StringUtils.notEmpty(state) && "1".equals(state)) {
+                //注册商家号
+                merchantRelationService.registerMerchantId(merchantAuth);
+            }
+        });
+    }
+
+    @Override
+    public int updateStatus(Long userId, Integer status) {
+        UpdateWrapper<MerchantAuth> update = Wrappers.update();
+        update.set("review_status", status);
+        update.eq("applicant", userId);
+        return baseMapper.update(null, update);
     }
 }

+ 135 - 17
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/MerchantRelationServiceImpl.java

@@ -1,24 +1,28 @@
 package com.chelvc.cloud.vehicle.server.service.impl;
 
 import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.parser.Feature;
 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.user.client.UserClient;
 import com.chelvc.cloud.vehicle.client.constant.TradeConstant;
+import com.chelvc.cloud.vehicle.client.util.SFTPUtils;
 import com.chelvc.cloud.vehicle.server.dao.MerchantRelationMapper;
-import com.chelvc.cloud.vehicle.server.entity.Merchant;
-import com.chelvc.cloud.vehicle.server.entity.MerchantApplyRecord;
-import com.chelvc.cloud.vehicle.server.entity.MerchantAuth;
-import com.chelvc.cloud.vehicle.server.entity.MerchantRelation;
+import com.chelvc.cloud.vehicle.server.entity.*;
 import com.chelvc.cloud.vehicle.server.handle.TradeHandle;
 import com.chelvc.cloud.vehicle.server.service.MerchantApplyRecordService;
 import com.chelvc.cloud.vehicle.server.service.MerchantRelationService;
 import com.chelvc.cloud.vehicle.server.service.MerchantService;
+import com.chelvc.framework.common.exception.ResourceUnavailableException;
+import com.upay.sdk.Constants;
+import com.upay.sdk.core.CipherWrapper;
 import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 
+import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.UUID;
 
@@ -38,7 +42,7 @@ public class MerchantRelationServiceImpl extends ServiceImpl<MerchantRelationMap
 
     @Override
     public void registerMerchantId(MerchantAuth merchantAuth) {
-        Merchant merchant = merchantService.getById(merchantAuth.getId());
+        Merchant merchant = merchantService.queryByApplicant(merchantAuth.getApplicant());
         String requestId = UUID.randomUUID().toString().replaceAll("-", "");
         JSONObject jsonObject = new JSONObject();
         String operationType = "CREATE";
@@ -51,9 +55,9 @@ public class MerchantRelationServiceImpl extends ServiceImpl<MerchantRelationMap
         //商户基本信息
         JSONObject baseInfo = new JSONObject();
         baseInfo.put("signedType", "BY_SPLIT_BILL");
-        baseInfo.put("signedName", merchantAuth.getLegalRepresentativeName());
+        baseInfo.put("signedName", merchantAuth.getBusinessName());
         baseInfo.put("registerRole", "INDIVIDUAL_BUSINESS"); //个体工商户
-        baseInfo.put("cerType", "INDIVIDUAL_BUSINESS_LICENCE "); //个体工商户营业执照
+        baseInfo.put("cerType", "INDIVIDUAL_BUSINESS_LICENCE"); //个体工商户营业执照
         baseInfo.put("signedShorthand", merchantAuth.getStoreName());
         baseInfo.put("businessAddressProvince", merchant.getProvince());
         baseInfo.put("businessAddressCity", merchant.getCity());
@@ -66,9 +70,7 @@ public class MerchantRelationServiceImpl extends ServiceImpl<MerchantRelationMap
 
         //结算信息
         JSONObject bankCardInfo = new JSONObject();
-        //bankCardInfo.put("bankName", ""); //开户行名称
-        //bankCardInfo.put("bankBranchName", ""); //支行名称
-        bankCardInfo.put("accountName", merchantAuth.getAccountName()); //开户名称
+        bankCardInfo.put("accountName", merchantAuth.getLegalRepresentativeName()); //开户名称
         bankCardInfo.put("bankCardNo", merchantAuth.getBankCardNo()); //开户账号
         bankCardInfo.put("accountType", "PRIVATE");
         bankCardInfo.put("liquidationType", "WITHDRAW");
@@ -83,16 +85,33 @@ public class MerchantRelationServiceImpl extends ServiceImpl<MerchantRelationMap
         certificateInfo.put("legalPersonPhone", merchantAuth.getMobileNumber());
         certificateInfo.put("legalPersonIdType", "IDCARD");
         certificateInfo.put("legalPersonIdNo", merchantAuth.getIdCardNumber());
-        certificateInfo.put("idEffectiveDateStart", merchantAuth.getIdCardExpirationDateStart());  //身份证号有效期开始
-        certificateInfo.put("idEffectiveDateEnd", merchantAuth.getIdCardExpirationDate());
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+        Date idCardExpirationDateStart = merchantAuth.getIdCardExpirationDateStart();
+        certificateInfo.put("idEffectiveDateStart", formatter.format(idCardExpirationDateStart));  //身份证号有效期开始
+        Date idCardExpirationDate = merchantAuth.getIdCardExpirationDate();
+        certificateInfo.put("idEffectiveDateEnd", formatter.format(idCardExpirationDate));
         certificateInfo.put("cerNo", merchantAuth.getBusinessLicenseId());
         certificateInfo.put("sellingArea", "C");
         certificateInfo.put("staffSize", "C");
-        certificateInfo.put("businessLicensePath", ""); //营业执照照片路径
-        certificateInfo.put("openAccountPath", "");  //	开户许可证照片路径
-        certificateInfo.put("legalIdCardProsPath", "");  //	法人证件人像面路径
-        certificateInfo.put("legalIdCardConsPath", "");  //	法人证件国徽面路径
-        certificateInfo.put("legalPersonBankCardPath", "");  //	法人银行卡图影印件路径
+        String businessPhoto = merchantAuth.getBusinessPhoto();
+        String businessPhotoPath = SFTPUtils.ftpUpload(businessPhoto,
+                merchant.getId() + "-businessLicensePath." + SFTPUtils.getSuffix(businessPhoto));
+        certificateInfo.put("businessLicensePath", businessPhotoPath); //营业执照照片路径
+
+        /*String businessLicensePhoto = merchantAuth.getBusinessLicensePhoto();
+        String openAccountPath = SFTPUtils.ftpUpload(businessLicensePhoto,
+                merchant.getId() + "-openAccountPath." + SFTPUtils.getSuffix(businessLicensePhoto));
+        certificateInfo.put("openAccountPath", openAccountPath);*/  //	开户许可证照片路径
+
+        String idCardFrontPhoto = merchantAuth.getIdCardFrontPhoto();
+        String legalIdCardProsPath = SFTPUtils.ftpUpload(idCardFrontPhoto,
+                merchant.getId() + "-legalIdCardProsPath." + SFTPUtils.getSuffix(idCardFrontPhoto));
+        certificateInfo.put("legalIdCardProsPath", legalIdCardProsPath);  //	法人证件人像面路径
+
+        String idCardBackPhoto = merchantAuth.getIdCardBackPhoto();
+        String legalIdCardConsPath = SFTPUtils.ftpUpload(idCardBackPhoto,
+                merchant.getId() + "-legalIdCardConsPath." + SFTPUtils.getSuffix(idCardBackPhoto));
+        certificateInfo.put("legalIdCardConsPath", legalIdCardConsPath);  //	法人证件国徽面路径
         jsonObject.put("certificateInfo", certificateInfo);
 
         //商户合同信息
@@ -110,6 +129,8 @@ public class MerchantRelationServiceImpl extends ServiceImpl<MerchantRelationMap
             recordStatus = 2;
         } else {
             recordStatus = 1;
+            String errorMessage = json.getString("errorMessage");
+            throw new ResourceUnavailableException("【首信易】:"+errorMessage);
         }
         String subMerchantId = json.getString("subMerchantId");
         MerchantApplyRecord record = new MerchantApplyRecord();
@@ -124,8 +145,105 @@ public class MerchantRelationServiceImpl extends ServiceImpl<MerchantRelationMap
         merchantApplyRecordService.insert(record);
     }
 
+    @Override
+    public void registerMerchantId(UserAuth userAuth) {
+        String requestId = UUID.randomUUID().toString().replaceAll("-", "");
+        JSONObject jsonObject = new JSONObject();
+        String operationType = "CREATE";
+        jsonObject.put("merchantId", TradeConstant.PARTNER_ID);
+        jsonObject.put("requestId", requestId);
+        jsonObject.put("operationType", operationType);
+        jsonObject.put("notifyUrl", TradeConstant.MERCHANT_NET_IN_NOTIFY_URL);
+        jsonObject.put("extendedParameters", "sendActiveEmail:FALSE,sendExpressPayMsg:FALSE");
+
+        //商户基本信息
+        JSONObject baseInfo = new JSONObject();
+        baseInfo.put("signedType", "BY_SPLIT_BILL");
+        baseInfo.put("signedName", userAuth.getUserName());
+        baseInfo.put("registerRole", "NATURAL_PERSON"); //个体工商户
+        baseInfo.put("signedShorthand", userAuth.getUserName()); //商户简称
+        baseInfo.put("businessAddressProvince", userAuth.getProvince()); //省
+        baseInfo.put("businessAddressCity", userAuth.getCity());    //市
+        baseInfo.put("businessAddressArea", userAuth.getDistrict()); //区
+        baseInfo.put("businessAddress", userAuth.getAddress());    //经营地址
+        baseInfo.put("contactName", userAuth.getUserName()); //联系人姓名
+        baseInfo.put("contactEmail", userAuth.getEmail());  //联系人邮箱
+        baseInfo.put("contactPhone", userAuth.getPhone()); //联系人电话
+        jsonObject.put("baseInfo", baseInfo);
+
+        //结算信息
+        JSONObject bankCardInfo = new JSONObject();
+        bankCardInfo.put("accountName", userAuth.getUserName()); //开户名称
+        bankCardInfo.put("bankCardNo", userAuth.getBankCardNo()); //开户账号
+        bankCardInfo.put("liquidationType", "WITHDRAW");
+        bankCardInfo.put("withdrawRateType", "SINGLE");
+        bankCardInfo.put("withdrawRate", "1.00");
+        jsonObject.put("bankCardInfo", bankCardInfo);
+
+        //商户资质信息
+        JSONObject certificateInfo = new JSONObject();
+        certificateInfo.put("legalPersonName", userAuth.getUserName()); //法人姓名
+        certificateInfo.put("profession", "2");  //职业 固定销售
+        certificateInfo.put("legalPersonIdType", "IDCARD");
+        certificateInfo.put("legalPersonIdNo", userAuth.getIdCardNo());  //身份证号
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+        Date idCardExpirationDateStart = userAuth.getIdCardExpirationDateStart();
+        certificateInfo.put("idEffectiveDateStart", formatter.format(idCardExpirationDateStart));  //身份证号有效期开始
+        Date idCardExpirationDate = userAuth.getIdCardExpirationDate();
+        certificateInfo.put("idEffectiveDateEnd", formatter.format(idCardExpirationDate));
+
+        String idCardFrontPhoto = userAuth.getIdCardFrontPhoto();
+        String legalIdCardProsPath = SFTPUtils.ftpUpload(idCardFrontPhoto,
+                userAuth.getUserId() + "-legalIdCardProsPath." + SFTPUtils.getSuffix(idCardFrontPhoto));
+        certificateInfo.put("legalIdCardProsPath", legalIdCardProsPath);  //	法人证件人像面路径
+
+        String idCardBackPhoto = userAuth.getIdCardBackPhoto();
+        String legalIdCardConsPath = SFTPUtils.ftpUpload(idCardBackPhoto,
+                userAuth.getUserId() + "-legalIdCardConsPath." + SFTPUtils.getSuffix(idCardBackPhoto));
+        certificateInfo.put("legalIdCardConsPath", legalIdCardConsPath);  //	法人证件国徽面路径
+        jsonObject.put("certificateInfo", certificateInfo);
+
+        //商户合同信息
+        JSONObject contractInfo = new JSONObject();
+        contractInfo.put("receiverName", userAuth.getUserName());
+        contractInfo.put("receiverPhone", userAuth.getPhone());
+        contractInfo.put("receiverAddress", userAuth.getAddress());
+        jsonObject.put("contractInfo", contractInfo);
+
+        JSONObject json = TradeHandle.handle(String.valueOf(jsonObject), TradeConstant.DECLARE_URL,
+                TradeConstant.PARTNER_ID, null);
+        String status = json.getString("status");
+        int recordStatus = 0;
+        if("SUCCESS".equals(status)){
+            recordStatus = 2;
+        } else {
+            recordStatus = 1;
+            String errorMessage = json.getString("errorMessage");
+            throw new ResourceUnavailableException("【首信易】:"+errorMessage);
+        }
+        String subMerchantId = json.getString("subMerchantId");
+        MerchantApplyRecord record = new MerchantApplyRecord();
+        record.setUserId(userAuth.getUserId());
+        record.setType(1);
+        record.setRequestId(requestId);
+        record.setStatus(recordStatus);
+        record.setOperationType("CREATE");
+        record.setExamineStatus("PROCESSING");
+        record.setSubMerchantId(subMerchantId);
+        record.setCreateTime(new Date());
+        merchantApplyRecordService.insert(record);
+    }
+
     @Override
     public int insert(Long userId, Integer type, String sxyMerchantId) {
+        LambdaQueryWrapper<MerchantRelation> wrapper = Wrappers.lambdaQuery();
+        wrapper.eq(MerchantRelation::getType, type);
+        wrapper.eq(MerchantRelation::getUserId, userId);
+        MerchantRelation merchantRelation = baseMapper.selectOne(wrapper);
+        if(merchantRelation != null){
+            merchantRelation.setSxyMerchantId(sxyMerchantId);
+            return baseMapper.updateById(merchantRelation);
+        }
         MerchantRelation relation = new MerchantRelation();
         relation.setType(type);
         relation.setUserId(userId);

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

@@ -564,4 +564,11 @@ public class MerchantServiceImpl extends ServiceImpl<MerchantMapper, Merchant> i
         merchantApplyRecordService.updateByNotify(param);
     }
 
+    @Override
+    public Merchant queryByApplicant(Long applicant) {
+        return this.lambdaQuery()
+                .eq(Merchant::getUserId, applicant)
+                .one();
+    }
+
 }

+ 84 - 0
vehicle-server/src/main/java/com/chelvc/cloud/vehicle/server/service/impl/UserAuthServiceImpl.java

@@ -0,0 +1,84 @@
+package com.chelvc.cloud.vehicle.server.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+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.client.dto.UserAuthDTO;
+import com.chelvc.cloud.vehicle.client.param.UserAuthParam;
+import com.chelvc.cloud.vehicle.server.dao.UserAuthMapper;
+import com.chelvc.cloud.vehicle.server.entity.UserAuth;
+import com.chelvc.cloud.vehicle.server.service.MerchantRelationService;
+import com.chelvc.cloud.vehicle.server.service.UserAuthService;
+import com.chelvc.framework.base.context.SessionContextHolder;
+import com.chelvc.framework.common.exception.ResourceUnavailableException;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+
+@Service
+@RequiredArgsConstructor(onConstructor = @__(@Autowired))
+public class UserAuthServiceImpl extends ServiceImpl<UserAuthMapper, UserAuth> implements UserAuthService {
+    private final MerchantRelationService merchantRelationService;
+    @Override
+    public UserAuthDTO getUserAuthInfo(Long userId) {
+        if(userId == null){
+            throw new ResourceUnavailableException("请重新登录账号");
+        }
+        UserAuthDTO userAuthInfo = baseMapper.getUserAuthInfo(userId);
+        if(userAuthInfo == null){
+            return new UserAuthDTO(0);
+        }
+        return userAuthInfo;
+    }
+
+    @Override
+    public void userAuth(UserAuthParam param) {
+        Long userId = SessionContextHolder.getId();
+        LambdaQueryWrapper<UserAuth> wrapper = Wrappers.lambdaQuery();
+        wrapper.eq(UserAuth::getUserId, userId);
+        UserAuth userAuth = baseMapper.selectOne(wrapper);
+        if(userAuth == null){
+            userAuth = new UserAuth();
+            BeanUtils.copyProperties(param, userAuth);
+            userAuth.setUserId(userId);
+            userAuth.setCreateTime(LocalDateTime.now());
+            userAuth.setStatus(1);
+            baseMapper.insert(userAuth);
+        } else {
+            Integer status = userAuth.getStatus();
+            if(status == 2){
+                throw new ResourceUnavailableException("已认证成功,不可重复认证");
+            }
+            userAuth.setBankCardNo(param.getBankCardNo());
+            userAuth.setIdCardBackPhoto(param.getIdCardBackPhoto());
+            userAuth.setIdCardFrontPhoto(param.getIdCardFrontPhoto());
+            userAuth.setUserName(param.getUserName());
+            userAuth.setProvince(510000);   //四川省
+            userAuth.setCity(510100);       //成都市
+            userAuth.setDistrict(510116);   //双流区
+            userAuth.setPhone(param.getPhone());
+            userAuth.setEmail("chelvc@qq.com");
+            userAuth.setAddress("四川省成都市双流区");
+            userAuth.setIdCardExpirationDateStart(param.getIdCardExpirationDateStart());
+            userAuth.setIdCardExpirationDate(param.getIdCardExpirationDate());
+            userAuth.setAccountName(param.getUserName());
+            userAuth.setIdCardNo(param.getIdCardNo());
+            userAuth.setStatus(1);
+            baseMapper.updateById(userAuth);
+        }
+        //首信易个人子商户认证
+        merchantRelationService.registerMerchantId(userAuth);
+    }
+
+    @Override
+    public int updateStatus(Long userId, Integer status) {
+        UpdateWrapper<UserAuth> update = Wrappers.update();
+        update.set("status", status);
+        update.eq("user_id", userId);
+        return baseMapper.update(null, update);
+    }
+}

+ 0 - 1
vehicle-server/src/main/resources/application.yml

@@ -29,7 +29,6 @@ spring:
     nacos:
       discovery:
         namespace: ${spring.profiles.active}
-        group: igl
   datasource:
     driver-class-name: com.mysql.cj.jdbc.Driver
     hikari:

+ 12 - 0
vehicle-server/src/main/resources/mapper/UserAuthMapper.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.chelvc.cloud.vehicle.server.dao.UserAuthMapper">
+
+    <select id="getUserAuthInfo" resultType="com.chelvc.cloud.vehicle.client.dto.UserAuthDTO">
+        SELECT
+            *
+        FROM
+            user_auth
+        where user_id = #{userId}
+    </select>
+</mapper>