Эх сурвалжийг харах

feat(api): 新增对外开放接口功能

周玉环 8 цаг өмнө
parent
commit
6015202435
16 өөрчлөгдсөн 459 нэмэгдсэн , 1 устгасан
  1. 1 1
      xinkeaboard-seller/src/pages/settledManage/businessInfo/index.js
  2. 59 0
      xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/controller/api/seller/OpenAPIController.java
  3. 23 0
      xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/dao/read/api/EnquiryApiMapper.java
  4. 16 0
      xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/dao/read/api/GoodsApiMapper.java
  5. 37 0
      xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/dto/ProductInfoDto.java
  6. 28 0
      xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/interceptor/BearerTokenConfiguration.java
  7. 70 0
      xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/interceptor/BearerTokenInterceptor.java
  8. 38 0
      xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/model/api/EnquiryApiModel.java
  9. 29 0
      xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/model/api/GoodsApiModel.java
  10. 22 0
      xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/vo/api/APIRequestVO.java
  11. 49 0
      xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/vo/api/EnquiryInfoVO.java
  12. 19 0
      xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/vo/api/EnquiryPageVO.java
  13. 18 0
      xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/vo/api/ProductInfoVO.java
  14. 1 0
      xinkeaboard-server/b2b2c-web/src/main/resources/application.yml
  15. 29 0
      xinkeaboard-server/b2b2c-web/src/main/resources/mapper/read/api/EnquiryApiMapper.xml
  16. 20 0
      xinkeaboard-server/b2b2c-web/src/main/resources/mapper/read/api/GoodsApiMapper.xml

+ 1 - 1
xinkeaboard-seller/src/pages/settledManage/businessInfo/index.js

