仿饿了么小程序

  • 前言
    该demo由于时间人力有限,只实现了简陋的界面和部分后台功能,主要有:从微信服务器获取用户信息,结合redis实现自动登录;
  • 项目结构
    在这里插入图片描述
  • 项目展示
    在这里插入图片描述
    在这里插入图片描述
    数据库信息在这里插入图片描述
  • 项目代码
    github
  • 讲下获取微信敏感信息
微信小程序端发起登录请求,携带的参数主要有:
    code:loginRes.code,//临时登录凭证
    rawData:infoRes.rawData,//用户非敏感信息
    signature:infoRes.signature,//签名
    encrypteData:infoRes.encryptedData,//用户敏感信息
    iv:infoRes.iv//解密算法的向量
public JSONObject getSessionKeyOrOpenId(String code){
	    //微信端登录code
	    String wxCode = code;
	    String requestUrl = "https://api.weixin.qq.com/sns/jscode2session";
	    Map<String,String> requestUrlParam = new HashMap<String, String>(  );
	    requestUrlParam.put( "appid","***" );//小程序appId
	    requestUrlParam.put( "secret","***" );小程序secret
	    requestUrlParam.put( "js_code",wxCode );//小程序端返回的code
	    requestUrlParam.put( "grant_type","authorization_code" );//默认参数
	 
	    //发送post请求读取调用微信接口获取openid用户唯一标识
	    JSONObject jsonObject = JSON.parseObject(HttpClientUtil.httpPost(requestUrl,requestUrlParam));
	    return jsonObject;
	}

由小程序那传输过来的 code,通过 HttpClientUtil 工具,通过个人的appid和secret,从微信服务器获取 openid 和 sessionkey 敏感信息,再sessionKey结合encryptedData和iv,通过解密算法 getUserInfo() 获取用户的私人信息;

public JSONObject getUserInfo(String encryptedData,String sessionKey,String iv){
	    // 被加密的数据
	    byte[] dataByte = Base64.decode(encryptedData);
	    // 加密秘钥
	    byte[] keyByte = Base64.decode(sessionKey);
	    // 偏移量
	    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/PKCS7Padding","BC");
	        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");
	            return JSON.parseObject(result);
	        }
	    } catch (NoSuchAlgorithmException e) {
	    } catch (NoSuchPaddingException e) {
	    } catch (InvalidParameterSpecException e) {
	    } catch (IllegalBlockSizeException e) {
	    } catch (BadPaddingException e) {
	    } catch (UnsupportedEncodingException e) {
	    } catch (InvalidKeyException e) {
	    } catch (InvalidAlgorithmParameterException e) {
	    } catch (NoSuchProviderException e) {
	    }
	    return null;
	}
  • 结合redis实现自动登录
    自动登录的思路:
    自动登录的关键是skey,在用户初次登录时,会通过uuid生成唯一key,我们命名为skey,我们同时将skey和openid存入redis,(并设置有效期),以及将skey传到小程序端,每次使用小程序时,会将本地的skey和redis服务器的skey进行辨别,如果不一致,就将重新进入初次登录的流程,以此类推;

    为什么要使用redis?
    其实完全可以使用mysql,但是考虑到redis的速度以及key-value的优越性,这样存储skey:openid会方便点;

 //uuid生成唯一key
String skey = UUID.randomUUID().toString();
//根据openid查询skey是否存在
	    String skey_redis = (String) redisTemplate.opsForValue().get( openid );
	    if(StringUtils.isNotBlank( skey_redis )){
	        //存在 删除 skey 重新生成skey 将skey返回
	        redisTemplate.delete( skey_redis );
	 
	    }
        //  缓存一份新的
        JSONObject sessionObj = new JSONObject(  );
        sessionObj.put( "openId",openid );
        sessionObj.put( "sessionKey",sessionKey );
        redisTemplate.opsForValue().set( skey,sessionObj.toJSONString() ,20,TimeUnit.MINUTES);
        redisTemplate.opsForValue().set( openid,skey ,20,TimeUnit.MINUTES);
 
        //把新的sessionKey和oppenid返回给小程序
        map.put( "skey",skey );
	    map.put( "result","1" );
	 

整个登陆流程如下
在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值