@@ -0,0 +1,28 @@ | |||
target/ | |||
/hjkjg-web/logs/*.log | |||
face_img/ | |||
ThinkFaceBackup/ | |||
### STS ### | |||
.apt_generated | |||
.classpath | |||
.factorypath | |||
.project | |||
.settings | |||
.springBeans | |||
.DS_Store | |||
### IntelliJ IDEA ### | |||
.idea | |||
*.iws | |||
*.iml | |||
*.ipr | |||
### NetBeans ### | |||
nbproject/private/ | |||
build/ | |||
nbbuild/ | |||
dist/ | |||
nbdist/ | |||
.nb-gradle/ |
@@ -0,0 +1,9 @@ | |||
FROM java:8 | |||
MAINTAINER yangkai | |||
ADD target/wechat-msg-sender-1.0-SNAPSHOT.jar wechat-msg-sender.jar | |||
COPY application.yml / | |||
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime | |||
EXPOSE 8080 | |||
ENTRYPOINT ["java","-jar","wechat-msg-sender.jar","--spring.config.location=/application.yml"] | |||
# docker run -d --restart=always --name wechat-sender -p 49180:8080 wechat-sender //运行镜像 |
@@ -0,0 +1,87 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<groupId>org.example</groupId> | |||
<artifactId>wechat-msg-sender</artifactId> | |||
<version>1.0-SNAPSHOT</version> | |||
<properties> | |||
<maven.compiler.source>8</maven.compiler.source> | |||
<maven.compiler.target>8</maven.compiler.target> | |||
</properties> | |||
<dependencies> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-web</artifactId> | |||
<version>2.0.6.RELEASE</version> | |||
<exclusions> | |||
<exclusion> | |||
<groupId>com.fasterxml.jackson.core</groupId> | |||
<artifactId>jackson-databind</artifactId> | |||
</exclusion> | |||
</exclusions> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.projectlombok</groupId> | |||
<artifactId>lombok</artifactId> | |||
<scope>provided</scope> | |||
<optional>true</optional> | |||
<version>1.16.22</version> | |||
</dependency> | |||
<!-- Testing Dependencies --> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-test</artifactId> | |||
<scope>test</scope> | |||
<version>2.0.6.RELEASE</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>redis.clients</groupId> | |||
<artifactId>jedis</artifactId> | |||
<version>3.3.0</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>weixin-java-mp</artifactId> | |||
<version>4.1.0</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.aliyun</groupId> | |||
<artifactId>dysmsapi20170525</artifactId> | |||
<version>2.0.5</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.alibaba</groupId> | |||
<artifactId>fastjson</artifactId> | |||
<version>1.2.44</version> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-maven-plugin</artifactId> | |||
<version>2.0.6.RELEASE</version> | |||
<executions> | |||
<execution> | |||
<goals> | |||
<goal>repackage</goal> | |||
</goals> | |||
</execution> | |||
</executions> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</project> |
@@ -0,0 +1,11 @@ | |||
package com.lecoo.wechat; | |||
import org.springframework.boot.SpringApplication; | |||
import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
@SpringBootApplication | |||
public class App { | |||
public static void main(String[] args) { | |||
SpringApplication.run(App.class); | |||
} | |||
} |
@@ -0,0 +1,17 @@ | |||
package com.lecoo.wechat.builder; | |||
import me.chanjar.weixin.mp.api.WxMpService; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
/** | |||
* @author Binary Wang(https://github.com/binarywang) | |||
*/ | |||
public abstract class AbstractBuilder { | |||
protected final Logger logger = LoggerFactory.getLogger(getClass()); | |||
public abstract WxMpXmlOutMessage build(String content, | |||
WxMpXmlMessage wxMessage, WxMpService service); | |||
} |
@@ -0,0 +1,22 @@ | |||
package com.lecoo.wechat.builder; | |||
import me.chanjar.weixin.mp.api.WxMpService; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage; | |||
/** | |||
* @author Binary Wang(https://github.com/binarywang) | |||
*/ | |||
public class TextBuilder extends AbstractBuilder { | |||
@Override | |||
public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, | |||
WxMpService service) { | |||
WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content(content) | |||
.fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) | |||
.build(); | |||
return m; | |||
} | |||
} |
@@ -0,0 +1,129 @@ | |||
package com.lecoo.wechat.config; | |||
import com.lecoo.wechat.handler.*; | |||
import lombok.AllArgsConstructor; | |||
import me.chanjar.weixin.common.redis.JedisWxRedisOps; | |||
import me.chanjar.weixin.mp.api.WxMpMessageRouter; | |||
import me.chanjar.weixin.mp.api.WxMpService; | |||
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; | |||
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl; | |||
import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl; | |||
import org.springframework.boot.context.properties.EnableConfigurationProperties; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.Configuration; | |||
import redis.clients.jedis.JedisPool; | |||
import redis.clients.jedis.JedisPoolConfig; | |||
import java.util.List; | |||
import java.util.stream.Collectors; | |||
import static me.chanjar.weixin.common.api.WxConsts.EventType; | |||
import static me.chanjar.weixin.common.api.WxConsts.EventType.SUBSCRIBE; | |||
import static me.chanjar.weixin.common.api.WxConsts.EventType.UNSUBSCRIBE; | |||
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; | |||
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType.EVENT; | |||
import static me.chanjar.weixin.mp.constant.WxMpEventConstants.CustomerService.*; | |||
import static me.chanjar.weixin.mp.constant.WxMpEventConstants.POI_CHECK_NOTIFY; | |||
/** | |||
* wechat mp configuration | |||
* | |||
* @author Binary Wang(https://github.com/binarywang) | |||
*/ | |||
@AllArgsConstructor | |||
@Configuration | |||
@EnableConfigurationProperties(WxMpProperties.class) | |||
public class WxMpConfiguration { | |||
private final LogHandler logHandler; | |||
private final NullHandler nullHandler; | |||
private final KfSessionHandler kfSessionHandler; | |||
private final StoreCheckNotifyHandler storeCheckNotifyHandler; | |||
private final LocationHandler locationHandler; | |||
private final MenuHandler menuHandler; | |||
private final MsgHandler msgHandler; | |||
private final UnsubscribeHandler unsubscribeHandler; | |||
private final SubscribeHandler subscribeHandler; | |||
private final ScanHandler scanHandler; | |||
private final WxMpProperties properties; | |||
@Bean | |||
public WxMpService wxMpService() { | |||
// 代码里 getConfigs()处报错的同学,请注意仔细阅读项目说明,你的IDE需要引入lombok插件!!!! | |||
final List<WxMpProperties.MpConfig> configs = this.properties.getConfigs(); | |||
if (configs == null) { | |||
throw new RuntimeException("大哥,拜托先看下项目首页的说明(readme文件),添加下相关配置,注意别配错了!"); | |||
} | |||
WxMpService service = new WxMpServiceImpl(); | |||
service.setMultiConfigStorages(configs | |||
.stream().map(a -> { | |||
WxMpDefaultConfigImpl configStorage; | |||
if (this.properties.isUseRedis()) { | |||
final WxMpProperties.RedisConfig redisConfig = this.properties.getRedisConfig(); | |||
JedisPoolConfig poolConfig = new JedisPoolConfig(); | |||
JedisPool jedisPool = new JedisPool(poolConfig, redisConfig.getHost(), redisConfig.getPort(), | |||
redisConfig.getTimeout(), redisConfig.getPassword()); | |||
configStorage = new WxMpRedisConfigImpl(new JedisWxRedisOps(jedisPool), a.getAppId()); | |||
} else { | |||
configStorage = new WxMpDefaultConfigImpl(); | |||
} | |||
configStorage.setAppId(a.getAppId()); | |||
configStorage.setSecret(a.getSecret()); | |||
configStorage.setToken(a.getToken()); | |||
configStorage.setAesKey(a.getAesKey()); | |||
return configStorage; | |||
}).collect(Collectors.toMap(WxMpDefaultConfigImpl::getAppId, a -> a, (o, n) -> o))); | |||
return service; | |||
} | |||
@Bean | |||
public WxMpMessageRouter messageRouter(WxMpService wxMpService) { | |||
final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService); | |||
// 记录所有事件的日志 (异步执行) | |||
newRouter.rule().handler(this.logHandler).next(); | |||
// 接收客服会话管理事件 | |||
newRouter.rule().async(false).msgType(EVENT).event(KF_CREATE_SESSION) | |||
.handler(this.kfSessionHandler).end(); | |||
newRouter.rule().async(false).msgType(EVENT).event(KF_CLOSE_SESSION) | |||
.handler(this.kfSessionHandler).end(); | |||
newRouter.rule().async(false).msgType(EVENT).event(KF_SWITCH_SESSION) | |||
.handler(this.kfSessionHandler).end(); | |||
// 门店审核事件 | |||
newRouter.rule().async(false).msgType(EVENT).event(POI_CHECK_NOTIFY).handler(this.storeCheckNotifyHandler).end(); | |||
// 自定义菜单事件 | |||
newRouter.rule().async(false).msgType(EVENT).event(EventType.CLICK).handler(this.menuHandler).end(); | |||
// 点击菜单连接事件 | |||
newRouter.rule().async(false).msgType(EVENT).event(EventType.VIEW).handler(this.nullHandler).end(); | |||
// 关注事件 | |||
newRouter.rule().async(false).msgType(EVENT).event(SUBSCRIBE).handler(this.subscribeHandler).end(); | |||
// 取消关注事件 | |||
newRouter.rule().async(false).msgType(EVENT).event(UNSUBSCRIBE).handler(this.unsubscribeHandler).end(); | |||
// 上报地理位置事件 | |||
newRouter.rule().async(false).msgType(EVENT).event(EventType.LOCATION).handler(this.locationHandler).end(); | |||
// 接收地理位置消息 | |||
newRouter.rule().async(false).msgType(XmlMsgType.LOCATION).handler(this.locationHandler).end(); | |||
// 扫码事件 | |||
newRouter.rule().async(false).msgType(EVENT).event(EventType.SCAN).handler(this.scanHandler).end(); | |||
// 默认 | |||
newRouter.rule().async(false).handler(this.msgHandler).end(); | |||
return newRouter; | |||
} | |||
public WxMpProperties getWxMpProperties(){ | |||
return this.properties; | |||
} | |||
} |
@@ -0,0 +1,102 @@ | |||
package com.lecoo.wechat.config; | |||
import lombok.Data; | |||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||
import java.util.List; | |||
/** | |||
* wechat mp properties | |||
* | |||
* @author Binary Wang(https://github.com/binarywang) | |||
*/ | |||
@Data | |||
@ConfigurationProperties(prefix = "wx.mp") | |||
public class WxMpProperties { | |||
/** | |||
* 是否使用redis存储access token | |||
*/ | |||
private boolean useRedis; | |||
/** | |||
* redis 配置 | |||
*/ | |||
private RedisConfig redisConfig; | |||
@Data | |||
public static class RedisConfig { | |||
/** | |||
* redis服务器 主机地址 | |||
*/ | |||
private String host; | |||
/** | |||
* redis服务器 端口号 | |||
*/ | |||
private Integer port; | |||
/** | |||
* redis服务器 密码 | |||
*/ | |||
private String password; | |||
/** | |||
* redis 服务连接超时时间 | |||
*/ | |||
private Integer timeout; | |||
} | |||
/** | |||
* 多个公众号配置信息 | |||
*/ | |||
private List<MpConfig> configs; | |||
@Data | |||
public static class MpConfig { | |||
/** | |||
* 设置微信公众号的appid | |||
*/ | |||
private String appId; | |||
/** | |||
* 设置微信公众号的app secret | |||
*/ | |||
private String secret; | |||
/** | |||
* 设置微信公众号的token | |||
*/ | |||
private String token; | |||
/** | |||
* 设置微信公众号的EncodingAESKey | |||
*/ | |||
private String aesKey; | |||
private String auditTemplateId; | |||
private String pushMsgTemplateId; | |||
private String regAuditTemplateId; | |||
private String url; | |||
} | |||
@Override | |||
public String toString() { | |||
return ""; | |||
} | |||
public List<MpConfig> getConfigs() { | |||
return configs; | |||
} | |||
public boolean isUseRedis() { | |||
return useRedis; | |||
} | |||
public RedisConfig getRedisConfig() { | |||
return redisConfig; | |||
} | |||
} |
@@ -0,0 +1,50 @@ | |||
package com.lecoo.wechat.controller; | |||
import com.alibaba.fastjson.JSONObject; | |||
import com.lecoo.wechat.entity.WxMsgReqEntity; | |||
import com.lecoo.wechat.utils.SendUtil; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
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.RestController; | |||
import javax.validation.Valid; | |||
@RestController | |||
public class IndexController { | |||
@Autowired | |||
SendUtil sendUtil; | |||
@RequestMapping(value = "/sendMsg", method = RequestMethod.POST) | |||
public JSONObject sendMsg(@Valid WxMsgReqEntity wxMsgReqEntity) { | |||
/*JSONObject json = new JSONObject(true); | |||
json.put("openid", "o5j-ms1AQyQD_wWcdP_bsAW6JZBM"); | |||
json.put("url", "http://www.baidu.com"); | |||
json.put("templateId", "FotvlSs3PYYBAofCtaS1DU6HqDc0y6SrsNOVnl8pJY0"); | |||
json.put("first", "success push msg"); | |||
json.put("second", "yangkai"); | |||
json.put("three", "4"); | |||
json.put("four", "2022-09-08"); | |||
json.put("five", "am");*/ | |||
JSONObject json = wxMsgReqEntity.toJson(); | |||
System.err.println(json); | |||
JSONObject result = new JSONObject(); | |||
result.put("status", 0); | |||
result.put("message", "send success!"); | |||
try { | |||
sendUtil.sendWxTemplateMsg(json); | |||
} catch (WxErrorException e) { | |||
result.put("status", -1); | |||
result.put("message", e.getMessage()); | |||
e.printStackTrace(); | |||
} | |||
return result; | |||
} | |||
} |
@@ -0,0 +1,42 @@ | |||
package com.lecoo.wechat.entity; | |||
import com.alibaba.fastjson.JSONObject; | |||
import lombok.Data; | |||
import javax.validation.constraints.NotBlank; | |||
@Data | |||
public class WxMsgReqEntity { | |||
@NotBlank(message = "openid不能为空") | |||
private String openid; | |||
@NotBlank(message = "url不能为空") | |||
private String url; | |||
@NotBlank(message = "templateId不能为空") | |||
private String templateId; | |||
private String first; | |||
private String second; | |||
private String three; | |||
private String four; | |||
private String five; | |||
private String six; | |||
public JSONObject toJson(){ | |||
JSONObject json = new JSONObject(true); | |||
json.put("openid", openid); | |||
json.put("url", url); | |||
json.put("templateId", templateId); | |||
if (null != first) | |||
json.put("first", first); | |||
if (null != second) | |||
json.put("second", second); | |||
if (null != three) | |||
json.put("three", three); | |||
if (null != four) | |||
json.put("four", four); | |||
if (null != five) | |||
json.put("five", five); | |||
if (null != six) | |||
json.put("six", six); | |||
return json; | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
package com.lecoo.wechat.handler; | |||
import me.chanjar.weixin.mp.api.WxMpMessageHandler; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
/** | |||
* @author Binary Wang(https://github.com/binarywang) | |||
*/ | |||
public abstract class AbstractHandler implements WxMpMessageHandler { | |||
protected Logger logger = LoggerFactory.getLogger(getClass()); | |||
} |
@@ -0,0 +1,52 @@ | |||
package com.lecoo.wechat.handler; | |||
import com.alibaba.fastjson.JSONObject; | |||
import org.springframework.http.HttpStatus; | |||
import org.springframework.validation.BindException; | |||
import org.springframework.validation.FieldError; | |||
import org.springframework.web.bind.MethodArgumentNotValidException; | |||
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; | |||
@ControllerAdvice | |||
public class ControllerExceptionHandler { | |||
@ExceptionHandler(Exception.class) | |||
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) | |||
@ResponseBody | |||
public JSONObject exceptionHandler(Exception exception) { | |||
exception.printStackTrace(); | |||
JSONObject jsonObject = new JSONObject(); | |||
if (exception instanceof MethodArgumentNotValidException) { | |||
JSONObject temp = new JSONObject(); | |||
((MethodArgumentNotValidException) exception).getBindingResult().getAllErrors().forEach((error) -> { | |||
String fieldName = ((FieldError) error).getField(); | |||
String errorMessage = error.getDefaultMessage(); | |||
temp.put(fieldName, errorMessage); | |||
}); | |||
jsonObject.put("status", 500); | |||
jsonObject.put("errors", temp); | |||
return jsonObject; | |||
} else if (exception instanceof BindException) { | |||
JSONObject temp = new JSONObject(); | |||
((BindException) exception).getBindingResult().getAllErrors().forEach((error) -> { | |||
String fieldName = ((FieldError) error).getField(); | |||
String errorMessage = error.getDefaultMessage(); | |||
temp.put(fieldName, errorMessage); | |||
}); | |||
jsonObject.put("status", 500); | |||
jsonObject.put("errors", temp); | |||
return jsonObject; | |||
} else { | |||
} | |||
JSONObject temp = new JSONObject(); | |||
temp.put("message", exception.getMessage()); | |||
jsonObject.put("status", 500); | |||
jsonObject.put("errors", temp); | |||
return jsonObject; | |||
} | |||
} |
@@ -0,0 +1,25 @@ | |||
package com.lecoo.wechat.handler; | |||
import me.chanjar.weixin.common.session.WxSessionManager; | |||
import me.chanjar.weixin.mp.api.WxMpService; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||
import org.springframework.stereotype.Component; | |||
import java.util.Map; | |||
/** | |||
* @author Binary Wang(https://github.com/binarywang) | |||
*/ | |||
@Component | |||
public class KfSessionHandler extends AbstractHandler { | |||
@Override | |||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||
Map<String, Object> context, WxMpService wxMpService, | |||
WxSessionManager sessionManager) { | |||
//TODO 对会话做处理 | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
package com.lecoo.wechat.handler; | |||
import com.lecoo.wechat.builder.TextBuilder; | |||
import me.chanjar.weixin.common.session.WxSessionManager; | |||
import me.chanjar.weixin.mp.api.WxMpService; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||
import org.springframework.stereotype.Component; | |||
import java.util.Map; | |||
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; | |||
/** | |||
* @author Binary Wang(https://github.com/binarywang) | |||
*/ | |||
@Component | |||
public class LocationHandler extends AbstractHandler { | |||
@Override | |||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||
Map<String, Object> context, WxMpService wxMpService, | |||
WxSessionManager sessionManager) { | |||
if (wxMessage.getMsgType().equals(XmlMsgType.LOCATION)) { | |||
//TODO 接收处理用户发送的地理位置消息 | |||
try { | |||
String content = "感谢反馈,您的的地理位置已收到!"; | |||
return new TextBuilder().build(content, wxMessage, null); | |||
} catch (Exception e) { | |||
this.logger.error("位置消息接收处理失败", e); | |||
return null; | |||
} | |||
} | |||
//上报地理位置事件 | |||
this.logger.info("上报地理位置,纬度 : {},经度 : {},精度 : {}", | |||
wxMessage.getLatitude(), wxMessage.getLongitude(), String.valueOf(wxMessage.getPrecision())); | |||
//TODO 可以将用户地理位置信息保存到本地数据库,以便以后使用 | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,25 @@ | |||
package com.lecoo.wechat.handler; | |||
import com.lecoo.wechat.utils.JsonUtils; | |||
import me.chanjar.weixin.common.session.WxSessionManager; | |||
import me.chanjar.weixin.mp.api.WxMpService; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||
import org.springframework.stereotype.Component; | |||
import java.util.Map; | |||
/** | |||
* @author Binary Wang(https://github.com/binarywang) | |||
*/ | |||
@Component | |||
public class LogHandler extends AbstractHandler { | |||
@Override | |||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||
Map<String, Object> context, WxMpService wxMpService, | |||
WxSessionManager sessionManager) { | |||
this.logger.info("\n接收到请求消息,内容:{}", JsonUtils.toJson(wxMessage)); | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,35 @@ | |||
package com.lecoo.wechat.handler; | |||
import me.chanjar.weixin.common.session.WxSessionManager; | |||
import me.chanjar.weixin.mp.api.WxMpService; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||
import org.springframework.stereotype.Component; | |||
import java.util.Map; | |||
import static me.chanjar.weixin.common.api.WxConsts.EventType; | |||
/** | |||
* @author Binary Wang(https://github.com/binarywang) | |||
*/ | |||
@Component | |||
public class MenuHandler extends AbstractHandler { | |||
@Override | |||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||
Map<String, Object> context, WxMpService weixinService, | |||
WxSessionManager sessionManager) { | |||
String msg = String.format("type:%s, event:%s, key:%s", | |||
wxMessage.getMsgType(), wxMessage.getEvent(), | |||
wxMessage.getEventKey()); | |||
if (EventType.VIEW.equals(wxMessage.getEvent())) { | |||
return null; | |||
} | |||
return WxMpXmlOutMessage.TEXT().content(msg) | |||
.fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) | |||
.build(); | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
package com.lecoo.wechat.handler; | |||
import com.lecoo.wechat.builder.TextBuilder; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.session.WxSessionManager; | |||
import me.chanjar.weixin.mp.api.WxMpService; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.springframework.stereotype.Component; | |||
import java.util.Map; | |||
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; | |||
/** | |||
* @author Binary Wang(https://github.com/binarywang) | |||
*/ | |||
@Component | |||
public class MsgHandler extends AbstractHandler { | |||
@Override | |||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||
Map<String, Object> context, WxMpService weixinService, | |||
WxSessionManager sessionManager) { | |||
if (!wxMessage.getMsgType().equals(XmlMsgType.EVENT)) { | |||
//TODO 可以选择将消息保存到本地 | |||
} | |||
//当用户输入关键词如“你好”,“客服”等,并且有客服在线时,把消息转发给在线客服 | |||
try { | |||
if (StringUtils.startsWithAny(wxMessage.getContent(), "你好", "客服") | |||
&& weixinService.getKefuService().kfOnlineList() | |||
.getKfOnlineList().size() > 0) { | |||
return WxMpXmlOutMessage.TRANSFER_CUSTOMER_SERVICE() | |||
.fromUser(wxMessage.getToUser()) | |||
.toUser(wxMessage.getFromUser()).build(); | |||
} | |||
} catch (WxErrorException e) { | |||
e.printStackTrace(); | |||
} | |||
//TODO 组装回复消息 | |||
String content = "收到信息内容:好的,已收到您的回复"; | |||
return new TextBuilder().build(content, wxMessage, weixinService); | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
package com.lecoo.wechat.handler; | |||
import me.chanjar.weixin.common.session.WxSessionManager; | |||
import me.chanjar.weixin.mp.api.WxMpService; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||
import org.springframework.stereotype.Component; | |||
import java.util.Map; | |||
/** | |||
* @author Binary Wang(https://github.com/binarywang) | |||
*/ | |||
@Component | |||
public class NullHandler extends AbstractHandler { | |||
@Override | |||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||
Map<String, Object> context, WxMpService wxMpService, | |||
WxSessionManager sessionManager) { | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
package com.lecoo.wechat.handler; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.session.WxSessionManager; | |||
import me.chanjar.weixin.mp.api.WxMpService; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||
import org.springframework.stereotype.Component; | |||
import java.util.Map; | |||
/** | |||
* @author Binary Wang(https://github.com/binarywang) | |||
*/ | |||
@Component | |||
public class ScanHandler extends AbstractHandler { | |||
@Override | |||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMpXmlMessage, Map<String, Object> map, | |||
WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException { | |||
// 扫码事件处理 | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
package com.lecoo.wechat.handler; | |||
import me.chanjar.weixin.common.session.WxSessionManager; | |||
import me.chanjar.weixin.mp.api.WxMpService; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||
import org.springframework.stereotype.Component; | |||
import java.util.Map; | |||
/** | |||
* 门店审核事件处理 | |||
* | |||
* @author Binary Wang(https://github.com/binarywang) | |||
*/ | |||
@Component | |||
public class StoreCheckNotifyHandler extends AbstractHandler { | |||
@Override | |||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||
Map<String, Object> context, WxMpService wxMpService, | |||
WxSessionManager sessionManager) { | |||
// TODO 处理门店审核事件 | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,71 @@ | |||
package com.lecoo.wechat.handler; | |||
import com.lecoo.wechat.builder.TextBuilder; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.session.WxSessionManager; | |||
import me.chanjar.weixin.mp.api.WxMpService; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||
import me.chanjar.weixin.mp.bean.result.WxMpUser; | |||
import org.springframework.stereotype.Component; | |||
import java.util.Map; | |||
/** | |||
* @author Binary Wang(https://github.com/binarywang) | |||
*/ | |||
@Component | |||
public class SubscribeHandler extends AbstractHandler { | |||
@Override | |||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||
Map<String, Object> context, WxMpService weixinService, | |||
WxSessionManager sessionManager) throws WxErrorException { | |||
this.logger.info("新关注用户 OPENID: " + wxMessage.getFromUser()); | |||
// 获取微信用户基本信息 | |||
try { | |||
WxMpUser userWxInfo = weixinService.getUserService() | |||
.userInfo(wxMessage.getFromUser(), null); | |||
if (userWxInfo != null) { | |||
// TODO 可以添加关注用户到本地数据库 | |||
System.out.println(userWxInfo); | |||
} | |||
} catch (WxErrorException e) { | |||
if (e.getError().getErrorCode() == 48001) { | |||
this.logger.info("该公众号没有获取用户信息权限!"); | |||
} | |||
} | |||
WxMpXmlOutMessage responseResult = null; | |||
try { | |||
responseResult = this.handleSpecial(wxMessage); | |||
} catch (Exception e) { | |||
this.logger.error(e.getMessage(), e); | |||
} | |||
if (responseResult != null) { | |||
return responseResult; | |||
} | |||
try { | |||
return new TextBuilder().build("感谢关注", wxMessage, weixinService); | |||
} catch (Exception e) { | |||
this.logger.error(e.getMessage(), e); | |||
} | |||
return null; | |||
} | |||
/** | |||
* 处理特殊请求,比如如果是扫码进来的,可以做相应处理 | |||
*/ | |||
private WxMpXmlOutMessage handleSpecial(WxMpXmlMessage wxMessage) | |||
throws Exception { | |||
//TODO | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
package com.lecoo.wechat.handler; | |||
import me.chanjar.weixin.common.session.WxSessionManager; | |||
import me.chanjar.weixin.mp.api.WxMpService; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||
import org.springframework.stereotype.Component; | |||
import java.util.Map; | |||
/** | |||
* @author Binary Wang(https://github.com/binarywang) | |||
*/ | |||
@Component | |||
public class UnsubscribeHandler extends AbstractHandler { | |||
@Override | |||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||
Map<String, Object> context, WxMpService wxMpService, | |||
WxSessionManager sessionManager) { | |||
String openId = wxMessage.getFromUser(); | |||
this.logger.info("取消关注用户 OPENID: " + openId); | |||
// TODO 可以更新本地数据库为取消关注状态 | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,17 @@ | |||
package com.lecoo.wechat.utils; | |||
import com.google.gson.Gson; | |||
import com.google.gson.GsonBuilder; | |||
/** | |||
* @author Binary Wang(https://github.com/binarywang) | |||
*/ | |||
public class JsonUtils { | |||
public static String toJson(Object obj) { | |||
Gson gson = new GsonBuilder() | |||
.setPrettyPrinting() | |||
.disableHtmlEscaping() | |||
.create(); | |||
return gson.toJson(obj); | |||
} | |||
} |
@@ -0,0 +1,59 @@ | |||
/** | |||
* @project AppService | |||
* @filename SignUtil.java | |||
* @date 2016年8月31日 | |||
* @author KeShanqiang | |||
*/ | |||
package com.lecoo.wechat.utils; | |||
import com.alibaba.fastjson.JSONObject; | |||
import com.lecoo.wechat.config.WxMpProperties; | |||
import lombok.AllArgsConstructor; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.mp.api.WxMpService; | |||
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData; | |||
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.stereotype.Component; | |||
import java.util.Set; | |||
@AllArgsConstructor | |||
@Component | |||
public class SendUtil { | |||
@Autowired | |||
private final WxMpService wxService; | |||
public String sendWxTemplateMsg(JSONObject jsonObject) throws WxErrorException { | |||
if (jsonObject.size()<4) { | |||
return "不合法的参数。。。。"; | |||
} | |||
Set keySet = jsonObject.keySet(); | |||
Object[] keyAry = keySet.toArray(); | |||
Integer i = 0, j = 1; | |||
String openid = (String) jsonObject.get(keyAry[i++]); | |||
String url = (String) jsonObject.get(keyAry[i++]); | |||
String templateId = (String) jsonObject.get(keyAry[i++]); | |||
WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder() | |||
.toUser(openid) | |||
.templateId(templateId) | |||
.url(url) | |||
.build(); | |||
templateMessage.addData(new WxMpTemplateData("first", (String) jsonObject.get(keyAry[i++]), "#FF00FF")); | |||
while (i<keyAry.length && j<6) { | |||
templateMessage.addData(new WxMpTemplateData("keyword"+(j++), (String) jsonObject.get(keyAry[i++]), "#000")); | |||
} | |||
templateMessage.addData(new WxMpTemplateData("remark", (String) jsonObject.get(keyAry[keyAry.length-1]), "#000")); | |||
String msgId = this.wxService.getTemplateMsgService().sendTemplateMsg(templateMessage); | |||
return msgId; | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
server: | |||
port: 8080 | |||
sys: | |||
baseUrl: http://dev.hjkjg.top | |||
wx: | |||
mp: | |||
useRedis: false | |||
redisConfig: | |||
host: 127.0.0.1 | |||
port: 6379 | |||
configs: | |||
- appId: wxde105494dd27c1ac # 第一个公众号的appid | |||
secret: f81e44ef5a1ed2235ce471f0ee3d1445 # 公众号的appsecret | |||
token: 83u4h # 接口配置里的Token值 | |||
pushMsgTemplateId: BQlE4WmvD6C2YG6aMYUxlSztBYbiSFe_KjQaneTWrHY | |||
auditTemplateId: Y1qGJ7SjY4GFky9V101dV8rYQzDR1uZ8g3e6d16M1Ts | |||
regAuditTemplateId: RYDfkUjIRHnCWSy_O1XfDaFT9uE-jYqDAtrpkp49350 | |||
url: ${sys.baseUrl}/f/wx/oauth2 | |||