增加微信通知功能
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"server/models"
|
||||
"server/pkg/jwtutil"
|
||||
"server/services/wechatmp"
|
||||
|
||||
beego "github.com/beego/beego/v2/server/web"
|
||||
)
|
||||
|
||||
// =============================================================
|
||||
// 租户端「微信公众号绑定」:
|
||||
// 扫码关注公众号 → 公众号被动回复验证码 → 本端输入验证码完成绑定
|
||||
// 绑定后(公众号认证后)可接收平台/租户侧的提醒、公告推送
|
||||
// =============================================================
|
||||
|
||||
// BackendWechatMpController 租户端微信公众号绑定
|
||||
type BackendWechatMpController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
func (c *BackendWechatMpController) claims() (*jwtutil.Claims, error) {
|
||||
auth := c.Ctx.Request.Header.Get("Authorization")
|
||||
if auth == "" {
|
||||
return nil, fmt.Errorf("未登录")
|
||||
}
|
||||
parts := strings.SplitN(auth, " ", 2)
|
||||
if len(parts) != 2 || parts[0] != "Bearer" {
|
||||
return nil, fmt.Errorf("认证信息格式错误")
|
||||
}
|
||||
claims, err := jwtutil.ParseToken(parts[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("无效的token")
|
||||
}
|
||||
if claims.UserType != "backend" && claims.UserType != "app" {
|
||||
return nil, fmt.Errorf("无权访问")
|
||||
}
|
||||
return claims, nil
|
||||
}
|
||||
|
||||
func (c *BackendWechatMpController) jsonErr(httpStatus, bizCode int, msg string) {
|
||||
c.Ctx.Output.SetStatus(httpStatus)
|
||||
c.Data["json"] = map[string]interface{}{"code": bizCode, "msg": msg}
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *BackendWechatMpController) ok(data interface{}, msg string) {
|
||||
if msg == "" {
|
||||
msg = "success"
|
||||
}
|
||||
resp := map[string]interface{}{"code": 200, "msg": msg}
|
||||
if data != nil {
|
||||
resp["data"] = data
|
||||
}
|
||||
c.Data["json"] = resp
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *BackendWechatMpController) readBody(out interface{}) bool {
|
||||
raw, err := io.ReadAll(c.Ctx.Request.Body)
|
||||
if err != nil {
|
||||
c.jsonErr(400, 400, "参数错误")
|
||||
return false
|
||||
}
|
||||
if err := json.Unmarshal(raw, out); err != nil {
|
||||
c.jsonErr(400, 400, "参数错误")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// BindStart POST /backend/wechatMp/bind/start
|
||||
func (c *BackendWechatMpController) BindStart() {
|
||||
claims, err := c.claims()
|
||||
if err != nil {
|
||||
c.jsonErr(401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
uid := uint64(claims.UserID)
|
||||
tid := uint64(claims.TenantId)
|
||||
if uid == 0 || tid == 0 {
|
||||
c.jsonErr(401, 401, "未获取到用户信息")
|
||||
return
|
||||
}
|
||||
scene, _, qrURL, expireAt, err := wechatmp.CreateVerifyCode(models.WechatBindTypeTenantUser, uid, tid, 0)
|
||||
if err != nil {
|
||||
c.jsonErr(400, 400, "生成二维码失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
c.ok(map[string]interface{}{
|
||||
"scene": scene,
|
||||
"qrcode_url": qrURL,
|
||||
"expire_at": expireAt,
|
||||
"expires_in": int(time.Until(expireAt).Seconds()),
|
||||
}, "生成成功")
|
||||
}
|
||||
|
||||
// BindStatus GET /backend/wechatMp/bind/status?scene=xxx
|
||||
func (c *BackendWechatMpController) BindStatus() {
|
||||
claims, err := c.claims()
|
||||
if err != nil {
|
||||
c.jsonErr(401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
scene := strings.TrimSpace(c.GetString("scene"))
|
||||
row, err := wechatmp.GetVerifyCode(scene)
|
||||
if err != nil {
|
||||
c.jsonErr(404, 404, err.Error())
|
||||
return
|
||||
}
|
||||
if row.BindType != models.WechatBindTypeTenantUser || row.BindID != uint64(claims.UserID) {
|
||||
c.jsonErr(403, 403, "该二维码不是当前账号发起,请重新获取")
|
||||
return
|
||||
}
|
||||
c.ok(map[string]interface{}{
|
||||
"status": row.Status,
|
||||
"expire_at": row.ExpireAt,
|
||||
}, "获取成功")
|
||||
}
|
||||
|
||||
// BindConfirm POST /backend/wechatMp/bind/confirm {scene, code}
|
||||
func (c *BackendWechatMpController) BindConfirm() {
|
||||
claims, err := c.claims()
|
||||
if err != nil {
|
||||
c.jsonErr(401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
var p struct {
|
||||
Scene string `json:"scene"`
|
||||
Code string `json:"code"`
|
||||
}
|
||||
if !c.readBody(&p) {
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(p.Code) == "" {
|
||||
c.jsonErr(400, 400, "请输入公众号返回的验证码")
|
||||
return
|
||||
}
|
||||
follower, err := wechatmp.ConfirmVerifyCode(
|
||||
models.WechatBindTypeTenantUser,
|
||||
uint64(claims.UserID),
|
||||
uint64(claims.TenantId),
|
||||
p.Scene,
|
||||
p.Code,
|
||||
)
|
||||
if err != nil {
|
||||
c.jsonErr(400, 400, err.Error())
|
||||
return
|
||||
}
|
||||
c.ok(map[string]interface{}{
|
||||
"openid": follower.OpenID,
|
||||
"nickname": follower.Nickname,
|
||||
"bind_time": follower.BindTime,
|
||||
}, "绑定成功")
|
||||
}
|
||||
|
||||
// MyBinding GET /backend/wechatMp/my
|
||||
func (c *BackendWechatMpController) MyBinding() {
|
||||
claims, err := c.claims()
|
||||
if err != nil {
|
||||
c.jsonErr(401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
follower, err := wechatmp.GetFollowerByUser(models.WechatBindTypeTenantUser, uint64(claims.UserID))
|
||||
if err != nil {
|
||||
c.jsonErr(500, 500, "查询失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
if follower == nil || follower.BindTid != uint64(claims.TenantId) {
|
||||
c.ok(map[string]interface{}{"bound": false}, "获取成功")
|
||||
return
|
||||
}
|
||||
c.ok(map[string]interface{}{
|
||||
"bound": true,
|
||||
"openid": follower.OpenID,
|
||||
"nickname": follower.Nickname,
|
||||
"avatar": follower.Avatar,
|
||||
"subscribe": follower.Subscribe,
|
||||
"bind_time": follower.BindTime,
|
||||
"subscribe_time": follower.SubscribeTime,
|
||||
}, "获取成功")
|
||||
}
|
||||
|
||||
// Unbind POST /backend/wechatMp/unbind
|
||||
func (c *BackendWechatMpController) Unbind() {
|
||||
claims, err := c.claims()
|
||||
if err != nil {
|
||||
c.jsonErr(401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
if err := wechatmp.UnbindByUser(models.WechatBindTypeTenantUser, uint64(claims.UserID)); err != nil {
|
||||
c.jsonErr(500, 500, "解绑失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
c.ok(nil, "已解绑")
|
||||
}
|
||||
Reference in New Issue
Block a user