hjl
2024-05-21 dc5ee858231553ac54cde4427ef79d770f2c46fc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
package com.ruoyi.study.service.impl;
 
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.constant.RedisConstants;
import com.ruoyi.common.core.constant.TokenConstants;
import com.ruoyi.common.core.exception.GlobalException;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.study.domain.TUser;
import com.ruoyi.study.dto.AppUserQuery;
import com.ruoyi.study.mapper.TUserMapper;
import com.ruoyi.study.service.ITUserService;
import com.ruoyi.study.utils.RandomVxUtil;
import com.ruoyi.study.utils.SignatureUtil;
import com.ruoyi.study.vo.AppUserVO;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
 
import javax.annotation.Resource;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
 
/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author 无关风月
 * @since 2024-04-26
 */
@Service
public class TUserServiceImpl extends ServiceImpl<TUserMapper, TUser> implements ITUserService {
 
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private TokenService tokenService;
 
    /**
     * 微信公众号的appid
     */
    @Value("wx.appId")
    private String appId;
 
    /**
     * 微信公众号的appSecret
     */
    @Value("wx.secret")
    private String secret;
 
    @Override
    public List<AppUserVO> listAll(AppUserQuery query) {
        return this.baseMapper.listAll(query);
    }
 
    @Override
    public Boolean phoneCode(String phone) {
        // 生成随机 6位数字 验证码
        String phoneCode = RandomUtil.randomNumbers(6);
        // todo 手机验证码暂时 123456
        phoneCode = "123456";
        // 判断redis中是否存在手机验证码
        Object phoneCodeRedis = redisTemplate.opsForValue().get(RedisConstants.PHONE_CODE + phone);
        if (phoneCodeRedis == null) {
            // 将手机验证码 key: reg:用户输入的手机号码  value: 随机验证码:时间戳
            phoneCodeRedis = phoneCode;
        } else {
            // redis有验证码,获取redis中value的时间戳,判断是否过期
            long oldTime = Long.parseLong(String.valueOf(phoneCodeRedis).split(":")[1]);
            // 没有超过1分钟的重发时间
            if (System.currentTimeMillis() - oldTime < (long) Constants.SIXTY * Constants.ONE_THOUSAND) {
                throw new GlobalException("操作频繁,稍后重试!!!");
            } else {
                phoneCode = String.valueOf(phoneCodeRedis).split(":")[0];
            }
        }
        /*
         * 保存信息到redis
         * key为 --> phone_code:手机号码 (phone_code表示该业务为 验证码登录)
         * value为 --> 随机验证码:时间戳 (时间戳用于计算是否超过1分钟的重发时间)
         */
        redisTemplate.opsForValue().set(RedisConstants.PHONE_CODE + phone, phoneCode + ":" + System.currentTimeMillis(), 3, TimeUnit.MINUTES);
        String sendMessage = "验证码发送成功,您的验证码为:" + phoneCode + ",该验证码三分钟内有效,请及时完成登陆";
        // todo 发送此消息
        System.out.println(sendMessage);
        return true;
    }
 
    @Override
    public Boolean isVip() {
        TUser user = lambdaQuery().eq(TUser::getId, tokenService.getLoginUserStudy().getUserid())
                .eq(TUser::getDisabled, 0).one();
        // 是否为vip 逻辑
        if (null == user) {
            return false;
        }
        // vip过期时间,字段为空也表示 当前用户不是vip
        Date vipEndTime = user.getVipEndTime();
        return null != vipEndTime && System.currentTimeMillis() <= vipEndTime.getTime();
    }
 
    @Override
    public Map<String, Object> weiXinShare(String url) {
        // 初始化微信API,并注册AppID
        long timestamp = System.currentTimeMillis() / 1000;
        String noncestr = RandomVxUtil.createRandomString(16);
        String ticket = getTicket(getToken(appId, secret));
        String str = "jsapi_ticket=" + ticket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + url;
        // 获取加密后的签名
        String signature = SignatureUtil.getSignature(str);
        Map<String, Object> map = new HashMap<>();
        map.put("appId", appId);
        map.put("timestamp", timestamp);
        map.put("nonceStr", noncestr);
        map.put("signature", signature);
        return map;
    }
 
    public String getToken(String appid, String secret) {
        //拼接访问地址
        String apiUrl = String.format(TokenConstants.VX_TOKEN_API_PREFIX, appid, secret);
        HttpClient client = HttpClients.createDefault();
        //get请求
        HttpGet get = new HttpGet(apiUrl);
        // 初始化解析json格式的对象
        String result = null;
        try {
            HttpResponse res = client.execute(get);
            // 初始化响应内容
            String responseContent;
            HttpEntity entity = res.getEntity();
            //设置编码格式
            responseContent = EntityUtils.toString(entity, "UTF-8");
            // 将json字符串转换为json对象
            JSONObject json = JSONObject.parseObject(responseContent);
            if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                if (json.get(Constants.ERR_CODE) != null) {
                    // 错误时微信会返回错误码等信息,{"errcode":40013,"errmsg":"invalid appid"}
                    throw new GlobalException("微信授权失败!");
                } else {
                    // 正常情况下{"access_token":"ACCESS_TOKEN","expires_in":7200}
                    result = String.valueOf(json.get("access_token"));
                }
            }
            return result;
        } catch (IOException e) {
            throw new GlobalException("微信授权失败!");
        }
    }
 
    public static String getTicket(String accessToken) {
        String turl = String.format(TokenConstants.VX_TICKET_API_PREFIX, accessToken);
        HttpClient client = HttpClients.createDefault();
        HttpGet get = new HttpGet(turl);
        String result = null;
        try {
            HttpResponse res = client.execute(get);
            // 响应内容
            String responseContent;
            HttpEntity entity = res.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
            JSONObject jsonObject = JSONObject.parseObject(responseContent);
            // 将json字符串转换为json对象
            if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                if (jsonObject.get(Constants.ERR_CODE) == null) {
                    // 错误时微信会返回错误码等信息,{"errcode":40013,"errmsg":"invalid appid"}
                    throw new GlobalException("微信授权失败!");
                } else {
                    // 正常情况下{"access_token":"ACCESS_TOKEN","expires_in":7200}
                    result = String.valueOf(jsonObject.get("ticket"));
                }
            }
            return result;
        } catch (IOException e) {
            throw new GlobalException("微信授权失败!");
        }
    }
 
}