187 lines
6.4 KiB
Go
187 lines
6.4 KiB
Go
package wechat
|
||
|
||
import (
|
||
"context"
|
||
XmlUtils "encoding/xml"
|
||
"net/http"
|
||
|
||
"code.gitea.io/gitea/modules/log"
|
||
"code.gitea.io/gitea/modules/setting"
|
||
"github.com/ArtisanCloud/PowerLibs/v3/http/helper"
|
||
|
||
"fmt"
|
||
|
||
"github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/contract"
|
||
"github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/messages"
|
||
models2 "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/models"
|
||
"github.com/ArtisanCloud/PowerWeChat/v3/src/officialAccount/server/handlers/models"
|
||
)
|
||
|
||
// CallbackVerifyMessage
|
||
/**
|
||
* 微信服务器验证消息
|
||
* GET /api/wechat/callback/message
|
||
* https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
|
||
*/
|
||
func CallbackVerifyMessage(responseWriter http.ResponseWriter, request *http.Request) {
|
||
resp, err := setting.Wechat.SDK.Server.VerifyURL(request)
|
||
if err != nil {
|
||
log.Error("[X] Failed to verify message in Wechat Official Account callback")
|
||
responseWriter.WriteHeader(resp.StatusCode)
|
||
responseWriter.Write([]byte("Failed to verify message in Wechat Official Account callback (CallbackVerifyMessage): " + err.Error()))
|
||
return
|
||
}
|
||
|
||
// 给微信服务器回信
|
||
err = helper.HttpResponseSend(resp, responseWriter)
|
||
if err != nil {
|
||
log.Error("[X] Failed to reply back to Wechat Server (CallbackVerifyMessage): ", err.Error())
|
||
responseWriter.WriteHeader(500)
|
||
}
|
||
}
|
||
|
||
// CallbackNotifyEvents
|
||
/**
|
||
* 微信服务器通知事件
|
||
* POST /api/wechat/callback/message
|
||
* https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
|
||
*/
|
||
func CallbackNotifyEvents(responseWriter http.ResponseWriter, request *http.Request) {
|
||
|
||
resp, err := setting.Wechat.SDK.Server.Notify(request, func(event contract.EventInterface) interface{} {
|
||
|
||
switch event.GetMsgType() {
|
||
|
||
case models2.CALLBACK_MSG_TYPE_EVENT:
|
||
// "event" 类型消息处理
|
||
return callbackMsgEventHandler(request, event)
|
||
|
||
case models2.CALLBACK_MSG_TYPE_TEXT:
|
||
// "text" 类型消息处理
|
||
return callbackMsgTextHandler(event)
|
||
}
|
||
|
||
return messages.NewText("undefined event type: " + event.GetMsgType())
|
||
})
|
||
|
||
if err != nil {
|
||
log.Error("[X] Failed to get notified in Wechat Official Account callback (CallbackNotifyEvents): ", err.Error())
|
||
responseWriter.WriteHeader(resp.StatusCode)
|
||
responseWriter.Write([]byte("Failed to verify message in Wechat Official Account callback" + err.Error()))
|
||
}
|
||
|
||
// 给微信服务器回信
|
||
err = helper.HttpResponseSend(resp, responseWriter)
|
||
if err != nil {
|
||
log.Error("[X] Failed to reply back to Wechat Server (CallbackNotifyEvents): ", err.Error())
|
||
responseWriter.WriteHeader(500)
|
||
}
|
||
}
|
||
|
||
func callbackMsgEventHandler(request *http.Request, event contract.EventInterface) *messages.Text {
|
||
ctx := request.Context()
|
||
|
||
// 根据不同 event 分别处理
|
||
switch event.GetEvent() {
|
||
|
||
case models.CALLBACK_EVENT_SUBSCRIBE:
|
||
// event:subscribe 新用户关注公众号事件
|
||
return eventSubscribeHandler(event)
|
||
|
||
case models.CALLBACK_EVENT_SCAN:
|
||
// event:SCAN 老用户扫描二维码事件
|
||
return eventScanHandler(ctx, event)
|
||
|
||
case models.CALLBACK_EVENT_UNSUBSCRIBE:
|
||
// event:unsubscribe 掉粉事件处理
|
||
return eventUnsubscribeHandler(event)
|
||
}
|
||
return messages.NewText("undefined event type: " + event.GetChangeType())
|
||
}
|
||
|
||
// "text" 类型消息处理
|
||
func callbackMsgTextHandler(event contract.EventInterface) *messages.Text {
|
||
msg := models.MessageText{}
|
||
err := event.ReadMessage(&msg)
|
||
if err != nil {
|
||
log.Error("[X] Failed to handle callback Message TEXT: " + err.Error())
|
||
return messages.NewText("error: " + err.Error())
|
||
}
|
||
// fmt.Dump(msg)
|
||
log.Info("[+] Got message from " + msg.FromUserName + ": " + msg.Content)
|
||
return messages.NewText("您发送的消息已收到,感谢您使用梦宁软件DevStar Studio \n\n" + " -- DevStar Studio" + "\n\n")
|
||
}
|
||
|
||
// event:subscribe 新用户关注公众号事件
|
||
func eventSubscribeHandler(event contract.EventInterface) *messages.Text {
|
||
msg := models.EventSubscribe{}
|
||
err := event.ReadMessage(&msg)
|
||
if err != nil {
|
||
log.Error("[X] Failed to handle callback Message event:subscribe: " + err.Error())
|
||
return messages.NewText("error: " + err.Error())
|
||
}
|
||
// log.Info("[+] event:subscribe User Subscribed: " + msg.FromUserName + ", at Timestamp " + msg.CreateTime)
|
||
return messages.NewText("欢迎新用户! 请关注公众号后重新扫码!\n\n" + " -- DevStar Studio" + "\n\n")
|
||
}
|
||
|
||
// event:SCAN 类型消息,已关注公众号的老用户扫码
|
||
func eventScanHandler(ctx context.Context, event contract.EventInterface) *messages.Text {
|
||
|
||
msg := models.EventScanCodePush{}
|
||
err := event.ReadMessage(&msg)
|
||
if err != nil {
|
||
log.Error("[X] Failed to handle callback event SCAN: " + err.Error())
|
||
return messages.NewText("error: " + err.Error())
|
||
}
|
||
|
||
var qrScanResponseDigest struct {
|
||
FromUserName string `xml:"FromUserName"`
|
||
Ticket string `xml:"Ticket"`
|
||
SceneStr string `xml:"EventKey"`
|
||
}
|
||
err = XmlUtils.Unmarshal([]byte(event.GetContent()), &qrScanResponseDigest)
|
||
if err != nil {
|
||
log.Error("[X] Failed to handle callback event SCAN: " + err.Error())
|
||
return messages.NewText("error: " + err.Error())
|
||
}
|
||
|
||
// 准备扫码状态VO对象
|
||
qrStatus := WechatTempQRStatus{
|
||
SceneStr: qrScanResponseDigest.SceneStr,
|
||
IsScanned: true,
|
||
OpenId: qrScanResponseDigest.FromUserName,
|
||
}
|
||
|
||
log.Info("扫码成功:\n" +
|
||
fmt.Sprintf(" Ticket: %s\n", qrScanResponseDigest.Ticket) +
|
||
fmt.Sprintf(" SceneStr: %s\n", qrStatus.SceneStr))
|
||
|
||
qrStatus.IsBinded = false
|
||
qrStatus.OpenId = qrScanResponseDigest.FromUserName
|
||
qrVOJsonString, err := qrStatus.Marshal2JSONString()
|
||
if err == nil {
|
||
SetWechatQrTicketWithTTL(
|
||
qrScanResponseDigest.Ticket,
|
||
qrVOJsonString,
|
||
setting.Wechat.TempQrExpireSeconds)
|
||
}
|
||
|
||
loginSuccessInfo := "您正在微信扫码登录" + fmt.Sprintf(" %s ", msg.EventKey) +
|
||
"\n\n" + " -- DevStar Studio" + "\n\n" +
|
||
"如非本人操作,请尽快重新绑定微信!"
|
||
|
||
return messages.NewText(loginSuccessInfo)
|
||
}
|
||
|
||
// event:unsubscribe 掉粉事件处理
|
||
func eventUnsubscribeHandler(event contract.EventInterface) *messages.Text {
|
||
msg := models.EventUnSubscribe{}
|
||
err := event.ReadMessage(&msg)
|
||
if err != nil {
|
||
log.Error("[X] Failed to handle callback Message event:unsubscribe: " + err.Error())
|
||
return messages.NewText("error: " + err.Error())
|
||
}
|
||
// log.Info("[+] event:unsubscribe User Unsubscribed: " + msg.ToUserName + ", at Timestamp " + msg.CreateTime)
|
||
return messages.NewText("user unsubscribed: " + msg.FromUserName)
|
||
}
|