All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gitlab.summercattle.addons.wechat.auth.service.impl.UserServiceImpl Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitlab.summercattle.addons.wechat.auth.service.impl;

import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.gitlab.summercattle.addons.wechat.auth.service.UserBindAuthType;
import com.gitlab.summercattle.addons.wechat.auth.service.UserInfo;
import com.gitlab.summercattle.addons.wechat.auth.service.UserService;
import com.gitlab.summercattle.addons.wechat.bind.BindUserInfo;
import com.gitlab.summercattle.addons.wechat.bind.UserBindHandle;
import com.gitlab.summercattle.addons.wechat.bind.UserBindObjectType;
import com.gitlab.summercattle.addons.wechat.common.AppType;
import com.gitlab.summercattle.addons.wechat.common.AbstractUserSession;
import com.gitlab.summercattle.addons.wechat.common.service.WeChatService;
import com.gitlab.summercattle.addons.wechat.configure.WeChatConfigProperties;
import com.gitlab.summercattle.addons.wechat.constants.WeChatConstants;
import com.gitlab.summercattle.addons.wechat.constants.WeChatExceptionConstants;
import com.gitlab.summercattle.addons.wechat.memory.CaptchaMemoryService;
import com.gitlab.summercattle.addons.wechat.memory.SessionMemoryService;
import com.gitlab.summercattle.addons.wechat.miniprogram.configure.MiniProgramConfigProperties;
import com.gitlab.summercattle.addons.wechat.store.UserBindInfo;
import com.gitlab.summercattle.addons.wechat.store.UserBindStoreService;
import com.gitlab.summercattle.commons.exception.CommonException;
import com.gitlab.summercattle.commons.utils.spring.RestTemplateUtils;

/**
 * 用户服务实现
 * @author orange
 *
 */
@Service
public class UserServiceImpl implements UserService {

	private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

	@Autowired(required = false)
	private UserBindHandle userBindHandle;

	@Autowired
	private WeChatConfigProperties weChatConfigProperties;

	@Autowired(required = false)
	private MiniProgramConfigProperties miniProgramConfigProperties;

	@Autowired
	private UserBindStoreService userBindStoreService;

	@Autowired
	private CaptchaMemoryService captchaMemoryService;

	@Autowired
	private SessionMemoryService sessionMemoryService;

	@Autowired
	private WeChatService weChatService;

	@Autowired
	@Qualifier(WeChatConstants.REST_TEMPLATE_UTILS_NAME)
	private RestTemplateUtils restTemplateUtils;

	@Override
	public void generateBindCaptcha(String source, String sessionId, UserBindObjectType objectType, String userObject, int captchaLength,
			Map parameters) throws CommonException {
		AbstractUserSession session = getSession(source, sessionId);
		if (session == null) {
			throw new CommonException("会话标识'" + sessionId + "'不存在");
		}
		if (session.isBindUser()) {
			throw new CommonException("用户已经绑定");
		}
		if (captchaLength <= 0) {
			throw new CommonException("验证码长度必须大于零");
		}
		if (userBindHandle == null) {
			throw new CommonException("用户绑定处理为空");
		}
		String captcha = captchaMemoryService.get(source, sessionId);
		int captchaTimeout = weChatConfigProperties.getCaptchaTimeout();
		if (StringUtils.isBlank(captcha)) {
			captcha = com.gitlab.summercattle.commons.utils.auxiliary.StringUtils.getRandomString(true, captchaLength);
			captchaMemoryService.save(source, sessionId, captcha, captchaTimeout);
			userBindHandle.sendCaptcha(objectType, userObject, captcha, captchaTimeout, parameters);
		}
		else {
			userBindHandle.resendCaptcha(objectType, userObject, captcha, parameters);
		}
	}