@@ -459,7 +459,7 @@ export default class BusinessInfo extends Component {
     } = this.state;
     
     return (
-      <div style={{ flex: 1 }}>
+      <div style={{ flex: 1, overflow: 'auto' }}>
         <div className={styles.title}>
           {sldLlineRtextAddGoodsAddMargin('#69A2F2', `${sldComLanguage('经营信息')}`, 0, 0, 5)}
         </div>

+ 59 - 0
xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/controller/api/seller/OpenAPIController.java

@@ -0,0 +1,59 @@
+package com.slodon.b2b2c.controller.api.seller;
+
+import java.util.List;
+
+import com.slodon.b2b2c.core.controller.BaseController;
+import com.slodon.b2b2c.core.response.JsonResult;
+import com.slodon.b2b2c.core.response.SldResponse;
+import com.slodon.b2b2c.model.api.EnquiryApiModel;
+import com.slodon.b2b2c.model.api.GoodsApiModel;
+import com.slodon.b2b2c.vo.api.APIRequestVO;
+import com.slodon.b2b2c.vo.api.EnquiryPageVO;
+import com.slodon.b2b2c.vo.api.ProductInfoVO;
+import io.swagger.annotations.Api;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+@Api(tags = "seller-对外接口")
+@RestController
+@RequestMapping("/openapi")
+@Slf4j
+public class OpenAPIController extends BaseController {
+
+    @Resource private GoodsApiModel goodsApiModel;
+
+    @Resource private EnquiryApiModel enquiryApiModel;
+
+
+    /** 外部api请求获取产品列表 */
+    @PostMapping("/product/list")
+    @ResponseBody
+    public JsonResult<List<ProductInfoVO>> listProducts(
+            @RequestBody APIRequestVO apiRequest) {
+        log.info("苏豪通请求该商家产品列表 parameter: {}", apiRequest.getStoreId());
+        List<ProductInfoVO> list = goodsApiModel.getGoodsByStoreId(apiRequest.getStoreId());
+        if (!CollectionUtils.isEmpty(list)) {
+            return SldResponse.success(list);
+        } else {
+            return SldResponse.fail("No product information found for this store");
+        }
+    }
+
+    /** 外部api请求获取询盘列表 */
+    @PostMapping("/enquiry/list")
+    @ResponseBody
+    public JsonResult<EnquiryPageVO> listEnquires(
+            @RequestBody APIRequestVO apiRequest) {
+        log.info("苏豪通请求该商家产品列表 parameter: {}", apiRequest.getStoreId());
+        EnquiryPageVO enquiryPage = enquiryApiModel.getEnquiryByStoreId(apiRequest);
+        if (enquiryPage!=null) {
+            return SldResponse.success(enquiryPage);
+        } else {
+            return SldResponse.fail("No enquiry information was found for this store");
+        }
+    }
+
+
+}

+ 23 - 0
xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/dao/read/api/EnquiryApiMapper.java

@@ -0,0 +1,23 @@
+package com.slodon.b2b2c.dao.read.api;
+
+import com.slodon.b2b2c.vo.api.APIRequestVO;
+import com.slodon.b2b2c.vo.api.EnquiryInfoVO;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface EnquiryApiMapper {
+    /**
+     *
+     * @param apiRequestVO 商家id、分页信息
+     * @return
+     */
+    List<EnquiryInfoVO> getEnquiryByStoreId(APIRequestVO apiRequestVO);
+
+    /**
+     *
+     * @param storeId 商家id
+     * @return
+     */
+    Long countEnquiryByStoreId(@Param("storeId") Long storeId);
+}

+ 16 - 0
xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/dao/read/api/GoodsApiMapper.java

@@ -0,0 +1,16 @@
+package com.slodon.b2b2c.dao.read.api;
+
+
+import com.slodon.b2b2c.dto.ProductInfoDto;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface GoodsApiMapper{
+    /**
+     *
+     * @param storeId 商家id
+     * @return
+     */
+    List<ProductInfoDto> getGoodsByStoreId(@Param("storeId") Long storeId);
+}

+ 37 - 0
xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/dto/ProductInfoDto.java

@@ -0,0 +1,37 @@
+package com.slodon.b2b2c.dto;
+
+import com.slodon.b2b2c.core.util.FileUrlUtil;
+import com.slodon.b2b2c.vo.api.ProductInfoVO;
+
+
+/**
+ * @author sunshihao
+ * @version 1.0
+ * @description: 数据库查询对象
+ * @date 2025/7/30 13:10
+ */
+public class ProductInfoDto {
+
+    private Long productId;
+
+    private String productName;
+
+    private String productNameCn;
+
+    private String productImage;
+
+    private Integer self;
+
+    private String storeName;
+
+    public ProductInfoVO productConverter() {
+        ProductInfoVO vo = new ProductInfoVO();
+        vo.setProductId(productId);
+        vo.setProductName(productName);
+        vo.setProductName(productName);
+        vo.setProductNameCn(productNameCn);
+        vo.setProductImage(FileUrlUtil.getFileUrl(productImage, null));
+        vo.setAuthorName(storeName);
+        return vo;
+    }
+}

+ 28 - 0
xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/interceptor/BearerTokenConfiguration.java

@@ -0,0 +1,28 @@
+package com.slodon.b2b2c.interceptor;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * @author sunshihao
+ * @version 1.0
+ * @description: TODO
+ * @date 2025/7/30 10:08
+ */
+@Configuration
+public class BearerTokenConfiguration implements WebMvcConfigurer {
+    public static String[] urlList = new String[]{"/openapi/**"};
+
+    @Bean
+    public BearerTokenInterceptor tokenConfiguration(){
+        return new BearerTokenInterceptor();
+    }
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        registry.addInterceptor(tokenConfiguration()).addPathPatterns(urlList);
+    }
+
+}

+ 70 - 0
xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/interceptor/BearerTokenInterceptor.java

