Browse Source

1、微信授权;

2、微信推送模板消息;
dev
mh 5 months ago
parent
commit
1d4c5bb07e
  1. 20
      user-service/pom.xml
  2. 9
      user-service/src/main/java/com/mh/user/config/RestTemplateConfig.java
  3. 58
      user-service/src/main/java/com/mh/user/config/WebSecurityConfig.java
  4. 94
      user-service/src/main/java/com/mh/user/config/wechat/WechatMpConfig.java
  5. 62
      user-service/src/main/java/com/mh/user/config/wechat/WechatSignUtil.java
  6. 119
      user-service/src/main/java/com/mh/user/controller/wechat/WechatController.java
  7. 35
      user-service/src/main/java/com/mh/user/entity/wechat/First.java
  8. 35
      user-service/src/main/java/com/mh/user/entity/wechat/Key1.java
  9. 36
      user-service/src/main/java/com/mh/user/entity/wechat/Key2.java
  10. 36
      user-service/src/main/java/com/mh/user/entity/wechat/Key3.java
  11. 36
      user-service/src/main/java/com/mh/user/entity/wechat/Key4.java
  12. 36
      user-service/src/main/java/com/mh/user/entity/wechat/Key5.java
  13. 115
      user-service/src/main/java/com/mh/user/entity/wechat/PushMsgEntity.java
  14. 36
      user-service/src/main/java/com/mh/user/entity/wechat/Remark.java
  15. 172
      user-service/src/main/java/com/mh/user/entity/wechat/WechatUserInfoEntity.java
  16. 49
      user-service/src/main/java/com/mh/user/job/PushDataToWechatJob.java
  17. 18
      user-service/src/main/java/com/mh/user/mapper/EnergyDataMapper.java
  18. 16
      user-service/src/main/java/com/mh/user/mapper/wechat/WechatUserInfoMapper.java
  19. 4
      user-service/src/main/java/com/mh/user/service/EnergyDataService.java
  20. 5
      user-service/src/main/java/com/mh/user/service/impl/EnergyDataServiceImpl.java
  21. 14
      user-service/src/main/java/com/mh/user/service/wechat/WechatService.java
  22. 21
      user-service/src/main/java/com/mh/user/service/wechat/WechatUserInfoService.java
  23. 73
      user-service/src/main/java/com/mh/user/service/wechat/impl/WechatServiceImpl.java
  24. 55
      user-service/src/main/java/com/mh/user/service/wechat/impl/WechatUserInfoServiceImpl.java
  25. 90
      user-service/src/main/java/com/mh/user/utils/CacheUtil.java
  26. 70
      user-service/src/main/java/com/mh/user/utils/SignUtil.java
  27. 1
      user-service/src/main/resources/static/MP_verify_KpSSuYz7qGU2WuoM.txt
  28. 5
      user-service/src/test/java/com/mh/user/DealDataTest.java
  29. 41
      user-service/src/test/java/com/mh/user/WechatTest.java
  30. 60
      user-service/src/test/java/com/mh/user/device/CRC16Test.java
  31. 30
      微信用户信息表.sql

20
user-service/pom.xml

@ -16,7 +16,6 @@
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
</properties>
<dependencies>
@ -186,18 +185,15 @@
<version>3.2.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.binarywang/weixin-java-mp -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>4.6.7.B</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<!-- 打包时拷贝MyBatis的映射文件 -->

9
user-service/src/main/java/com/mh/user/config/RestTemplateConfig.java

@ -1,14 +1,21 @@
package com.mh.user.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @author ljf
* @title
* @description redis配置
* @description 缓存配置
* @updateTime 2020-08-20
* @throws
*/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

58
user-service/src/main/java/com/mh/user/config/WebSecurityConfig.java

@ -42,36 +42,36 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 禁用 csrf, 由于使用的是JWT,我们这里不需要csrf
System.out.println("test0");
http.cors().and().csrf().disable()
.authorizeRequests()
// 跨域预检请求
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// web jars
.antMatchers("/webjars/**").permitAll()
// 查看SQL监控(druid)
.antMatchers("/druid/**").permitAll()
// 首页和登录页面
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
// swagger
.antMatchers("/swagger-ui.html").permitAll()
.antMatchers("/swagger-resources/**").permitAll()
.antMatchers("/v2/api-docs").permitAll()
.antMatchers("/webjars/springfox-swagger-ui/**").permitAll()
// 验证码
.antMatchers("/captcha.jpg**").permitAll()
// 服务监控
.antMatchers("/actuator/**").permitAll()
// 其他所有请求需要身份认证
.anyRequest().authenticated();
// 退出登录处理器
http.logout().logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler());
// token验证过滤器
http.addFilterBefore(new JwtAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);
System.out.println("test0_1");
// System.out.println("test0");
// http.cors().and().csrf().disable()
// .authorizeRequests()
// // 跨域预检请求
// .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// // web jars
// .antMatchers("/webjars/**").permitAll()
// // 查看SQL监控(druid)
// .antMatchers("/druid/**").permitAll()
// // 首页和登录页面
// .antMatchers("/").permitAll()
// .antMatchers("/login").permitAll()
// // swagger
// .antMatchers("/swagger-ui.html").permitAll()
// .antMatchers("/swagger-resources/**").permitAll()
// .antMatchers("/v2/api-docs").permitAll()
// .antMatchers("/webjars/springfox-swagger-ui/**").permitAll()
// // 验证码
// .antMatchers("/captcha.jpg**").permitAll()
// // 服务监控
// .antMatchers("/actuator/**").permitAll()
// // 其他所有请求需要身份认证
// .anyRequest().authenticated();
// // 退出登录处理器
// http.logout().logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler());
// // token验证过滤器
// http.addFilterBefore(new JwtAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);
// System.out.println("test0_1");
// 禁用token验证
// http.csrf().disable().authorizeRequests().anyRequest().permitAll().and().logout().permitAll();
http.csrf().disable().authorizeRequests().anyRequest().permitAll().and().logout().permitAll();
}
@Bean