	@Override
	public void bind(String source, String sessionId, UserBindObjectType objectType, UserBindAuthType authType, String userObject, String authInfo,
			Map parameters) throws CommonException {
		AbstractUserSession session = getSession(source, sessionId);
		if (session == null) {
			throw new CommonException("会话标识'" + sessionId + "'不存在");
		}
		if (session.isBindUser()) {
			throw new CommonException("用户已经绑定");
		}
		if (objectType == null) {
			throw new CommonException("用户绑定对象类型为空");
		}
		if (authType == null) {
			throw new CommonException("用户绑定验证类型为空");
		}
		if (StringUtils.isBlank(userObject)) {
			throw new CommonException("用户对象为空");
		}
		if (StringUtils.isBlank(authInfo)) {
			throw new CommonException("验证信息为空");
		}
		if (userBindHandle == null) {
			throw new CommonException("用户绑定处理为空");
		}
		boolean autoCreate = false;
		BindUserInfo bindUserInfo = userBindHandle.process(objectType, userObject, parameters);
		if (bindUserInfo == null) {
			if (userBindHandle.isAutoCreated(objectType, parameters)) {
				bindUserInfo = userBindHandle.create(objectType, userObject, parameters);
				autoCreate = true;
			}
		}
		if (bindUserInfo == null) {
			userBindHandle.bindingFailed();
		}
		if (!autoCreate) {
			if (authType == UserBindAuthType.Captcha) {
				String captcha = captchaMemoryService.get(source, sessionId);
				if (StringUtils.isBlank(captcha) || !captcha.equals(authInfo)) {
					throw new CommonException("验证码失效");
				}
				captchaMemoryService.invalid(source, sessionId);
			}
			else if (authType == UserBindAuthType.Password) {
				userBindHandle.verifyPassword(objectType, userObject, authInfo, parameters);
			}
			else {
				throw new CommonException("用户绑定验证类型'" + authType.toString() + "'不支持");
			}
		}
		if (bindUserInfo.getUserType() == 0) {
			throw new CommonException("用户类型没有设置");
		}
		if (StringUtils.isBlank(bindUserInfo.getInfo())) {
			throw new CommonException("绑定信息为空");
		}
		String bindId = userBindStoreService.save(source, session.getType(), session.getOpenId(), session.getUnionId(), bindUserInfo.getUserType(),
				bindUserInfo.getInfo());
		sessionMemoryService.invalid(source, sessionId);
		session.setBindUser(true);
		session.setBindId(bindId);
		session.setUserType(bindUserInfo.getUserType());
		session.setBindInfo(bindUserInfo.getInfo());
		int sessionTimeout = 0;
		if (session.getType() == AppType.MiniProgram) {
			if (miniProgramConfigProperties == null) {
				throw new CommonException("微信小程序配置信息为空");
			}
			sessionTimeout = miniProgramConfigProperties.getSessionTimeout();
		}
		else {
			throw new CommonException("应用类型'" + session.getType().toString() + "'暂不支持");
		}
		sessionMemoryService.save(source, session, sessionTimeout);
	}

	@Override
	public void unbind(String source, String sessionId) throws CommonException {
		AbstractUserSession session = getSession(source, sessionId);
		if (session == null) {
			throw new CommonException("会话标识'" + sessionId + "'不存在");
		}
		if (!session.isBindUser()) {
			throw new CommonException("用户未绑定");
		}
		userBindStoreService.delete(source, session.getType(), session.getOpenId());
		sessionMemoryService.invalid(source, sessionId);
	}

	@Override
	public void unbind(String source, AppType type, String openId) throws CommonException {
		if (StringUtils.isBlank(source)) {
			throw new CommonException("来源为空");
		}
		if (StringUtils.isBlank(openId)) {
			throw new CommonException("微信标识Id为空");
		}
		userBindStoreService.delete(source, type, openId);
	}

	@Override
	public boolean isOtherBind(String source, String sessionId) throws CommonException {
		AbstractUserSession session = getSession(source, sessionId);
		if (session.isBindUser()) {
			return userBindStoreService.isOtherBind(source, session.getType(), session.getOpenId());
		}
		return false;
	}

	@Override
	public AbstractUserSession getSession(String source, String sessionId) throws CommonException {
		if (StringUtils.isBlank(source)) {
			throw new CommonException("来源为空");
		}
		if (StringUtils.isBlank(sessionId)) {
			throw new CommonException("会话标识为空");
		}
		Object sessionObj = sessionMemoryService.get(source, sessionId);
		if (sessionObj == null) {
			throw new CommonException(WeChatExceptionConstants.WECHAT_SESSION_INVALID, "会话'" + sessionId + "'已经失效");
		}
		return (AbstractUserSession) sessionObj;
	}

