java版微信小程序登录商城源码Spring Cloud+Spring Boot+mybatis+security+uniapp+Redis+MQ+VR全景+b2b2c多商家入驻前后端分离商城源码

@源码地址来源: https://minglisoft.cn/honghu/business.html

微信小程序登录代码:

/**
 * Copyright &copy; 2012-2017 <a href="http://minglisoft.cn">HongHu</a> All rights reserved.
 */
package com.honghu.cloud.controller;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.bouncycastle.util.encoders.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.auth0.jwt.internal.org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.google.common.collect.Maps;
import com.honghu.cloud.bean.User;
import com.honghu.cloud.code.ResponseCode;
import com.honghu.cloud.constant.Globals;
import com.honghu.cloud.dto.AccessoryDto;
import com.honghu.cloud.dto.PaymentDto;
import com.honghu.cloud.dto.StoreDto;
import com.honghu.cloud.dto.SysConfigDto;
import com.honghu.cloud.dto.UserDto;
import com.honghu.cloud.feign.AccessoryFeignClient;
import com.honghu.cloud.feign.DistributionUserFeignClient;
import com.honghu.cloud.feign.FtpFileFeignClient;
import com.honghu.cloud.feign.PaymentFeignClient;
import com.honghu.cloud.feign.StoreFeignClient;
import com.honghu.cloud.feign.SysConfigFeignClient;
import com.honghu.cloud.feign.TencentIMFeignClient;
import com.honghu.cloud.redis.RedisUtil;
import com.honghu.cloud.service.IUserService;
import com.honghu.cloud.tools.SecurityUserHolder;
import com.honghu.cloud.tools.wx.WXCore;
import com.honghu.cloud.utils.CommUtil;
import com.honghu.cloud.utils.Exceptions;
import com.honghu.cloud.utils.HttpClientUtils;
import com.honghu.cloud.utils.JWT;
import com.honghu.cloud.utils.tools.Md5Encrypt;

import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;

/**
 * 微信小程序登录Controller
 * @author Administrator
 *
 */
@Slf4j
@RestController
@RequestMapping(value = "/weChat")
public class WeChatLoginController  {

	@Autowired
	private IUserService userService;
	@Autowired
	private RedisUtil redisUtil;
	@Autowired
	private SysConfigFeignClient sysConfigFeignClient;
	@Autowired
	private DistributionUserFeignClient disUserFeignClient;
	@Autowired
	private FtpFileFeignClient ftpFileFeignClient;
	@Autowired
	private TencentIMFeignClient tencentIMFeignClient;
	@Autowired
	private StoreFeignClient storeFeignClient;
	@Autowired
	private PaymentFeignClient paymentFeignClient;
/*	@Autowired
	private AccessoryFeignClient accessoryFeignClient;*/
	
	private static final Logger logger = LoggerFactory.getLogger(WeChatLoginController.class);
	
	/***微信获取登录凭证url***/
	private static final String CODE2SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session";
	
