1、收码

This commit is contained in:
2025-07-24 23:34:07 +08:00
parent 398b8af489
commit 854d7bee0c
24 changed files with 2479 additions and 10 deletions

352
app/admin/apis/sms_phone.go Normal file
View File

@ -0,0 +1,352 @@
package apis
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/go-admin-team/go-admin-core/sdk/api"
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
"go-admin/app/admin/models"
"go-admin/app/admin/service"
"go-admin/app/admin/service/dto"
"go-admin/common/actions"
"go-admin/common/statuscode"
)
type SmsPhone struct {
api.Api
}
// GetPage 获取号码管理-号码列表列表
// @Summary 获取号码管理-号码列表列表
// @Description 获取号码管理-号码列表列表
// @Tags 号码管理-号码列表
// @Param service query string false "sms 服务"
// @Param serviceCode query string false "服务code"
// @Param pageSize query int false "页条数"
// @Param pageIndex query int false "页码"
// @Success 200 {object} response.Response{data=response.Page{list=[]models.SmsPhone}} "{"code": 200, "data": [...]}"
// @Router /api/v1/sms-phone [get]
// @Security Bearer
func (e SmsPhone) GetPage(c *gin.Context) {
req := dto.SmsPhoneGetPageReq{}
s := service.SmsPhone{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
p := actions.GetPermissionFromContext(c)
list := make([]models.SmsPhone, 0)
var count int64
err = s.GetPage(&req, p, &list, &count)
if err != nil {
e.Error(500, err, fmt.Sprintf("获取号码管理-号码列表失败,\r\n失败信息 %s", err.Error()))
return
}
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
}
// Get 获取号码管理-号码列表
// @Summary 获取号码管理-号码列表
// @Description 获取号码管理-号码列表
// @Tags 号码管理-号码列表
// @Param id path int false "id"
// @Success 200 {object} response.Response{data=models.SmsPhone} "{"code": 200, "data": [...]}"
// @Router /api/v1/sms-phone/{id} [get]
// @Security Bearer
func (e SmsPhone) Get(c *gin.Context) {
req := dto.SmsPhoneGetReq{}
s := service.SmsPhone{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
var object models.SmsPhone
p := actions.GetPermissionFromContext(c)
err = s.Get(&req, p, &object)
if err != nil {
e.Error(500, err, fmt.Sprintf("获取号码管理-号码列表失败,\r\n失败信息 %s", err.Error()))
return
}
e.OK(object, "查询成功")
}
// Insert 创建号码管理-号码列表
// @Summary 创建号码管理-号码列表
// @Description 创建号码管理-号码列表
// @Tags 号码管理-号码列表
// @Accept application/json
// @Product application/json
// @Param data body dto.SmsPhoneInsertReq true "data"
// @Success 200 {object} response.Response "{"code": 200, "message": "添加成功"}"
// @Router /api/v1/sms-phone [post]
// @Security Bearer
func (e SmsPhone) Insert(c *gin.Context) {
req := dto.SmsPhoneInsertReq{}
s := service.SmsPhone{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
// 设置创建人
req.SetCreateBy(user.GetUserId(c))
err = s.Insert(&req)
if err != nil {
e.Error(500, err, fmt.Sprintf("创建号码管理-号码列表失败,\r\n失败信息 %s", err.Error()))
return
}
e.OK(req.GetId(), "创建成功")
}
// Update 修改号码管理-号码列表
// @Summary 修改号码管理-号码列表
// @Description 修改号码管理-号码列表
// @Tags 号码管理-号码列表
// @Accept application/json
// @Product application/json
// @Param id path int true "id"
// @Param data body dto.SmsPhoneUpdateReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}"
// @Router /api/v1/sms-phone/{id} [put]
// @Security Bearer
func (e SmsPhone) Update(c *gin.Context) {
req := dto.SmsPhoneUpdateReq{}
s := service.SmsPhone{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
req.SetUpdateBy(user.GetUserId(c))
p := actions.GetPermissionFromContext(c)
err = s.Update(&req, p)
if err != nil {
e.Error(500, err, fmt.Sprintf("修改号码管理-号码列表失败,\r\n失败信息 %s", err.Error()))
return
}
e.OK(req.GetId(), "修改成功")
}
// Delete 删除号码管理-号码列表
// @Summary 删除号码管理-号码列表
// @Description 删除号码管理-号码列表
// @Tags 号码管理-号码列表
// @Param data body dto.SmsPhoneDeleteReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}"
// @Router /api/v1/sms-phone [delete]
// @Security Bearer
func (e SmsPhone) Delete(c *gin.Context) {
s := service.SmsPhone{}
req := dto.SmsPhoneDeleteReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
// req.SetUpdateBy(user.GetUserId(c))
p := actions.GetPermissionFromContext(c)
err = s.Remove(&req, p)
if err != nil {
e.Error(500, err, fmt.Sprintf("删除号码管理-号码列表失败,\r\n失败信息 %s", err.Error()))
return
}
e.OK(req.GetId(), "删除成功")
}
// 租赁号码
func (e SmsPhone) GetNumber(c *gin.Context) {
req := dto.GetNumberReq{}
s := service.SmsPhone{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
if err := req.Validate(); err != nil {
e.Logger.Errorf("租赁号码失败,%s", err.Error())
e.Error(500, err, "服务器错误请联系管理员")
return
}
userId := user.GetUserId(c)
balance, code := s.GetNumber(&req, userId)
if code != statuscode.Success {
e.Error(code, nil, statuscode.GetMsg(code, "zh"))
return
}
e.OK(balance, "租赁号码成功")
}
// 获取验证码
func (e SmsPhone) GetCodeByActivationId(c *gin.Context) {
req := dto.GetCodeReq{}
s := service.SmsPhone{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
if len(req.ActivationIds) == 0 {
e.OK([]interface{}{}, "获取验证码成功")
return
}
userId := user.GetUserId(c)
codeData, code := s.GetCodeByActivationId(&req, userId)
if code != statuscode.Success {
e.Error(code, nil, statuscode.GetMsg(code, "zh"))
return
}
e.OK(codeData, "获取验证码成功")
}
// 获取自己的号码的列表
func (e SmsPhone) GetMyPage(c *gin.Context) {
req := dto.SmsPhoneGetPageReq{}
s := service.SmsPhone{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
userId := user.GetUserId(c)
list := make([]models.SmsPhone, 0)
var count int64
code := s.GetMyPage(&req, userId, &list, &count)
if code != statuscode.Success {
e.Error(code, nil, statuscode.GetMsg(code, "zh"))
return
}
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
}
// 唤醒长效号码
func (e SmsPhone) WeakUp(c *gin.Context) {
req := dto.WeakUpReq{}
s := service.SmsPhone{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
if err := req.Validate(); err != nil {
e.Logger.Errorf("唤醒长效号码失败,%s", err.Error())
e.Error(500, err, "服务器错误请联系管理员")
return
}
userId := user.GetUserId(c)
code := s.WeakUp(&req, userId)
if code != statuscode.Success {
e.Error(code, nil, statuscode.GetMsg(code, "zh"))
return
}
e.OK(nil, "唤醒长效号码成功")
}
// cancelWeakUp 取消号码
func (e SmsPhone) DeleteMyNumber(c *gin.Context) {
req := dto.DeleteMyNumberReq{}
s := service.SmsPhone{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
if err := req.Validate(); err != nil {
e.Logger.Errorf("取消号码失败,%s", err.Error())
e.Error(500, err, "服务器错误请联系管理员")
return
}
userId := user.GetUserId(c)
code := s.DeleteMyNumber(&req, userId)
if code != statuscode.Success {
e.Error(code, nil, statuscode.GetMsg(code, "zh"))
return
}
e.OK(nil, "取消号码成功")
}

View File

@ -0,0 +1,219 @@
package apis
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/go-admin-team/go-admin-core/sdk/api"
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
"go-admin/app/admin/models"
"go-admin/app/admin/service"
"go-admin/app/admin/service/dto"
"go-admin/common/actions"
)
type SmsReceiveLog struct {
api.Api
}
// GetPage 获取验证码获取记录列表
// @Summary 获取验证码获取记录列表
// @Description 获取验证码获取记录列表
// @Tags 验证码获取记录
// @Param service query string false "服务"
// @Param serviceCode query string false "服务code"
// @Param status query int64 false "状态 0-等待验证码 1-成功 2-失败"
// @Param pageSize query int false "页条数"
// @Param pageIndex query int false "页码"
// @Success 200 {object} response.Response{data=response.Page{list=[]models.SmsReceiveLog}} "{"code": 200, "data": [...]}"
// @Router /api/v1/sms-receive-log [get]
// @Security Bearer
func (e SmsReceiveLog) GetPage(c *gin.Context) {
req := dto.SmsReceiveLogGetPageReq{}
s := service.SmsReceiveLog{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
p := actions.GetPermissionFromContext(c)
list := make([]models.SmsReceiveLog, 0)
var count int64
err = s.GetPage(&req, p, &list, &count)
if err != nil {
e.Error(500, err, fmt.Sprintf("获取验证码获取记录失败,\r\n失败信息 %s", err.Error()))
return
}
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
}
// Get 获取验证码获取记录
// @Summary 获取验证码获取记录
// @Description 获取验证码获取记录
// @Tags 验证码获取记录
// @Param id path int false "id"
// @Success 200 {object} response.Response{data=models.SmsReceiveLog} "{"code": 200, "data": [...]}"
// @Router /api/v1/sms-receive-log/{id} [get]
// @Security Bearer
func (e SmsReceiveLog) Get(c *gin.Context) {
req := dto.SmsReceiveLogGetReq{}
s := service.SmsReceiveLog{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
var object models.SmsReceiveLog
p := actions.GetPermissionFromContext(c)
err = s.Get(&req, p, &object)
if err != nil {
e.Error(500, err, fmt.Sprintf("获取验证码获取记录失败,\r\n失败信息 %s", err.Error()))
return
}
e.OK(object, "查询成功")
}
// Insert 创建验证码获取记录
// @Summary 创建验证码获取记录
// @Description 创建验证码获取记录
// @Tags 验证码获取记录
// @Accept application/json
// @Product application/json
// @Param data body dto.SmsReceiveLogInsertReq true "data"
// @Success 200 {object} response.Response "{"code": 200, "message": "添加成功"}"
// @Router /api/v1/sms-receive-log [post]
// @Security Bearer
func (e SmsReceiveLog) Insert(c *gin.Context) {
req := dto.SmsReceiveLogInsertReq{}
s := service.SmsReceiveLog{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
// 设置创建人
req.SetCreateBy(user.GetUserId(c))
err = s.Insert(&req)
if err != nil {
e.Error(500, err, fmt.Sprintf("创建验证码获取记录失败,\r\n失败信息 %s", err.Error()))
return
}
e.OK(req.GetId(), "创建成功")
}
// Update 修改验证码获取记录
// @Summary 修改验证码获取记录
// @Description 修改验证码获取记录
// @Tags 验证码获取记录
// @Accept application/json
// @Product application/json
// @Param id path int true "id"
// @Param data body dto.SmsReceiveLogUpdateReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}"
// @Router /api/v1/sms-receive-log/{id} [put]
// @Security Bearer
func (e SmsReceiveLog) Update(c *gin.Context) {
req := dto.SmsReceiveLogUpdateReq{}
s := service.SmsReceiveLog{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
req.SetUpdateBy(user.GetUserId(c))
p := actions.GetPermissionFromContext(c)
err = s.Update(&req, p)
if err != nil {
e.Error(500, err, fmt.Sprintf("修改验证码获取记录失败,\r\n失败信息 %s", err.Error()))
return
}
e.OK(req.GetId(), "修改成功")
}
// Delete 删除验证码获取记录
// @Summary 删除验证码获取记录
// @Description 删除验证码获取记录
// @Tags 验证码获取记录
// @Param data body dto.SmsReceiveLogDeleteReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}"
// @Router /api/v1/sms-receive-log [delete]
// @Security Bearer
func (e SmsReceiveLog) Delete(c *gin.Context) {
s := service.SmsReceiveLog{}
req := dto.SmsReceiveLogDeleteReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
// req.SetUpdateBy(user.GetUserId(c))
p := actions.GetPermissionFromContext(c)
err = s.Remove(&req, p)
if err != nil {
e.Error(500, err, fmt.Sprintf("删除验证码获取记录失败,\r\n失败信息 %s", err.Error()))
return
}
e.OK(req.GetId(), "删除成功")
}
// WebHook 接收短信发送记录回调
func (e SmsReceiveLog) WebHook(c *gin.Context) {
req := dto.SmsReceiveWebHookReq{}
s := service.SmsReceiveLog{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
err = s.WebHook(&req)
if err != nil {
c.JSON(500, gin.H{})
return
}
e.OK(nil, "接收短信发送记录回调成功")
}

View File

@ -0,0 +1,236 @@
package apis
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/go-admin-team/go-admin-core/sdk/api"
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
"go-admin/app/admin/models"
"go-admin/app/admin/service"
"go-admin/app/admin/service/dto"
"go-admin/common/actions"
)
type SmsServices struct {
api.Api
}
// GetPage 获取SmsServices列表
// @Summary 获取SmsServices列表
// @Description 获取SmsServices列表
// @Tags SmsServices
// @Param pageSize query int false "页条数"
// @Param pageIndex query int false "页码"
// @Success 200 {object} response.Response{data=response.Page{list=[]models.SmsServices}} "{"code": 200, "data": [...]}"
// @Router /api/v1/sms-services [get]
// @Security Bearer
func (e SmsServices) GetPage(c *gin.Context) {
req := dto.SmsServicesGetPageReq{}
s := service.SmsServices{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
p := actions.GetPermissionFromContext(c)
list := make([]models.SmsServices, 0)
var count int64
err = s.GetPage(&req, p, &list, &count)
if err != nil {
e.Error(500, err, fmt.Sprintf("获取SmsServices失败\r\n失败信息 %s", err.Error()))
return
}
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
}
// Get 获取SmsServices
// @Summary 获取SmsServices
// @Description 获取SmsServices
// @Tags SmsServices
// @Param id path int false "id"
// @Success 200 {object} response.Response{data=models.SmsServices} "{"code": 200, "data": [...]}"
// @Router /api/v1/sms-services/{id} [get]
// @Security Bearer
func (e SmsServices) Get(c *gin.Context) {
req := dto.SmsServicesGetReq{}
s := service.SmsServices{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
var object models.SmsServices
p := actions.GetPermissionFromContext(c)
err = s.Get(&req, p, &object)
if err != nil {
e.Error(500, err, fmt.Sprintf("获取SmsServices失败\r\n失败信息 %s", err.Error()))
return
}
e.OK(object, "查询成功")
}
// Insert 创建SmsServices
// @Summary 创建SmsServices
// @Description 创建SmsServices
// @Tags SmsServices
// @Accept application/json
// @Product application/json
// @Param data body dto.SmsServicesInsertReq true "data"
// @Success 200 {object} response.Response "{"code": 200, "message": "添加成功"}"
// @Router /api/v1/sms-services [post]
// @Security Bearer
func (e SmsServices) Insert(c *gin.Context) {
req := dto.SmsServicesInsertReq{}
s := service.SmsServices{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
// 设置创建人
req.SetCreateBy(user.GetUserId(c))
err = s.Insert(&req)
if err != nil {
e.Error(500, err, fmt.Sprintf("创建SmsServices失败\r\n失败信息 %s", err.Error()))
return
}
e.OK(req.GetId(), "创建成功")
}
// Update 修改SmsServices
// @Summary 修改SmsServices
// @Description 修改SmsServices
// @Tags SmsServices
// @Accept application/json
// @Product application/json
// @Param id path int true "id"
// @Param data body dto.SmsServicesUpdateReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}"
// @Router /api/v1/sms-services/{id} [put]
// @Security Bearer
func (e SmsServices) Update(c *gin.Context) {
req := dto.SmsServicesUpdateReq{}
s := service.SmsServices{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
req.SetUpdateBy(user.GetUserId(c))
p := actions.GetPermissionFromContext(c)
err = s.Update(&req, p)
if err != nil {
e.Error(500, err, fmt.Sprintf("修改SmsServices失败\r\n失败信息 %s", err.Error()))
return
}
e.OK(req.GetId(), "修改成功")
}
// Delete 删除SmsServices
// @Summary 删除SmsServices
// @Description 删除SmsServices
// @Tags SmsServices
// @Param data body dto.SmsServicesDeleteReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}"
// @Router /api/v1/sms-services [delete]
// @Security Bearer
func (e SmsServices) Delete(c *gin.Context) {
s := service.SmsServices{}
req := dto.SmsServicesDeleteReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
// req.SetUpdateBy(user.GetUserId(c))
p := actions.GetPermissionFromContext(c)
err = s.Remove(&req, p)
if err != nil {
e.Error(500, err, fmt.Sprintf("删除SmsServices失败\r\n失败信息 %s", err.Error()))
return
}
e.OK(req.GetId(), "删除成功")
}
// 获取选项列表
func (e SmsServices) GetList(c *gin.Context) {
s := service.SmsServices{}
err := e.MakeContext(c).
MakeOrm().
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
list := make([]dto.SmsServicesGetListResp, 0)
err = s.GetList(&list)
if err != nil {
e.Logger.Errorf("获取选项列表失败,\r\n失败信息 %s", err.Error())
e.Error(500, nil, "服务器错误请联系管理员")
return
}
e.OK(list, "获取选项列表成功")
}
// 获取价格
func (e SmsServices) GetPrice(c *gin.Context) {
req := dto.SmsGetPriceReq{}
s := service.SmsServices{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
price, err := s.GetPrice(&req)
if err != nil {
e.Logger.Errorf("获取价格失败,\r\n失败信息 %s", err.Error())
e.Error(500, nil, "服务器错误请联系管理员")
return
}
e.OK(price, "获取价格成功")
}

View File

@ -0,0 +1,38 @@
package models
import (
"go-admin/common/models"
"time"
)
type SmsPhone struct {
models.Model
UserId int `json:"userId" gorm:"type:bigint;comment:用户Id"`
Service string `json:"service" gorm:"type:varchar(50);comment:sms 服务"`
ServiceCode string `json:"serviceCode" gorm:"type:varchar(30);comment:服务code"`
Type int `json:"type" gorm:"type:tinyint;comment:类型 0-短效 1-长效"`
Period int `json:"period" gorm:"type:int;comment:时长(月)"`
Phone string `json:"phone" gorm:"type:varchar(30);comment:号码"`
ActivationId int `json:"activationId" gorm:"type:int;comment:激活码id"`
NewActivationId int `json:"newActivationId" gorm:"type:int;comment:新激活码id 每次获取验证码会刷新"`
MessageId int `json:"messageId" gorm:"type:int;comment:短信模板id"`
Code string `json:"code" gorm:"type:varchar(10);comment:验证码"`
Status int `json:"status" gorm:"type:tinyint;comment:状态 1-等待验证码 2-已获取"`
ExpireTime *time.Time `json:"expireTime" gorm:"type:datetime;comment:过期时间"`
models.ModelTime
models.ControlBy
}
func (SmsPhone) TableName() string {
return "sms_phone"
}
func (e *SmsPhone) Generate() models.ActiveRecord {
o := *e
return &o
}
func (e *SmsPhone) GetId() interface{} {
return e.Id
}

View File

@ -0,0 +1,32 @@
package models
import (
"go-admin/common/models"
)
type SmsReceiveLog struct {
models.Model
UserId int `json:"userId" gorm:"type:bigint;comment:用户id"`
Service string `json:"service" gorm:"type:varchar(30);comment:服务"`
ServiceCode string `json:"serviceCode" gorm:"type:varchar(30);comment:服务code"`
MessageId int `json:"messageId" gorm:"type:int;comment:短信id"`
Phone string `json:"phone" gorm:"type:varchar(30);comment:号码"`
Code string `json:"code" gorm:"type:varchar(20);comment:验证码"`
Status int `json:"status" gorm:"type:tinyint;comment:状态 0-等待验证码 1-成功 2-失败"`
models.ModelTime
models.ControlBy
}
func (SmsReceiveLog) TableName() string {
return "sms_receive_log"
}
func (e *SmsReceiveLog) Generate() models.ActiveRecord {
o := *e
return &o
}
func (e *SmsReceiveLog) GetId() interface{} {
return e.Id
}

View File

@ -0,0 +1,29 @@
package models
import (
"go-admin/common/models"
)
type SmsServices struct {
models.Model
Name string `json:"name" gorm:"type:varchar(255);comment:服务名称"`
Code string `json:"code" gorm:"type:varchar(50);comment:编码"`
models.ModelTime
models.ControlBy
}
func (SmsServices) TableName() string {
return "sms_services"
}
func (e *SmsServices) Generate() models.ActiveRecord {
o := *e
return &o
}
func (e *SmsServices) GetId() interface{} {
return e.Id
}

View File

@ -0,0 +1,38 @@
package router
import (
"github.com/gin-gonic/gin"
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
"go-admin/app/admin/apis"
"go-admin/common/actions"
"go-admin/common/middleware"
)
func init() {
routerCheckRole = append(routerCheckRole, registerSmsPhoneRouter)
}
// registerSmsPhoneRouter
func registerSmsPhoneRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
api := apis.SmsPhone{}
r1 := v1.Group("/sms-phone").Use(authMiddleware.MiddlewareFunc())
{
r1.POST("getNumber", api.GetNumber) //租赁号码
r1.GET("getCodeByActivationId", api.GetCodeByActivationId) //获取验证码
r1.GET("list", api.GetMyPage) // 获取自己的号码列表
r1.POST("weakUp", api.WeakUp) // 新增号码
r1.DELETE("my-number", api.DeleteMyNumber) // 删除自己的号码
}
r := v1.Group("/sms-phone").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
{
r.GET("", actions.PermissionAction(), api.GetPage)
r.GET("/:id", actions.PermissionAction(), api.Get)
r.POST("", api.Insert)
r.PUT("/:id", actions.PermissionAction(), api.Update)
r.DELETE("", api.Delete)
}
}

View File

@ -0,0 +1,32 @@
package router
import (
"github.com/gin-gonic/gin"
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
"go-admin/app/admin/apis"
"go-admin/common/actions"
"go-admin/common/middleware"
)
func init() {
routerCheckRole = append(routerCheckRole, registerSmsReceiveLogRouter)
}
// registerSmsReceiveLogRouter
func registerSmsReceiveLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
api := apis.SmsReceiveLog{}
r := v1.Group("/sms-receive-log").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
{
r.GET("", actions.PermissionAction(), api.GetPage)
r.GET("/:id", actions.PermissionAction(), api.Get)
r.POST("", api.Insert)
r.PUT("/:id", actions.PermissionAction(), api.Update)
r.DELETE("", api.Delete)
}
r1 := v1.Group("sms-receive-log")
{
r1.POST("webhook", api.WebHook) //接收短信发送记录回调
}
}

View File

@ -0,0 +1,33 @@
package router
import (
"github.com/gin-gonic/gin"
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
"go-admin/app/admin/apis"
"go-admin/common/actions"
"go-admin/common/middleware"
)
func init() {
routerCheckRole = append(routerCheckRole, registerSmsServicesRouter)
}
// registerSmsServicesRouter
func registerSmsServicesRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
api := apis.SmsServices{}
r := v1.Group("/sms-services").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
{
r.GET("", actions.PermissionAction(), api.GetPage)
r.GET("/:id", actions.PermissionAction(), api.Get)
r.POST("", api.Insert)
r.PUT("/:id", actions.PermissionAction(), api.Update)
r.DELETE("", api.Delete)
}
r1 := v1.Group("/sms-services").Use(authMiddleware.MiddlewareFunc())
{
r1.GET("list", api.GetList) //获取服务列表
r1.GET("price", api.GetPrice) //获取服务价格
}
}

View File

@ -73,7 +73,7 @@ func (e *CliProxyService) UseIp(req *dto.CliProxyIPUseReq, userId int) (decimal.
configService := SysConfig{Service: e.Service}
deductStandard := dto.GetSysConfigByKEYForServiceResp{}
configService.GetWithKey(&dto.SysConfigByKeyReq{ConfigKey: "deduction_standard"}, &deductStandard)
configService.GetWithKey(&dto.SysConfigByKeyReq{ConfigKey: "ip_deduction_standard"}, &deductStandard)
if deductStandard.ConfigValue == "" {
return decimal.Decimal{}, errors.New("server error")
@ -81,6 +81,12 @@ func (e *CliProxyService) UseIp(req *dto.CliProxyIPUseReq, userId int) (decimal.
price, _ := decimal.NewFromString(deductStandard.ConfigValue)
if price.Cmp(decimal.Zero) <= 0 {
e.Log.Errorf("ip提取费用配置错误,%s", deductStandard.ConfigValue)
return decimal.Zero, errors.New("服务器错误,请联系管理员")
}
if balance.LessThan(price) {
return balance, errors.New("余额不足")
}

View File

@ -0,0 +1,165 @@
package dto
import (
"errors"
"go-admin/app/admin/models"
"go-admin/common/dto"
common "go-admin/common/models"
)
type SmsPhoneGetPageReq struct {
dto.Pagination `search:"-"`
Service string `form:"service" search:"type:exact;column:service;table:sms_phone" comment:"sms 服务"`
ServiceCode string `form:"serviceCode" search:"type:exact;column:service_code;table:sms_phone" comment:"服务code"`
Type int `form:"type" search:"-" comment:"类型 0-短效 1-长效"`
SmsPhoneOrder
}
type SmsPhoneOrder struct {
Id string `form:"idOrder" search:"type:order;column:id;table:sms_phone"`
UserId string `form:"userIdOrder" search:"type:order;column:user_id;table:sms_phone"`
Service string `form:"serviceOrder" search:"type:order;column:service;table:sms_phone"`
ServiceCode string `form:"serviceCodeOrder" search:"type:order;column:service_code;table:sms_phone"`
TypeOrder string `form:"typeOrder" search:"type:order;column:type;table:sms_phone"`
Period string `form:"periodOrder" search:"type:order;column:period;table:sms_phone"`
Phone string `form:"phoneOrder" search:"type:order;column:phone;table:sms_phone"`
CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:sms_phone"`
UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:sms_phone"`
DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:sms_phone"`
CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:sms_phone"`
UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:sms_phone"`
}
func (m *SmsPhoneGetPageReq) GetNeedSearch() interface{} {
return *m
}
type SmsPhoneInsertReq struct {
Id int `json:"-" comment:"主键id"` // 主键id
UserId int `json:"userId" comment:"用户Id"`
Service string `json:"service" comment:"sms 服务"`
ServiceCode string `json:"serviceCode" comment:"服务code"`
Type int `json:"type" comment:"类型 0-短效 1-长效"`
Period int `json:"period" comment:"时长(月)"`
Phone string `json:"phone" comment:"号码"`
common.ControlBy
}
func (s *SmsPhoneInsertReq) Generate(model *models.SmsPhone) {
if s.Id == 0 {
model.Model = common.Model{Id: s.Id}
}
model.UserId = s.UserId
model.Service = s.Service
model.ServiceCode = s.ServiceCode
model.Type = s.Type
model.Period = s.Period
model.Phone = s.Phone
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的
}
func (s *SmsPhoneInsertReq) GetId() interface{} {
return s.Id
}
type SmsPhoneUpdateReq struct {
Id int `uri:"id" comment:"主键id"` // 主键id
UserId int `json:"userId" comment:"用户Id"`
Service string `json:"service" comment:"sms 服务"`
ServiceCode string `json:"serviceCode" comment:"服务code"`
Type int `json:"type" comment:"类型 0-短效 1-长效"`
Period int `json:"period" comment:"时长(月)"`
Phone string `json:"phone" comment:"号码"`
common.ControlBy
}
func (s *SmsPhoneUpdateReq) Generate(model *models.SmsPhone) {
if s.Id == 0 {
model.Model = common.Model{Id: s.Id}
}
model.UserId = s.UserId
model.Service = s.Service
model.ServiceCode = s.ServiceCode
model.Type = s.Type
model.Period = s.Period
model.Phone = s.Phone
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的
}
func (s *SmsPhoneUpdateReq) GetId() interface{} {
return s.Id
}
// SmsPhoneGetReq 功能获取请求参数
type SmsPhoneGetReq struct {
Id int `uri:"id"`
}
func (s *SmsPhoneGetReq) GetId() interface{} {
return s.Id
}
// SmsPhoneDeleteReq 功能删除请求参数
type SmsPhoneDeleteReq struct {
Ids []int `json:"ids"`
}
func (s *SmsPhoneDeleteReq) GetId() interface{} {
return s.Ids
}
type GetNumberReq struct {
Type int `json:"type" form:"type" comment:"类型 0-短效 1-长效"`
ServiceCode string `json:"serviceCode" form:"serviceCode" comment:"服务code"`
Period int `json:"period" form:"period" comment:"时长(月)"`
}
func (s *GetNumberReq) Validate() error {
if s.Type > 1 || s.Type < 0 {
return errors.New("租赁类型错误")
}
if s.ServiceCode == "" {
return errors.New("请先选择服务")
}
if s.Type == 1 && s.Period <= 0 {
return errors.New("长租时长不能为空")
}
return nil
}
type GetCodeReq struct {
ActivationIds []int `form:"activationIds"`
}
type GetCodeResp struct {
ActivationId int `json:"activationId" comment:"激活码id"`
Code string `json:"code" comment:"验证码"`
Status int `json:"status" comment:"状态 1-等待验证码 2-已获取"`
}
type WeakUpReq struct {
ActivationId int `json:"activationId" comment:"激活码id"`
}
func (s *WeakUpReq) Validate() error {
if s.ActivationId <= 0 {
return errors.New("激活码id不能为空")
}
return nil
}
type DeleteMyNumberReq struct {
Id int `json:"id" comment:"短信号码id"`
}
func (s *DeleteMyNumberReq) Validate() error {
if s.Id <= 0 {
return errors.New("号码不能为空")
}
return nil
}

View File

@ -0,0 +1,118 @@
package dto
import (
"go-admin/app/admin/models"
"go-admin/common/dto"
common "go-admin/common/models"
)
type SmsReceiveLogGetPageReq struct {
dto.Pagination `search:"-"`
Service string `form:"service" search:"type:exact;column:service;table:sms_receive_log" comment:"服务"`
ServiceCode string `form:"serviceCode" search:"type:exact;column:service_code;table:sms_receive_log" comment:"服务code"`
Status int64 `form:"status" search:"type:exact;column:status;table:sms_receive_log" comment:"状态 0-等待验证码 1-成功 2-失败"`
SmsReceiveLogOrder
}
type SmsReceiveLogOrder struct {
Id string `form:"idOrder" search:"type:order;column:id;table:sms_receive_log"`
UserId string `form:"userIdOrder" search:"type:order;column:user_id;table:sms_receive_log"`
Service string `form:"serviceOrder" search:"type:order;column:service;table:sms_receive_log"`
ServiceCode string `form:"serviceCodeOrder" search:"type:order;column:service_code;table:sms_receive_log"`
Phone string `form:"phoneOrder" search:"type:order;column:phone;table:sms_receive_log"`
Code string `form:"codeOrder" search:"type:order;column:code;table:sms_receive_log"`
Status string `form:"statusOrder" search:"type:order;column:status;table:sms_receive_log"`
CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:sms_receive_log"`
UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:sms_receive_log"`
DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:sms_receive_log"`
CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:sms_receive_log"`
UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:sms_receive_log"`
}
func (m *SmsReceiveLogGetPageReq) GetNeedSearch() interface{} {
return *m
}
type SmsReceiveLogInsertReq struct {
Id int `json:"-" comment:"主键id"` // 主键id
UserId int `json:"userId" comment:"用户id"`
Service string `json:"service" comment:"服务"`
ServiceCode string `json:"serviceCode" comment:"服务code"`
Phone string `json:"phone" comment:"号码"`
Code string `json:"code" comment:"验证码"`
Status int `json:"status" comment:"状态 0-等待验证码 1-成功 2-失败"`
common.ControlBy
}
func (s *SmsReceiveLogInsertReq) Generate(model *models.SmsReceiveLog) {
if s.Id == 0 {
model.Model = common.Model{Id: s.Id}
}
model.UserId = s.UserId
model.Service = s.Service
model.ServiceCode = s.ServiceCode
model.Phone = s.Phone
model.Code = s.Code
model.Status = s.Status
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的
}
func (s *SmsReceiveLogInsertReq) GetId() interface{} {
return s.Id
}
type SmsReceiveLogUpdateReq struct {
Id int `uri:"id" comment:"主键id"` // 主键id
UserId int `json:"userId" comment:"用户id"`
Service string `json:"service" comment:"服务"`
ServiceCode string `json:"serviceCode" comment:"服务code"`
Phone string `json:"phone" comment:"号码"`
Code string `json:"code" comment:"验证码"`
Status int `json:"status" comment:"状态 0-等待验证码 1-成功 2-失败"`
common.ControlBy
}
func (s *SmsReceiveLogUpdateReq) Generate(model *models.SmsReceiveLog) {
if s.Id == 0 {
model.Model = common.Model{Id: s.Id}
}
model.UserId = s.UserId
model.Service = s.Service
model.ServiceCode = s.ServiceCode
model.Phone = s.Phone
model.Code = s.Code
model.Status = s.Status
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的
}
func (s *SmsReceiveLogUpdateReq) GetId() interface{} {
return s.Id
}
// SmsReceiveLogGetReq 功能获取请求参数
type SmsReceiveLogGetReq struct {
Id int `uri:"id"`
}
func (s *SmsReceiveLogGetReq) GetId() interface{} {
return s.Id
}
// SmsReceiveLogDeleteReq 功能删除请求参数
type SmsReceiveLogDeleteReq struct {
Ids []int `json:"ids"`
}
func (s *SmsReceiveLogDeleteReq) GetId() interface{} {
return s.Ids
}
type SmsReceiveWebHookReq struct {
ActivationID int `json:"activationId"`
MessageID int `json:"messageId"`
Service string `json:"service"`
Text string `json:"text"`
Code string `json:"code"`
Country int `json:"country"`
ReceivedAt string `json:"receivedAt"`
}

View File

@ -0,0 +1,94 @@
package dto
import (
"go-admin/app/admin/models"
"go-admin/common/dto"
common "go-admin/common/models"
)
type SmsServicesGetPageReq struct {
dto.Pagination `search:"-"`
SmsServicesOrder
}
type SmsServicesOrder struct {
Id string `form:"idOrder" search:"type:order;column:id;table:sms_services"`
Name string `form:"nameOrder" search:"type:order;column:name;table:sms_services"`
Code string `form:"codeOrder" search:"type:order;column:code;table:sms_services"`
CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:sms_services"`
UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:sms_services"`
DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:sms_services"`
CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:sms_services"`
UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:sms_services"`
}
func (m *SmsServicesGetPageReq) GetNeedSearch() interface{} {
return *m
}
type SmsServicesInsertReq struct {
Id int `json:"-" comment:""` //
Name string `json:"name" comment:"服务名称"`
Code string `json:"code" comment:"编码"`
common.ControlBy
}
func (s *SmsServicesInsertReq) Generate(model *models.SmsServices) {
if s.Id == 0 {
model.Model = common.Model{Id: s.Id}
}
model.Name = s.Name
model.Code = s.Code
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的
}
func (s *SmsServicesInsertReq) GetId() interface{} {
return s.Id
}
type SmsServicesUpdateReq struct {
Id int `uri:"id" comment:""` //
Name string `json:"name" comment:"服务名称"`
Code string `json:"code" comment:"编码"`
common.ControlBy
}
func (s *SmsServicesUpdateReq) Generate(model *models.SmsServices) {
if s.Id == 0 {
model.Model = common.Model{Id: s.Id}
}
model.Name = s.Name
model.Code = s.Code
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的
}
func (s *SmsServicesUpdateReq) GetId() interface{} {
return s.Id
}
// SmsServicesGetReq 功能获取请求参数
type SmsServicesGetReq struct {
Id int `uri:"id"`
}
func (s *SmsServicesGetReq) GetId() interface{} {
return s.Id
}
// SmsServicesDeleteReq 功能删除请求参数
type SmsServicesDeleteReq struct {
Ids []int `json:"ids"`
}
func (s *SmsServicesDeleteReq) GetId() interface{} {
return s.Ids
}
type SmsServicesGetListResp struct {
Name string `json:"name" comment:"服务名称"`
Code string `json:"code" comment:"编码"`
}
type SmsGetPriceReq struct {
Type int `json:"type" form:"type" comment:"类型"`
}

View File

@ -0,0 +1,586 @@
package service
import (
"errors"
"fmt"
"strconv"
"strings"
"time"
"github.com/go-admin-team/go-admin-core/sdk/service"
"github.com/shopspring/decimal"
"gorm.io/gorm"
"go-admin/app/admin/models"
"go-admin/app/admin/service/dto"
"go-admin/common/actions"
cDto "go-admin/common/dto"
"go-admin/common/statuscode"
"go-admin/config"
"go-admin/utils/httphelper"
)
type SmsPhone struct {
service.Service
}
// 删除断信号码
func (e SmsPhone) DeleteMyNumber(req *dto.DeleteMyNumberReq, userId int) int {
var data models.SmsPhone
if err := e.Orm.Model(data).Where("id =? and user_id= ?", req.Id, userId).First(&data).Error; err != nil {
e.Log.Errorf("删除短信号码失败, %s", err)
return statuscode.AccountExisted
}
if data.ExpireTime != nil && data.ExpireTime.After(time.Now()) && data.Type == 1 {
return statuscode.SmsNotExpired
}
db := e.Orm.Model(&data).Delete(&data, data.GetId())
if db.Error != nil {
e.Log.Errorf("删除短信号码失败 id:%d, %s", req.Id, db.Error.Error())
return statuscode.ServerError
}
if db.RowsAffected == 0 {
return statuscode.ServerError
}
return statuscode.Success
}
// 唤醒长效号码
func (e SmsPhone) WeakUp(req *dto.WeakUpReq, userId int) int {
smsPhone := models.SmsPhone{}
if err := e.Orm.Model(smsPhone).Where("activation_id =? and user_id= ?", req.ActivationId, userId).First(&smsPhone).Error; err != nil {
e.Log.Errorf("获取短信号码失败, %s", err)
return statuscode.ServerError
}
if smsPhone.Status != 1 {
newActivationId, code := e.getExtraActivation(smsPhone.ActivationId)
if code == statuscode.ServerError {
return code
} else if code == statuscode.Success {
if err := e.Orm.Model(smsPhone).Updates(map[string]interface{}{"new_activation_id": newActivationId, "status": 1, "code": ""}).Error; err != nil {
e.Log.Errorf("更新短信号码失败, %s", err)
return statuscode.ServerError
}
} else if code == statuscode.SmsLongNumWaitCode {
e.Log.Info("无须唤醒")
if err := e.Orm.Model(smsPhone).Updates(map[string]interface{}{"status": 1, "code": ""}).Error; err != nil {
e.Log.Errorf("更新短信号码失败, %s", err)
return statuscode.ServerError
}
return statuscode.Success
}
}
return statuscode.Success
}
// 分页查询自己的号码列表
func (e SmsPhone) GetMyPage(req *dto.SmsPhoneGetPageReq, userId int, phone *[]models.SmsPhone, count *int64) int {
var data models.SmsPhone
if err := e.Orm.Model(data).Where("user_id =? and type =?", userId, req.Type).Scopes(
cDto.MakeCondition(req.GetNeedSearch()),
cDto.Paginate(req.GetPageSize(), req.GetPageIndex()),
).
Order("id desc").
Find(phone).Limit(-1).Offset(-1).
Count(count).Error; err != nil {
e.Log.Errorf("获取数据失败, %s", err)
return statuscode.ServerError
}
return statuscode.Success
}
// 租赁号码
func (e SmsPhone) GetNumber(req *dto.GetNumberReq, userId int) (decimal.Decimal, int) {
config := dto.GetSysConfigByKEYForServiceResp{}
configReq := dto.SysConfigByKeyReq{}
configService := SysConfig{Service: e.Service}
if req.Type == 0 {
configReq.ConfigKey = "number_fee_short_term"
} else {
configReq.ConfigKey = "number_fee_long_term"
}
err := configService.GetWithKey(&configReq, &config)
if err != nil {
return decimal.Zero, statuscode.ServerError
}
if config.ConfigValue == "" {
e.Log.Errorf("短期或长期租赁费用不能为空")
return decimal.Zero, statuscode.ServerError
}
price, err := decimal.NewFromString(config.ConfigValue)
if err != nil {
e.Log.Errorf("短期或长期租赁费用格式错误")
return decimal.Zero, statuscode.ServerError
}
smsService := SmsServices{Service: e.Service}
balanceService := MemberBalance{Service: e.Service}
balance := balanceService.GetBalance(userId)
serviceItem, err := smsService.GetByCode(req.ServiceCode)
if err != nil {
e.Log.Errorf("短信服务报错:%v", err)
return decimal.Zero, statuscode.ServerError
}
if serviceItem.Code == "" {
e.Log.Error("短信服务不存在")
return decimal.Zero, statuscode.ServerError
}
if balance.LessThan(price) {
e.Log.Error("余额不足")
return decimal.Zero, statuscode.BalanceNotEnough
}
now := time.Now()
activationId, phone, code := e.GetNumberForApi(req.Type, req.ServiceCode, price, req.Period)
if code != statuscode.Success {
return decimal.Zero, code
}
smsPhone := models.SmsPhone{}
smsPhone.Phone = phone
smsPhone.UserId = userId
smsPhone.Service = serviceItem.Name
smsPhone.ServiceCode = req.ServiceCode
smsPhone.Type = req.Type
smsPhone.Period = req.Period
smsPhone.ActivationId = activationId
smsPhone.MessageId = activationId
smsPhone.NewActivationId = activationId
if req.Type == 1 {
now = now.AddDate(0, req.Period, 0)
smsPhone.ExpireTime = &now
}
smsPhone.Status = 1
if err := e.Orm.Save(&smsPhone).Error; err != nil {
e.Log.Errorf("获取手机号失败", err)
return decimal.Zero, statuscode.ServerError
}
// if req.Type == 0 {
// smsReceiveLog := models.SmsReceiveLog{
// UserId: userId,
// MessageId: activationId,
// Service: serviceItem.Name,
// ServiceCode: serviceItem.Code,
// Phone: phone,
// Status: 1,
// }
// if err := e.Orm.Save(&smsReceiveLog).Error; err != nil {
// e.Log.Errorf("保存短信接收日志失败", err)
// return decimal.Zero, statuscode.ServerError
// }
// }
if req.Type == 1 {
//保存长效号码
if code := e.KeepLongTerm(smsPhone.ActivationId); code != statuscode.Success {
return decimal.Zero, code
}
}
if err := e.Orm.Exec("UPDATE member_balance SET balance = balance -? WHERE user_id =?", price, userId).Error; err != nil {
e.Log.Errorf("更新余额失败", err)
return decimal.Zero, statuscode.ServerError
}
balance = balanceService.GetBalance(userId)
return balance, statuscode.Success
}
// GetNumberForApi 获取短期或长期租赁号码
// getType 0-短效 1-长效
// service 服务code
// maxPrice 最大价格
// period 时长(月)
func (e *SmsPhone) GetNumberForApi(getType int, serviceCode string, maxPrice decimal.Decimal, period int) (int, string, int) {
acitvationId := 0
result := ""
resultCode := statuscode.Success
configResp, code := GetApiKey(e)
if code != statuscode.Success {
return acitvationId, result, code
}
url := fmt.Sprintf("?api_key=%s&action=getNumber&service=%s", configResp.ConfigValue, serviceCode)
if getType == 1 {
url = fmt.Sprintf("%s&duration=%dM", url, period)
}
client := httphelper.NewHTTPClient(10*time.Second, config.ExtConfig.DaisysmsUrl, nil)
//ACCESS_NUMBER:999999:13476711222
bytes, err := client.GetRaw(url, nil)
if err != nil {
e.Log.Errorf("租赁请求失败 %s", err.Error())
return acitvationId, result, statuscode.ServerError
}
content := string(bytes)
if strings.Contains(content, "ACCESS_NUMBER:") {
if len(strings.Split(content, ":")) < 2 {
e.Log.Errorf("租赁请求失败 %s", content)
return acitvationId, result, statuscode.ServerError
}
acitvationId, _ = strconv.Atoi(strings.Split(content, ":")[1])
result = strings.Split(content, ":")[2]
} else if strings.Contains(content, "MAX_PRICE_EXCEEDED:") {
e.Log.Errorf("租赁价格超过最大价格")
resultCode = statuscode.NoNumbers
} else if strings.Contains(content, "NO_NUMBERS") {
e.Log.Error("平台号码不足")
resultCode = statuscode.NoNumbers
} else if strings.Contains(content, "TOO_MANY_ACTIVE_RENTALS") {
e.Log.Error("租赁数量超过限制")
resultCode = statuscode.ServerError
} else if strings.Contains(content, "NO_MONEY") {
e.Log.Error("余额不足")
resultCode = statuscode.BalanceNotEnough
} else {
e.Log.Errorf("租赁请求失败 %s", content)
resultCode = statuscode.ServerError
}
return acitvationId, result, resultCode
}
// 设置租赁结束
func (e *SmsPhone) setStatus(id int) int {
configResp, code := GetApiKey(e)
if code != statuscode.Success {
return code
}
url := fmt.Sprintf("?api_key=%s&action=setStatus&id=%d&status=6", configResp.ConfigValue, id)
client := httphelper.NewHTTPClient(10*time.Second, config.ExtConfig.DaisysmsUrl, nil)
bytes, err := client.GetRaw(url, nil)
if err != nil {
e.Log.Errorf("租赁请求失败 %s", err.Error())
return statuscode.ServerError
}
content := string(bytes)
if content == "ACCESS_ACTIVATION" {
return statuscode.Success
} else {
e.Log.Errorf("租赁请求失败 %s", content)
return statuscode.ServerError
}
}
func GetApiKey(e *SmsPhone) (dto.GetSysConfigByKEYForServiceResp, int) {
configService := SysConfig{Service: e.Service}
configResp := dto.GetSysConfigByKEYForServiceResp{}
err := configService.GetWithKey(&dto.SysConfigByKeyReq{ConfigKey: "sms_key"}, &configResp)
if err != nil {
e.Log.Errorf("获取短信api失败, %s", err)
return dto.GetSysConfigByKEYForServiceResp{}, statuscode.ServerError
}
if configResp.ConfigValue == "" {
e.Log.Error("短信api不能为空")
return dto.GetSysConfigByKEYForServiceResp{}, statuscode.ServerError
}
return configResp, statuscode.Success
}
func (e *SmsPhone) GetCodeByActivationId(req *dto.GetCodeReq, userId int) ([]dto.GetCodeResp, int) {
var smsPhone []models.SmsPhone
result := []dto.GetCodeResp{}
if err := e.Orm.Model(models.SmsPhone{}).Where("user_id =? and activation_id in ?", userId, req.ActivationIds).Find(&smsPhone).Error; err != nil {
return result, statuscode.ServerError
}
for _, item := range smsPhone {
if item.Status == 1 {
continue
}
resultItem := dto.GetCodeResp{}
resultItem.ActivationId = item.ActivationId
resultItem.Code = item.Code
resultItem.Status = item.Status
result = append(result, resultItem)
}
return result, statuscode.Success
}
// 获取验证码
func (e *SmsPhone) GetCode(req *dto.GetCodeReq, userId int) (string, int) {
code := ""
status := statuscode.ServerError
return code, status
}
// SyncCodes 同步短信验证码
func (e *SmsPhone) SyncCodes() error {
var phones []models.SmsPhone
if err := e.Orm.Model(models.SmsPhone{}).Where("status =1").Find(&phones).Error; err != nil {
return err
}
for _, item := range phones {
code, codeStatus := e.GetCodeForApi(item.ActivationId)
mapData := make(map[string]interface{})
remark := ""
if codeStatus == statuscode.SmsWaitCode {
continue
} else if codeStatus == statuscode.Success {
mapData["code"] = code
mapData["status"] = 2
} else if codeStatus == statuscode.SmsNoActivation || codeStatus == statuscode.SmsCancel {
mapData["code"] = code
mapData["status"] = 3
remark = statuscode.GetMsg(codeStatus, "zh")
} else {
continue
}
if err := e.Orm.Model(&item).Updates(mapData).Error; err != nil {
e.Log.Errorf("同步短信验证码失败:%s", err.Error())
continue
}
if remark != "" {
mapData["remark"] = remark
}
if err := e.Orm.Model(models.SmsReceiveLog{}).Where("message_id =?", item.MessageId).Updates(mapData).Error; err != nil {
e.Log.Errorf("同步短信接收日志失败:%s", err.Error())
}
}
return nil
}
// GetCodeForApi 获取验证码
// messageId 短信id
// return 验证码, 状态码
func (e *SmsPhone) GetCodeForApi(messageId int) (string, int) {
result := ""
key, code := GetApiKey(e)
if code != statuscode.Success {
return result, code
}
url := fmt.Sprintf("?api_key=%s&action=getStatus&id=%d", key.ConfigValue, messageId)
client := httphelper.NewHTTPClient(10*time.Second, config.ExtConfig.DaisysmsUrl, nil)
bytes, err := client.GetRaw(url, nil)
if err != nil {
e.Log.Errorf("租赁请求失败 %s", err.Error())
return result, statuscode.ServerError
}
content := string(bytes)
if strings.Contains(content, "STATUS_OK:") && content != "STATUS_OK:KEEP" {
result = strings.Split(content, ":")[1]
} else if content == "NO_ACTIVATION" {
code = statuscode.SmsNoActivation
} else if content == "STATUS_WAIT_CODE" || content == "STATUS_OK:KEEP" {
code = statuscode.SmsWaitCode
} else if content == "STATUS_CANCEL" {
code = statuscode.SmsCancel
} else {
e.Log.Errorf("租赁请求失败 %s", content)
return result, statuscode.ServerError
}
return result, code
}
// getExtraActivation 获取额外的激活
// messageId 短信id
// return 验证码, 状态码
func (e *SmsPhone) getExtraActivation(activationId int) (int, int) {
result := 0
key, err := GetApiKey(e)
if err != statuscode.Success {
return 0, statuscode.ServerError
}
url := fmt.Sprintf("?api_key=%s&action=getExtraActivation&activationId=%d", key.ConfigValue, activationId)
client := httphelper.NewHTTPClient(10*time.Second, config.ExtConfig.DaisysmsUrl, nil)
bytes, err1 := client.GetRaw(url, nil)
if err1 != nil {
e.Log.Errorf("租赁请求失败 %s", err1.Error())
return 0, statuscode.ServerError
}
content := string(bytes)
if strings.Contains(content, "ASLEEP:") {
message := strings.Split(content, ":")[1]
result, _ = strconv.Atoi(message)
if result > 0 {
return result, statuscode.Success
}
} else if strings.Contains(content, "STATUS_OK:") {
return 0, statuscode.SmsLongNumWaitCode
} else if strings.Contains(content, "ACCESS_NUMBER:") {
message := strings.Split(content, ":")[1]
result, _ = strconv.Atoi(message)
if result > 0 {
return result, statuscode.Success
}
}
e.Log.Errorf("激活长效号码失败,%s", content)
return 0, statuscode.ServerError
}
// KeepLongTerm 长期租赁
func (e *SmsPhone) KeepLongTerm(activationId int) int {
key, code := GetApiKey(e)
if code != statuscode.Success {
return statuscode.ServerError
}
url := fmt.Sprintf("?api_key=%s&action=keep&id=%d", key.ConfigValue, activationId)
client := httphelper.NewHTTPClient(10*time.Second, config.ExtConfig.DaisysmsUrl, nil)
bytes, err := client.GetRaw(url, nil)
if err != nil {
e.Log.Errorf("租赁请求失败 %s", err.Error())
return statuscode.ServerError
}
content := string(bytes)
if content == "OK" {
return statuscode.Success
} else {
e.Log.Errorf("租赁请求失败 %s", content)
return statuscode.ServerError
}
return statuscode.Success
}
// GetPage 获取SmsPhone列表
func (e *SmsPhone) GetPage(c *dto.SmsPhoneGetPageReq, p *actions.DataPermission, list *[]models.SmsPhone, count *int64) error {
var err error
var data models.SmsPhone
err = e.Orm.Model(&data).
Scopes(
cDto.MakeCondition(c.GetNeedSearch()),
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
actions.Permission(data.TableName(), p),
).
Find(list).Limit(-1).Offset(-1).
Count(count).Error
if err != nil {
e.Log.Errorf("SmsPhoneService GetPage error:%s \r\n", err)
return err
}
return nil
}
// Get 获取SmsPhone对象
func (e *SmsPhone) Get(d *dto.SmsPhoneGetReq, p *actions.DataPermission, model *models.SmsPhone) error {
var data models.SmsPhone
err := e.Orm.Model(&data).
Scopes(
actions.Permission(data.TableName(), p),
).
First(model, d.GetId()).Error
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
err = errors.New("查看对象不存在或无权查看")
e.Log.Errorf("Service GetSmsPhone error:%s \r\n", err)
return err
}
if err != nil {
e.Log.Errorf("db error:%s", err)
return err
}
return nil
}
// Insert 创建SmsPhone对象
func (e *SmsPhone) Insert(c *dto.SmsPhoneInsertReq) error {
var err error
var data models.SmsPhone
c.Generate(&data)
err = e.Orm.Create(&data).Error
if err != nil {
e.Log.Errorf("SmsPhoneService Insert error:%s \r\n", err)
return err
}
return nil
}
// Update 修改SmsPhone对象
func (e *SmsPhone) Update(c *dto.SmsPhoneUpdateReq, p *actions.DataPermission) error {
var err error
var data = models.SmsPhone{}
e.Orm.Scopes(
actions.Permission(data.TableName(), p),
).First(&data, c.GetId())
c.Generate(&data)
db := e.Orm.Save(&data)
if err = db.Error; err != nil {
e.Log.Errorf("SmsPhoneService Save error:%s \r\n", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权更新该数据")
}
return nil
}
// Remove 删除SmsPhone
func (e *SmsPhone) Remove(d *dto.SmsPhoneDeleteReq, p *actions.DataPermission) error {
var data models.SmsPhone
db := e.Orm.Model(&data).
Scopes(
actions.Permission(data.TableName(), p),
).Delete(&data, d.GetId())
if err := db.Error; err != nil {
e.Log.Errorf("Service RemoveSmsPhone error:%s \r\n", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权删除该数据")
}
return nil
}

View File

@ -0,0 +1,150 @@
package service
import (
"errors"
"github.com/go-admin-team/go-admin-core/sdk/service"
"gorm.io/gorm"
"go-admin/app/admin/models"
"go-admin/app/admin/service/dto"
"go-admin/common/actions"
cDto "go-admin/common/dto"
"go-admin/common/statuscode"
)
type SmsReceiveLog struct {
service.Service
}
// 收到消息web hook
func (e SmsReceiveLog) WebHook(req *dto.SmsReceiveWebHookReq) error {
var data models.SmsReceiveLog
var phoneLog models.SmsPhone
if req.Code == "KEEP" {
return nil
}
if err := e.Orm.Model(&phoneLog).Where("new_activation_id =?", req.ActivationID).Updates(map[string]interface{}{"status": "2", "code": req.Code, "message_id": req.MessageID}).Error; err != nil {
e.Log.Errorf("webhook 修改phone code失败:%s \r\n", err)
return err
}
e.Orm.Model(&phoneLog).Where("new_activation_id =?", req.ActivationID).First(&phoneLog)
if phoneLog.Id > 0 {
data = models.SmsReceiveLog{
UserId: phoneLog.UserId,
Service: phoneLog.Service,
ServiceCode: phoneLog.ServiceCode,
MessageId: req.MessageID,
Phone: phoneLog.Phone,
Code: req.Code,
Status: 2,
}
if err := e.Orm.Create(&data).Error; err != nil {
e.Log.Errorf("WebHook 创建receive_log失败:%s \r\n", err)
return err
}
phoneService := SmsPhone{Service: e.Service}
if code := phoneService.setStatus(req.ActivationID); code != statuscode.Success {
e.Log.Errorf("接受验证码回调后修改状态失败 %d", code)
}
}
return nil
}
// GetPage 获取SmsReceiveLog列表
func (e *SmsReceiveLog) GetPage(c *dto.SmsReceiveLogGetPageReq, p *actions.DataPermission, list *[]models.SmsReceiveLog, count *int64) error {
var err error
var data models.SmsReceiveLog
err = e.Orm.Model(&data).
Scopes(
cDto.MakeCondition(c.GetNeedSearch()),
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
actions.Permission(data.TableName(), p),
).
Find(list).Limit(-1).Offset(-1).
Count(count).Error
if err != nil {
e.Log.Errorf("SmsReceiveLogService GetPage error:%s \r\n", err)
return err
}
return nil
}
// Get 获取SmsReceiveLog对象
func (e *SmsReceiveLog) Get(d *dto.SmsReceiveLogGetReq, p *actions.DataPermission, model *models.SmsReceiveLog) error {
var data models.SmsReceiveLog
err := e.Orm.Model(&data).
Scopes(
actions.Permission(data.TableName(), p),
).
First(model, d.GetId()).Error
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
err = errors.New("查看对象不存在或无权查看")
e.Log.Errorf("Service GetSmsReceiveLog error:%s \r\n", err)
return err
}
if err != nil {
e.Log.Errorf("db error:%s", err)
return err
}
return nil
}
// Insert 创建SmsReceiveLog对象
func (e *SmsReceiveLog) Insert(c *dto.SmsReceiveLogInsertReq) error {
var err error
var data models.SmsReceiveLog
c.Generate(&data)
err = e.Orm.Create(&data).Error
if err != nil {
e.Log.Errorf("SmsReceiveLogService Insert error:%s \r\n", err)
return err
}
return nil
}
// Update 修改SmsReceiveLog对象
func (e *SmsReceiveLog) Update(c *dto.SmsReceiveLogUpdateReq, p *actions.DataPermission) error {
var err error
var data = models.SmsReceiveLog{}
e.Orm.Scopes(
actions.Permission(data.TableName(), p),
).First(&data, c.GetId())
c.Generate(&data)
db := e.Orm.Save(&data)
if err = db.Error; err != nil {
e.Log.Errorf("SmsReceiveLogService Save error:%s \r\n", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权更新该数据")
}
return nil
}
// Remove 删除SmsReceiveLog
func (e *SmsReceiveLog) Remove(d *dto.SmsReceiveLogDeleteReq, p *actions.DataPermission) error {
var data models.SmsReceiveLog
db := e.Orm.Model(&data).
Scopes(
actions.Permission(data.TableName(), p),
).Delete(&data, d.GetId())
if err := db.Error; err != nil {
e.Log.Errorf("Service RemoveSmsReceiveLog error:%s \r\n", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权删除该数据")
}
return nil
}

View File

@ -0,0 +1,60 @@
package service
import (
"go-admin/app/admin/service/dto"
"go-admin/config"
"go-admin/utils/redishelper"
"testing"
"github.com/go-admin-team/go-admin-core/logger"
"github.com/go-admin-team/go-admin-core/sdk"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func initSetting() {
dsn := "root:123456@tcp(127.0.0.1:3306)/proxy_server?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
sdk.Runtime.SetDb("default", db)
config.ExtConfig.TrxGridUrl = "https://api.trongrid.io"
config.ExtConfig.DaisysmsUrl = "https://daisysms.com/stubs/handler_api.php"
redishelper.InitDefaultRedis("127.0.0.1:6379", "", 4)
redishelper.InitLockRedisConn("127.0.0.1:6379", "", "4")
}
func TestSmsReceiveLog(t *testing.T) {
initSetting()
receiveService := SmsReceiveLog{}
receiveService.Orm = sdk.Runtime.GetDbByKey("default")
receiveService.Log = logger.NewHelper(logger.DefaultLogger)
// receiveService.
}
func TestSmsPhone(t *testing.T) {
initSetting()
receiveService := SmsPhone{}
receiveService.Orm = sdk.Runtime.GetDbByKey("default")
receiveService.Log = logger.NewHelper(logger.DefaultLogger)
req := dto.GetNumberReq{
Type: 0,
ServiceCode: "lf",
}
receiveService.GetNumber(&req, 1)
}
// 测试获取长效号码
func TestPeriodPhone(t *testing.T) {
initSetting()
receiveService := SmsPhone{}
receiveService.Orm = sdk.Runtime.GetDbByKey("default")
receiveService.Log = logger.NewHelper(logger.DefaultLogger)
req := dto.GetNumberReq{
Type: 1,
ServiceCode: "lf",
Period: 1,
}
receiveService.GetNumber(&req, 1)
}

View File

@ -0,0 +1,164 @@
package service
import (
"errors"
"github.com/go-admin-team/go-admin-core/sdk/service"
"github.com/shopspring/decimal"
"gorm.io/gorm"
"go-admin/app/admin/models"
"go-admin/app/admin/service/dto"
"go-admin/common/actions"
cDto "go-admin/common/dto"
)
type SmsServices struct {
service.Service
}
// GetPrice 获取SmsServices价格
func (e SmsServices) GetPrice(req *dto.SmsGetPriceReq) (decimal.Decimal, error) {
key := "number_fee_short_term"
if req.Type == 1 {
key = "number_fee_long_term"
}
var price decimal.Decimal
configService := SysConfig{Service: e.Service}
configResp := dto.GetSysConfigByKEYForServiceResp{}
err := configService.GetWithKey(&dto.SysConfigByKeyReq{ConfigKey: key}, &configResp)
if err != nil {
return price, err
}
price, err = decimal.NewFromString(configResp.ConfigValue)
if err != nil {
return price, err
}
return price, nil
}
// GetList 获取SmsServices列表
func (e SmsServices) GetList(resp *[]dto.SmsServicesGetListResp) error {
var data []models.SmsServices
err := e.Orm.Find(&data).Error
if err != nil {
e.Log.Errorf("SmsServicesService GetList error:%s \r\n", err)
return err
}
for _, item := range data {
respItem := dto.SmsServicesGetListResp{
Name: item.Name,
Code: item.Code,
}
*resp = append(*resp, respItem)
}
return nil
}
// GetPage 获取SmsServices列表
func (e *SmsServices) GetPage(c *dto.SmsServicesGetPageReq, p *actions.DataPermission, list *[]models.SmsServices, count *int64) error {
var err error
var data models.SmsServices
err = e.Orm.Model(&data).
Scopes(
cDto.MakeCondition(c.GetNeedSearch()),
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
actions.Permission(data.TableName(), p),
).
Find(list).Limit(-1).Offset(-1).
Count(count).Error
if err != nil {
e.Log.Errorf("SmsServicesService GetPage error:%s \r\n", err)
return err
}
return nil
}
// Get 获取SmsServices对象
func (e *SmsServices) Get(d *dto.SmsServicesGetReq, p *actions.DataPermission, model *models.SmsServices) error {
var data models.SmsServices
err := e.Orm.Model(&data).
Scopes(
actions.Permission(data.TableName(), p),
).
First(model, d.GetId()).Error
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
err = errors.New("查看对象不存在或无权查看")
e.Log.Errorf("Service GetSmsServices error:%s \r\n", err)
return err
}
if err != nil {
e.Log.Errorf("db error:%s", err)
return err
}
return nil
}
// Insert 创建SmsServices对象
func (e *SmsServices) Insert(c *dto.SmsServicesInsertReq) error {
var err error
var data models.SmsServices
c.Generate(&data)
err = e.Orm.Create(&data).Error
if err != nil {
e.Log.Errorf("SmsServicesService Insert error:%s \r\n", err)
return err
}
return nil
}
// Update 修改SmsServices对象
func (e *SmsServices) Update(c *dto.SmsServicesUpdateReq, p *actions.DataPermission) error {
var err error
var data = models.SmsServices{}
e.Orm.Scopes(
actions.Permission(data.TableName(), p),
).First(&data, c.GetId())
c.Generate(&data)
db := e.Orm.Save(&data)
if err = db.Error; err != nil {
e.Log.Errorf("SmsServicesService Save error:%s \r\n", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权更新该数据")
}
return nil
}
// Remove 删除SmsServices
func (e *SmsServices) Remove(d *dto.SmsServicesDeleteReq, p *actions.DataPermission) error {
var data models.SmsServices
db := e.Orm.Model(&data).
Scopes(
actions.Permission(data.TableName(), p),
).Delete(&data, d.GetId())
if err := db.Error; err != nil {
e.Log.Errorf("Service RemoveSmsServices error:%s \r\n", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权删除该数据")
}
return nil
}
func (e *SmsServices) GetByCode(code string) (models.SmsServices, error) {
var data models.SmsServices
if err := e.Orm.Model(data).Where("code =?", code).First(&data).Error; err != nil {
return data, err
}
return data, nil
}

View File

@ -16,6 +16,7 @@ func InitJob() {
"RenewalJob": RenewalJob{},
"ExpireProxyJob": ExpireProxyJob{},
"CleanExpiredOrderJob": CleanExpiredOrderJob{},
"SmsJob": SmsJob{},
// ...
}
}

18
app/jobs/sms_job.go Normal file
View File

@ -0,0 +1,18 @@
package jobs
import (
"go-admin/app/admin/service"
"github.com/go-admin-team/go-admin-core/logger"
)
type SmsJob struct{}
// 定时查询结果
func (j SmsJob) Exec(args interface{}) error {
phoneService := service.SmsPhone{}
phoneService.Orm = GetDb()
phoneService.Log = logger.NewHelper(logger.DefaultLogger)
return phoneService.SyncCodes()
}

16
app/jobs/sms_job_test.go Normal file
View File

@ -0,0 +1,16 @@
package jobs
import (
"go-admin/config"
"testing"
)
func TestSendSMS(t *testing.T) {
initSetting()
config.ExtConfig.DaisysmsUrl = "https://daisysms.com/stubs/handler_api.php"
job := SmsJob{}
if err := job.Exec(nil); err != nil {
t.Error(err)
}
}

View File

@ -11,6 +11,17 @@ var StatusCodeZh = map[int]string{
PasswordEmpty: "密码不能为空",
ConfirmPasswordEmpty: "确认密码不能为空",
VerifyCodeError: "验证码错误",
BalanceNotEnough: "余额不足",
MaxPriceExceeded: "超过最大接受单价",
NoNumbers: "号码不足",
RentalsNotFinished: "需要先完成部分租赁才能继续租赁",
SmsCancel: "短信验证码_手机号过期",
SmsNoActivation: "短信验证码_手机号不存在",
SmsWaitCode: "短信验证码_等待验证码",
SmsLongNumWaitCode: "短信验证码_长效号码已唤醒",
SmsNotExisted: "号码不存在",
SmsNotExpired: "号码未过期无法删除",
}
var StatusCodeEn = map[int]string{
@ -24,6 +35,17 @@ var StatusCodeEn = map[int]string{
PasswordEmpty: "password can not be empty",
ConfirmPasswordEmpty: "confirm password can not be empty",
VerifyCodeError: "verify code error",
BalanceNotEnough: "balance not enough",
MaxPriceExceeded: "max price exceeded",
NoNumbers: "no numbers",
RentalsNotFinished: "need to finish some rentals before renting more",
SmsCancel: "sms code expired",
SmsNoActivation: "sms code not exist",
SmsWaitCode: "sms code wait for input",
SmsLongNumWaitCode: "sms code long num wake up",
SmsNotExisted: "number not exist",
SmsNotExpired: "number not expired, can not delete",
}
func GetMsg(code int, lang string) string {
@ -59,4 +81,26 @@ const (
ConfirmPasswordEmpty = 10008
//验证码错误
VerifyCodeError = 10009
//余额不足
BalanceNotEnough = 10010
//超过最大接受单价
MaxPriceExceeded = 10011
//号码不足
NoNumbers = 10012
// Need to finish some rentals before renting more
RentalsNotFinished = 10013
//短信验证码_手机号过期
SmsCancel = 20014
//短信验证码_手机号不存在
SmsNoActivation = 20015
//短信验证码_等待验证码
SmsWaitCode = 20016
//短信验证码_长效号码已唤醒
SmsLongNumWaitCode = 20017
//号码不存在
SmsNotExisted = 20018
//号码未过期无法删除
SmsNotExpired = 20019
)

View File

@ -14,6 +14,7 @@ type Extend struct {
TrxGridUrl string
CliproxyUrl string //cliproxy服务地址
CliproxyApiUrl string //cliproxy api地址
DaisysmsUrl string //daisysms服务地址
}
type AMap struct {

View File

@ -55,6 +55,8 @@ settings:
cliproxyUrl: "https://f.cliproxy.com"
#cliproxy api url
cliproxyApiUrl: "https://api.cliproxy.com"
#daisysms api url
daisysmsUrl: "https://daisysms.com/stubs/handler_api.php"
cache:
redis:
addr: 127.0.0.1:6379

View File

@ -48,12 +48,14 @@ func (c *HTTPClient) applyHeaders(req *http.Request, customHeaders map[string]st
// path: 请求路径,将与 BaseURL 拼接
// requestBody: 请求体数据,如果为 GET/DELETE 请求则为 nil
// customHeaders: 自定义请求头,将覆盖默认请求头
// responseData: 用于存储响应数据的目标结构体(指针类型)
// responseData: 用于存储响应数据的目标结构体(指针类型),如果为 nil 则表示不需要 JSON 解码
// rawResponse: 用于存储原始响应体字节切片(*[]byte如果为 nil 则表示不需要原始响应
func (c *HTTPClient) doRequest(
method, path string,
requestBody interface{},
customHeaders map[string]string,
responseData interface{},
rawResponse *[]byte, // 新增参数:指向字节切片的指针,用于存储原始响应
) error {
// 拼接完整的 URL
url := c.BaseURL + path
@ -93,7 +95,7 @@ func (c *HTTPClient) doRequest(
return fmt.Errorf("http request failed with status: %d, body: %s", resp.StatusCode, string(bodyBytes))
}
// 解码 JSON 响应(支持 gzip
// 解码响应(支持 gzip
var reader io.Reader = resp.Body
if resp.Header.Get("Content-Encoding") == "gzip" {
gzipReader, err := gzip.NewReader(resp.Body)
@ -104,8 +106,20 @@ func (c *HTTPClient) doRequest(
reader = gzipReader
}
// 首先读取整个响应体,然后决定如何处理
bodyBytes, err := io.ReadAll(reader)
if err != nil {
return fmt.Errorf("read response body failed: %w", err)
}
// 如果提供了原始响应目标,则填充它
if rawResponse != nil {
*rawResponse = bodyBytes
}
// 如果提供了 JSON 解码目标,则尝试解码
if responseData != nil {
err = json.NewDecoder(reader).Decode(responseData)
err = json.Unmarshal(bodyBytes, responseData) // 直接对字节切片使用 Unmarshal
if err != nil {
return fmt.Errorf("json decode response body failed: %w", err)
}
@ -119,7 +133,7 @@ func (c *HTTPClient) doRequest(
// customHeaders: 自定义请求头
// responseData: 用于存储响应数据的目标结构体(指针类型)
func (c *HTTPClient) Get(path string, customHeaders map[string]string, responseData interface{}) error {
return c.doRequest(http.MethodGet, path, nil, customHeaders, responseData)
return c.doRequest(http.MethodGet, path, nil, customHeaders, responseData, nil) // rawResponse 传递 nil
}
// Post 发送 POST 请求
@ -128,7 +142,7 @@ func (c *HTTPClient) Get(path string, customHeaders map[string]string, responseD
// customHeaders: 自定义请求头
// responseData: 用于存储响应数据的目标结构体(指针类型)
func (c *HTTPClient) Post(path string, requestBody interface{}, customHeaders map[string]string, responseData interface{}) error {
return c.doRequest(http.MethodPost, path, requestBody, customHeaders, responseData)
return c.doRequest(http.MethodPost, path, requestBody, customHeaders, responseData, nil) // rawResponse 传递 nil
}
// PostWithContentType 发送 POST 请求,支持自定义 Content-Type如 application/json 或 multipart/form-data
@ -196,8 +210,15 @@ func (c *HTTPClient) PostWithContentType(path string, requestBody interface{}, c
reader = gzipReader
}
// 首先读取整个响应体,然后决定如何处理
bodyBytes, err := io.ReadAll(reader)
if err != nil {
return fmt.Errorf("read response body failed: %w", err)
}
// 如果提供了 JSON 解码目标,则尝试解码
if responseData != nil {
err = json.NewDecoder(reader).Decode(responseData)
err = json.Unmarshal(bodyBytes, responseData)
if err != nil {
return fmt.Errorf("json decode response body failed: %w", err)
}
@ -212,7 +233,7 @@ func (c *HTTPClient) PostWithContentType(path string, requestBody interface{}, c
// customHeaders: 自定义请求头
// responseData: 用于存储响应数据的目标结构体(指针类型)
func (c *HTTPClient) Put(path string, requestBody interface{}, customHeaders map[string]string, responseData interface{}) error {
return c.doRequest(http.MethodPut, path, requestBody, customHeaders, responseData)
return c.doRequest(http.MethodPut, path, requestBody, customHeaders, responseData, nil) // rawResponse 传递 nil
}
// Delete 发送 DELETE 请求
@ -221,7 +242,7 @@ func (c *HTTPClient) Put(path string, requestBody interface{}, customHeaders map
// responseData: 用于存储响应数据的目标结构体(指针类型)
func (c *HTTPClient) Delete(path string, customHeaders map[string]string, responseData interface{}) error {
// DELETE 请求通常没有请求体,但某些 RESTful API 可能支持
return c.doRequest(http.MethodDelete, path, nil, customHeaders, responseData)
return c.doRequest(http.MethodDelete, path, nil, customHeaders, responseData, nil) // rawResponse 传递 nil
}
// Patch 发送 PATCH 请求
@ -230,5 +251,19 @@ func (c *HTTPClient) Delete(path string, customHeaders map[string]string, respon
// customHeaders: 自定义请求头
// responseData: 用于存储响应数据的目标结构体(指针类型)
func (c *HTTPClient) Patch(path string, requestBody interface{}, customHeaders map[string]string, responseData interface{}) error {
return c.doRequest(http.MethodPatch, path, requestBody, customHeaders, responseData)
return c.doRequest(http.MethodPatch, path, requestBody, customHeaders, responseData, nil) // rawResponse 传递 nil
}
// GetRaw 发送 GET 请求并返回原始响应体
// path: 请求路径
// customHeaders: 自定义请求头
// 返回值: 原始响应体字节切片或错误
func (c *HTTPClient) GetRaw(path string, customHeaders map[string]string) ([]byte, error) {
var raw []byte
// responseData 传递 nilrawResponse 传递 &raw
err := c.doRequest(http.MethodGet, path, nil, customHeaders, nil, &raw)
if err != nil {
return nil, err
}
return raw, nil
}