feat: 互动处理
This commit is contained in:
@@ -91,7 +91,7 @@ func (s *ChannelService) GetChannelById(userId, id string) (radio.RadioChannel,
|
||||
return channel, nil
|
||||
}
|
||||
channel.HasSubscribed = 0
|
||||
if userId != "" {
|
||||
if userId != "" && userId != "0" {
|
||||
var sub radio.RadioSubscription
|
||||
err = global.DB.Model(&radio.RadioSubscription{}).
|
||||
Where("user_id = ?", userId).
|
||||
|
||||
@@ -8,6 +8,7 @@ type ServiceGroup struct {
|
||||
InteractionService
|
||||
PayService
|
||||
OrderService
|
||||
VipService
|
||||
}
|
||||
|
||||
var GroupApp = new(ServiceGroup)
|
||||
|
||||
@@ -3,6 +3,7 @@ package radio
|
||||
import (
|
||||
"errors"
|
||||
"sundynix-go/model/radio"
|
||||
"sundynix-go/model/system"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
@@ -12,7 +13,7 @@ type OrderService struct{}
|
||||
|
||||
var OrderServiceApp = new(OrderService)
|
||||
|
||||
// ExecuteOrderUnlock 核心原子操作:解锁权限
|
||||
// ExecuteOrderUnlock 订阅/开通vip 核心原子操作:解锁权限
|
||||
func (s *OrderService) ExecuteOrderUnlock(tx *gorm.DB, outTradeNo string) error {
|
||||
var order radio.Order
|
||||
// 1. 锁住订单行,防止回调和主动查询并发导致时长翻倍
|
||||
@@ -33,40 +34,48 @@ func (s *OrderService) ExecuteOrderUnlock(tx *gorm.DB, outTradeNo string) error
|
||||
}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 4. 根据订单中的 sub_type 决定增加几个月
|
||||
var months int
|
||||
switch order.SubscriptionType {
|
||||
case "1":
|
||||
months = 1 // 月
|
||||
case "2":
|
||||
months = 3 // 季
|
||||
case "3":
|
||||
months = 12 // 年
|
||||
}
|
||||
|
||||
// 5. 更新或创建订阅权限
|
||||
var sub radio.RadioSubscription
|
||||
now := time.Now()
|
||||
err := tx.Where("user_id = ? AND channel_id = ?", order.UserId, order.ChannelId).First(&sub).Error
|
||||
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 首次订阅
|
||||
return tx.Create(&radio.RadioSubscription{
|
||||
UserId: order.UserId,
|
||||
ChannelId: order.ChannelId,
|
||||
ExpiredAt: now.AddDate(0, months, 0),
|
||||
Status: 1,
|
||||
if order.Type == 2 {
|
||||
//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 {
|
||||
// 续费逻辑
|
||||
newExpiredAt := sub.ExpiredAt
|
||||
if sub.ExpiredAt.Before(now) {
|
||||
newExpiredAt = now // 已过期,从现在开始往后加
|
||||
} else if order.Type == 1 {
|
||||
// 4. 订阅 根据订单中的 sub_type 决定增加几个月
|
||||
var months int
|
||||
switch order.SubscriptionType {
|
||||
case "1":
|
||||
months = 1 // 月
|
||||
case "2":
|
||||
months = 3 // 季
|
||||
case "3":
|
||||
months = 12 // 年
|
||||
}
|
||||
|
||||
// 5. 更新或创建订阅权限
|
||||
var sub radio.RadioSubscription
|
||||
now := time.Now()
|
||||
err := tx.Where("user_id = ? AND channel_id = ?", order.UserId, order.ChannelId).First(&sub).Error
|
||||
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 首次订阅
|
||||
return tx.Create(&radio.RadioSubscription{
|
||||
UserId: order.UserId,
|
||||
ChannelId: order.ChannelId,
|
||||
ExpiredAt: now.AddDate(0, months, 0),
|
||||
Status: 1,
|
||||
}).Error
|
||||
} else {
|
||||
// 续费逻辑
|
||||
newExpiredAt := sub.ExpiredAt
|
||||
if sub.ExpiredAt.Before(now) {
|
||||
newExpiredAt = now // 已过期,从现在开始往后加
|
||||
}
|
||||
return tx.Model(&sub).Updates(map[string]interface{}{
|
||||
"expired_at": newExpiredAt.AddDate(0, months, 0),
|
||||
"status": 1,
|
||||
}).Error
|
||||
}
|
||||
return tx.Model(&sub).Updates(map[string]interface{}{
|
||||
"expired_at": newExpiredAt.AddDate(0, months, 0),
|
||||
"status": 1,
|
||||
}).Error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ func (s *PayService) PrePay(orderId, userId string) (resp *jsapi.PrepayWithReque
|
||||
Total: core.Int64(int64(order.Amount)),
|
||||
},
|
||||
Payer: &jsapi.Payer{
|
||||
Openid: core.String(user.MiniOpenId),
|
||||
Openid: core.String(user.OpenId),
|
||||
},
|
||||
//Detail: &jsapi.Detail{
|
||||
// CostPrice: core.Int64(608800),
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
common "sundynix-go/model/commom/request"
|
||||
"sundynix-go/model/radio"
|
||||
"sundynix-go/model/radio/request"
|
||||
"sundynix-go/model/system"
|
||||
"sundynix-go/utils/uniqueid"
|
||||
"sundynix-go/utils/wechat"
|
||||
|
||||
@@ -64,6 +65,11 @@ func (s *SubscriptionService) UnlockChannel(userId string, req request.UnlockCha
|
||||
if err != nil {
|
||||
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 创建不同的订单
|
||||
var price int
|
||||
var orderName string
|
||||
@@ -81,6 +87,7 @@ func (s *SubscriptionService) UnlockChannel(userId string, req request.UnlockCha
|
||||
return nil, "", errors.New("无效的订阅类型")
|
||||
}
|
||||
order := radio.Order{
|
||||
Type: 1, //很重要 1订阅 2开通vip
|
||||
UserId: userId,
|
||||
OutTradeNo: uniqueid.GenOrderNo(),
|
||||
ChannelId: req.ChannelId,
|
||||
@@ -93,11 +100,6 @@ func (s *SubscriptionService) UnlockChannel(userId string, req request.UnlockCha
|
||||
return nil, "", err
|
||||
}
|
||||
//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()
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user