LoginServiceImpl.java 11 KB
package com.infoloop.tianting.service.impl;

import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.infoloop.rpc.meizhongyiheservice.HospitalStatus;
import com.infoloop.tianting.WOperatorStatus;
import com.infoloop.tianting.clientcustomerservice.ClientCustomerHospitalRecordHospitalStatusEnum;
import com.infoloop.tianting.constant.CommonConstants;
import com.infoloop.tianting.context.LoginContextHolder;
import com.infoloop.tianting.exception.ClientEndExceptions;
import com.infoloop.tianting.exception.ErrorCodeEnum;
import com.infoloop.tianting.mealorderservice.MpAccountCreation;
import com.infoloop.tianting.mealorderservice.MpAccountModification;
import com.infoloop.tianting.mealorderservice.MpAccountStatusEnum;
import com.infoloop.tianting.mealorderservice.SingleMpAccountRpcResponse;
import com.infoloop.tianting.model.dto.MpAccountDTO;
import com.infoloop.tianting.model.dto.PermissionDTO.LoginDto;
import com.infoloop.tianting.model.vo.MpAccountVO;
import com.infoloop.tianting.service.LoginService;
import com.infoloop.tianting.service.client.ClientCustomerServiceRpcClient;
import com.infoloop.tianting.service.client.MealOrderServiceRpcClient;
import com.infoloop.tianting.service.client.MeiZhongYiHeServiceClient;
import com.infoloop.tianting.service.client.OperatorServiceRpcClient;
import com.infoloop.tianting.service.client.WOperatorServiceRpcClient;
import com.infoloop.tianting.service.client.WxMiniProgramHttpClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class LoginServiceImpl implements LoginService {

    private final ClientCustomerServiceRpcClient clientCustomerServiceRpcClient;
    private final MealOrderServiceRpcClient mealOrderServiceRpcClient;
    private final OperatorServiceRpcClient operatorServiceRpcClient;
    private final WxMiniProgramHttpClient wxMiniProgramHttpClient;
    private final WOperatorServiceRpcClient wOperatorServiceRpcClient;
    private final MeiZhongYiHeServiceClient meiZhongYiHeServiceClient;

    @Override
    public SaTokenInfo login(LoginDto loginDto) throws NoSuchAlgorithmException {
        if (loginDto.isShouldLoginWithOpenCode()) {
            final var wxUserOpenIdDto = wxMiniProgramHttpClient.getUserOpenIdByCode(loginDto.getOpenCode());
            StpUtil.login(wxUserOpenIdDto.getOpenid(), SaLoginModel.create()
                    .setExtra(CommonConstants.ENTERPRISE_ID, loginDto.getEnterpriseId())
                    .setExtra(CommonConstants.LOGIN_SOURCE, loginDto.getLoginSourceEnum().getValue())
                    .build());
            return StpUtil.getTokenInfo();
        } else if (loginDto.isShouldLoginWithOpenId()){
            final var mpAccountByOpenId = mealOrderServiceRpcClient.getMpAccountByOpenId(loginDto.getOpenId());
            int mpAccountId;
            if (mpAccountByOpenId == null) {
                mpAccountId = mealOrderServiceRpcClient.createMpAccount(loginDto.getEnterpriseId(), MpAccountCreation.newBuilder()
                        .setOpenId(loginDto.getOpenId())
                        .setStatus(MpAccountStatusEnum.MP_ACCOUNT_STATUS_ENABLE)
                        .setPhoneNumber(loginDto.getOperatorPhone() != null ? loginDto.getOperatorPhone() : "")
                        .build()).getId();
            } else {
                mpAccountId = mpAccountByOpenId.getId();
            }
            Assert.isTrue(mpAccountId != 0, "创建小程序账号失败");
            StpUtil.login(loginDto.getOpenId(), SaLoginModel.create()
                    .setExtra(CommonConstants.ENTERPRISE_ID, loginDto.getEnterpriseId())
                    .setExtra(CommonConstants.USER_ID, mpAccountId)
                    .setExtra(CommonConstants.LOGIN_SOURCE, loginDto.getLoginSourceEnum().getValue())
                    .build());
            return StpUtil.getTokenInfo();
        } else if (loginDto.isShouldLoginWithHisCustomerNo()) {
            var customer = clientCustomerServiceRpcClient.getClientCustomerByHISCustomerNo(loginDto.getHisCustomerNo()).getResponse();
            if (customer.getId() == 0) {
                // 根据hisCustomerNo拿不到用户的话再去根据合同号去his查一次,即认为是月子中心客户
                customer = clientCustomerServiceRpcClient.getClientCustomerByContactNo(loginDto.getHisCustomerNo()).getResponse();
                if (customer.getId() == 0) {
                    throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.VALIDATE_FAILED.name());
                } else {
                    var record = clientCustomerServiceRpcClient.getClientCustomerHospitalRecordsByCustomerId(customer.getEnterpriseId(), customer.getId());
                    if (!record.hasResponse() || record.getResponse().getHospitalStatus() != ClientCustomerHospitalRecordHospitalStatusEnum.CURRENT) {
                        throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.VALIDATE_FAILED.name());
                    }
                }
            } else {
                var record = clientCustomerServiceRpcClient.getClientCustomerHospitalRecordsByCustomerId(customer.getEnterpriseId(), customer.getId());
                if (!record.hasResponse() || record.getResponse().getHospitalStatus() != ClientCustomerHospitalRecordHospitalStatusEnum.CURRENT) {
                    throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.VALIDATE_FAILED.name());
                }
                //还需要去读取HIS系统最新用户住院信息
                final var hisCustomerHospitalRecord = meiZhongYiHeServiceClient.getCustomerDetailById(customer.getHISCustomerId(), record.getResponse().getContractNo()).getCustomerHospitalRecord();
                if (hisCustomerHospitalRecord.getHospitalStatus() != HospitalStatus.CURRENT) {
                    throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.VALIDATE_FAILED.name());
                }
            }
            final var wxUserOpenIdDto = wxMiniProgramHttpClient.getUserOpenIdByCode(loginDto.getOpenCode());
            StpUtil.login(customer.getId(), SaLoginModel.create()
                    .setExtra(CommonConstants.ENTERPRISE_ID, customer.getEnterpriseId())
                    .setExtra(CommonConstants.LOGIN_SOURCE, loginDto.getLoginSourceEnum().getValue())
                    .setExtra(CommonConstants.OPEN_ID, wxUserOpenIdDto.getOpenid())
                    .build());
            return StpUtil.getTokenInfo();
        } else if (loginDto.isShouldLoginWithOperatorPhone()) {
            final var operator = operatorServiceRpcClient.getCOperatorByMobileOrEmail(loginDto.getOperatorPhone());
            if (operator.getId() == 0) {
                throw ClientEndExceptions.AuthenticationFailure.build(ErrorCodeEnum.UNAUTHORIZED.name());
            }
            if (!operator.getPassword().equals(sha1Hash(loginDto.getPassword()))) {
                throw ClientEndExceptions.AuthenticationFailure.build(ErrorCodeEnum.VALIDATE_FAILED.name());
            }
            if (operator.getStatus() != 1) {
                throw ClientEndExceptions.AuthenticationFailure.build(ErrorCodeEnum.VALIDATE_FAILED.name());
            }
            StpUtil.login(operator.getId(), SaLoginModel.create()
                            .setExtra(CommonConstants.ENTERPRISE_ID, operator.getEnterpriseId())
                            .setExtra(CommonConstants.LOGIN_SOURCE, loginDto.getLoginSourceEnum().getValue())
                            .build());
            return StpUtil.getTokenInfo();
        } else {
            final var operator = wOperatorServiceRpcClient.getWOperatorByEmail(loginDto.getEmail()).getResponse();
            if (operator.getId() == 0) {
                throw ClientEndExceptions.AuthenticationFailure.build(ErrorCodeEnum.UNAUTHORIZED.name());
            }
            if (!operator.getPassword().equals(sha1Hash(loginDto.getPassword()))) {
                throw ClientEndExceptions.AuthenticationFailure.build(ErrorCodeEnum.VALIDATE_FAILED.name());
            }
            if (operator.getStatus() != WOperatorStatus.SHOW) {
                throw ClientEndExceptions.AuthenticationFailure.build(ErrorCodeEnum.VALIDATE_FAILED.name());
            }
            StpUtil.login(operator.getId(), SaLoginModel.create()
                            .setExtra(CommonConstants.ENTERPRISE_ID, operator.getEnterpriseId())
                            .setExtra(CommonConstants.LOGIN_SOURCE, loginDto.getLoginSourceEnum().getValue())
                            .build());
            return StpUtil.getTokenInfo();
        }
    }

    @Override
    public MpAccountVO getMpAccountByOpenId(String openId) {
        final var mpAccountByOpenId = mealOrderServiceRpcClient.getMpAccountByOpenId(openId);
        if (mpAccountByOpenId == null) {
            return null;
        }
        return MpAccountVO.builder()
                .id(mpAccountByOpenId.getId())
                .enterpriseId(mpAccountByOpenId.getEnterpriseId())
                .openId(mpAccountByOpenId.getOpenId())
                .unionId(mpAccountByOpenId.getUnionId())
                .nickname(mpAccountByOpenId.getNickname())
                .avatarUrl(mpAccountByOpenId.getAvatarUrl())
                .gender(mpAccountByOpenId.getGender())
                .phoneNumber(mpAccountByOpenId.getPhoneNumber())
                .build();
    }

    @Override
    public void updateMpAccount(SingleMpAccountRpcResponse mpAccount, MpAccountDTO.ModifyMpAccountDTO modifyMpAccountDTO) {
        mealOrderServiceRpcClient.updateMpAccount(LoginContextHolder.getLoginInfo(), MpAccountModification.newBuilder()
                .setId(mpAccount.getId())
                .setShouldUpdateNickname(modifyMpAccountDTO.getNickName() != null)
                .setNickname(modifyMpAccountDTO.getNickName() != null ? modifyMpAccountDTO.getNickName() : mpAccount.getNickname())
                .setShouldUpdateAvatarUrl(modifyMpAccountDTO.getAvatarUrl() != null)
                .setAvatarUrl(modifyMpAccountDTO.getAvatarUrl() != null ? modifyMpAccountDTO.getAvatarUrl() : mpAccount.getAvatarUrl())
                .setShouldUpdateGender(modifyMpAccountDTO.getGender() != null)
                .setGender(modifyMpAccountDTO.getGender() != null ? modifyMpAccountDTO.getGender() : mpAccount.getGender())
                .build());
    }

    public static String sha1Hash(String input) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        md.update(input.getBytes());
        byte[] digest = md.digest();
        return bytesToHex(digest);
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}