feat: 互动处理
This commit is contained in:
@@ -54,6 +54,10 @@ func (a *ChannelApi) GetFreeChannelList(c *gin.Context) {
|
|||||||
// @Router /radio/channel/list [post]
|
// @Router /radio/channel/list [post]
|
||||||
func (a *ChannelApi) GetChannelList(c *gin.Context) {
|
func (a *ChannelApi) GetChannelList(c *gin.Context) {
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
var req request.GetChannelList
|
var req request.GetChannelList
|
||||||
err := c.ShouldBindJSON(&req)
|
err := c.ShouldBindJSON(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -86,6 +90,10 @@ func (a *ChannelApi) GetChannelList(c *gin.Context) {
|
|||||||
// @Router /radio/channel/detail [get]
|
// @Router /radio/channel/detail [get]
|
||||||
func (a *ChannelApi) GetChannelDetail(c *gin.Context) {
|
func (a *ChannelApi) GetChannelDetail(c *gin.Context) {
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
id := c.Query("id")
|
id := c.Query("id")
|
||||||
if id == "" {
|
if id == "" {
|
||||||
response.FailWithMsg("参数错误: id不能为空", c)
|
response.FailWithMsg("参数错误: id不能为空", c)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ type ApiGroup struct {
|
|||||||
SubscriptionApi
|
SubscriptionApi
|
||||||
InteractionApi
|
InteractionApi
|
||||||
PayApi
|
PayApi
|
||||||
|
VipApi
|
||||||
}
|
}
|
||||||
|
|
||||||
var ApiGroupApp = new(ApiGroup)
|
var ApiGroupApp = new(ApiGroup)
|
||||||
@@ -20,4 +21,5 @@ var (
|
|||||||
subscriptionService = service.GroupApp.RadioServiceGroup.SubscriptionService
|
subscriptionService = service.GroupApp.RadioServiceGroup.SubscriptionService
|
||||||
interactionService = service.GroupApp.RadioServiceGroup.InteractionService
|
interactionService = service.GroupApp.RadioServiceGroup.InteractionService
|
||||||
payService = service.GroupApp.RadioServiceGroup.PayService
|
payService = service.GroupApp.RadioServiceGroup.PayService
|
||||||
|
vipService = service.GroupApp.RadioServiceGroup.VipService
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ type InteractionApi struct{}
|
|||||||
// @Router /history/add [post]
|
// @Router /history/add [post]
|
||||||
func (a *InteractionApi) AddHistory(c *gin.Context) {
|
func (a *InteractionApi) AddHistory(c *gin.Context) {
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
var req request.AddHistory
|
var req request.AddHistory
|
||||||
err := c.ShouldBindJSON(&req)
|
err := c.ShouldBindJSON(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -52,6 +56,10 @@ func (a *InteractionApi) DeleteHistory(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
err = interactionService.DeleteHistory(userId, req.ProgramId)
|
err = interactionService.DeleteHistory(userId, req.ProgramId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Error("删除收听历史失败!", zap.Error(err))
|
global.Logger.Error("删除收听历史失败!", zap.Error(err))
|
||||||
@@ -69,6 +77,10 @@ func (a *InteractionApi) DeleteHistory(c *gin.Context) {
|
|||||||
// @Router /history/deleteAllHistory [get]
|
// @Router /history/deleteAllHistory [get]
|
||||||
func (a *InteractionApi) DeleteAllHistory(c *gin.Context) {
|
func (a *InteractionApi) DeleteAllHistory(c *gin.Context) {
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
err := interactionService.DeleteAllHistory(userId)
|
err := interactionService.DeleteAllHistory(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Error("删除所有收听历史失败!", zap.Error(err))
|
global.Logger.Error("删除所有收听历史失败!", zap.Error(err))
|
||||||
@@ -87,6 +99,10 @@ func (a *InteractionApi) DeleteAllHistory(c *gin.Context) {
|
|||||||
// @Router /history/list [post]
|
// @Router /history/list [post]
|
||||||
func (a *InteractionApi) GetHistoryList(c *gin.Context) {
|
func (a *InteractionApi) GetHistoryList(c *gin.Context) {
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
var req request.GetHistoryList
|
var req request.GetHistoryList
|
||||||
err := c.ShouldBindJSON(&req)
|
err := c.ShouldBindJSON(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -117,6 +133,10 @@ func (a *InteractionApi) GetHistoryList(c *gin.Context) {
|
|||||||
// @Router /like/toggle [post]
|
// @Router /like/toggle [post]
|
||||||
func (a *InteractionApi) ToggleLike(c *gin.Context) {
|
func (a *InteractionApi) ToggleLike(c *gin.Context) {
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
var req request.ToggleLike
|
var req request.ToggleLike
|
||||||
err := c.ShouldBindJSON(&req)
|
err := c.ShouldBindJSON(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -143,6 +163,10 @@ func (a *InteractionApi) ToggleLike(c *gin.Context) {
|
|||||||
// @Router /favorite/list [post]
|
// @Router /favorite/list [post]
|
||||||
func (a *InteractionApi) GetFavoriteList(c *gin.Context) {
|
func (a *InteractionApi) GetFavoriteList(c *gin.Context) {
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
var req request.GetFavoriteList
|
var req request.GetFavoriteList
|
||||||
err := c.ShouldBindJSON(&req)
|
err := c.ShouldBindJSON(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -173,6 +197,10 @@ func (a *InteractionApi) GetFavoriteList(c *gin.Context) {
|
|||||||
// @Router /favorite/add [post]
|
// @Router /favorite/add [post]
|
||||||
func (a *InteractionApi) AddFavorite(c *gin.Context) {
|
func (a *InteractionApi) AddFavorite(c *gin.Context) {
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
var req request.AddFavorite
|
var req request.AddFavorite
|
||||||
err := c.ShouldBindJSON(&req)
|
err := c.ShouldBindJSON(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -198,6 +226,10 @@ func (a *InteractionApi) AddFavorite(c *gin.Context) {
|
|||||||
// @Router /favorite/remove [post]
|
// @Router /favorite/remove [post]
|
||||||
func (a *InteractionApi) RemoveFavorite(c *gin.Context) {
|
func (a *InteractionApi) RemoveFavorite(c *gin.Context) {
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
var req request.RemoveFavorite
|
var req request.RemoveFavorite
|
||||||
err := c.ShouldBindJSON(&req)
|
err := c.ShouldBindJSON(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -223,6 +255,10 @@ func (a *InteractionApi) RemoveFavorite(c *gin.Context) {
|
|||||||
// @Router /favorite/removeAll [get]
|
// @Router /favorite/removeAll [get]
|
||||||
func (a *InteractionApi) RemoveAllFavorite(c *gin.Context) {
|
func (a *InteractionApi) RemoveAllFavorite(c *gin.Context) {
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
err := interactionService.RemoveAllFavorite(userId)
|
err := interactionService.RemoveAllFavorite(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Error("清空所有收藏失败!", zap.Error(err))
|
global.Logger.Error("清空所有收藏失败!", zap.Error(err))
|
||||||
@@ -270,6 +306,10 @@ func (a *InteractionApi) GetCommentList(c *gin.Context) {
|
|||||||
// @Router /comment/add [post]
|
// @Router /comment/add [post]
|
||||||
func (a *InteractionApi) AddComment(c *gin.Context) {
|
func (a *InteractionApi) AddComment(c *gin.Context) {
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
var req request.AddComment
|
var req request.AddComment
|
||||||
err := c.ShouldBindJSON(&req)
|
err := c.ShouldBindJSON(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -295,6 +335,10 @@ func (a *InteractionApi) AddComment(c *gin.Context) {
|
|||||||
// @Router /comment/delete [post]
|
// @Router /comment/delete [post]
|
||||||
func (a *InteractionApi) DeleteComment(c *gin.Context) {
|
func (a *InteractionApi) DeleteComment(c *gin.Context) {
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
var req request.DeleteComment
|
var req request.DeleteComment
|
||||||
err := c.ShouldBindJSON(&req)
|
err := c.ShouldBindJSON(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
+9
-1
@@ -23,6 +23,10 @@ type PayApi struct{}
|
|||||||
func (a *PayApi) PrePay(c *gin.Context) {
|
func (a *PayApi) PrePay(c *gin.Context) {
|
||||||
orderId := c.Query("orderId")
|
orderId := c.Query("orderId")
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
res, err := payService.PrePay(orderId, userId)
|
res, err := payService.PrePay(orderId, userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Error("支付失败", zap.Error(err))
|
global.Logger.Error("支付失败", zap.Error(err))
|
||||||
@@ -32,7 +36,7 @@ func (a *PayApi) PrePay(c *gin.Context) {
|
|||||||
response.OkWithData(res, c)
|
response.OkWithData(res, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryPay 查询支付
|
// QueryPay 查询订阅支付状态
|
||||||
// @Tags 微信支付
|
// @Tags 微信支付
|
||||||
// @Summary 支付
|
// @Summary 支付
|
||||||
// @Security BasicAuth
|
// @Security BasicAuth
|
||||||
@@ -43,6 +47,10 @@ func (a *PayApi) PrePay(c *gin.Context) {
|
|||||||
func (a *PayApi) QueryPay(c *gin.Context) {
|
func (a *PayApi) QueryPay(c *gin.Context) {
|
||||||
outTradeNo := c.Query("outTradeNo")
|
outTradeNo := c.Query("outTradeNo")
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
res, err := payService.QueryPay(outTradeNo, userId)
|
res, err := payService.QueryPay(outTradeNo, userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Error("支付失败", zap.Error(err))
|
global.Logger.Error("支付失败", zap.Error(err))
|
||||||
|
|||||||
@@ -57,6 +57,10 @@ func (a *ProgramApi) GetProgramDetail(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
program, err := programService.GetProgramById(id, userId)
|
program, err := programService.GetProgramById(id, userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Error("获取节目详情失败!", zap.Error(err))
|
global.Logger.Error("获取节目详情失败!", zap.Error(err))
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ type SubscriptionApi struct{}
|
|||||||
// @Router /radio/subscription/list [post]
|
// @Router /radio/subscription/list [post]
|
||||||
func (a *SubscriptionApi) GetSubscriptionList(c *gin.Context) {
|
func (a *SubscriptionApi) GetSubscriptionList(c *gin.Context) {
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
var req common.PageInfo
|
var req common.PageInfo
|
||||||
err := c.ShouldBindJSON(&req)
|
err := c.ShouldBindJSON(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -60,6 +64,10 @@ func (a *SubscriptionApi) UnlockChannel(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
res, no, err := subscriptionService.UnlockChannel(userId, req)
|
res, no, err := subscriptionService.UnlockChannel(userId, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Error("解锁频道失败!", zap.Error(err))
|
global.Logger.Error("解锁频道失败!", zap.Error(err))
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package radio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sundynix-go/model/commom/response"
|
||||||
|
"sundynix-go/model/radio/request"
|
||||||
|
radioRes "sundynix-go/model/radio/response"
|
||||||
|
"sundynix-go/utils/auth"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type VipApi struct{}
|
||||||
|
|
||||||
|
// UpdateVipConfig 更新VIP配置
|
||||||
|
// @Tags VIP管理
|
||||||
|
// @Summary 更新VIP配置
|
||||||
|
// @Accept application/json
|
||||||
|
// @Produce application/json
|
||||||
|
// @Param data body request.UpdateVipConfig true "VIP配置信息"
|
||||||
|
// @Success 200 {object} response.Response
|
||||||
|
// @Router /vip/config/update [post]
|
||||||
|
func (a *VipApi) UpdateVipConfig(c *gin.Context) {
|
||||||
|
var req request.UpdateVipConfig
|
||||||
|
err := c.ShouldBindJSON(&req)
|
||||||
|
if err != nil {
|
||||||
|
response.FailWithMsg("参数错误: "+err.Error(), c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = vipService.UpdateVipConfig(req)
|
||||||
|
if err != nil {
|
||||||
|
response.FailWithMsg(err.Error(), c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.OkWithMsg("更新成功", c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// VipConfigDetail 获取VIP配置详情
|
||||||
|
// @Tags VIP管理
|
||||||
|
// @Summary 获取VIP配置详情
|
||||||
|
// @Produce application/json
|
||||||
|
// @Param id query string true "id"
|
||||||
|
// @Success 200 {object} response.Response
|
||||||
|
// @Router /vip/config/detail [get]
|
||||||
|
func (a *VipApi) VipConfigDetail(c *gin.Context) {
|
||||||
|
vipConfig, err := vipService.VipConfigDetail()
|
||||||
|
if err != nil {
|
||||||
|
response.FailWithMsg(err.Error(), c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.OkWithData(vipConfig, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// VipVip 开通vip
|
||||||
|
// @Tags VIP管理
|
||||||
|
// @Summary 开通vip
|
||||||
|
// @Produce application/json
|
||||||
|
// @Success 200 {object} response.Response
|
||||||
|
// @Router /vip/vip [post]
|
||||||
|
func (a *VipApi) VipVip(c *gin.Context) {
|
||||||
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res, no, err := vipService.VipVip(userId)
|
||||||
|
if err != nil {
|
||||||
|
response.FailWithMsg(err.Error(), c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.OkWithData(radioRes.PrePayResult{
|
||||||
|
Payments: res,
|
||||||
|
OutTradeNo: no,
|
||||||
|
}, c)
|
||||||
|
}
|
||||||
@@ -56,6 +56,10 @@ func (a *AuthApi) Login(c *gin.Context) {
|
|||||||
func (a *AuthApi) Logout(c *gin.Context) {
|
func (a *AuthApi) Logout(c *gin.Context) {
|
||||||
token := auth.GetToken(c)
|
token := auth.GetToken(c)
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
err := jwtService.PutBlacklist(userId, token)
|
err := jwtService.PutBlacklist(userId, token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Error("登出失败!", zap.Error(err))
|
global.Logger.Error("登出失败!", zap.Error(err))
|
||||||
|
|||||||
@@ -138,6 +138,10 @@ func (m *MenuApi) GetAllMenuTree(c *gin.Context) {
|
|||||||
// @Router /menu/getUserMenuTree [get]
|
// @Router /menu/getUserMenuTree [get]
|
||||||
func (m *MenuApi) GetUserMenuTree(c *gin.Context) {
|
func (m *MenuApi) GetUserMenuTree(c *gin.Context) {
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
routes, err := menuService.GetUserRoutes(userId)
|
routes, err := menuService.GetUserRoutes(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Error("获取用户菜单失败!", zap.Error(err))
|
global.Logger.Error("获取用户菜单失败!", zap.Error(err))
|
||||||
@@ -156,6 +160,10 @@ func (m *MenuApi) GetUserMenuTree(c *gin.Context) {
|
|||||||
// @Router /menu/route [get]
|
// @Router /menu/route [get]
|
||||||
func (m *MenuApi) Route(c *gin.Context) {
|
func (m *MenuApi) Route(c *gin.Context) {
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" || userId == "0" {
|
||||||
|
response.FailWithMsg("用户未登录", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
routes, err := menuService.GetUserRoutes(userId)
|
routes, err := menuService.GetUserRoutes(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Error("获取用户菜单失败!", zap.Error(err))
|
global.Logger.Error("获取用户菜单失败!", zap.Error(err))
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ type UserApi struct {
|
|||||||
// @Router /user/info [get]
|
// @Router /user/info [get]
|
||||||
func (u *UserApi) CurrentUser(c *gin.Context) {
|
func (u *UserApi) CurrentUser(c *gin.Context) {
|
||||||
userId := auth.GetUserId(c)
|
userId := auth.GetUserId(c)
|
||||||
|
if userId == "" {
|
||||||
|
|
||||||
|
}
|
||||||
user, err := userService.GetUserById(userId)
|
user, err := userService.GetUserById(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Error("获取用户信息失败!", zap.Error(err))
|
global.Logger.Error("获取用户信息失败!", zap.Error(err))
|
||||||
|
|||||||
+1
-1
@@ -39,11 +39,11 @@ func MigrateTable() {
|
|||||||
system.SysOperationRecord{},
|
system.SysOperationRecord{},
|
||||||
system.Oss{},
|
system.Oss{},
|
||||||
|
|
||||||
|
radio.Vip{},
|
||||||
radio.RadioCategory{},
|
radio.RadioCategory{},
|
||||||
radio.RadioChannel{},
|
radio.RadioChannel{},
|
||||||
radio.RadioProgram{},
|
radio.RadioProgram{},
|
||||||
radio.RadioSubscription{},
|
radio.RadioSubscription{},
|
||||||
radio.RadioUser{},
|
|
||||||
radio.Order{},
|
radio.Order{},
|
||||||
radio.PayNotify{},
|
radio.PayNotify{},
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ func Routers() {
|
|||||||
systemRouter.InitOssRouter(NeedAuthGroup) //OSS相关
|
systemRouter.InitOssRouter(NeedAuthGroup) //OSS相关
|
||||||
|
|
||||||
// Radio模块路由
|
// Radio模块路由
|
||||||
|
radioRouter.InitVipRouter(NeedAuthGroup) //VIP相关
|
||||||
radioRouter.InitCategoryRouter(NeedAuthGroup) //分类相关
|
radioRouter.InitCategoryRouter(NeedAuthGroup) //分类相关
|
||||||
radioRouter.InitChannelRouter(NeedAuthGroup) //频道相关
|
radioRouter.InitChannelRouter(NeedAuthGroup) //频道相关
|
||||||
radioRouter.InitProgramRouter(NeedAuthGroup) //节目相关
|
radioRouter.InitProgramRouter(NeedAuthGroup) //节目相关
|
||||||
|
|||||||
@@ -7,3 +7,5 @@
|
|||||||
[sundynix-radio-server]2026-02-28 15:39:51 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm.go:49 Migrate table failed,err: {"error": "invalid field found for struct sundynix-go/model/radio.RadioCategory's field Cover: define a valid foreign key for relations or implement the Valuer/Scanner interface"}
|
[sundynix-radio-server]2026-02-28 15:39:51 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm.go:49 Migrate table failed,err: {"error": "invalid field found for struct sundynix-go/model/radio.RadioCategory's field Cover: define a valid foreign key for relations or implement the Valuer/Scanner interface"}
|
||||||
[sundynix-radio-server]2026-02-28 15:40:52 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/redis.go:43 Redis connect ping failed,err: {"name": "", "error": "dial tcp 127.0.0.1:6379: connect: connection refused"}
|
[sundynix-radio-server]2026-02-28 15:40:52 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/redis.go:43 Redis connect ping failed,err: {"name": "", "error": "dial tcp 127.0.0.1:6379: connect: connection refused"}
|
||||||
[sundynix-radio-server]2026-02-28 15:40:52 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/redis.go:17 Redis connect failed,err: {"error": "dial tcp 127.0.0.1:6379: connect: connection refused"}
|
[sundynix-radio-server]2026-02-28 15:40:52 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/redis.go:17 Redis connect failed,err: {"error": "dial tcp 127.0.0.1:6379: connect: connection refused"}
|
||||||
|
[sundynix-radio-server]2026-02-28 16:03:16 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/redis.go:43 Redis connect ping failed,err: {"name": "", "error": "dial tcp 127.0.0.1:6379: connect: connection refused"}
|
||||||
|
[sundynix-radio-server]2026-02-28 16:03:16 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/redis.go:17 Redis connect failed,err: {"error": "dial tcp 127.0.0.1:6379: connect: connection refused"}
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
[sundynix-radio-server]2026-02-28 15:39:45 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm_mysql.go:40 Mysql connect success
|
[sundynix-radio-server]2026-02-28 15:39:45 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm_mysql.go:40 Mysql connect success
|
||||||
[sundynix-radio-server]2026-02-28 15:40:52 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm_mysql.go:40 Mysql connect success
|
[sundynix-radio-server]2026-02-28 15:40:52 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm_mysql.go:40 Mysql connect success
|
||||||
[sundynix-radio-server]2026-02-28 15:41:00 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm.go:52 Migrate table success
|
[sundynix-radio-server]2026-02-28 15:41:00 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm.go:52 Migrate table success
|
||||||
|
[sundynix-radio-server]2026-02-28 16:03:16 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm_mysql.go:40 Mysql connect success
|
||||||
|
[sundynix-radio-server]2026-02-28 16:03:30 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm.go:52 Migrate table success
|
||||||
|
[sundynix-radio-server]2026-02-28 16:03:45 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm_mysql.go:40 Mysql connect success
|
||||||
|
[sundynix-radio-server]2026-02-28 16:03:45 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/redis.go:46 Redis connect ping response: {"name": "", "pong": "PONG"}
|
||||||
|
[sundynix-radio-server]2026-02-28 16:03:59 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm.go:52 Migrate table success
|
||||||
|
|||||||
@@ -15,5 +15,6 @@ type Order struct {
|
|||||||
Amount int `json:"amount" gorm:"column:amount;comment:金额分"`
|
Amount int `json:"amount" gorm:"column:amount;comment:金额分"`
|
||||||
Status int `json:"status" gorm:"column:status;comment:订单状态"` // 0:待支付 1:已支付 2:已关闭
|
Status int `json:"status" gorm:"column:status;comment:订单状态"` // 0:待支付 1:已支付 2:已关闭
|
||||||
PayStatus string `json:"payStatus" gorm:"column:pay_status;comment:支付状态"`
|
PayStatus string `json:"payStatus" gorm:"column:pay_status;comment:支付状态"`
|
||||||
|
Type int `json:"type" gorm:"column:type;default:1;comment:支付类型"` // 1.订阅支付(包含包月包季包年) 2:vip支付
|
||||||
User *system.User `json:"user" gorm:"foreignKey:UserId"`
|
User *system.User `json:"user" gorm:"foreignKey:UserId"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
package radio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sundynix-go/global"
|
|
||||||
"sundynix-go/model/system"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RadioUser 小程序用户信息表
|
|
||||||
type RadioUser struct {
|
|
||||||
global.BaseModel
|
|
||||||
UserId string `gorm:"size:50;uniqueIndex" json:"userId"` // 关联system用户ID
|
|
||||||
OpenId string `gorm:"size:80;uniqueIndex" json:"openId"` // 微信openid
|
|
||||||
UnionId string `gorm:"size:80" json:"unionId"` // 微信unionid
|
|
||||||
SessionKey string `gorm:"size:200" json:"sessionKey"` // 会话密钥
|
|
||||||
NickName string `gorm:"size:50" json:"nickName"` // 昵称
|
|
||||||
AvatarId string `gorm:"size:50" json:"avatarId"` // 头像OSS ID
|
|
||||||
Avatar *system.Oss `gorm:"foreignKey:AvatarId" json:"avatar"` // 头像OSS
|
|
||||||
Gender int `gorm:"default:0" json:"gender"` // 性别 0:未知 1:男 2:女
|
|
||||||
Country string `gorm:"size:50" json:"country"` // 国家
|
|
||||||
Province string `gorm:"size:50" json:"province"` // 省份
|
|
||||||
City string `gorm:"size:50" json:"city"` // 城市
|
|
||||||
Language string `gorm:"size:20" json:"language"` // 语言
|
|
||||||
IsVip int `gorm:"default:0" json:"isVip"` // 是否VIP 0:否 1:是
|
|
||||||
VipExpireAt *int64 `gorm:"type:bigint" json:"vipExpireAt"` // VIP过期时间
|
|
||||||
}
|
|
||||||
|
|
||||||
func (RadioUser) TableName() string {
|
|
||||||
return "sundynix_radio_user"
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package radio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sundynix-go/global"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Vip struct {
|
||||||
|
global.BaseModel
|
||||||
|
Price int `gorm:"default:0;comment:价格,单位,分 " json:"price"` //vip价格 单位:分
|
||||||
|
DiscountedPrice int `gorm:"default:0;comment:优惠价格,单位,分 " json:"discountedPrice"` // 优惠价格 单位:分
|
||||||
|
ExpiredAt time.Time `gorm:"index;column:expired_at" json:"expiredAt"` //过期时间
|
||||||
|
Remark string `gorm:"column:remark" json:"remark"` //备注
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Vip) TableName() string {
|
||||||
|
return "sundynix_radio_vip_config"
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package request
|
||||||
|
|
||||||
|
type UpdateVipConfig struct {
|
||||||
|
Id string `json:"id" binding:"required"`
|
||||||
|
Price int `json:"price" binding:"required"`
|
||||||
|
DiscountedPrice int `json:"discountedPrice"`
|
||||||
|
Remark string `json:"remark"`
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package system
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"sundynix-go/global"
|
"sundynix-go/global"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Login interface {
|
type Login interface {
|
||||||
@@ -20,10 +21,16 @@ type User struct {
|
|||||||
Phone string `gorm:"size:20;column:phone" json:"phone" form:"phone"`
|
Phone string `gorm:"size:20;column:phone" json:"phone" form:"phone"`
|
||||||
SessionKey string `gorm:"size:80;column:session_key" json:"sessionKey" form:"sessionKey"`
|
SessionKey string `gorm:"size:80;column:session_key" json:"sessionKey" form:"sessionKey"`
|
||||||
UnionId string `gorm:"size:80;column:union_id" json:"unionId"`
|
UnionId string `gorm:"size:80;column:union_id" json:"unionId"`
|
||||||
MiniOpenId string `gorm:"size:80;column:mini_open_id" json:"miniOpenId" form:"miniOpenId"`
|
OpenId string `gorm:"size:80;column:open_id" json:"openId" form:"openId"`
|
||||||
SaOpenId string `gorm:"size:80;column:sa_open_id" json:"saOpenId"`
|
|
||||||
AvatarId string `gorm:"size:50;column:avatar_id" json:"avatarId"`
|
AvatarId string `gorm:"size:50;column:avatar_id" json:"avatarId"`
|
||||||
Avatar *Oss `gorm:"foreignKey:AvatarId" json:"avatar"`
|
Avatar *Oss `gorm:"foreignKey:AvatarId" json:"avatar"`
|
||||||
|
Gender int `gorm:"default:0" json:"gender"` // 性别 0:未知 1:男 2:女
|
||||||
|
Country string `gorm:"size:50" json:"country"` // 国家
|
||||||
|
Province string `gorm:"size:50" json:"province"` // 省份
|
||||||
|
City string `gorm:"size:50" json:"city"` // 城市
|
||||||
|
Language string `gorm:"size:20" json:"language"` // 语言
|
||||||
|
IsVip int `gorm:"default:0" json:"isVip"` // 是否VIP 0:否 1:是
|
||||||
|
VipExpireAt *time.Time `gorm:"column:vip_expire_at" json:"vipExpireAt"` // VIP过期时间
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) GetAccount() string {
|
func (u *User) GetAccount() string {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ type RadioRouterGroup struct {
|
|||||||
SubscriptionRouter
|
SubscriptionRouter
|
||||||
InteractionRouter
|
InteractionRouter
|
||||||
PayRouter
|
PayRouter
|
||||||
|
VipRouter
|
||||||
}
|
}
|
||||||
|
|
||||||
var GroupApp = new(RadioRouterGroup)
|
var GroupApp = new(RadioRouterGroup)
|
||||||
@@ -20,4 +21,5 @@ var (
|
|||||||
subscriptionApi = v1.ApiGroupApp.RadioApiGroup.SubscriptionApi
|
subscriptionApi = v1.ApiGroupApp.RadioApiGroup.SubscriptionApi
|
||||||
interactionApi = v1.ApiGroupApp.RadioApiGroup.InteractionApi
|
interactionApi = v1.ApiGroupApp.RadioApiGroup.InteractionApi
|
||||||
payApi = v1.ApiGroupApp.RadioApiGroup.PayApi
|
payApi = v1.ApiGroupApp.RadioApiGroup.PayApi
|
||||||
|
vipApi = v1.ApiGroupApp.RadioApiGroup.VipApi
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package radio
|
||||||
|
|
||||||
|
import "github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
type VipRouter struct{}
|
||||||
|
|
||||||
|
func (r *VipRouter) InitVipRouter(Router *gin.RouterGroup) {
|
||||||
|
vipRouter := Router.Group("/vip")
|
||||||
|
{
|
||||||
|
vipRouter.POST("config/update", vipApi.UpdateVipConfig)
|
||||||
|
vipRouter.POST("config/detail", vipApi.VipConfigDetail)
|
||||||
|
// 开通vip
|
||||||
|
vipRouter.POST("vip", vipApi.VipVip)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -91,7 +91,7 @@ func (s *ChannelService) GetChannelById(userId, id string) (radio.RadioChannel,
|
|||||||
return channel, nil
|
return channel, nil
|
||||||
}
|
}
|
||||||
channel.HasSubscribed = 0
|
channel.HasSubscribed = 0
|
||||||
if userId != "" {
|
if userId != "" && userId != "0" {
|
||||||
var sub radio.RadioSubscription
|
var sub radio.RadioSubscription
|
||||||
err = global.DB.Model(&radio.RadioSubscription{}).
|
err = global.DB.Model(&radio.RadioSubscription{}).
|
||||||
Where("user_id = ?", userId).
|
Where("user_id = ?", userId).
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ type ServiceGroup struct {
|
|||||||
InteractionService
|
InteractionService
|
||||||
PayService
|
PayService
|
||||||
OrderService
|
OrderService
|
||||||
|
VipService
|
||||||
}
|
}
|
||||||
|
|
||||||
var GroupApp = new(ServiceGroup)
|
var GroupApp = new(ServiceGroup)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package radio
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"sundynix-go/model/radio"
|
"sundynix-go/model/radio"
|
||||||
|
"sundynix-go/model/system"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@@ -12,7 +13,7 @@ type OrderService struct{}
|
|||||||
|
|
||||||
var OrderServiceApp = new(OrderService)
|
var OrderServiceApp = new(OrderService)
|
||||||
|
|
||||||
// ExecuteOrderUnlock 核心原子操作:解锁权限
|
// ExecuteOrderUnlock 订阅/开通vip 核心原子操作:解锁权限
|
||||||
func (s *OrderService) ExecuteOrderUnlock(tx *gorm.DB, outTradeNo string) error {
|
func (s *OrderService) ExecuteOrderUnlock(tx *gorm.DB, outTradeNo string) error {
|
||||||
var order radio.Order
|
var order radio.Order
|
||||||
// 1. 锁住订单行,防止回调和主动查询并发导致时长翻倍
|
// 1. 锁住订单行,防止回调和主动查询并发导致时长翻倍
|
||||||
@@ -33,8 +34,14 @@ func (s *OrderService) ExecuteOrderUnlock(tx *gorm.DB, outTradeNo string) error
|
|||||||
}).Error; err != nil {
|
}).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if order.Type == 2 {
|
||||||
// 4. 根据订单中的 sub_type 决定增加几个月
|
//4.开通vip 过期时间为2099 年
|
||||||
|
return tx.Model(&system.User{}).Where("id = ?", order.UserId).Updates(map[string]interface{}{
|
||||||
|
"is_vip": 1,
|
||||||
|
"vip_expire_at": time.Date(2099, 12, 31, 23, 59, 59, 999, time.Local),
|
||||||
|
}).Error
|
||||||
|
} else if order.Type == 1 {
|
||||||
|
// 4. 订阅 根据订单中的 sub_type 决定增加几个月
|
||||||
var months int
|
var months int
|
||||||
switch order.SubscriptionType {
|
switch order.SubscriptionType {
|
||||||
case "1":
|
case "1":
|
||||||
@@ -70,3 +77,5 @@ func (s *OrderService) ExecuteOrderUnlock(tx *gorm.DB, outTradeNo string) error
|
|||||||
}).Error
|
}).Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ func (s *PayService) PrePay(orderId, userId string) (resp *jsapi.PrepayWithReque
|
|||||||
Total: core.Int64(int64(order.Amount)),
|
Total: core.Int64(int64(order.Amount)),
|
||||||
},
|
},
|
||||||
Payer: &jsapi.Payer{
|
Payer: &jsapi.Payer{
|
||||||
Openid: core.String(user.MiniOpenId),
|
Openid: core.String(user.OpenId),
|
||||||
},
|
},
|
||||||
//Detail: &jsapi.Detail{
|
//Detail: &jsapi.Detail{
|
||||||
// CostPrice: core.Int64(608800),
|
// CostPrice: core.Int64(608800),
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
common "sundynix-go/model/commom/request"
|
common "sundynix-go/model/commom/request"
|
||||||
"sundynix-go/model/radio"
|
"sundynix-go/model/radio"
|
||||||
"sundynix-go/model/radio/request"
|
"sundynix-go/model/radio/request"
|
||||||
|
"sundynix-go/model/system"
|
||||||
"sundynix-go/utils/uniqueid"
|
"sundynix-go/utils/uniqueid"
|
||||||
"sundynix-go/utils/wechat"
|
"sundynix-go/utils/wechat"
|
||||||
|
|
||||||
@@ -64,6 +65,11 @@ func (s *SubscriptionService) UnlockChannel(userId string, req request.UnlockCha
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
var user system.User
|
||||||
|
err = global.DB.Where("id = ?", userId).First(&user).Error
|
||||||
|
if err != nil || user.OpenId == "" {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
//2.创建一个订单 根据eventType 创建不同的订单
|
//2.创建一个订单 根据eventType 创建不同的订单
|
||||||
var price int
|
var price int
|
||||||
var orderName string
|
var orderName string
|
||||||
@@ -81,6 +87,7 @@ func (s *SubscriptionService) UnlockChannel(userId string, req request.UnlockCha
|
|||||||
return nil, "", errors.New("无效的订阅类型")
|
return nil, "", errors.New("无效的订阅类型")
|
||||||
}
|
}
|
||||||
order := radio.Order{
|
order := radio.Order{
|
||||||
|
Type: 1, //很重要 1订阅 2开通vip
|
||||||
UserId: userId,
|
UserId: userId,
|
||||||
OutTradeNo: uniqueid.GenOrderNo(),
|
OutTradeNo: uniqueid.GenOrderNo(),
|
||||||
ChannelId: req.ChannelId,
|
ChannelId: req.ChannelId,
|
||||||
@@ -93,11 +100,6 @@ func (s *SubscriptionService) UnlockChannel(userId string, req request.UnlockCha
|
|||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
//4.调用微信api 拉起支付
|
//4.调用微信api 拉起支付
|
||||||
var user radio.RadioUser
|
|
||||||
err = global.DB.Where("user_id = ?", userId).First(&user).Error
|
|
||||||
if err != nil {
|
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
payClient, err := wechat.GetWxPayClient()
|
payClient, err := wechat.GetWxPayClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package radio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sundynix-go/global"
|
||||||
|
"sundynix-go/model/radio"
|
||||||
|
"sundynix-go/model/radio/request"
|
||||||
|
"sundynix-go/model/system"
|
||||||
|
"sundynix-go/utils/uniqueid"
|
||||||
|
"sundynix-go/utils/wechat"
|
||||||
|
|
||||||
|
"github.com/wechatpay-apiv3/wechatpay-go/core"
|
||||||
|
"github.com/wechatpay-apiv3/wechatpay-go/services/payments/jsapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
type VipService struct{}
|
||||||
|
|
||||||
|
func (s *VipService) UpdateVipConfig(req request.UpdateVipConfig) error {
|
||||||
|
updateData := map[string]interface{}{
|
||||||
|
"price": req.Price,
|
||||||
|
"discountedPrice": req.DiscountedPrice,
|
||||||
|
"remark": req.Remark,
|
||||||
|
}
|
||||||
|
err := global.DB.Model(&radio.Vip{}).Where("id = ?", req.Id).Updates(updateData).Error
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *VipService) VipConfigDetail() (radio.Vip, error) {
|
||||||
|
var vip radio.Vip
|
||||||
|
err := global.DB.Model(&radio.Vip{}).First(&vip).Error
|
||||||
|
return vip, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// VipVip 开通vip
|
||||||
|
func (s *VipService) VipVip(userId string) (*jsapi.PrepayWithRequestPaymentResponse, string, error) {
|
||||||
|
//1.查询vip配置
|
||||||
|
var config radio.Vip
|
||||||
|
err := global.DB.Model(&radio.Vip{}).First(&config).Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
//2.创建订单
|
||||||
|
order := radio.Order{
|
||||||
|
Type: 2, //很重要 1订阅 2开通vip
|
||||||
|
UserId: userId,
|
||||||
|
OutTradeNo: uniqueid.GenOrderNo(),
|
||||||
|
SubscriptionType: "vip sub",
|
||||||
|
Amount: config.DiscountedPrice,
|
||||||
|
Name: "vip sub",
|
||||||
|
}
|
||||||
|
err = global.DB.Create(&order).Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
//3.调用微信api 拉起支付
|
||||||
|
var user system.User
|
||||||
|
err = global.DB.Where("id = ?", userId).First(&user).Error
|
||||||
|
if err != nil || user.OpenId == "" {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
payClient, err := wechat.GetWxPayClient()
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
svc := jsapi.JsapiApiService{Client: payClient}
|
||||||
|
result, _, err := svc.PrepayWithRequestPayment(context.Background(),
|
||||||
|
jsapi.PrepayRequest{
|
||||||
|
Appid: core.String(global.Config.MiniProgram.AppId),
|
||||||
|
Mchid: core.String(global.Config.WechatPay.MchId),
|
||||||
|
Description: core.String(order.Name),
|
||||||
|
OutTradeNo: core.String(order.OutTradeNo),
|
||||||
|
//TimeExpire: core.Time(time.Now()), //选填
|
||||||
|
//Attach: core.String("自定义数据说明"), //选填
|
||||||
|
NotifyUrl: core.String(global.Config.WechatPay.NotifyUrl),
|
||||||
|
//GoodsTag: core.String("WXG"), //选填
|
||||||
|
//SupportFapiao: core.Bool(false), //选填
|
||||||
|
Amount: &jsapi.Amount{
|
||||||
|
Currency: core.String("CNY"),
|
||||||
|
Total: core.Int64(int64(config.DiscountedPrice)),
|
||||||
|
},
|
||||||
|
Payer: &jsapi.Payer{
|
||||||
|
Openid: core.String(user.OpenId),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, order.OutTradeNo, nil
|
||||||
|
}
|
||||||
@@ -12,7 +12,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"sundynix-go/global"
|
"sundynix-go/global"
|
||||||
common "sundynix-go/model/commom/request"
|
common "sundynix-go/model/commom/request"
|
||||||
"sundynix-go/model/radio"
|
|
||||||
"sundynix-go/model/system"
|
"sundynix-go/model/system"
|
||||||
systemReq "sundynix-go/model/system/request"
|
systemReq "sundynix-go/model/system/request"
|
||||||
systemResp "sundynix-go/model/system/response"
|
systemResp "sundynix-go/model/system/response"
|
||||||
@@ -145,29 +144,19 @@ func (userService *UserService) MiniLogin(code string) (result *system.User, err
|
|||||||
|
|
||||||
// 7. 根据openid查询用户 存在--> 更新session_key 返回数据
|
// 7. 根据openid查询用户 存在--> 更新session_key 返回数据
|
||||||
var user system.User
|
var user system.User
|
||||||
err = global.DB.Where("mini_open_id = ?", wxResp.Openid).Preload("Avatar").First(&user).Error
|
err = global.DB.Where("open_id = ?", wxResp.Openid).Preload("Avatar").First(&user).Error
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
// 8. 使用 Transaction 闭包管理事务
|
// 8. 使用 Transaction 闭包管理事务
|
||||||
err = global.DB.Transaction(func(tx *gorm.DB) error {
|
err = global.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
// 创建新用户
|
// 创建新用户
|
||||||
newUser := system.User{
|
newUser := system.User{
|
||||||
Name: uniqueid.GenerateName(),
|
Name: uniqueid.GenerateRadioUsername(),
|
||||||
MiniOpenId: wxResp.Openid,
|
OpenId: wxResp.Openid,
|
||||||
SessionKey: wxResp.SessionKey,
|
SessionKey: wxResp.SessionKey,
|
||||||
}
|
}
|
||||||
if err := tx.Create(&newUser).Error; err != nil {
|
if err := tx.Create(&newUser).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// 创建小程序用户
|
|
||||||
mpUser := radio.RadioUser{
|
|
||||||
UserId: newUser.Id,
|
|
||||||
OpenId: wxResp.Openid,
|
|
||||||
UnionId: wxResp.Unionid,
|
|
||||||
SessionKey: wxResp.SessionKey,
|
|
||||||
}
|
|
||||||
if err := tx.Create(&mpUser).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 赋值给外部变量以便返回
|
// 赋值给外部变量以便返回
|
||||||
user = newUser
|
user = newUser
|
||||||
|
|||||||
@@ -109,3 +109,8 @@ func TestGetZeroTime(t *testing.T) {
|
|||||||
fmt.Printf("当天零点: %v\n", zeroTime)
|
fmt.Printf("当天零点: %v\n", zeroTime)
|
||||||
fmt.Printf("时间戳(秒): %v\n", zeroTime.Unix())
|
fmt.Printf("时间戳(秒): %v\n", zeroTime.Unix())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGenName(t *testing.T) {
|
||||||
|
username := uniqueid.GenerateRadioUsername()
|
||||||
|
fmt.Println(username)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package uniqueid
|
package uniqueid
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/rand"
|
||||||
"strings"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
@@ -17,25 +16,30 @@ func GenerateId() string {
|
|||||||
return uuidV1.String()
|
return uuidV1.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateName() string {
|
// GenerateRadioUsername 生成具有电台氛围的用户名称
|
||||||
str := uuid.New().String()
|
func GenerateRadioUsername() string {
|
||||||
//生成一个用户名 比如花友u278bb 中文后的字符随机生成 不可重复 取str的前六位
|
// 1. 文艺词库
|
||||||
return "花友" + str[6:12]
|
adjectives := []string{"虚构", "私奔", "落日", "低空", "巡航", "无声", "迷失", "告白", "极光", "霓虹"}
|
||||||
|
nouns := []string{"调频", "电波", "磁带", "频率", "回声", "岛屿", "信箱", "航站", "独白", "碎片"}
|
||||||
|
|
||||||
|
// 2. 初始化随机种子 (使用纳秒级时间戳)
|
||||||
|
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
|
||||||
|
// 3. 随机抽取词库
|
||||||
|
adj := adjectives[r.Intn(len(adjectives))]
|
||||||
|
noun := nouns[r.Intn(len(nouns))]
|
||||||
|
|
||||||
|
// 4. 获取当前时间的微秒/纳秒部分作为“身份码”
|
||||||
|
// 取纳秒的最后5位,既能体现随机性,又不会像日期那样冗长
|
||||||
|
timeSuffix := time.Now().UnixNano() % 100000
|
||||||
|
|
||||||
|
// 5. 混合生成:采用不同的模板增加随机感
|
||||||
|
templates := []string{
|
||||||
|
"%s%s_%05d", // 如:落日电波_12345
|
||||||
|
"Hz.%d-%s%s", // 如:Hz.67890-虚构独白
|
||||||
|
"%s%s-%d-FM", // 如:迷失频率-54321-FM
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateRandomCode 生成邀请码
|
selectedTemplate := templates[r.Intn(len(templates))]
|
||||||
func GenerateRandomCode(length int) string {
|
return fmt.Sprintf(selectedTemplate, adj, noun, timeSuffix)
|
||||||
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
|
||||||
var sb strings.Builder
|
|
||||||
for i := 0; i < length; i++ {
|
|
||||||
n, _ := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))
|
|
||||||
sb.WriteByte(charset[n.Int64()])
|
|
||||||
}
|
|
||||||
return sb.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenCodeKey 生成邀请码的key
|
|
||||||
func GenCodeKey(userId string) string {
|
|
||||||
return fmt.Sprintf("code:%s", userId)
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user