1.4 对接SaaS代码实现

根据前边接口SaaS步骤 的分析,需要在商户平台 完成新增员工、新增门店、设置门店管理员等功能。

1.4.1 商户服务新增门店接口

1.4.1.1 接口定义

在商户服务定义新增门店接口

1、接口描述如下:

1)商户注册的同时新增默认门店

2、接口定义如下:

生成StoreDTO类。

在MerchantService接口类中定义如下接口:

/**  
 \* 商户下新增门店  
 \* @param storeDTO  
 */  
StoreDTO createStore(StoreDTO storeDTO) throws BusinessException;
1.4.1.2 接口实现

编写StoreConvert。

package com.huiminpay.merchant.convert;

import com.huiminpay.merchant.api.dto.StoreDTO;
import com.huiminpay.merchant.entity.Store;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

import java.util.List;

@Mapper
public interface StoreConvert {

    StoreConvert INSTANCE = Mappers.getMapper(StoreConvert.class);

    StoreDTO entity2dto(Store entity);

    Store dto2entity(StoreDTO dto);

    List<StoreDTO> listentity2dto(List<Store> staff);
}

在MerchantServiceImpl类中实现createStore方法。

/**
     *  商户下 新增门店
     * @author glls
     * @param storeDTO
     * @return com.huiminpay.merchant.api.dto.StoreDTO
     * @date 2021/2/27 11:48
     */
@Override
public StoreDTO createStore(StoreDTO storeDTO) throws BusinessException {
    Store store = StoreConvert.INSTANCE.dto2entity(storeDTO);
    log.info("商户下新增门店"+ JSON.toJSONString(store));
    storeMapper.insert(store);
    return StoreConvert.INSTANCE.entity2dto(store);
}

1.4.2 商户服务新增员工接口

1.4.2.1 接口定义

在商户服务定义新增员工接口

1、接口描述如下:

1)接收商户填写的员工数据

2)请求商户服务进行新增员工

员工的账号和手机号需要保持唯一性。

3)返回结果

2、接口定义如下:

生成StaffDTO类。 员工信息类

在MerchantService接口类中定义如下接口:

/**
* 商户新增员工
* @param staffDTO
*/
StaffDTO createStaff(StaffDTO staffDTO) throws BusinessException;
1.4.2.2 接口实现

编写StaffConvert。

package com.huiminpay.merchant.convert;

import com.huiminpay.merchant.api.dto.StaffDTO;
import com.huiminpay.merchant.entity.Staff;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

import java.util.List;

@Mapper
public interface StaffConvert {

    StaffConvert INSTANCE = Mappers.getMapper(StaffConvert.class);

    StaffDTO entity2dto(Staff entity);

    Staff dto2entity(StaffDTO dto);

    List<StaffDTO> listentity2dto(List<Staff> staff);

}

在MerchantServiceImpl类中定义createStaff方法:

@Autowired
private StaffMapper staffMapper;

/**
     * 商户下 新增员工
     * @param staffDTO
     */
@Override
public StaffDTO createStaff(StaffDTO staffDTO) throws BusinessException {
    //1.校验手机号格式及是否存在
    String mobile = staffDTO.getMobile();
    if(StringUtils.isBlank(mobile)){
        throw new BusinessException(CommonErrorCode.E_100112);
    }
    //根据商户id和手机号校验唯一性
    if(isExistStaffByMobile(mobile, staffDTO.getMerchantId())){
        throw new BusinessException(CommonErrorCode.E_100113);
    }
    //2.校验用户名是否为空
    String username = staffDTO.getUsername();
    if(StringUtils.isBlank(username)){
        throw new BusinessException(CommonErrorCode.E_100110);
    }
    //根据商户id和账号校验唯一性
    if(isExistStaffByUserName(username, staffDTO.getMerchantId())){
        throw new BusinessException(CommonErrorCode.E_100114);
    }
    Staff entity = StaffConvert.INSTANCE.dto2entity(staffDTO);
    log.info("商户下新增员工");
    staffMapper.insert(entity);
    return StaffConvert.INSTANCE.entity2dto(entity);
}

/**
     * 根据手机号判断员工是否已在指定商户存在
     * @param mobile 手机号
     * @return
     */