94
user-service/src/main/java/com/mh/user/config/wechat/WechatMpConfig.java

@ -0,0 +1,94 @@
package com.mh.user.config.wechat;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.config.WxMpConfigStorage;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import java.net.URLEncoder;
/**
* @author chison
* @date 2020-04-03 15:42
* @Description 微信网页授权信息配置类
*/
@Component
@Configuration
public class WechatMpConfig {
@Value("${wechat.mpAppId}")
private String mpAppId;
@Value("${wechat.mpAppSecret}")
private String mpAppSecret;
@Value("${wechat.redirectUri}")
private String redirectUri;
@Value("${wechat.authorizedUrl}")
private String authorizedUrl;
@Value("${wechat.access_token}")
private String accessToken;
@Value("${wechat.userinfo}")
private String userinfo;
@Value("${wechat.pushUrl}")
private String pushUrl;
@Value("${wechat.baseUrl}")
private String baseUrl;
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public String getAuthorizedUrl() {
return authorizedUrl.replace("mpAppId", mpAppId).replace("REDIRECT_URI", URLEncoder.encode(redirectUri));
}
public String getAccessTokenUrl() {
return accessToken.replace("APPID", mpAppId).replace("SECRET", mpAppSecret);
}
public String getUserInfo(String accessToken, String openId) {
return userinfo.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
}
public String getPushMsgUrl(String accessToken) {
return pushUrl.replace("ACCESS_TOKEN", accessToken);
}
public String getMpAppId() {
return mpAppId;
}
public String getMpAppSecret() {
return mpAppSecret;
}
/**
* 配置WxMpService所需信息
*
* @return
*/
@Bean // 此注解指定在Spring容器启动时,就执行该方法并将该方法返回的对象交由Spring容器管理
public WxMpService wxMpService() {
WxMpService wxMpService = new WxMpServiceImpl();
// 设置配置信息的存储位置
wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
return wxMpService;
}
public WxMpConfigStorage wxMpConfigStorage() {
// 使用这个实现类则表示将配置信息存储在内存中
WxMpDefaultConfigImpl wxMpInMemoryConfigStorage = new WxMpDefaultConfigImpl();
wxMpInMemoryConfigStorage.setAppId(getMpAppId());
wxMpInMemoryConfigStorage.setSecret(getMpAppSecret());
return wxMpInMemoryConfigStorage;
}
}

62
user-service/src/main/java/com/mh/user/config/wechat/WechatSignUtil.java