@@ -0,0 +1,70 @@
+package com.slodon.b2b2c.interceptor;
+
+import cn.hutool.crypto.digest.HMac;
+import cn.hutool.crypto.digest.HmacAlgorithm;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @description: 认证拦截器
+ * @author sunshihao
+ * @date: 2025/7/30 10:05
+ */
+@Slf4j
+public class BearerTokenInterceptor implements HandlerInterceptor {
+    private static final String SK = "Bearer uxl9Wpzh65vXNUyDvynJDjBo";
+    // 允许的最大时间差(5分钟)
+    private static final long MAX_TIME_DIFF = 5*60*1000;
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
+        log.info("request URI = {}", request.getRequestURI());
+        log.info("request QueryString = {}", request.getQueryString());
+        String msgId = request.getHeader("msgId");
+        String signature = request.getHeader("signature");
+        String nonce = request.getHeader("nonce");
+        String url = request.getHeader("url");
+        if(msgId==null||signature==null||nonce==null||url==null){
+            log.error("Incomplete certification parameters");
+            return false;
+        }
+        return validateAuthToken(msgId,url,nonce,signature);
+    }
+
+    private boolean validateAuthToken(String msgId, String url, String nonce, String signature) {
+        try {
+            long clientTime = Long.parseLong(nonce);
+            long serverTime = System.currentTimeMillis();
+            long timeDiff = Math.abs(serverTime - clientTime);
+            if (timeDiff > MAX_TIME_DIFF) {
+                log.error("Nonce overtime");
+                return false;
+            }
+        } catch (NumberFormatException e) {
+            log.error("Invalid nonce format");
+            return false;
+        }
+        if(!signature.equals(generateSign(msgId,url,nonce))){
+            log.error("Invalid signature");
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * @description:计算请求签名
+     * @param msgId 唯一标识
+     * @param url 请求相对路径
+     * @param nonce 时间戳
+     * @author sunshihao
+     * @date: 2025/7/29 14:11
+     */
+    private String generateSign(String msgId, String url, String nonce) {
+        String newStr = String.join("&", msgId,url, nonce);
+        HMac mac = new HMac(HmacAlgorithm.HmacSHA256, SK.getBytes());
+        return mac.digestHex(newStr);
+    }
+
+}

+ 38 - 0
xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/model/api/EnquiryApiModel.java

@@ -0,0 +1,38 @@
+package com.slodon.b2b2c.model.api;
+
+import com.slodon.b2b2c.dao.read.api.EnquiryApiMapper;
+import com.slodon.b2b2c.vo.api.APIRequestVO;
+import com.slodon.b2b2c.vo.api.EnquiryInfoVO;
+import com.slodon.b2b2c.vo.api.EnquiryPageVO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component
+@Slf4j
+public class EnquiryApiModel {
+
+    public static final long ZERO = 0L;
+    @Resource
+    private EnquiryApiMapper enquiryApiMapper;
+
+    public EnquiryPageVO getEnquiryByStoreId(APIRequestVO apiRequestVO){
+        Long count = enquiryApiMapper.countEnquiryByStoreId(apiRequestVO.getStoreId());
+        if(!count.equals(ZERO)){
+            List<EnquiryInfoVO> list = enquiryApiMapper.getEnquiryByStoreId(apiRequestVO);
+//            List<EnquiryInfoVO> enquiryInfoVLists=  list.stream().map(EnquiryInfoVO::enquiryInfoVOConverter).collect(Collectors.toList());
+            EnquiryPageVO enquiryPage = new EnquiryPageVO();
+            enquiryPage.setSize((long) apiRequestVO.getPageSize());
+            enquiryPage.setCurrent((long) apiRequestVO.getPageNo());
+            enquiryPage.setTotal(count);
+            enquiryPage.setRecords(list);
+            return enquiryPage;
+        } else {
+            return null;
+        }
+    }
+
+}

+ 29 - 0
xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/model/api/GoodsApiModel.java

@@ -0,0 +1,29 @@
+package com.slodon.b2b2c.model.api;
+
+import com.slodon.b2b2c.dao.read.api.GoodsApiMapper;
+import com.slodon.b2b2c.dto.ProductInfoDto;
+import com.slodon.b2b2c.vo.api.ProductInfoVO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.CollectionUtils;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component
+@Slf4j
+public class GoodsApiModel {
+
+    @Resource
+    private GoodsApiMapper goodsApiMapper;
+
+    public List<ProductInfoVO>  getGoodsByStoreId(Long storeId){
+        List<ProductInfoDto> list = goodsApiMapper.getGoodsByStoreId(storeId);
+        if (!CollectionUtils.isEmpty(list)) {
+            return list.stream().map(ProductInfoDto::productConverter).collect(Collectors.toList());
+        } else {
+            return null;
+        }
+    }
+}

+ 22 - 0
xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/vo/api/APIRequestVO.java

@@ -0,0 +1,22 @@
+package com.slodon.b2b2c.vo.api;
+
+import lombok.Data;
+
+@Data
+public class APIRequestVO {
+
+    /**
+     * 商家id
+     */
+    Long storeId;
+    /**
+     * 页面数量
+     */
+    private Integer pageNo = 1;
+
+    /**
+     * 页面大小
+     */
+    private Integer pageSize = 10;
+
+}

+ 49 - 0
xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/vo/api/EnquiryInfoVO.java

@@ -0,0 +1,49 @@
+package com.slodon.b2b2c.vo.api;
+
+
+import lombok.Data;
+
+
+@Data
+public class EnquiryInfoVO {
+
+    private Long id;
+
+    private String name;
+
+    private String email;
+
+    private String phone;
+
+    private String message;
+
+    private String pageUrl;
+
+    private String siteHost;
+
+    private String createTime;
+
+    public EnquiryInfoVO enquiryInfoVOConverter() {
+        EnquiryInfoVO vo = new EnquiryInfoVO();
+        vo.setId(id);
+        vo.setName(name);
+        vo.setEmail(email);
+        vo.setPhone(phone);
+        vo.setMessage(message);
+        vo.setPageUrl(pageUrl);
+        vo.setSiteHost(removeHttpsPrefix(pageUrl));
+        vo.setCreateTime(createTime);
+        return vo;
+    }
+
+    public String removeHttpsPrefix(String url) {
+        if (url != null && url.startsWith("https://")) {
+            return url.substring("https://".length());
+        }else if (url != null && url.startsWith("http://")) {
+            return url.substring("http://".length());
+        }
+        return url; // 如果不是以 http[s]:// 开头,或者为 null,则原样返回
+    }
+
+
+}

+ 19 - 0
xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/vo/api/EnquiryPageVO.java

@@ -0,0 +1,19 @@
+package com.slodon.b2b2c.vo.api;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class EnquiryPageVO {
+
+    private Long total;
+
+    private Long size;
+
+    private Long current;
+
+    private Long pages;
+
+    private List<EnquiryInfoVO> records;
+}

+ 18 - 0
xinkeaboard-server/b2b2c-web/src/main/java/com/slodon/b2b2c/vo/api/ProductInfoVO.java

@@ -0,0 +1,18 @@
+package com.slodon.b2b2c.vo.api;
+
+import lombok.Data;
+
+@Data
+public class ProductInfoVO {
+
+    private Long productId;
+
+    private String productName;
+
+    private String productNameCn;
+
+    private String productImage;
+
+    private String authorName;
+
+}

+ 1 - 0
xinkeaboard-server/b2b2c-web/src/main/resources/application.yml

@@ -42,6 +42,7 @@ secure:
       - "/v3/goods/front/goods/searchWords/list"
       - "/v3/member/front/active/**"
       - "/v3/open/api/sso/login/**"
+      - "/openapi/**"
     #      - "/v3/seller/seller/enquiry/sendMsgStr"
     login-urls: #登录接口
       - "/v3/frontLogin/**"

+ 29 - 0
xinkeaboard-server/b2b2c-web/src/main/resources/mapper/read/api/EnquiryApiMapper.xml

@@ -0,0 +1,29 @@
+<?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.slodon.b2b2c.dao.read.api.EnquiryApiMapper">
+    <resultMap id="BaseResultMap" type="com.slodon.b2b2c.vo.api.EnquiryInfoVO">
+        <id column="id" jdbcType="BIGINT" property="id" />
+        <result column="name" jdbcType="VARCHAR" property="name" />
+        <result column="email" jdbcType="VARCHAR" property="email" />
+        <result column="phone" jdbcType="VARCHAR" property="phone" />
+        <result column="message" jdbcType="VARCHAR" property="message" />
+<!--        <result column="page_url" jdbcType="VARCHAR" property="pageUrl" />-->
+        <result column="create_time" jdbcType="VARCHAR" property="createTime" />
+
+    </resultMap>
+
+    <select id="getEnquiryByStoreId" resultMap="BaseResultMap">
+        SELECT id,name,email,phone,message,DATE_FORMAT(create_time, '%Y/%m/%d %H:%i:%s') AS create_time
+        FROM enquiry
+        where store_id = #{storeId} and valid_status = 0
+        order by last_time desc
+        limit #{pageNo},#{pageSize}
+    </select>
+
+    <select id="countEnquiryByStoreId" resultType="java.lang.Long">
+        SELECT count(1)
+        FROM enquiry
+        where store_id = #{storeId} and valid_status = 0
+    </select>
+
+</mapper>

+ 20 - 0
xinkeaboard-server/b2b2c-web/src/main/resources/mapper/read/api/GoodsApiMapper.xml

@@ -0,0 +1,20 @@
+<?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.slodon.b2b2c.dao.read.api.GoodsApiMapper">
+    <resultMap id="BaseResultMap" type="com.slodon.b2b2c.dto.ProductInfoDto">
+        <id column="goods_id" jdbcType="BIGINT" property="productId" />
+        <result column="goods_name" jdbcType="VARCHAR" property="productName" />
+        <result column="goods_name_cn" jdbcType="VARCHAR" property="productNameCn" />
+        <result column="main_image" jdbcType="VARCHAR" property="productImage" />
+        <result column="is_self" jdbcType="INTEGER" property="self" />
+        <result column="store_name" jdbcType="VARCHAR" property="storeName" />
+    </resultMap>
+
+    <select id="getGoodsByStoreId" resultMap="BaseResultMap">
+        SELECT goods_id,goods_name,goods_name_cn,main_image,is_self,store_name
+        FROM `goods`
+        where store_id = #{storeId} and is_delete = 0
+        order by update_time desc
+    </select>
+
+</mapper>