repo init
This commit is contained in:
13
user-8072/src/main/java/com/ivmiku/tutorial/Main8072.java
Normal file
13
user-8072/src/main/java/com/ivmiku/tutorial/Main8072.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package com.ivmiku.tutorial;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
@MapperScan("com.ivmiku.tutorial.mapper")
|
||||
public class Main8072 {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Main8072.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ivmiku.tutorial.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
|
||||
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
|
||||
// 设置key序列化方式string,RedisSerializer.string() 等价于 new StringRedisSerializer()
|
||||
redisTemplate.setKeySerializer(RedisSerializer.string());
|
||||
// 设置value的序列化方式json,使用GenericJackson2JsonRedisSerializer替换默认序列化,RedisSerializer.json() 等价于 new GenericJackson2JsonRedisSerializer()
|
||||
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
|
||||
// 设置hash的key的序列化方式
|
||||
redisTemplate.setHashKeySerializer(RedisSerializer.string());
|
||||
// 设置hash的value的序列化方式
|
||||
redisTemplate.setHashValueSerializer(RedisSerializer.json());
|
||||
// 使配置生效
|
||||
redisTemplate.afterPropertiesSet();
|
||||
return redisTemplate;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.ivmiku.tutorial.config;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
|
||||
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
|
||||
import cn.binarywang.wx.miniapp.message.WxMaMessageHandler;
|
||||
import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
|
||||
import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.error.WxRuntimeException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(WxMaProperties.class)
|
||||
public class WxMaConfiguration {
|
||||
private final WxMaProperties properties;
|
||||
|
||||
@Autowired
|
||||
public WxMaConfiguration(WxMaProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WxMaService wxMaService() {
|
||||
List<WxMaProperties.Config> configs = this.properties.getConfigs();
|
||||
if (configs == null) {
|
||||
throw new WxRuntimeException("大哥,拜托先看下项目首页的说明(readme文件),添加下相关配置,注意别配错了!");
|
||||
}
|
||||
WxMaService maService = new WxMaServiceImpl();
|
||||
maService.setMultiConfigs(
|
||||
configs.stream()
|
||||
.map(a -> {
|
||||
WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
|
||||
// WxMaDefaultConfigImpl config = new WxMaRedisConfigImpl(new JedisPool());
|
||||
// 使用上面的配置时,需要同时引入jedis-lock的依赖,否则会报类无法找到的异常
|
||||
config.setAppid(a.getAppid());
|
||||
config.setSecret(a.getSecret());
|
||||
config.setToken(a.getToken());
|
||||
config.setAesKey(a.getAesKey());
|
||||
config.setMsgDataFormat(a.getMsgDataFormat());
|
||||
return config;
|
||||
}).collect(Collectors.toMap(WxMaDefaultConfigImpl::getAppid, a -> a, (o, n) -> o)));
|
||||
return maService;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WxMaMessageRouter wxMaMessageRouter(WxMaService wxMaService) {
|
||||
final WxMaMessageRouter router = new WxMaMessageRouter(wxMaService);
|
||||
router
|
||||
.rule().handler(logHandler).next()
|
||||
.rule().async(false).content("订阅消息").handler(subscribeMsgHandler).end()
|
||||
.rule().async(false).content("文本").handler(textHandler).end()
|
||||
.rule().async(false).content("图片").handler(picHandler).end()
|
||||
.rule().async(false).content("二维码").handler(qrcodeHandler).end();
|
||||
return router;
|
||||
}
|
||||
|
||||
private final WxMaMessageHandler subscribeMsgHandler = (wxMessage, context, service, sessionManager) -> {
|
||||
service.getMsgService().sendSubscribeMsg(WxMaSubscribeMessage.builder()
|
||||
.templateId("此处更换为自己的模板id")
|
||||
.data(Lists.newArrayList(
|
||||
new WxMaSubscribeMessage.MsgData("keyword1", "339208499")))
|
||||
.toUser(wxMessage.getFromUser())
|
||||
.build());
|
||||
return null;
|
||||
};
|
||||
|
||||
private final WxMaMessageHandler logHandler = (wxMessage, context, service, sessionManager) -> {
|
||||
log.info("收到消息:" + wxMessage.toString());
|
||||
service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("收到信息为:" + wxMessage.toJson())
|
||||
.toUser(wxMessage.getFromUser()).build());
|
||||
return null;
|
||||
};
|
||||
|
||||
private final WxMaMessageHandler textHandler = (wxMessage, context, service, sessionManager) -> {
|
||||
service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("回复文本消息")
|
||||
.toUser(wxMessage.getFromUser()).build());
|
||||
return null;
|
||||
};
|
||||
|
||||
private final WxMaMessageHandler picHandler = (wxMessage, context, service, sessionManager) -> {
|
||||
try {
|
||||
WxMediaUploadResult uploadResult = service.getMediaService()
|
||||
.uploadMedia("image", "png",
|
||||
ClassLoader.getSystemResourceAsStream("tmp.png"));
|
||||
service.getMsgService().sendKefuMsg(
|
||||
WxMaKefuMessage
|
||||
.newImageBuilder()
|
||||
.mediaId(uploadResult.getMediaId())
|
||||
.toUser(wxMessage.getFromUser())
|
||||
.build());
|
||||
} catch (WxErrorException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
private final WxMaMessageHandler qrcodeHandler = (wxMessage, context, service, sessionManager) -> {
|
||||
try {
|
||||
final File file = service.getQrcodeService().createQrcode("123", 430);
|
||||
WxMediaUploadResult uploadResult = service.getMediaService().uploadMedia("image", file);
|
||||
service.getMsgService().sendKefuMsg(
|
||||
WxMaKefuMessage
|
||||
.newImageBuilder()
|
||||
.mediaId(uploadResult.getMediaId())
|
||||
.toUser(wxMessage.getFromUser())
|
||||
.build());
|
||||
} catch (WxErrorException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.ivmiku.tutorial.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "wx.miniapp")
|
||||
public class WxMaProperties {
|
||||
|
||||
private List<Config> configs;
|
||||
|
||||
@Data
|
||||
public static class Config {
|
||||
/**
|
||||
* 设置微信小程序的appid
|
||||
*/
|
||||
private String appid;
|
||||
|
||||
/**
|
||||
* 设置微信小程序的Secret
|
||||
*/
|
||||
private String secret;
|
||||
|
||||
/**
|
||||
* 设置微信小程序消息服务器配置的token
|
||||
*/
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* 设置微信小程序消息服务器配置的EncodingAESKey
|
||||
*/
|
||||
private String aesKey;
|
||||
|
||||
/**
|
||||
* 消息格式,XML或者JSON
|
||||
*/
|
||||
private String msgDataFormat;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.ivmiku.tutorial.controller;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||
import cn.binarywang.wx.miniapp.util.WxMaConfigHolder;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.ivmiku.tutorial.entity.User;
|
||||
import com.ivmiku.tutorial.mapper.UserMapper;
|
||||
import com.ivmiku.tutorial.response.Result;
|
||||
import com.ivmiku.tutorial.utils.RedisUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/user")
|
||||
public class UserController {
|
||||
@Resource
|
||||
private WxMaService wxMaService;
|
||||
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@GetMapping("/login")
|
||||
public Object login(@RequestParam(name = "code") String code, @RequestParam(name = "rawdata") String rawData, @RequestParam(name = "signature") String signature
|
||||
) {
|
||||
WxMaJscode2SessionResult session;
|
||||
try {
|
||||
session = wxMaService.getUserService().getSessionInfo(code);
|
||||
} catch (WxErrorException e) {
|
||||
return JSON.toJSON(Result.error(e.getMessage()));
|
||||
}
|
||||
StpUtil.login(session.getOpenid());
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
if (userMapper.selectById(session.getOpenid()) == null) {
|
||||
if (!wxMaService.getUserService().checkUserInfo(session.getSessionKey(), rawData, signature)) {
|
||||
WxMaConfigHolder.remove();//清理ThreadLocal
|
||||
return JSON.toJSON(Result.error("用户数据验证错误!"));
|
||||
}
|
||||
JSONObject raw = JSONObject.parseObject(rawData);
|
||||
User user = new User();
|
||||
user.setOpenid(session.getOpenid());
|
||||
user.setNickname(raw.getString("nickname"));
|
||||
user.setAvatarUrl(raw.getString("avatarUrl"));
|
||||
userMapper.insert(user);
|
||||
}
|
||||
map.put("token", StpUtil.getTokenValue());
|
||||
redisUtil.insertKey(session.getOpenid(), session.getSessionKey());
|
||||
WxMaConfigHolder.remove();
|
||||
return JSON.toJSON(Result.ok(map));
|
||||
}
|
||||
}
|
||||
14
user-8072/src/main/java/com/ivmiku/tutorial/entity/User.java
Normal file
14
user-8072/src/main/java/com/ivmiku/tutorial/entity/User.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package com.ivmiku.tutorial.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
@TableName("user")
|
||||
@Data
|
||||
public class User {
|
||||
@TableId
|
||||
private String openid;
|
||||
private String nickname;
|
||||
private String avatarUrl;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ivmiku.tutorial.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ivmiku.tutorial.entity.User;
|
||||
|
||||
public interface UserMapper extends BaseMapper<User> {
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.ivmiku.tutorial.utils;
|
||||
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
import com.alibaba.csp.sentinel.slots.block.BlockException;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.ivmiku.tutorial.response.Result;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* @author Aurora
|
||||
*/
|
||||
@Slf4j
|
||||
@ControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
@ExceptionHandler(value = SaTokenException.class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
@ResponseBody
|
||||
public Object SaTokenExceptionHandler(SaTokenException e) {
|
||||
log.error("SaTokenException:" + e.getLocalizedMessage());
|
||||
return JSON.toJSON(Result.error("身份认证错误:" + e.getMessage()));
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = ParseException.class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
@ResponseBody
|
||||
public Object parseExceptionHandler(ParseException e) {
|
||||
|
||||
log.error("ParseException:" + e.getLocalizedMessage());
|
||||
return JSON.toJSON(Result.error("请检查日期是否合法"));
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = SQLException.class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
@ResponseBody
|
||||
public Object SQLExceptionHandler(SQLException e) {
|
||||
log.error("SQLException:" + e.getLocalizedMessage());
|
||||
return JSON.toJSON(Result.error("数据库出错!(内部错误)\n" + e.getMessage()));
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = BlockException.class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
@ResponseBody
|
||||
public Object sentinelHandler(BlockException e) {
|
||||
return JSON.toJSON(Result.error("系统繁忙,请稍后再试"));
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = Exception.class)
|
||||
@ResponseBody
|
||||
public Object exceptionHandler(Exception e) {
|
||||
log.error("Exception:" + e.getLocalizedMessage());
|
||||
return JSON.toJSON(Result.error("服务器内部错误:" + e.getClass() + ":" + e.getMessage()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ivmiku.tutorial.utils;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author Aurora
|
||||
*/
|
||||
@Component
|
||||
public class RedisUtil {
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
public void insertKey(String userId, String sessionKey) {
|
||||
redisTemplate.opsForValue().set("sessionkey:" + userId, sessionKey);
|
||||
}
|
||||
|
||||
public String getKey(String userId) {
|
||||
return (String) redisTemplate.opsForValue().get("sessionkey:" + userId);
|
||||
}
|
||||
}
|
||||
21
user-8072/src/main/resources/application-dep.properties
Normal file
21
user-8072/src/main/resources/application-dep.properties
Normal file
@@ -0,0 +1,21 @@
|
||||
wx.miniapp.configs[0].appid=wx0d4fdb5c7bf3b12b
|
||||
wx.miniapp.configs[0].secret=989f155fcc3aee616568473faf1b1d3b
|
||||
|
||||
spring.data.redis.host=redis
|
||||
spring.data.redis.port=6379
|
||||
spring.data.redis.database=0
|
||||
|
||||
spring.application.name=user
|
||||
|
||||
server.port=8072
|
||||
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
spring.datasource.username=root
|
||||
spring.datasource.password=Shuodedaoli114514
|
||||
spring.datasource.url=jdbc:mysql://mysql:4514/tutorial?useUnicode=true&characterEncoding=utf8&useSSL=false&ServerTimezone=Asia/Shanghai
|
||||
|
||||
spring.cloud.nacos.discovery.server-addr=nacos:8848
|
||||
spring.cloud.nacos.discovery.enabled=true
|
||||
|
||||
management.zipkin.tracing.endpoint=http://zipkin:9411/api/v2/spans
|
||||
management.tracing.sampling.probability=1.0
|
||||
15
user-8072/src/main/resources/application-dev.properties
Normal file
15
user-8072/src/main/resources/application-dev.properties
Normal file
@@ -0,0 +1,15 @@
|
||||
wx.miniapp.configs[0].appid=wx0d4fdb5c7bf3b12b
|
||||
wx.miniapp.configs[0].secret=989f155fcc3aee616568473faf1b1d3b
|
||||
|
||||
spring.data.redis.host=localhost
|
||||
spring.data.redis.port=6379
|
||||
spring.data.redis.database=0
|
||||
|
||||
spring.application.name=user
|
||||
|
||||
server.port=8072
|
||||
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
spring.datasource.username=root
|
||||
spring.datasource.password=12345abcde
|
||||
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/tutorial?useUnicode=true&characterEncoding=utf8&useSSL=false&ServerTimezone=Asia/Shanghai
|
||||
1
user-8072/src/main/resources/application.properties
Normal file
1
user-8072/src/main/resources/application.properties
Normal file
@@ -0,0 +1 @@
|
||||
spring.profiles.active=dep
|
||||
Reference in New Issue
Block a user