	/**
	 * 小程序登录
	 * @param js_code 登录code
	 * @param iv  加密算法的初始向量
	 * @param encryptedData 敏感用户数据
	 * @param share_uid 邀请注册用户
	 * @return
	 */
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public  Map<String, Object>  login(@RequestBody JSONObject json) {
		String js_code = json.optString("js_code");
		String iv = json.optString("iv");
		String encryptedData = json.optString("encryptedData");
		String share_uid = json.optString("share_uid");
		String source_type = json.optString("source_type");
		String nickName = json.optString("nickName");
		String userphoto = json.optString("photo");
		/*SysConfigDto sysConfigDto = sysConfigFeignClient.getSysConfig();
		String appid = sysConfigDto.getOpen_weixin_appId(); 
		String secret = sysConfigDto.getOpen_weixin_appSecret();*/ 
		// 微信APPID、微信密匙
		Map<String, Object> param = Maps.newHashMap();
		param.put("mark", "wx_miniprogram");
		List<PaymentDto> payments = paymentFeignClient.queryPageList(param);
		PaymentDto payment =null;
		if (payments.size() > 0) {
			 payment = (PaymentDto) payments.get(0);
		}
		if (payment==null||StringUtils.isEmpty(payment.getWx_appid()) || StringUtils.isEmpty(payment.getWx_appSecret())) {
			return ResponseCode.buildCodeMap("40031", "获取微信配置信息有误!", null);
		}
		Map<String,String> params = new HashMap<String, String>();
		params.put("appid", payment.getWx_appid());
		params.put("secret", payment.getWx_appSecret());
		params.put("js_code", js_code);
		params.put("grant_type", "authorization_code");
		String jsonStr = HttpClientUtils.doGet(CODE2SESSION_URL, params, "UTF-8");
		JSONObject jsonObj = JSONObject.fromObject(jsonStr);
		
		// 错误码
		String errcode = jsonObj.optString("errcode");
		if(StringUtils.equals(errcode, "40028")){ // code 无效
			return ResponseCode.buildCodeMap("40028", "code 无效!", null);
		}
		
		// errcode[-1:系统繁忙,此时请开发者稍候再试;45011:频率限制,每个用户每分钟100次]
		if(StringUtils.equals(errcode, "45011") || StringUtils.equals(errcode, "-1")){
			return ResponseCode.buildCodeMap("45011", "系统繁忙,请稍后再试!", null);
		}
		
		String session_key = jsonObj.optString("session_key");
		String openid = jsonObj.optString("openid");
		// 会话密钥和用户唯一标识为空,表示服务请求失败,记录日志
		if(StringUtils.isEmpty(session_key) || StringUtils.isEmpty(openid)){
			return ResponseCode.buildCodeMap("40029", "code无效!", null);
		}
		
		// 解析小程序加密用户数据
		String userInfo = WXCore.decrypt(payment.getWx_appid(), encryptedData, session_key, iv);
		if(StringUtils.isEmpty(userInfo)){
			return ResponseCode.buildCodeMap("40030", "获取用户数据失败!", null);
		}
		JSONObject userJson = JSONObject.fromObject(userInfo);
		// 开放平台的唯一标识符
		String unionid = userJson.optString("unionId");
		if(StringUtils.isEmpty(unionid)){
			return ResponseCode.buildCodeMap("40032", "获取用户数据失败!", null);
		}
		
		boolean phone=false;
		User user=null;
		boolean flag = false;   //true 则不需要授权手机号
		// 根据开放平台的唯一标识签,查询用户对象是否存在,不存在注册一条数据
		synchronized (this) {
			user = userService.selectByUnionid(unionid);
			if(user !=  null && user.getSecurity() == 1){
				return ResponseCode.buildCodeMap("40031", "账户存在安全隐患禁止登录!", null);
			 }
			if (user!=null&&user.getUsername()!=null&&StringUtils.isNotBlank(user.getMobile())) {
				phone=true;
			}
			if(user == null){
				flag = true;
				user = new User();
				user.setOpenId(openid);
				if (StringUtils.isNotEmpty(nickName)) {
					user.setNickName(nickName);
				}else{
					user.setNickName(userJson.optString("nickName"));  //微信提供的默认头像
				}
				user.setWeixin_unionID(unionid);
				user.setDay_msg_count(0); 
				user.setDeleteStatus(0);
				user.setAddTime(new Date());
				user.setPassword(Md5Encrypt.md5("123456").toLowerCase());//设置默认密码为123456
				user.setYears(0); // 用户年龄
				user.setIs_live(0);
				user.setLive_code(userService.selectMaxLiveCode() + 1);
				user.setUser_type(0); // 用户类别,默认为0个人用户,1为企业用户
				user.setStore_apply_step(0); // 店铺申请进行的步骤,默认为0
				user.setInvoiceType(0); // 发票类型
				user.setWhether_attention(1); //是否允许关注 0为不允许,1为允许
				user.setUser_form("miniProgram"); //注册来源,分为pc,android,ios,miniProgram, WXOffiaccount
				if (StringUtils.isNotEmpty(source_type)) {
					user.setSource_type(CommUtil.null2Int(source_type));    //1为海报
				}
				userService.saveEntity(user);
				user = userService.selectByUnionid(unionid);
			}else if(StringUtils.equals(user.getUser_form(), "WXOffiaccount") && StringUtils.isBlank(user.getOpenId())){  //通过微信公众号注册的
				user.setOpenId(openid);
				userService.updateById(user);
				flag = true;   //微信注册第一次进来分销关系重新建立
			}
		}
		
		boolean isUpdate=false;
		// 处理用户头像(用户头像不存在,将微信的头像保存到用户头像)
		//String photo_url = userJson.optString("avatarUrl");
		if(user.getPhoto_id() == null && StringUtils.isNotEmpty(userphoto)){
			AccessoryDto photo = uploadPhotoFile(userphoto, user.getId());
			if(photo != null){
				user.setPhoto(photo);
				user.setPhoto_id(photo.getId());
				isUpdate=true;
			}
		}
		//用户换名称或头像
		if(user.getNickName()==null){
			user.setNickName(nickName);
			isUpdate=true;
		}
		if (user.getLive_code()==null) {
			user.setLive_code(userService.selectMaxLiveCode() + 1);
			isUpdate=true;
		}
		if (StringUtils.isNotEmpty(nickName) && StringUtils.isEmpty(user.getNickName())) {
			user.setNickName(nickName);
			isUpdate = true;
		}
		if (StringUtils.isEmpty(user.getOpenId())) {
			user.setOpenId(openid);
			isUpdate = true;
		}
		if (isUpdate) {
			userService.updateById(user);
		}
		//所有用户都是分销用户
		if(flag){
			userService.saveDisUser(user, share_uid);
		}
		// 生成token,格式:用户id;时间戳  
		String token = JWT.sign(user.getId() + ";" + System.currentTimeMillis()+";"+"small", 0);
		// 将token存到redis中,有效期24小时 
		redisUtil.set(Globals.WECHAT_LOGIN_MARK + user.getId(), token, Globals.USER_INFO_EXPIRE_TIME);
		
		// 覆盖redis用户信息
		UserDto userDto = new UserDto();
		BeanUtils.copyProperties(user, userDto);
		redisUtil.set(Globals.USER_INFO_MARK + user.getId(), userDto, Globals.USER_INFO_EXPIRE_TIME);
		
		String storestatus="";
		if (userDto.getStore_id()!=null) {
			StoreDto storeDto = storeFeignClient.selectByPrimaryKey(userDto.getStore_id());
			if (storeDto!=null) {
				storestatus=storeDto.getStore_status()+"";
			}
		}
		HashMap<String, Object> result = new HashMap<>();
		result.put("token", token);
		result.put("storestatus", storestatus);
		SysConfigDto sysConfig = sysConfigFeignClient.getSysConfig();
		if (sysConfig.getOpen_live()==0) {
			result.put("phone", true);
		}else{
			result.put("phone", phone);
		}
		
		result.put("session_key", session_key);
		result.put("user", user);
		
		if (user != null&&user.getIs_live()!=null) {
			result.put("is_live", user.getIs_live()==2?true:false);
		}else{
			result.put("is_live", false);
		}
		return ResponseCode.buildSuccessMap(result);
	}
	
	
	/**
	 * 保存用户手机号
	 * @return
	 */
	@RequestMapping(value = "/savePhone", method = RequestMethod.POST)
	public Map<String, Object> savePhone(HttpServletRequest request, @RequestBody JSONObject json) {
		String session_key = json.optString("session_key");
		String iv = json.optString("iv");
		String encryptedData = json.optString("encrypData");

		if (StringUtils.isBlank(session_key)) {
			return ResponseCode.buildFailMap("获取失败,session_key信息错误", null);

		}
		if (StringUtils.isBlank(iv)) {
			return ResponseCode.buildFailMap("获取失败,iv信息错误", null);
			
		}
		if (StringUtils.isBlank(encryptedData)) {
			return ResponseCode.buildFailMap("获取失败,encryptedData信息错误", null);
			
		}
		byte[] dataByte = Base64.decode(encryptedData);
		// 加密秘钥
		byte[] keyByte = Base64.decode(session_key);
		// 偏移量
		byte[] ivByte = Base64.decode(iv);
		try {
			// 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
			int base = 16;
			if (keyByte.length % base != 0) {
				int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
				byte[] temp = new byte[groups * base];
				Arrays.fill(temp, (byte) 0);
				System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
				keyByte = temp;
			}
			// 初始化
			Security.addProvider(new BouncyCastleProvider());
			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
			SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
			AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
			parameters.init(new IvParameterSpec(ivByte));
			cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
			byte[] resultByte = cipher.doFinal(dataByte);
			if (null != resultByte && resultByte.length > 0) {
				String result = new String(resultByte, "UTF-8");

				JSONObject fromObject = JSONObject.fromObject(result);
				Object object = fromObject.get("purePhoneNumber");
				User user = userService.selectByPrimaryKey(SecurityUserHolder.getCurrentUserId(request));
				//查询是否已经存在该手机号
				User UserName = userService.selectByUserName(CommUtil.null2String(object));
				
				//需要合并用户    ,          手机号存在, 并且 unionid 为空     
				if (UserName!=null&&StringUtils.isEmpty(UserName.getWeixin_unionID())) {
					
					UserName.setWeixin_unionID(user.getWeixin_unionID());    //将新unionid 存入旧数据中
					if (UserName.getLive_code()==null) {
						UserName.setLive_code(userService.selectMaxLiveCode() + 1);
					}
					if (StringUtils.isEmpty(UserName.getNickName())) {
						UserName.setNickName(user.getNickName());
					}
					if (user.getPhoto_id()!=null) {
						UserName.setPhoto_id(user.getPhoto_id());
					}
					if (user.getOpenId()!=null) {
						UserName.setOpenId(user.getOpenId());
					}
					if (user.getWx_open_id()!=null) {
						UserName.setWx_open_id(user.getWx_open_id());;
					}
					userService.updateById(UserName);
					user.setDeleteStatus(1);
					user.setMobile("del"+CommUtil.null2String(object));
					user.setUserName("del"+CommUtil.null2String(object));
					user.setWeixin_unionID("del"+UserName.getId()+"");
					userService.updateById(user);
					disUserFeignClient.deleteByUserId(user.getId());   //删除新的 分销关系表
					redisUtil.remove(Globals.WECHAT_LOGIN_MARK + user.getId());
					//换用户登录
					// 生成token,格式:用户id;时间戳  
					String token = JWT.sign(UserName.getId() + ";" + System.currentTimeMillis()+";"+"small", 0);
					// 将token存到redis中,有效期24小时 
					redisUtil.set(Globals.WECHAT_LOGIN_MARK + UserName.getId(), token, Globals.USER_INFO_EXPIRE_TIME);
					
					// 覆盖redis用户信息
					UserDto userDto = new UserDto();
					BeanUtils.copyProperties(UserName, userDto);
					redisUtil.set(Globals.USER_INFO_MARK + UserName.getId(), userDto, Globals.USER_INFO_EXPIRE_TIME);
					return ResponseCode.buildSuccessMap(token);
					
				}
				//删除
				
				
				/*//手机号跟原来一致, 直接通过
				if (CommUtil.null2String(object).equals(user.getUserName())) {
					return ResponseCode.buildSuccessMap("isOk");
				}*/
				//手机号已存在
				if (UserName!=null) {
					return ResponseCode.buildFailMap("手机号已存在", "false");
				}
				user.setUserName(CommUtil.null2String(object));
				user.setMobile(CommUtil.null2String(object));
				userService.updateById(user);
				return ResponseCode.buildSuccessMap(null);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ResponseCode.buildFailMap("信息有误", "false");
	}
	
	
	
	/**
	 * 分享邀请用户注册的分享链接
	 * @return
	 */
	@RequestMapping(value = "/shareLogin", method = RequestMethod.POST)
	public Map<String, Object> shareLogin( HttpServletRequest request) {
		UserDto user = SecurityUserHolder.getCurrentUser(request);
		if(user == null || user.getId() == null){
			return ResponseCode.buildEnumMap(ResponseCode.TOKEN_EXPIRE, null);
		}
		return ResponseCode.buildSuccessMap(user.getId());
	}
	/**
	 * 分享邀请用户注册的分享链接
	 * @return
	 */
	@RequestMapping(value = "/checkUserPhone", method = RequestMethod.POST)
	public Map<String, Object> checkUserPhone( HttpServletRequest request) {
		UserDto user = SecurityUserHolder.getCurrentUser(request);
		if(user == null || user.getId() == null){
			return ResponseCode.buildEnumMap(ResponseCode.TOKEN_EXPIRE, null);
		}
		User new_user = userService.selectByPrimaryKey(user.getId());
		if (new_user.getMobile()==null||new_user.getUserName()==null) {
			return ResponseCode.buildEnumMap(ResponseCode.RESPONSE_CODE_USER_MOBILE_OR_TELEPHONE_NOT_EMPTY, null);
		}
		return ResponseCode.buildSuccessMap(null);
	}
	
	
	/**
	 * 分享邀请用户购买商品的分享链接
	 * @return
	 */
	@RequestMapping(value = "/shareGoods", method = RequestMethod.POST)
	public Map<String, Object> shareGoods( HttpServletRequest request) {
		UserDto user = SecurityUserHolder.getCurrentUser(request);
		if(user == null || user.getId() == null){
			return ResponseCode.buildEnumMap(ResponseCode.TOKEN_EXPIRE, null);
		}
		return ResponseCode.buildSuccessMap(user.getId());
	}
	
	
	
	
	/**
	* @Description 将字符串中的emoji表情转换成可以在utf-8字符集数据库中保存的格式(表情占4个字节,需要utf8mb4字符集)
	* @param str
	* 待转换字符串
	* @return 转换后字符串
	* @throws UnsupportedEncodingException
	* exception
	*/
	public static String emojiConvert1(String str) {
		String patternString = "([\\x{10000}-\\x{10ffff}\ud800-\udfff])";
		Pattern pattern = Pattern.compile(patternString);
		Matcher matcher = pattern.matcher(str);
		StringBuffer sb = new StringBuffer();
		while (matcher.find()) {
			try {
				matcher.appendReplacement(sb, "[[" + URLEncoder.encode(matcher.group(1), "UTF-8") + "]]");
			} catch (Exception e) {
			}
		}
		matcher.appendTail(sb);
		return sb.toString();
	}
	
	
	/**
	 * 微信授权登录上传头像
	 * @param photo_url
	 * @param user_id
	 * @return
	 */
	public AccessoryDto uploadPhotoFile(String photo_url, Long user_id){
		try {
			AccessoryDto accessoryDto = ftpFileFeignClient.upload("user/image", "", "JPG", user_id, photo_url);
			return accessoryDto;
		} catch (Exception e) {
			log.error("微信授权登录上传头像失败:"+Exceptions.getStackTraceAsString(e));
		}
		return null;
	}
	
	
	/**
	 * 将全部的用户注册IM账号
	 * @return
	 */
	@RequestMapping(value = "/IM/outImportMultipleAccounts", method = RequestMethod.GET)
	public boolean outImportMultipleAccounts() {
		//获取所有用户的信息
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("deleteStatus", "0");
		int count = userService.selectCount(params);
		int pageNum = (count/100)+1;    //腾讯只支持最多100个账号删除
		boolean bol = true;
		for(int i = 1; i <= pageNum; i++){
			params.put("currentPage", i);
			params.put("pageSize", 100);
			List<User> list = userService.queryPages(params);
			List<String> uids = new ArrayList<String>();
			for (User user : list) {
				uids.add(user.getId().toString());
			}
			bol = tencentIMFeignClient.importMultipleAccounts(uids);
		}
		return bol;
	}
	
	
	/**
	 * 将全部的用户注册IM账号
	 * @return
	 */
	@RequestMapping(value = "/IM/outAccountDelete", method = RequestMethod.GET)
	public boolean outAccountDelete() {
		//获取所有用户的信息
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("deleteStatus", "0");
		int count = userService.selectCount(params);
		int pageNum = (count/100)+1;    //腾讯只支持最多100个账号删除
		boolean bol = true;
		for(int i = 1; i <= pageNum; i++){
			params.put("currentPage", i);
			params.put("pageSize", 100);
			List<User> list = userService.queryPages(params);
			List<String> uids = new ArrayList<String>();
			for (User user : list) {
				uids.add(user.getId().toString());
			}
			bol = tencentIMFeignClient.accountDelete(uids);
		}
		return bol;
	}
	
	/**
     * 微信授权登录
     * @param code 授权临时票据
     * @return map
     * @throws Exception
     */
    @RequestMapping(value = "/weChatLogin" , method = RequestMethod.GET)
    public Map<String, Object> weChatLogin(@RequestParam("code") String code) throws Exception {
        return userService.weChatLogin(code);
    }
    /**
     * 微信授权登录(uniapp使用)
     * @param code 授权临时票据
     * @return map
     * @throws Exception
     */
    @RequestMapping(value = "/appWeChatLogin" , method = RequestMethod.POST)
    public Map<String, Object> appWeChatLogin(@RequestBody JSONObject json) throws Exception {
        return userService.appWeChatLogin(json);
    }
    @RequestMapping(value = "/appWeChatLoginNew" , method = RequestMethod.POST)
    public Map<String, Object> appWeChatLoginNew(@RequestBody JSONObject json) throws Exception {
    	return userService.appWeChatLoginNew(json);
    }
    
    /**
     * 微信授权登录
     * @param code 授权临时票据
     * @return map
     * @throws Exception
     */
    @RequestMapping(value = "/weChatH5Login" , method = RequestMethod.GET)
    public Map<String, Object> weChatH5Login(@RequestParam("code") String code) throws Exception {
    	return userService.weChatH5Login(code);
    }
	
}
@源码地址来源: https://minglisoft.cn/honghu/business.html
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

企业软件定制

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值