	@Override
	public AbstractUserSession[] getSessions(String source) throws CommonException {
		return sessionMemoryService.getAll(source);
	}

	@Override
	public String getOpenId(String source, AppType type, int userType, String userInfo) throws CommonException {
		if (StringUtils.isBlank(source)) {
			throw new CommonException("来源为空");
		}
		if (userType == 0) {
			throw new CommonException("用户类型没有设置");
		}
		if (StringUtils.isBlank(userInfo)) {
			throw new CommonException("用户信息为空");
		}
		return userBindStoreService.getOpenId(source, type, userType, userInfo);
	}

	@Override
	public UserBindInfo getUserBindInfo(String source, AppType type, String openId) throws CommonException {
		if (StringUtils.isBlank(source)) {
			throw new CommonException("来源为空");
		}
		if (type == AppType.OfficialAccounts) {
			if (StringUtils.isBlank(openId)) {
				throw new CommonException("微信公众号标识Id为空");
			}
		}
		else if (type == AppType.MiniProgram) {
			if (StringUtils.isBlank(openId)) {
				throw new CommonException("微信小程序标识Id为空");
			}
		}
		else {
			throw new CommonException("应用类型'" + type.toString() + "'暂不支持");
		}
		return userBindStoreService.getUserBindInfo(source, type, openId, null);
	}

	@Override
	public UserInfo getUserInfo(String source, String openId, String lang) throws CommonException {
		if (StringUtils.isBlank(source)) {
			throw new CommonException("来源为空");
		}
		if (StringUtils.isBlank(openId)) {
			throw new CommonException("微信公众号标识Id为空");
		}
		String accessToken = weChatService.getAccessToken(AppType.OfficialAccounts, source);
		if (StringUtils.isBlank(accessToken)) {
			throw new CommonException("微信公众号访问令牌为空");
		}
		String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openId + "&lang="
				+ (StringUtils.isNotBlank(lang) ? lang : "zh_CN");
		logger.debug("微信的获得用户信息请求地址:" + url);
		JSONObject resultJson = restTemplateUtils.get(url, MediaType.APPLICATION_JSON, null, JSONObject.class);
		logger.debug("微信的获得用户信息返回:" + resultJson.toString());
		boolean isErrMsg = resultJson.containsKey("errmsg");
		if (isErrMsg) {
			throw new CommonException("微信的获得用户信息接口异常,错误码:" + resultJson.getString("errcode") + ",错误信息:" + resultJson.getString("errmsg"));
		}
		String rOpenId = resultJson.getString("openid");
		if (!StringUtils.equals(rOpenId, openId)) {
			throw new CommonException("微信的获得用户信息接口得到数据异常");
		}
		List tagIdList = null;
		JSONArray tagIdListJson = resultJson.getJSONArray("tagid_list");
		if (tagIdListJson != null && tagIdListJson.size() > 0) {
			tagIdList = new Vector();
			for (int i = 0; i < tagIdListJson.size(); i++) {
				tagIdList.add(tagIdListJson.getLong(i));
			}
		}
		Integer subscribe = resultJson.getInteger("subscribe");
		if (subscribe == 1) {
			return new UserInfo(resultJson.getString("nickname"), resultJson.getInteger("sex"), resultJson.getString("country"),
					resultJson.getString("province"), resultJson.getString("city"), resultJson.getString("headimgurl"),
					resultJson.getString("unionid"), resultJson.getLong("subscribe_time"), resultJson.getString("language"),
					resultJson.getString("remark"), resultJson.getLong("groupid"), tagIdList, resultJson.getString("subscribe_scene"),
					resultJson.getLong("qr_scene"), resultJson.getString("qr_scene_str"));
		}
		return null;
	}

	@Override
	public void bindInit(String source, AppType type, String openId, String unionId) throws CommonException {
		if (StringUtils.isBlank(source)) {
			throw new CommonException("来源为空");
		}
		if (StringUtils.isBlank(openId)) {
			throw new CommonException("微信标识Id为空");
		}
		if (StringUtils.isBlank(unionId)) {
			throw new CommonException("微信唯一标识Id为空");
		}
		userBindStoreService.saveInit(source, type, openId, unionId);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy