feat(server-go): 微信订阅消息骨架(#11,绑定/订阅/巡检触发,配置占位)

This commit is contained in:
weijuesen
2026-08-12 17:28:07 +08:00
parent 79e524b1d4
commit 921b185da2
9 changed files with 517 additions and 4 deletions
+129
View File
@@ -0,0 +1,129 @@
package handler
import (
"encoding/json"
"net/http"
"silk-server-go/internal/middleware"
"silk-server-go/internal/model"
"silk-server-go/internal/service"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// RegisterWechatRoutes 注册微信订阅消息路由(骨架,配置占位)
func RegisterWechatRoutes(rg *gin.RouterGroup, db *gorm.DB, wechat *service.WechatService) {
read := middleware.RequirePermission(db, "notification:read")
write := middleware.RequirePermission(db, "notification:write")
rg.GET("/wechat/binding", read, getWechatBinding(db))
rg.POST("/wechat/bind", write, bindWechat(db, wechat))
rg.POST("/wechat/subscribe", write, updateWechatSubscribe(db))
}
// getWechatBinding 当前用户的微信绑定与授权模板
func getWechatBinding(db *gorm.DB) gin.HandlerFunc {
return func(c *gin.Context) {
uid := currentUserID(c)
if uid == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "未登录"})
return
}
var b model.WechatBinding
if db.Where("user_id = ?", *uid).First(&b).Error != nil {
c.JSON(http.StatusOK, gin.H{"bound": false})
return
}
c.JSON(http.StatusOK, gin.H{
"bound": true,
"openId": b.OpenID,
"authorized": b.AuthorizedTemplates,
})
}
}
// bindWechat 用 wx.login 的 code 换 openid 并绑定当前用户
func bindWechat(db *gorm.DB, wechat *service.WechatService) gin.HandlerFunc {
return func(c *gin.Context) {
uid := currentUserID(c)
if uid == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "未登录"})
return
}
var body struct {
Code string `json:"code"`
}
if err := c.ShouldBindJSON(&body); err != nil || body.Code == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "缺少 code"})
return
}
openid, err := wechat.Code2Session(c.Request.Context(), body.Code)
if err != nil {
c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
return
}
var b model.WechatBinding
if db.Where("user_id = ?", *uid).First(&b).Error != nil {
b = model.WechatBinding{UserID: *uid, OpenID: openid}
if err := db.Create(&b).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "绑定失败"})
return
}
} else {
db.Model(&model.WechatBinding{}).Where("id = ?", b.ID).Update("open_id", openid)
}
c.JSON(http.StatusOK, gin.H{"bound": true, "openId": openid})
}
}
// updateWechatSubscribe 更新用户对某场景的订阅授权(alarm/inspection
func updateWechatSubscribe(db *gorm.DB) gin.HandlerFunc {
return func(c *gin.Context) {
uid := currentUserID(c)
if uid == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "未登录"})
return
}
var body struct {
Template string `json:"template"`
Authorized bool `json:"authorized"`
}
if err := c.ShouldBindJSON(&body); err != nil || body.Template == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "缺少 template"})
return
}
var b model.WechatBinding
if db.Where("user_id = ?", *uid).First(&b).Error != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "请先绑定微信"})
return
}
var templates []string
if len(b.AuthorizedTemplates) > 0 {
_ = json.Unmarshal(b.AuthorizedTemplates, &templates)
}
templates = toggleTemplate(templates, body.Template, body.Authorized)
raw, _ := json.Marshal(templates)
db.Model(&model.WechatBinding{}).Where("id = ?", b.ID).Update("authorized_templates", raw)
c.JSON(http.StatusOK, gin.H{"authorized": templates})
}
}
// toggleTemplate 增删授权模板键
func toggleTemplate(list []string, key string, add bool) []string {
out := make([]string, 0, len(list))
exists := false
for _, k := range list {
if k == key {
exists = true
if add {
out = append(out, k)
}
continue
}
out = append(out, k)
}
if add && !exists {
out = append(out, key)
}
return out
}