|
@@ -6,11 +6,13 @@ import cn.tonyandmoney.tuon.core.error.OpException
|
|
|
import cn.tonyandmoney.tuon.core.error.SessionNoUserException
|
|
|
import cn.tonyandmoney.tuon.core.session.SessionUtils
|
|
|
import cn.tonyandmoney.tuon.core.user.IUser
|
|
|
+import cn.tonyandmoney.tuon.core.utils.DateUtils
|
|
|
import cn.tonyandmoney.tuon.qywx.QywxProperties
|
|
|
import cn.tonyandmoney.tuon.qywx.WxErrorCode
|
|
|
import cn.tonyandmoney.tuon.qywx.aes.WXBizMsgCrypt
|
|
|
import cn.tonyandmoney.tuon.qywx.bean.WxMsg
|
|
|
import cn.tonyandmoney.tuon.qywx.bean.WxUser
|
|
|
+import cn.tonyandmoney.tuon.qywx.service.IDutyService
|
|
|
import cn.tonyandmoney.tuon.qywx.service.IQywxService
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper
|
|
|
import org.slf4j.LoggerFactory
|
|
@@ -18,13 +20,19 @@ import org.slf4j.MarkerFactory
|
|
|
import org.springframework.beans.factory.annotation.Autowired
|
|
|
import org.springframework.beans.factory.annotation.Qualifier
|
|
|
import org.springframework.core.io.buffer.DataBufferUtils
|
|
|
+import org.springframework.http.MediaType.APPLICATION_XML_VALUE
|
|
|
import org.springframework.http.server.reactive.ServerHttpRequest
|
|
|
-import org.springframework.stereotype.Controller
|
|
|
import org.springframework.web.bind.annotation.*
|
|
|
import org.springframework.web.server.ServerWebExchange
|
|
|
import reactor.core.publisher.Mono
|
|
|
|
|
|
-@Controller
|
|
|
+/**
|
|
|
+ * 企业微信相关的接口
|
|
|
+ * 1、根据临时code获取用户身份信息
|
|
|
+ * 2、消息接受接口
|
|
|
+ * 3、消息接受验证接口
|
|
|
+ */
|
|
|
+@RestController
|
|
|
@RequestMapping("/qywx")
|
|
|
class QywxController {
|
|
|
|
|
@@ -39,12 +47,19 @@ class QywxController {
|
|
|
private lateinit var properties: QywxProperties
|
|
|
@Autowired
|
|
|
private lateinit var wxBizMsgCrypt: WXBizMsgCrypt
|
|
|
+ @Autowired
|
|
|
+ private lateinit var dutyService: IDutyService
|
|
|
+
|
|
|
@Autowired
|
|
|
@Qualifier("xmlObjectMapper")
|
|
|
private lateinit var objectMapper: ObjectMapper
|
|
|
|
|
|
+ /**
|
|
|
+ * @param code 凭据
|
|
|
+ * 根据授code获取用户身份信息,先判断session中是否有该用户的身份信息,
|
|
|
+ * 如果有,则直接返回session身份信息,如果code为空,则只判断session中的数据
|
|
|
+ */
|
|
|
@GetMapping("/user")
|
|
|
- @ResponseBody
|
|
|
fun getUserInfo(@RequestParam("code", required = false) code: String?,
|
|
|
@RequestParam("agentId") agentId: String,
|
|
|
exchange: ServerWebExchange): Mono<BaseResp<IUser>> {
|
|
@@ -67,14 +82,14 @@ class QywxController {
|
|
|
Mono.just(BaseResp.error(it))
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/**
|
|
|
* 接收消息,返回的数据类型
|
|
|
+ * 如果收到值班关键词,则查询当天的值班人员,返回
|
|
|
*/
|
|
|
- @PostMapping("/config/message", produces = ["application/xml;charset=UTF-8"])
|
|
|
+ @PostMapping("/config/message", produces = [APPLICATION_XML_VALUE])
|
|
|
fun configUserMessage(@RequestParam("msg_signature") signature: String,
|
|
|
@RequestParam("timestamp") timestamp: String,
|
|
|
@RequestParam("nonce") nonce: String,
|
|
@@ -82,38 +97,77 @@ class QywxController {
|
|
|
|
|
|
return DataBufferUtils.join(request.body)
|
|
|
.flatMap { dataBuffer ->
|
|
|
- Mono.create<String> {
|
|
|
+ Mono.create<WxMsg> {
|
|
|
val bytes = ByteArray(dataBuffer.readableByteCount())
|
|
|
dataBuffer.read(bytes)
|
|
|
+ val content = wxBizMsgCrypt.DecryptMsg(signature, timestamp, nonce, String(bytes))
|
|
|
+ val wxMsg = objectMapper.readValue<WxMsg>(content, WxMsg::class.java)
|
|
|
|
|
|
- val wxMsg = objectMapper.readValue<WxMsg>(bytes, WxMsg::class.java)
|
|
|
- val content = wxBizMsgCrypt.decryptMsg(signature, timestamp, nonce, wxMsg.encrypt)
|
|
|
- logger.info(msgMarker, "content:{}", content)
|
|
|
- val resp = ""
|
|
|
- if ("值班" == content) {
|
|
|
+ logger.info(msgMarker, "wxMsg :{}", wxMsg)
|
|
|
+ it.success(wxMsg)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .flatMap<String> { wxMsg ->
|
|
|
+ if ("值班" == wxMsg.content) {
|
|
|
+ getEncryptDutyMsg(wxMsg)
|
|
|
+ } else {
|
|
|
+ Mono.empty()
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- } else {
|
|
|
+ }
|
|
|
|
|
|
+ /**
|
|
|
+ * 获取今日值班信息,并按照企业微信回复消息格式进行封装,加密
|
|
|
+ */
|
|
|
+ private fun getEncryptDutyMsg(wxMsg: WxMsg): Mono<String> {
|
|
|
+ return dutyService.queryByDate(DateUtils.today())
|
|
|
+ .flatMap { list ->
|
|
|
+ Mono.create<String> {
|
|
|
+ val time = System.currentTimeMillis().toString()
|
|
|
+ val respMsg = WxMsg().apply {
|
|
|
+ fromUserName = wxMsg.toUserName
|
|
|
+ toUserName = wxMsg.fromUserName
|
|
|
+ msgType = "text"
|
|
|
+ content = "今日值班人员:${list.map { duty -> duty.userName }.joinToString(",")}"
|
|
|
+ createTime = time
|
|
|
}
|
|
|
- Mono.just(resp)
|
|
|
+ val respText = objectMapper.writeValueAsString(respMsg)
|
|
|
+ logger.info(msgMarker, "reply msg: {}", respText)
|
|
|
+ val resp = wxBizMsgCrypt.EncryptMsg(respText, time, WXBizMsgCrypt.getRandomStr())
|
|
|
+ it.success(resp)
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 验证URL
|
|
|
+ * 验证URL接口,当在企业微信后台,添加消息接受接口的时候,会调用改接口做验证
|
|
|
*/
|
|
|
- @GetMapping("/config/message",produces = ["application/xml;charset=UTF-8"])
|
|
|
+ @GetMapping("/config/message", produces = [APPLICATION_XML_VALUE])
|
|
|
fun verifySignature(@RequestParam("msg_signature") signature: String,
|
|
|
@RequestParam("timestamp") timestamp: String,
|
|
|
@RequestParam("nonce") nonce: String,
|
|
|
@RequestParam("echostr") echostr: String): Mono<String> {
|
|
|
return Mono.create {
|
|
|
- logger.info(msgMarker,"signature:{},timestamp:{},nonce:{},echostr:{}",signature,timestamp,nonce,echostr)
|
|
|
+ logger.info(msgMarker, "signature:{},timestamp:{},nonce:{},echostr:{}", signature, timestamp, nonce, echostr)
|
|
|
val utils = WXBizMsgCrypt(properties.token, properties.encodingAESKey, properties.corpid)
|
|
|
it.success(utils.VerifyURL(signature, timestamp, nonce, echostr))
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 返回XML数据,一个测试接口
|
|
|
+ */
|
|
|
+ @PostMapping("/xml", produces = [APPLICATION_XML_VALUE])
|
|
|
+ fun producesXml(): Mono<String> {
|
|
|
+ return Mono.create {
|
|
|
+ val wxMsg = WxMsg().apply {
|
|
|
+ toUserName = "TuoNian"
|
|
|
+ agentID = "123"
|
|
|
+ }
|
|
|
+ it.success(objectMapper.writeValueAsString(wxMsg))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
}
|