Files
web_huangguo_web/app/api/web/deposit.go
T
fish03andClaude Opus 5.5 bef9f8b4ed Initial commit
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 14:43:16 +07:00

245 lines
5.7 KiB
Go

package web
import (
"net/http"
"strings"
"videoweb/app/service/authser"
"videoweb/app/service/rechargeser"
"videoweb/pub/common/log"
"videoweb/pub/common/useragent"
"github.com/gin-gonic/gin"
)
type buyPayBody struct {
PackageID int64 `json:"packageId"`
PayMode string `json:"payMode"`
}
// attachWalletFromGetInfo 登录态拉取 getInfo,刷新 cookie,并写入模板金币余额。
// 返回 true 表示注册账号会话失效,调用方应跳转登录。
func attachWalletFromGetInfo(c *gin.Context, data gin.H) bool {
if data == nil || useragent.TokenFromRequest(c.Request) == "" {
return false
}
env, user, err := authser.GetInfo(c)
if err != nil {
log.Error("wallet getInfo failed", log.E(err))
return false
}
if env != nil && authser.IsSessionExpiredCode(env.Code) {
retry, needLogin := authser.OnSessionExpired(c, env.Code)
if needLogin {
return true
}
if retry {
env, user, err = authser.GetInfo(c)
if err != nil {
log.Error("wallet getInfo retry failed", log.E(err))
return false
}
}
}
if env == nil || env.Code != 200 || user == nil {
return false
}
authser.SetAuthCookies(c, user)
data["userId"] = authser.FormatUserID(user.UserID)
data["recharge"] = user.Recharge
data["rechargeText"] = authser.FormatRecharge(user.Recharge)
data["vipType"] = user.VipType
data["showCardId"] = user.ShowCardID
data["showCardName"] = strings.TrimSpace(user.ShowCardName)
active := authser.IsActiveVipUser(user.VipType, user.CurrentVipExpire)
data["isVip"] = active
if active {
data["vipLabel"] = authser.VipDisplayLabel(user.ShowCardName, user.VipType)
data["vipExpireText"] = authser.FormatVipExpireText(user.CurrentVipExpire)
} else {
delete(data, "vipLabel")
delete(data, "vipExpireText")
}
return false
}
// Deposit 金币与会员充值页 SSR:套餐列表 + 金币流水明细。
// Query tab=coin 时默认选中金币充值套餐。
func Deposit(c *gin.Context) {
// 先补游客会话,保证可拉流水。
authser.EnsureGuestOnEnter(c)
preferTab := routeOrQuery(c, "tab", "tab")
if hasQuery(c, "tab") {
target := "/deposit"
if preferTab != "" {
target += "/" + preferTab
}
target += "/"
if redirectCanonical(c, target) {
return
}
}
raw := rechargeser.FetchPackageListOrEmpty(c)
vm := rechargeser.BuildDepositPageVM(raw, preferTab)
if useragent.TokenFromRequest(c.Request) != "" {
list, code, err := rechargeser.FetchCoinTransList(c, 1, 20)
if err != nil {
retry, needLogin := authser.OnSessionExpired(c, code)
if needLogin {
RedirectToLogin(c)
return
}
if retry {
list, _, err = rechargeser.FetchCoinTransList(c, 1, 20)
}
if err != nil {
log.Error("fetch coin trans list failed", log.E(err))
list = nil
}
}
vm.AttachTxList(list)
}
data := gin.H{
"title": "金币与会员",
"vipList": vm.VipList,
"coinList": vm.CoinList,
"payMethods": vm.PayMethods,
"txList": vm.TxList,
"preferTab": preferTab,
}
setNoIndex(data, false)
if attachWalletFromGetInfo(c, data) {
RedirectToLogin(c)
return
}
HTMLOK(c, "deposit.html", data)
}
// CoinBuy 代理上游 POST /api/app/coin/buy。
func CoinBuy(c *gin.Context) {
handleBuyPay(c, "coin")
}
// VipPay 代理上游 POST /api/app/vip/pay。
func VipPay(c *gin.Context) {
handleBuyPay(c, "vip")
}
func handleBuyPay(c *gin.Context, kind string) {
if useragent.TokenFromRequest(c.Request) == "" {
c.JSON(http.StatusOK, gin.H{
"code": 401,
"msg": "unauthorized",
"tip": "请先登录后再支付",
"data": nil,
})
return
}
var body buyPayBody
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"code": 1001,
"msg": "参数错误",
"tip": "参数错误",
"data": nil,
})
return
}
body.PayMode = rechargeser.NormalizePayMode(body.PayMode)
if body.PackageID <= 0 || body.PayMode == "" {
c.JSON(http.StatusOK, gin.H{
"code": 1001,
"msg": "参数错误",
"tip": "请选择套餐和支付方式",
"data": nil,
})
return
}
req := rechargeser.BuyPayReq{
PackageID: body.PackageID,
PayMode: body.PayMode,
}
var (
env *rechargeser.APIEnvelope[rechargeser.PayOrderResp]
err error
)
switch kind {
case "coin":
env, err = rechargeser.BuyCoin(c, req)
default:
env, err = rechargeser.VipPay(c, req)
}
if err != nil {
log.Error("buy/pay upstream failed", log.E(err))
c.JSON(http.StatusOK, gin.H{
"code": 500,
"msg": "pay failed",
"tip": "发起支付失败,请稍后重试",
"data": nil,
})
return
}
if env != nil && TryJSONSessionRecover(c, env.Code) {
switch kind {
case "coin":
env, err = rechargeser.BuyCoin(c, req)
default:
env, err = rechargeser.VipPay(c, req)
}
if err != nil {
log.Error("buy/pay retry failed", log.E(err))
c.JSON(http.StatusOK, gin.H{
"code": 500,
"msg": "pay failed",
"tip": "发起支付失败,请稍后重试",
"data": nil,
})
return
}
}
if env == nil || env.Code != 200 {
tip := "发起支付失败"
msg := ""
code := 500
if env != nil {
code = env.Code
msg = env.Msg
tip = firstNonEmpty(env.Tip, env.Msg, tip)
}
c.JSON(http.StatusOK, gin.H{
"code": code,
"msg": msg,
"tip": tip,
"data": nil,
})
return
}
payURL := strings.TrimSpace(env.Data.PayURL)
if payURL == "" {
c.JSON(http.StatusOK, gin.H{
"code": 500,
"msg": "empty payUrl",
"tip": "未获取到支付链接,请稍后重试",
"data": nil,
})
return
}
c.JSON(http.StatusOK, gin.H{
"code": 200,
"msg": firstNonEmpty(env.Msg, "success"),
"tip": firstNonEmpty(env.Tip, "请完成支付"),
"data": gin.H{
"isOpenNewBrowser": env.Data.IsOpenNewBrowser,
"payUrl": payURL,
"payUrlMode": env.Data.PayURLMode,
"tradeNo": env.Data.TradeNo,
},
})
}