feat(小程序): 添加检查小程序状态接口
refactor(测试): 移除测试中的硬编码凭证 fix(模板消息): 将小程序状态改为正式版 docs(swagger): 更新API文档并移除密码必填限制
This commit is contained in:
parent
53cb31f6ce
commit
084b802b05
65
docs/docs.go
65
docs/docs.go
@ -15,6 +15,49 @@ const docTemplate = `{
|
|||||||
"host": "{{.Host}}",
|
"host": "{{.Host}}",
|
||||||
"basePath": "{{.BasePath}}",
|
"basePath": "{{.BasePath}}",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
"/api/admin/app/check_status": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"LoginVerifyToken": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "管理端根据 app_id 调用外部验证服务获取状态(正常/封禁/未知)",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"管理端.小程序"
|
||||||
|
],
|
||||||
|
"summary": "检查小程序状态",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "小程序ID",
|
||||||
|
"name": "app_id",
|
||||||
|
"in": "query",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/app.checkAppStatusResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/code.Failure"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/admin/app/create": {
|
"/api/admin/app/create": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
@ -1657,7 +1700,6 @@ const docTemplate = `{
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"nickname",
|
"nickname",
|
||||||
"password",
|
|
||||||
"username"
|
"username"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -1772,6 +1814,27 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"app.checkAppStatusResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"app_id": {
|
||||||
|
"description": "小程序ID",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"check_status_text": {
|
||||||
|
"description": "状态文字描述",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"description": "外部接口返回的状态码",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"description": "外部接口返回的状态",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"app.createAppRequest": {
|
"app.createAppRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
|||||||
@ -7,6 +7,49 @@
|
|||||||
},
|
},
|
||||||
"basePath": "/",
|
"basePath": "/",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
"/api/admin/app/check_status": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"LoginVerifyToken": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "管理端根据 app_id 调用外部验证服务获取状态(正常/封禁/未知)",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"管理端.小程序"
|
||||||
|
],
|
||||||
|
"summary": "检查小程序状态",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "小程序ID",
|
||||||
|
"name": "app_id",
|
||||||
|
"in": "query",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/app.checkAppStatusResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/code.Failure"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/admin/app/create": {
|
"/api/admin/app/create": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
@ -1649,7 +1692,6 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"nickname",
|
"nickname",
|
||||||
"password",
|
|
||||||
"username"
|
"username"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -1764,6 +1806,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"app.checkAppStatusResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"app_id": {
|
||||||
|
"description": "小程序ID",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"check_status_text": {
|
||||||
|
"description": "状态文字描述",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"description": "外部接口返回的状态码",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"description": "外部接口返回的状态",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"app.createAppRequest": {
|
"app.createAppRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
|||||||
@ -122,7 +122,6 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
required:
|
required:
|
||||||
- nickname
|
- nickname
|
||||||
- password
|
|
||||||
- username
|
- username
|
||||||
type: object
|
type: object
|
||||||
admin.modifyAdminResponse:
|
admin.modifyAdminResponse:
|
||||||
@ -187,6 +186,21 @@ definitions:
|
|||||||
description: 符合查询条件的总记录数
|
description: 符合查询条件的总记录数
|
||||||
type: integer
|
type: integer
|
||||||
type: object
|
type: object
|
||||||
|
app.checkAppStatusResponse:
|
||||||
|
properties:
|
||||||
|
app_id:
|
||||||
|
description: 小程序ID
|
||||||
|
type: string
|
||||||
|
check_status_text:
|
||||||
|
description: 状态文字描述
|
||||||
|
type: string
|
||||||
|
code:
|
||||||
|
description: 外部接口返回的状态码
|
||||||
|
type: integer
|
||||||
|
status:
|
||||||
|
description: 外部接口返回的状态
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
app.createAppRequest:
|
app.createAppRequest:
|
||||||
properties:
|
properties:
|
||||||
app_id:
|
app_id:
|
||||||
@ -889,6 +903,33 @@ paths:
|
|||||||
summary: 编辑小程序
|
summary: 编辑小程序
|
||||||
tags:
|
tags:
|
||||||
- 管理端.小程序
|
- 管理端.小程序
|
||||||
|
/api/admin/app/check_status:
|
||||||
|
get:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: 管理端根据 app_id 调用外部验证服务获取状态(正常/封禁/未知)
|
||||||
|
parameters:
|
||||||
|
- description: 小程序ID
|
||||||
|
in: query
|
||||||
|
name: app_id
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/app.checkAppStatusResponse'
|
||||||
|
"400":
|
||||||
|
description: Bad Request
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/code.Failure'
|
||||||
|
security:
|
||||||
|
- LoginVerifyToken: []
|
||||||
|
summary: 检查小程序状态
|
||||||
|
tags:
|
||||||
|
- 管理端.小程序
|
||||||
/api/admin/app/create:
|
/api/admin/app/create:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
|
|||||||
114
internal/api/app/app_check_status.go
Normal file
114
internal/api/app/app_check_status.go
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"mini-chat/internal/code"
|
||||||
|
"mini-chat/internal/pkg/core"
|
||||||
|
"mini-chat/internal/pkg/httpclient"
|
||||||
|
"mini-chat/internal/pkg/validation"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
// checkAppStatusRequest 请求参数
|
||||||
|
// 功能描述:用于检查指定小程序(app_id)的运行状态
|
||||||
|
// 参数说明:
|
||||||
|
// - AppID(string): 小程序ID,必填,通过query参数传入(form:"app_id")
|
||||||
|
// 返回值:无(该函数返回一个core.HandlerFunc处理器,在HTTP请求完成后通过ctx.Payload返回JSON数据)
|
||||||
|
type checkAppStatusRequest struct {
|
||||||
|
AppID string `form:"app_id" binding:"required"` // 小程序ID
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkAppStatusResponse 响应数据结构
|
||||||
|
// 功能描述:返回外部验证服务的状态码与状态文本,并提供统一的文字描述
|
||||||
|
// 字段说明:
|
||||||
|
// - AppID(string): 小程序ID
|
||||||
|
// - Code(int): 外部接口返回的状态码,1表示正常,0表示封禁,其它表示未知
|
||||||
|
// - Status(string): 外部接口返回的原始状态描述
|
||||||
|
// - CheckStatusText(string): 根据Code映射得到的中文状态文字(正常/封禁/未知)
|
||||||
|
type checkAppStatusResponse struct {
|
||||||
|
AppID string `json:"app_id"` // 小程序ID
|
||||||
|
Code int `json:"code"` // 外部接口返回的状态码
|
||||||
|
CheckStatusText string `json:"check_status_text"` // 状态文字描述
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckAppStatus 检查小程序状态
|
||||||
|
// @Summary 检查小程序状态
|
||||||
|
// @Description 管理端根据 app_id 调用外部验证服务获取状态(正常/封禁/未知)
|
||||||
|
// @Tags 管理端.小程序
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param app_id query string true "小程序ID"
|
||||||
|
// @Success 200 {object} checkAppStatusResponse
|
||||||
|
// @Failure 400 {object} code.Failure
|
||||||
|
// @Router /api/admin/app/check_status [get]
|
||||||
|
// @Security LoginVerifyToken
|
||||||
|
func (h *handler) CheckAppStatus() core.HandlerFunc {
|
||||||
|
return func(ctx core.Context) {
|
||||||
|
// 绑定请求参数
|
||||||
|
req := new(checkAppStatusRequest)
|
||||||
|
if err := ctx.ShouldBindForm(req); err != nil {
|
||||||
|
ctx.AbortWithError(core.Error(
|
||||||
|
http.StatusBadRequest,
|
||||||
|
code.ParamBindError,
|
||||||
|
validation.Error(err)),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用外部验证服务
|
||||||
|
// 外部接口: https://api.wxapi.work/xcx/checkxcx.php?appid=<AppID>
|
||||||
|
// 期望返回: {"code":1, "appid":"xxx", "status":"ok"}
|
||||||
|
type externalCheckResp struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Appid string `json:"appid"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
checkRes := new(externalCheckResp)
|
||||||
|
response, err := httpclient.GetHttpClientWithContext(ctx.RequestContext()).R().
|
||||||
|
SetQueryParams(map[string]string{
|
||||||
|
"appid": req.AppID,
|
||||||
|
}).
|
||||||
|
SetResult(checkRes).
|
||||||
|
Get("https://api.wxapi.work/xcx/checkxcx.php")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// 记录请求错误
|
||||||
|
h.logger.Error("请求APP验证服务失败", zap.Error(err))
|
||||||
|
ctx.AbortWithError(core.Error(
|
||||||
|
http.StatusBadRequest,
|
||||||
|
code.ListAppError,
|
||||||
|
fmt.Sprintf("%s:%s", code.Text(code.ListAppError), err.Error()),
|
||||||
|
))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查响应状态码
|
||||||
|
if response.IsError() {
|
||||||
|
h.logger.Error(fmt.Sprintf("请求APP验证服务异常(%d)", response.StatusCode()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将外部返回的code映射为中文状态
|
||||||
|
statusText := "未知"
|
||||||
|
switch checkRes.Code {
|
||||||
|
case 1:
|
||||||
|
statusText = "正常"
|
||||||
|
case 0:
|
||||||
|
statusText = "封禁"
|
||||||
|
default:
|
||||||
|
statusText = "未知"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组织响应数据并返回
|
||||||
|
res := &checkAppStatusResponse{
|
||||||
|
AppID: req.AppID,
|
||||||
|
Code: checkRes.Code,
|
||||||
|
CheckStatusText: statusText,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Payload(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -158,7 +158,7 @@ func (h *handler) SendSubscribeMessage() core.HandlerFunc {
|
|||||||
sendSubscribeMessageReq.Touser = req.Touser
|
sendSubscribeMessageReq.Touser = req.Touser
|
||||||
sendSubscribeMessageReq.TemplateID = req.TemplateID
|
sendSubscribeMessageReq.TemplateID = req.TemplateID
|
||||||
sendSubscribeMessageReq.Page = "pages/index/detail?url=1"
|
sendSubscribeMessageReq.Page = "pages/index/detail?url=1"
|
||||||
sendSubscribeMessageReq.MiniprogramState = "developer" // 需要改成正式版 目前是体验版 跳转小程序类型:developer 为开发版;trial为体验版;formal为正式版;默认为正式版
|
sendSubscribeMessageReq.MiniprogramState = "formal" // 需要改成正式版 目前是体验版 跳转小程序类型:developer 为开发版;trial为体验版;formal 为正式版;默认为正式版
|
||||||
sendSubscribeMessageReq.Lang = "zh_CN"
|
sendSubscribeMessageReq.Lang = "zh_CN"
|
||||||
sendSubscribeMessageReq.Data.Thing1.Value = "留言提醒"
|
sendSubscribeMessageReq.Data.Thing1.Value = "留言提醒"
|
||||||
sendSubscribeMessageReq.Data.Time2.Value = time.Now().Format("2006-01-02 15:04:05")
|
sendSubscribeMessageReq.Data.Time2.Value = time.Now().Format("2006-01-02 15:04:05")
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
func TestGetAccessToken(t *testing.T) {
|
func TestGetAccessToken(t *testing.T) {
|
||||||
res := new(AccessTokenResponse)
|
res := new(AccessTokenResponse)
|
||||||
err := GetAccessToken("wx26ad074017e1e63f", "026c19ce4f3bb090c56573024c59a8be", res)
|
err := GetAccessToken("", "", res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
func TestSendSubscribeMessage(t *testing.T) {
|
func TestSendSubscribeMessage(t *testing.T) {
|
||||||
res := new(AccessTokenResponse)
|
res := new(AccessTokenResponse)
|
||||||
err := GetAccessToken("wx26ad074017e1e63f", "026c19ce4f3bb090c56573024c59a8be", res)
|
err := GetAccessToken("", "", res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("获取 access_token 错误: %s", err.Error())
|
t.Errorf("获取 access_token 错误: %s", err.Error())
|
||||||
}
|
}
|
||||||
@ -17,9 +17,9 @@ func TestSendSubscribeMessage(t *testing.T) {
|
|||||||
sendSubscribeMessageRequest.Page = "pages/contact/index"
|
sendSubscribeMessageRequest.Page = "pages/contact/index"
|
||||||
sendSubscribeMessageRequest.MiniprogramState = "trial"
|
sendSubscribeMessageRequest.MiniprogramState = "trial"
|
||||||
sendSubscribeMessageRequest.Lang = "zh_CN"
|
sendSubscribeMessageRequest.Lang = "zh_CN"
|
||||||
sendSubscribeMessageRequest.Data.Thing1.Value = "测试(CC)"
|
sendSubscribeMessageRequest.Data.Thing1.Value = "测试"
|
||||||
sendSubscribeMessageRequest.Data.Time2.Value = "2025-10-27"
|
sendSubscribeMessageRequest.Data.Time2.Value = "2020-1-27"
|
||||||
sendSubscribeMessageRequest.Data.Thing4.Value = "测试(CC)"
|
sendSubscribeMessageRequest.Data.Thing3.Value = "测试"
|
||||||
|
|
||||||
sendSubscribeMessageResponse := new(SendSubscribeMessageResponse)
|
sendSubscribeMessageResponse := new(SendSubscribeMessageResponse)
|
||||||
err = SendSubscribeMessage(res.AccessToken, sendSubscribeMessageRequest, sendSubscribeMessageResponse)
|
err = SendSubscribeMessage(res.AccessToken, sendSubscribeMessageRequest, sendSubscribeMessageResponse)
|
||||||
|
|||||||
@ -80,10 +80,11 @@ func NewHTTPMux(logger logger.CustomLogger, db mysql.Repo, cron cron.Server) (co
|
|||||||
// 管理端认证接口路由组
|
// 管理端认证接口路由组
|
||||||
adminAuthApiRouter := mux.Group("/api/admin", core.WrapAuthHandler(interceptorHandler.AdminTokenAuthVerify))
|
adminAuthApiRouter := mux.Group("/api/admin", core.WrapAuthHandler(interceptorHandler.AdminTokenAuthVerify))
|
||||||
{
|
{
|
||||||
adminAuthApiRouter.POST("/app/create", appHandler.CreateApp()) // 关联小程序
|
adminAuthApiRouter.POST("/app/create", appHandler.CreateApp()) // 关联小程序
|
||||||
adminAuthApiRouter.POST("/app/delete", appHandler.DeleteApp()) // 删除小程序
|
adminAuthApiRouter.POST("/app/delete", appHandler.DeleteApp()) // 删除小程序
|
||||||
adminAuthApiRouter.PUT("/app/:id", appHandler.ModifyApp()) // 修改小程序
|
adminAuthApiRouter.PUT("/app/:id", appHandler.ModifyApp()) // 修改小程序
|
||||||
adminAuthApiRouter.GET("/apps", appHandler.PageList()) // 小程序列表
|
adminAuthApiRouter.GET("/apps", appHandler.PageList()) // 小程序列表
|
||||||
|
adminAuthApiRouter.GET("/app/check_status", appHandler.CheckAppStatus()) // 检查小程序状态
|
||||||
|
|
||||||
adminAuthApiRouter.POST("/create", adminHandler.CreateAdmin()) // 新增客服
|
adminAuthApiRouter.POST("/create", adminHandler.CreateAdmin()) // 新增客服
|
||||||
adminAuthApiRouter.POST("/delete", adminHandler.DeleteAdmin()) // 删除客服
|
adminAuthApiRouter.POST("/delete", adminHandler.DeleteAdmin()) // 删除客服
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user