private boolean isExistStaffByMobile(String mobile, Long merchantId) {
    LambdaQueryWrapper<Staff> lambdaQueryWrapper = new LambdaQueryWrapper<Staff>();
    lambdaQueryWrapper.eq(Staff::getMobile, mobile).eq(Staff::getMerchantId, merchantId);
    int i = staffMapper.selectCount(lambdaQueryWrapper);
    return i > 0;
}

/**
     * 根据账号判断员工是否已在指定商户存在
     * @param userName
     * @param merchantId
     * @return
     */
private boolean isExistStaffByUserName(String userName, Long merchantId) {
    LambdaQueryWrapper<Staff> lambdaQueryWrapper = new LambdaQueryWrapper<Staff>();
    lambdaQueryWrapper.eq(Staff::getUsername, userName).eq(Staff::getMerchantId,merchantId);
    int i = staffMapper.selectCount(lambdaQueryWrapper);
    return i > 0;
}

1.4.3 商户服务门店设置管理员接口

1.4.3.1 接口定义

1、接口描述如下:绑定门店和员工对应关系

2、接口定义如下:

在MerchantService接口类中定义如下接口:

/**
     * 为门店设置管理员
     * @param storeId
     * @param staffId
     * @throws BusinessException
     */
void bindStaffToStore(Long storeId, Long staffId) throws BusinessException;
1.4.3.2 接口实现

在MerchantServiceImpl实现bindStaffToStore。

/**
     *  给门店设置管理员
     * @author glls
     * @param storeId 门店id
     * @param staffId  员工id
     * @return void
     * @date 2021/2/27 13:00
     */
@Override
public void bindStaffToStore(Long storeId, Long staffId) throws BusinessException {
    StoreStaff storeStaff = new StoreStaff();
    storeStaff.setStoreId(storeId);
    storeStaff.setStaffId(staffId);
    storeStaffMapper.insert(storeStaff);
}

1.4.4 商户服务商户注册接口修改

1.4.4.1 接口说明

SaaS系统的用户服务提供注册租户的接口,如下 :

/**
     * 创建租户
     * 新增租户、新增租户管理员,同时初始化套餐
     * 1.若管理员用户名已存在(目前不会出现,用户名内部随机生成)
     * 2.手机号已存在,禁止创建
     * @param createTenantRequest 创建租户请求信息
     * @return
     */
 TenantDTO createTenantAndAccount(CreateTenantRequestDTO createTenantRequest);

接口参数:

1、手机号

2、账号

3、密码

4、租户类型:huimin-merchant 5、默认套餐:huimin-merchant

6、租户名称,同账号名

1.4.4.2 接口实现

1、添加SaaS的用户服务API依赖:打开huiminpay-merchant-service工程的pom.xml

<dependency>
     <groupId>com.huiminpay</groupId>
     <artifactId>huiminpay-user-api</artifactId>
     <version>1.0-SNAPSHOT</version>
 </dependency>

2、MerchantServiceImpl,完善createMerchant()方法:

/**
     * 注册商户服务接口,接收账号、密码、手机号,为了可扩展性使用merchantDto接收数据
     *
     *  调用SaaS接口: 新增租户 用户 绑定租户和用户的关系 初始化权限
     * @param merchantDTO 商户注册信息
     * @return 注册成功的商户信息
     */