@ -0,0 +1,62 @@
package com.mh.user.config.wechat;
import lombok.extern.slf4j.Slf4j;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Map;
import java.util.TreeMap;
/**
* @Author : Rainbow
* @date : 2024-09-14
*/
@Slf4j
public class WechatSignUtil {
/**
* SHA-1加密
* @param params
* @return
*/
public static String generateSignature(Map<String, String> params) {
// 使用TreeMap进行自然排序(按照key的ASCII码排序)
TreeMap<String, String> sortedParams = new TreeMap<>(params);
// 拼接字符串
StringBuilder stringBuilder = new StringBuilder();
for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
if (stringBuilder.length() > 0) {
stringBuilder.append("&");
}
stringBuilder.append(entry.getKey()).append("=").append(entry.getValue());
}
String string1 = stringBuilder.toString();
// SHA-1加密
try {
// 获取SHA-1实例
MessageDigest digest = MessageDigest.getInstance("SHA-1");
// 将输入字符串转换为字节数组
byte[] encodedHash = digest.digest(string1.getBytes());
// 可选:将字节数组转换为Base64字符串,便于显示和传输
String base64Encoded = Base64.getEncoder().encodeToString(encodedHash);
log.info("SHA-1 (Base64 Encoded): {}", base64Encoded);
// 或者,直接以16进制形式输出
StringBuilder hexString = new StringBuilder();
for (byte b : encodedHash) {
String hex = Integer.toHexString(0xff & b);
if(hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
log.info("SHA-1 (Hexadecimal): {}", hexString);
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("SHA-1 algorithm not found", e);
}
}
}

119
user-service/src/main/java/com/mh/user/controller/wechat/WechatController.java

@ -0,0 +1,119 @@
package com.mh.user.controller.wechat;
import com.alibaba.fastjson2.JSONObject;
import com.github.benmanes.caffeine.cache.Cache;
import com.mh.user.config.wechat.WechatMpConfig;
import com.mh.user.service.wechat.WechatUserInfoService;
import com.mh.user.utils.CacheUtil;
import com.mh.user.utils.SignUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
import java.util.concurrent.TimeUnit;
/**
* @author LJF
* @version 1.0
* @project mh_esi
* @description 微信相关接口
* @date 2024-11-27 15:37:57
*/
@Slf4j
@Controller
@RequestMapping("/wechat")
public class WechatController {
@Autowired
private WechatMpConfig wechatMpConfig;
@Autowired
private RestTemplate restTemplate;
@Autowired
private WechatUserInfoService wechatUserInfoService;
/**
* 微信校验
*
* @param signature
* @param timestamp
* @param nonce
* @param echostr
* @return
*/
@GetMapping("/checkToken")
@ResponseBody
public String checkSignature(@RequestParam("signature") String signature,
@RequestParam("timestamp") String timestamp,
@RequestParam("nonce") String nonce,
@RequestParam("echostr") String echostr) {
if (SignUtil.checkSignature(signature, timestamp, nonce)) {
return echostr;
} else {
return null;
}
}
@GetMapping("/authorize")
@ResponseBody
public String authorize() {
log.info("进入authorize,redirect:{}", wechatMpConfig.getAuthorizedUrl());
return "redirect:" + wechatMpConfig.getAuthorizedUrl();
}
@GetMapping("/userInfo")
@ResponseBody
public String userInfo(@RequestParam("code") String code, @RequestParam("state") String returnUrl) {
try {
// {"access_token":"86_OnLuaNu9da1Xeh3Q4PE77sLaX_CQQFNY5rvnWTK6o_-vhIeb74rydT93HCowiVKkYUAWPG8186mvQaP55Cy47Xtuo4EkqOSyiagyW1q4mVU","expires_in":7200,"refresh_token":"86_6YSDe0P0KkFnJH0KnJzvtodh9z62GdDbdl8aG-VF7Rn46DKsWvQOuES3EluhDUQ38uUboZNr9a5wU9LvoI9HDqhkWm9hoE-1T8vUPfjoLhc","openid":"o0qeN5lw4JquQy_H9Rk5QN-CyMRU","scope":"snsapi_userinfo"}
// 判断cache中是否存在access_token
// CacheUtil instance = CacheUtil.getInstance();
// Cache<Object, Object> cache = instance.getCache("accessToken");
String accessToken = "";
String openId = "";
// if (cache != null ) {
// log.info("cache中存在access_token,直接使用");
// accessToken = cache.getIfPresent("accessToken").toString();
// } else {
// 使用code换取access_token信息
String getAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
"appid=" + wechatMpConfig.getMpAppId() + "&secret=" + wechatMpConfig.getMpAppSecret() + "&" +
"code=" + code + "&grant_type=authorization_code";
String tokenResult = restTemplate.getForObject(getAccessTokenUrl, String.class);
JSONObject jsonObj = JSONObject.parseObject(tokenResult);
if (jsonObj == null || !jsonObj.containsKey("access_token")) {
return "获取access_token失败";
}
log.info("获取access_token==>{}", jsonObj.toJSONString());
accessToken = jsonObj.get("access_token").toString();
openId = jsonObj.get("openid").toString();
// 存储access_token到缓存中
// instance.createCache("accessToken", 6000, TimeUnit.SECONDS);
// }
String getUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?" +
"access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN";
String userInfoResult = restTemplate.getForObject(getUserInfoUrl, String.class);
userInfoResult = new String(userInfoResult.getBytes("ISO-8859-1"), "utf-8");
System.out.println(userInfoResult);
// 判断用户是否存在 0:不存在;1:存在
int exist = wechatUserInfoService.existsUser(JSONObject.parseObject(userInfoResult));
System.out.println("exist: " + exist);
// 重定向到我们要跳转的页面
String result = "";
result = "redirect:" + wechatMpConfig.getBaseUrl() + "/#/?openId=" + openId;
return result;
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
}
}

35
user-service/src/main/java/com/mh/user/entity/wechat/First.java

@ -0,0 +1,35 @@
package com.mh.user.entity.wechat;
/**
* @author chison
* @date 2020-09-14 10:59
* @Description
*/
public class First {
public String value;
public String color;
public First() {
}
public First(String value, String color) {
this.value = value;
this.color = color;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}

35
user-service/src/main/java/com/mh/user/entity/wechat/Key1.java

@ -0,0 +1,35 @@
package com.mh.user.entity.wechat;
/**
* @author chison
* @date 2020-09-14 10:59
* @Description
*/
public class Key1 {
public String value;
public String color;
public Key1() {
}
public Key1(String value, String color) {
this.value = value;
this.color = color;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}

36
user-service/src/main/java/com/mh/user/entity/wechat/Key2.java

@ -0,0 +1,36 @@
package com.mh.user.entity.wechat;
/**
* @author chison
* @date 2020-09-14 10:59
* @Description
*/
public class Key2 {
public String value;
public String color;
public Key2() {
}
public Key2(String value, String color) {
this.value = value;
this.color = color;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}

36
user-service/src/main/java/com/mh/user/entity/wechat/Key3.java

@ -0,0 +1,36 @@
package com.mh.user.entity.wechat;
/**
* @author chison
* @date 2020-09-14 11:00
* @Description
*/
public class Key3 {
public String value;
public String color;
public Key3() {
}
public Key3(String value, String color) {
this.value = value;
this.color = color;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}

36
user-service/src/main/java/com/mh/user/entity/wechat/Key4.java

@ -0,0 +1,36 @@
package com.mh.user.entity.wechat;
/**
* @author chison
* @date 2020-09-14 11:00
* @Description
*/
public class Key4 {
public String value;
public String color;
public Key4() {
}
public Key4(String value, String color) {
this.value = value;
this.color = color;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}

36
user-service/src/main/java/com/mh/user/entity/wechat/Key5.java

@ -0,0 +1,36 @@
package com.mh.user.entity.wechat;
/**
* @author chison
* @date 2020-09-14 11:00
* @Description
*/
public class Key5 {
public String value;
public String color;
public Key5() {
}
public Key5(String value, String color) {
this.value = value;
this.color = color;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}

115
user-service/src/main/java/com/mh/user/entity/wechat/PushMsgEntity.java

@ -0,0 +1,115 @@
package com.mh.user.entity.wechat;
/**
* @author chison
* @date 2020-09-14 10:58
* @Description 推送消息实体类
*/
public class PushMsgEntity {
public String touser; //接收人
public String templateId; //微信提供模板id
public String url; //消息推送消息url
public First first; //消息头消息
public Key1 key1;
public Key2 key2;
public Key3 key3;
public Key4 key4;
public Key5 key5;
public Remark remark;
public String getTouser() {
return touser;
}
public void setTouser(String touser) {
this.touser = touser;
}
public String getTemplateId() {
return templateId;
}
public void setTemplateId(String templateId) {
this.templateId = templateId;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public First getFirst() {
return first;
}
public void setFirst(First first) {
this.first = first;
}
public Key1 getKey1() {
return key1;
}
public void setKey1(Key1 key1) {
this.key1 = key1;
}
public Key2 getKey2() {
return key2;
}
public void setKey2(Key2 key2) {
this.key2 = key2;
}
public Key3 getKey3() {
return key3;
}
public void setKey3(Key3 key3) {
this.key3 = key3;
}
public Key4 getKey4() {
return key4;
}
public void setKey4(Key4 key4) {
this.key4 = key4;
}
public Key5 getKey5() {
return key5;
}
public void setKey5(Key5 key5) {
this.key5 = key5;
}
public Remark getRemark() {
return remark;
}
public void setRemark(Remark remark) {
this.remark = remark;
}
@Override
public String toString() {
return "PushMsgEntity{" +
"touser='" + touser + '\'' +
", templateId='" + templateId + '\'' +
", url='" + url + '\'' +
", first=" + first +
", key1=" + key1 +
", key2=" + key2 +
", key3=" + key3 +
", key4=" + key4 +
", key5=" + key5 +
", remark=" + remark +
'}';
}
}

36
user-service/src/main/java/com/mh/user/entity/wechat/Remark.java

@ -0,0 +1,36 @@
package com.mh.user.entity.wechat;
/**
* @author chison
* @date 2020-09-14 15:47
* @Description
*/
public class Remark {
public String value;
public String color;
public Remark() {
}
public Remark(String value, String color) {
this.value = value;
this.color = color;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}

172
user-service/src/main/java/com/mh/user/entity/wechat/WechatUserInfoEntity.java

@ -0,0 +1,172 @@
package com.mh.user.entity.wechat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.util.Date;
/**
* @author LJF
* @version 1.0
* @project mh_esi
* @description 微信用户实体类
* @date 2024-11-27 16:58:55
*/
@TableName("wechat_user_info")
public class WechatUserInfoEntity {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private String userName;
private String telNum;
private String openId;
private String nickName;
private int sex;
private String province;
private String city;
private String country;
private String headimgurl;
private int isStatus;
private Date createTime;
private Date updateTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getTelNum() {
return telNum;
}
public void setTelNum(String telNum) {
this.telNum = telNum;
}
public String getOpenId() {
return openId;
}
public void setOpenId(String openId) {
this.openId = openId;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public int getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public void setSex(int sex) {
this.sex = sex;
}
public String getHeadimgurl() {
return headimgurl;
}
public void setHeadimgurl(String headimgurl) {
this.headimgurl = headimgurl;
}
public int getIsStatus() {
return isStatus;
}
public void setIsStatus(int isStatus) {
this.isStatus = isStatus;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
return "WechatUserInfoEntity{" +
"id=" + id +
", userName='" + userName + '\'' +
", telNum='" + telNum + '\'' +
", openId='" + openId + '\'' +
", nickName='" + nickName + '\'' +
", sex=" + sex +
", province='" + province + '\'' +
", city='" + city + '\'' +
", country='" + country + '\'' +
", headimgurl='" + headimgurl + '\'' +
", isStatus=" + isStatus +
", createTime=" + createTime +
", updateTime=" + updateTime +
'}';
}
}

49
user-service/src/main/java/com/mh/user/job/PushDataToWechatJob.java

@ -0,0 +1,49 @@
package com.mh.user.job;
import com.mh.user.entity.EnergyDataEntity;
import com.mh.user.entity.ProjectInfoEntity;
import com.mh.user.service.EnergyDataService;
import com.mh.user.service.ProjectInfoService;
import com.mh.user.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author LJF
* @version 1.0
* @project mh_esi
* @description 推送给微信公众号
* @date 2024-11-28 16:39:33
*/
@Slf4j
@Component
public class PushDataToWechatJob {
@Autowired
private ProjectInfoService projectInfoService;
@Autowired
private EnergyDataService energyDataService;
@Scheduled(cron = "25 0/2 * * * ?") //每2分钟一次
public void pushDataToWechat() {
log.info("推送给微信公众号");
String curDate = DateUtil.dateToString(DateUtil.getNowDate(), "yyyy-MM-dd");
// 查询有多少项目
List<ProjectInfoEntity> projectInfoEntities = projectInfoService.queryProjectInfo("1");
for (ProjectInfoEntity projectInfoEntity : projectInfoEntities) {
EnergyDataEntity energyDataEntity = energyDataService.queryEnergyDataByDate(curDate, String.valueOf(projectInfoEntity.getId()));
if (energyDataEntity == null) {
log.info("没有数据");
} else {
log.info("有数据");
// 开始推送数据
}
}
}
}

18
user-service/src/main/java/com/mh/user/mapper/EnergyDataMapper.java

@ -141,4 +141,22 @@ public interface EnergyDataMapper extends BaseMapper<EnergyDataEntity> {
@Param("lastStartDate") String lastStartDate,
@Param("lastEndDate") String lastEndDate,
@Param("dateType") String dateType);
@Select("select top 1 edd.*,pi.project_name from energy_data_day edd " +
" left join project_info pi on edd.project_id = pi.id " +
" where cur_date = #{curDate} and project_id = #{projectId} ")
@Results({
@Result(property = "id", column = "id"),
@Result(property = "curDate", column = "cur_date"),
@Result(property = "ambTemp", column = "amb_temp"),
@Result(property = "humidity", column = "humidity"),
@Result(property = "water", column = "water"),
@Result(property = "elect", column = "elect"),
@Result(property = "cl", column = "cl"),
@Result(property = "cop", column = "cop"),
@Result(property = "projectId", column = "project_id"),
@Result(property = "projectName", column = "project_name")
})
EnergyDataEntity queryEnergyDataByDate(@Param("curDate") String curDate,
@Param("projectId") String projectId);
}

16
user-service/src/main/java/com/mh/user/mapper/wechat/WechatUserInfoMapper.java

@ -0,0 +1,16 @@
package com.mh.user.mapper.wechat;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mh.user.entity.wechat.WechatUserInfoEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* @author LJF
* @version 1.0
* @project mh_esi
* @description 微信用户mapper类
* @date 2024-11-27 17:02:40
*/
@Mapper
public interface WechatUserInfoMapper extends BaseMapper<WechatUserInfoEntity> {
}

4
user-service/src/main/java/com/mh/user/service/EnergyDataService.java

@ -1,8 +1,6 @@
package com.mh.user.service;
import com.github.pagehelper.PageInfo;
import com.mh.common.page.PageResult;
import com.mh.user.dto.EnergyMomYoyDataDTO;
import com.mh.user.entity.EnergyDataEntity;
import com.mh.user.model.EnergyModel;
import java.util.List;
@ -16,4 +14,6 @@ public interface EnergyDataService {
PageResult queryMomEnergyData(EnergyModel energyModel);
PageResult queryYoyEnergyData(EnergyModel energyModel);
EnergyDataEntity queryEnergyDataByDate(String curDate, String projectId);
}

5
user-service/src/main/java/com/mh/user/service/impl/EnergyDataServiceImpl.java

@ -337,4 +337,9 @@ public class EnergyDataServiceImpl implements EnergyDataService {
dateType);
return MybatisPageHelper.getPageResult(pageRequest, new PageInfo<>(resultList));
}
@Override
public EnergyDataEntity queryEnergyDataByDate(String curDate, String projectId) {
return energyDataMapper.queryEnergyDataByDate(curDate, projectId);
}
}

14
user-service/src/main/java/com/mh/user/service/wechat/WechatService.java

@ -0,0 +1,14 @@
package com.mh.user.service.wechat;
import com.mh.user.entity.wechat.PushMsgEntity;
/**
* @author chison
* @date 2020-09-14 10:48
* @Description 微信业务
*/
public interface WechatService {
void PushMsg(PushMsgEntity pushMsgEntity);
}

21
user-service/src/main/java/com/mh/user/service/wechat/WechatUserInfoService.java

@ -0,0 +1,21 @@
package com.mh.user.service.wechat;
import com.alibaba.fastjson2.JSONObject;
/**
* @author LJF
* @version 1.0
* @project mh_esi
* @description 微信用户服务类
* @date 2024-11-27 17:03:34
*/
public interface WechatUserInfoService {
/**
* 判断是否存在用户信息
* @param jsonObject
* @return
*/
int existsUser(JSONObject jsonObject);
}

73
user-service/src/main/java/com/mh/user/service/wechat/impl/WechatServiceImpl.java

@ -0,0 +1,73 @@
package com.mh.user.service.wechat.impl;
import com.alibaba.fastjson2.JSONObject;
import com.github.benmanes.caffeine.cache.Cache;
import com.mh.user.config.wechat.WechatMpConfig;
import com.mh.user.entity.wechat.PushMsgEntity;
import com.mh.user.service.wechat.WechatService;
import com.mh.user.utils.CacheUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.concurrent.TimeUnit;
/**
* @author LJF
* @version 1.0
* @project mh_esi
* @description 微信服务类
* @date 2024-11-28 17:05:16
*/
@Slf4j
@Service
public class WechatServiceImpl implements WechatService {
@Autowired
private RestTemplate restTemplate;
@Autowired
private WechatMpConfig wechatMpConfig;
@Override
public void PushMsg(PushMsgEntity pushMsgEntity) {
// 判断cache中是否存在access_token
CacheUtil instance = CacheUtil.getInstance();
Cache<Object, Object> cache = instance.getCache("accessToken");
String accessToken = "";
if (cache != null ) {
log.info("cache中存在access_token,直接使用");
accessToken = cache.getIfPresent("accessToken").toString();
} else {
String tokenResult = restTemplate.getForObject(wechatMpConfig.getAccessTokenUrl(),String.class);
JSONObject jsonObj = JSONObject.parseObject(tokenResult);
if (jsonObj == null || !jsonObj.containsKey("access_token")) {
return;
}
accessToken = jsonObj.get("access_token").toString();
instance.createCache("accessToken", 6000, TimeUnit.SECONDS);
}
// 封装推送内容
JSONObject jsonObject = new JSONObject();
jsonObject.put("touser",pushMsgEntity.getTouser());
jsonObject.put("template_id",pushMsgEntity.getTemplateId());
jsonObject.put("url",pushMsgEntity.getUrl());
JSONObject data = new JSONObject();
data.put("first",pushMsgEntity.getFirst());
data.put("keyword1",pushMsgEntity.getKey1());
data.put("keyword2",pushMsgEntity.getKey2());
data.put("keyword3",pushMsgEntity.getKey3());
data.put("keyword4",pushMsgEntity.getKey4());
data.put("keyword5",pushMsgEntity.getKey5());
data.put("remark",pushMsgEntity.getRemark());
jsonObject.put("data",data);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
HttpEntity<Object> entity = new HttpEntity<Object>(jsonObject, headers);
String result = restTemplate.postForObject(wechatMpConfig.getPushMsgUrl(accessToken),entity,String.class);
log.info("推送结果:{}", result);
}
}

55
user-service/src/main/java/com/mh/user/service/wechat/impl/WechatUserInfoServiceImpl.java

@ -0,0 +1,55 @@
package com.mh.user.service.wechat.impl;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mh.user.entity.wechat.WechatUserInfoEntity;
import com.mh.user.mapper.wechat.WechatUserInfoMapper;
import com.mh.user.service.wechat.WechatUserInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* @author LJF
* @version 1.0
* @project mh_esi
* @description 微信服务实体实现类
* @date 2024-11-27 17:03:56
*/
@Service
public class WechatUserInfoServiceImpl implements WechatUserInfoService {
@Autowired
private WechatUserInfoMapper wechatUserInfoMapper;
@Transactional
@Override
public int existsUser(JSONObject jsonObject) {
if (jsonObject == null || !jsonObject.containsKey("openid")) return 0;
String openId = jsonObject.get("openid").toString();
// 根据openId判断用户是否存在
long count = wechatUserInfoMapper.selectCount(new QueryWrapper<WechatUserInfoEntity>().eq("open_id", openId));
// count:0:未找到用户,1:有用户但未完成注册
if (count != 0) {
// 0:未注册;1:完成注册
return 0;
}
WechatUserInfoEntity userEntity = new WechatUserInfoEntity();
userEntity.setIsStatus(2);
userEntity.setOpenId(openId);
userEntity.setNickName(jsonObject.containsKey("nickname") ? jsonObject.get("nickname").toString() : null);
if (jsonObject.containsKey("sex")) {
userEntity.setSex(Integer.parseInt(jsonObject.get("sex").toString()));
} else {
userEntity.setSex(null);
}
userEntity.setProvince(jsonObject.containsKey("province") ? jsonObject.get("province").toString() : null);
userEntity.setCountry(jsonObject.containsKey("country") ? jsonObject.get("country").toString() : null);
userEntity.setCity(jsonObject.containsKey("city") ? jsonObject.get("city").toString() : null);
userEntity.setHeadimgurl(jsonObject.containsKey("headimgurl") ? jsonObject.get("headimgurl").toString() : null);
//用户不存在基本信息先入库
wechatUserInfoMapper.insert(userEntity);
return 0;
}
}

90
user-service/src/main/java/com/mh/user/utils/CacheUtil.java

@ -0,0 +1,90 @@
package com.mh.user.utils;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author LJF
* @version 1.0
* @project mh_esi
* @description 缓存工具类
* @date 2024-11-28 09:42:14
*/
public class CacheUtil {
private static class Holder {
private static final CacheUtil INSTANCE = new CacheUtil();
}
public static CacheUtil getInstance() {
return Holder.INSTANCE;
}
private final ConcurrentHashMap<String, Cache<Object, Object>> caches = new ConcurrentHashMap<>();
private final AtomicLong cacheIdCounter = new AtomicLong(0);
private CacheUtil() {
// 私有构造函数,防止外部实例化
}
/**
* 创建一个带有指定过期时间的缓存实例
*
* @param expireAfterWrite 过期时间写后
* @param unit 时间单位
* @return 缓存ID
*/
public void createCache(String key, long expireAfterWrite, TimeUnit unit) {
Cache<Object, Object> cache = Caffeine.newBuilder()
.expireAfterWrite(expireAfterWrite, unit)
.build();
caches.put(key, cache);
}
/**
* 通过缓存ID获取缓存实例
*
* @param cacheId 缓存ID
* @return 缓存实例
*/
public Cache<Object, Object> getCache(String cacheId) {
return caches.get(cacheId);
}
/**
* 将键值对放入缓存
*
* @param cache 缓存实例
* @param key
* @param value
*/
public void put(Cache<Object, Object> cache, Object key, Object value) {
cache.put(key, value);
}
/**
* 从缓存中获取值
*
* @param cache 缓存实例
* @param key
* @return
*/
public Object get(Cache<Object, Object> cache, Object key) {
return cache.getIfPresent(key);
}
/**
* 从缓存中移除键值对
*
* @param cache 缓存实例
* @param key
*/
public void remove(Cache<Object, Object> cache, Object key) {
cache.invalidate(key);
}
}

70
user-service/src/main/java/com/mh/user/utils/SignUtil.java

@ -0,0 +1,70 @@
package com.mh.user.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
/**
* @author chison
* @date 2020-04-03 11:40
* @Description 工具类
*/
public class SignUtil {
/**与微信配置保持一致*/
private static String token = "WechatTest";
/**
* 校验签名
* @param signature
* @param timestamp
* @param nonce
* @return
*/
public static boolean checkSignature(String signature,String timestamp,String nonce) {
String checktext = null;
if (null != signature) {
//对ToKen,timestamp,nonce 按字典排序
String[] paramArr = new String[]{token,timestamp,nonce};
Arrays.sort(paramArr);
//将排序后的结果拼成一个字符串
String content = paramArr[0].concat(paramArr[1]).concat(paramArr[2]);
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
//对接后的字符串进行sha1加密
byte[] digest = md.digest(content.toString().getBytes());
checktext = byteToStr(digest);
} catch (NoSuchAlgorithmException e){
e.printStackTrace();
}
}
//将加密后的字符串与signature进行对比
return checktext !=null ? checktext.equals(signature.toUpperCase()) : false;
}
/**
* 将字节数组转化成16进制字符串
* @param byteArrays
* @return
*/
private static String byteToStr(byte[] byteArrays){
String str = "";
for (int i = 0; i < byteArrays.length; i++) {
str += byteToHexStr(byteArrays[i]);
}
return str;
}
/**
* 将字节转化为十六进制字符串
* @param myByte
* @return
*/
private static String byteToHexStr(byte myByte) {
char[] Digit = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
char[] tampArr = new char[2];
tampArr[0] = Digit[(myByte >>> 4) & 0X0F];
tampArr[1] = Digit[myByte & 0X0F];
String str = new String(tampArr);
return str;
}
}

1
user-service/src/main/resources/static/MP_verify_KpSSuYz7qGU2WuoM.txt

@ -0,0 +1 @@
KpSSuYz7qGU2WuoM

5
user-service/src/test/java/com/mh/user/DealDataTest.java

@ -56,10 +56,11 @@ public class DealDataTest extends UserServiceApplicationTests {
EnergyModel energyModel = new EnergyModel();
energyModel.setPage(1);
energyModel.setLimit(10);
energyModel.setStartDate("2024-07");
energyModel.setStartDate("2023");
energyModel.setEndDate("2024");
energyModel.setProjectId("3");
energyModel.setQueryType(0);
energyModel.setType(3);
energyModel.setType(5);
PageResult pageResult = energyDataService.queryMomEnergyData(energyModel);
System.out.println(pageResult);

41
user-service/src/test/java/com/mh/user/WechatTest.java

@ -0,0 +1,41 @@
package com.mh.user;
import com.alibaba.fastjson2.JSONObject;
import com.google.gson.JsonObject;
import com.mh.user.service.wechat.WechatUserInfoService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @author LJF
* @version 1.0
* @project mh_esi
* @description 微信测试
* @date 2024-11-28 14:03:01
*/
@Slf4j
public class WechatTest extends UserServiceApplicationTests{
@Autowired
private WechatUserInfoService wechatUserInfoService;
@Test
public void testInertWechatUserInfo()
{
String test = "{" +
" \"openid\": \"o0qeN5lw4JquQy_H9Rk5QN-CyMRU\"," +
" \"nickname\": \"道法自然\"," +
" \"sex\": 0," +
" \"language\": \"\"," +
" \"city\": \"\"," +
" \"province\": \"\"," +
" \"country\": \"\"," +
" \"headimgurl\": \"https://thirdwx.qlogo.cn/mmopen/vi_32/PiajxSqBRaEI5eF3IWJv4l884KWkjngFSE5VQdlHzZ5YqYAHE7eticnZVyBhPDuObiawraByzMHDY5e8YiboprN9kljwIUYdehiaxkjsKGgpFicM2rtZQk9Q7dBw/132\"," +
" \"privilege\": []" +
"}";
JSONObject jsonObject = JSONObject.parseObject(test);
wechatUserInfoService.existsUser(jsonObject);
}
}

60
user-service/src/test/java/com/mh/user/device/CRC16Test.java

@ -5,6 +5,7 @@ import com.mh.user.utils.ExchangeStringUtil;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
/**
* @Classname CRC16Test
@ -83,22 +84,49 @@ public class CRC16Test {
// String checkWord = ExchangeStringUtil.getStrCRC16(str); //CRC16校验
// str = str + checkWord;
// System.out.println(str);
String receiveData = "04030202CDB4B1";
String dataLength = receiveData.substring(4, 6);
int dataLengthInt = Integer.parseInt(dataLength, 16);
// 截取数据域
String data = receiveData;
data = receiveData.substring(6, 6 + dataLengthInt * 2);
System.out.println(data);
String sValue = ExchangeStringUtil.hexToDec(data);
System.out.println(ExchangeStringUtil.hexToDec(data));
System.out.println(ExchangeStringUtil.rightAddZeroForNum("1", 2+1));
BigDecimal test1 = new BigDecimal(ExchangeStringUtil.rightAddZeroForNum("1", 2+1));
System.out.println(test1);
sValue = (new BigDecimal(sValue)).divide(test1, 2, RoundingMode.HALF_UP).toString();
System.out.println(sValue);
String test = String.valueOf(Math.abs(ExchangeStringUtil.hexToSingle(data)));
System.out.println(test);
// String receiveData = "04030202CDB4B1";
// String dataLength = receiveData.substring(4, 6);
// int dataLengthInt = Integer.parseInt(dataLength, 16);
// // 截取数据域
// String data = receiveData;
// data = receiveData.substring(6, 6 + dataLengthInt * 2);
// System.out.println(data);
// String sValue = ExchangeStringUtil.hexToDec(data);
// System.out.println(ExchangeStringUtil.hexToDec(data));
// System.out.println(ExchangeStringUtil.rightAddZeroForNum("1", 2+1));
// BigDecimal test1 = new BigDecimal(ExchangeStringUtil.rightAddZeroForNum("1", 2+1));
// System.out.println(test1);
// sValue = (new BigDecimal(sValue)).divide(test1, 2, RoundingMode.HALF_UP).toString();
// System.out.println(sValue);
// String test = String.valueOf(Math.abs(ExchangeStringUtil.hexToSingle(data)));
// System.out.println(test);
// 假设传入的时间格式为 "2023"
String yearStr = "2023";
// 1. 获取当前年份
int year = Integer.parseInt(yearStr);
// 2. 计算今年的开始月份
int startMonth = 1;
// 3. 获取当前月份
LocalDate now = LocalDate.now();
int currentMonth = now.getMonthValue();
// 4. 计算环比月份
int yearForComparison = year;
int monthForComparison = currentMonth - 1;
if (monthForComparison == 0) {
monthForComparison = 12;
yearForComparison = year - 1;
}
// 输出结果
System.out.println("当前年份: " + year);
System.out.println("今年的开始月份: " + startMonth);
System.out.println("当前月份: " + currentMonth);
System.out.println("环比月份: " + yearForComparison + "-" + monthForComparison);
}

30
微信用户信息表.sql

@ -0,0 +1,30 @@
create table wechat_user_info
(
id int identity(1,1) not null,
user_name varchar(100) collate chinese_prc_ci_as null,
tel_num varchar(50) collate chinese_prc_ci_as null,
open_id varchar(100) collate chinese_prc_ci_as not null,
nick_name varchar(100) collate chinese_prc_ci_as null,
sex int null,
province varchar(50) collate chinese_prc_ci_as null,
city varchar(50) collate chinese_prc_ci_as null,
country varchar(50) collate chinese_prc_ci_as null,
headimgurl varchar(500) collate chinese_prc_ci_as null,
is_status int not null,
create_time datetime default getdate() not null,
update_time datetime not null
);
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'微信用户信息表', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'wechat_user_info';
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'编号', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'wechat_user_info', @level2type=N'Column', @level2name=N'id';
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'用户名', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'wechat_user_info', @level2type=N'Column', @level2name=N'user_name';
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'手机号码', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'wechat_user_info', @level2type=N'Column', @level2name=N'tel_num';
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'openid', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'wechat_user_info', @level2type=N'Column', @level2name=N'open_id';
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'昵称', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'wechat_user_info', @level2type=N'Column', @level2name=N'nick_name';
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'性别', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'wechat_user_info', @level2type=N'Column', @level2name=N'sex';
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'省份', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'wechat_user_info', @level2type=N'Column', @level2name=N'province';
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'城市', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'wechat_user_info', @level2type=N'Column', @level2name=N'city';
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'国家', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'wechat_user_info', @level2type=N'Column', @level2name=N'country';
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'头像', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'wechat_user_info', @level2type=N'Column', @level2name=N'headimgurl';
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'状态标识', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'wechat_user_info', @level2type=N'Column', @level2name=N'is_status';
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'创建时间', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'wechat_user_info', @level2type=N'Column', @level2name=N'create_time';
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'更新时间', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'wechat_user_info', @level2type=N'Column', @level2name=N'update_time';
Loading…
Cancel
Save