@Override
@Transactional
public MerchantDTO createMerchant(MerchantDTO merchantDTO)  throws BusinessException {
    // 1.校验
    if (merchantDTO == null) {
        throw new BusinessException(CommonErrorCode.E_100108);
    }
    //手机号非空校验
    if (StringUtils.isBlank(merchantDTO.getMobile())) {
        throw new BusinessException(CommonErrorCode.E_100112);
    }
    //校验手机号的合法性
    if (!PhoneUtil.isMatches(merchantDTO.getMobile())) {
        throw new BusinessException(CommonErrorCode.E_100109);
    }
    //联系人非空校验
    if (StringUtils.isBlank(merchantDTO.getUsername())) {
        throw new BusinessException(CommonErrorCode.E_100110);
    }
    //密码非空校验
    if (StringUtils.isBlank(merchantDTO.getPassword())) {
        throw new BusinessException(CommonErrorCode.E_100111);
    }

    //校验商户手机号的唯一性,根据商户的手机号查询商户表,如果存在记录则说明已有相同的手机号重复
    LambdaQueryWrapper<Merchant> lambdaQryWrapper = new LambdaQueryWrapper<Merchant>()
        .eq(Merchant::getMobile,merchantDTO.getMobile());
    Integer count = merchantMapper.selectCount(lambdaQryWrapper);
    if(count>0){
        throw new BusinessException(CommonErrorCode.E_100113);
    }

    //2.调用SaaS接口 添加 租户并绑定和门店 员工 商户之间的关系
    /**
         1、手机号
         2、账号
         3、密码
         4、租户类型:huimin-merchant
         5、默认套餐:huimin-merchant
         6、租户名称,同账号名
         */
    CreateTenantRequestDTO createTenantRequestDTO = new CreateTenantRequestDTO();
    createTenantRequestDTO.setMobile(merchantDTO.getMobile());
    //租户的账号信息
    createTenantRequestDTO.setUsername(merchantDTO.getUsername());
    createTenantRequestDTO.setPassword(merchantDTO.getPassword());
    //表示该租户类型是商户
    createTenantRequestDTO.setTenantTypeCode("huimin-merchant");//租户类型
    //设置租户套餐为初始化套餐餐  //套餐,根据套餐进行分配权限
    createTenantRequestDTO.setBundleCode("huimin-merchant");
    //租户名称,和账号名一样
    createTenantRequestDTO.setName(merchantDTO.getUsername());

    //如果租户在SaaS已经存在,SaaS直接 返回此租户的信息,否则进行添加
    TenantDTO tenantAndAccount = tenantService.createTenantAndAccount(createTenantRequestDTO);
    //获取租户的id
    if(tenantAndAccount == null || tenantAndAccount.getId() == null){
        throw new BusinessException(CommonErrorCode.E_200012);
    }
    //租户的id
    Long tenantId = tenantAndAccount.getId();
    //租户id在商户表唯一      租户  和   商户 是  一一对应的, 商户就是在  saas 中的租户
    //根据租户id从商户表查询,如果存在记录则不允许添加商户
    Integer count1 = merchantMapper.selectCount(new LambdaQueryWrapper<Merchant>().eq(Merchant::getTenantId, tenantId));
    if(count1>0){
        throw new BusinessException(CommonErrorCode.E_200017);
    }

    // 3. 设置 租户 和 商户 绑定关系
    //将dto转成entity
    Merchant entity = MerchantConvert.INSTANCE.dto2entity(merchantDTO);
    //设置所对应的租户的Id
    entity.setTenantId(tenantId);  // 设置 商户 所属的租户id  注意 商户和租户是一一对应的
    //设置审核状态0‐未申请,1‐已申请待审核,2‐审核通过,3‐审核拒绝
    entity.setAuditStatus("0");
    //保存商户信息
    merchantMapper.insert(entity);

    //4.新增门店  创建根门店
    StoreDTO storeDTO = new StoreDTO();
    storeDTO.setStoreName("根门店");
    storeDTO.setMerchantId(entity.getId());//商户id 也是 租户id
    StoreDTO store = createStore(storeDTO);

    //5.新增员工
    StaffDTO staffDTO = new StaffDTO();
    staffDTO.setMobile(merchantDTO.getMobile());//手机号
    staffDTO.setUsername(merchantDTO.getUsername());//账号
    // 给员工设置所属门店 此处为根门店
    staffDTO.setStoreId(store.getId());//员所属门店id
    staffDTO.setMerchantId(entity.getId());//商户id

    StaffDTO staff = createStaff(staffDTO);

    //6.为门店设置管理员
    bindStaffToStore(store.getId(), staff.getId());

    //将entity转成 dto
    MerchantDTO merchantDTONew = MerchantConvert.INSTANCE.entity2dto(entity);
    return merchantDTONew;
}
1.4.4.2 测试

使用Postman进行商户注册,请求:http://localhost:57010/merchant/merchants/register

注册成功后观察huiminpay_user数据库下的account、tenant、tenant_account表是否有新注册的账号、租户信息。