This commit is contained in:
乘风
2026-04-20 09:46:18 +08:00
parent 0ce86645b1
commit 34d284c129

View File

@@ -1,6 +1,7 @@
package handler
import (
"errors"
"fmt"
"net/http"
"strings"
@@ -11,6 +12,7 @@ import (
"soul-api/internal/wechat"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// WechatLogin POST /api/wechat/login
@@ -51,13 +53,25 @@ func WechatPhoneLogin(c *gin.Context) {
db := database.DB()
var user model.User
result := db.Where("open_id = ?", openID).First(&user)
isNewUser := result.Error != nil
isNewUser := errors.Is(result.Error, gorm.ErrRecordNotFound)
if result.Error != nil && !isNewUser {
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "查询用户失败"})
return
}
if isNewUser {
// 软删除后再次登录:旧记录 id=openid 仍存在,需用新 id 避免主键冲突
userID := "user_" + randomSuffix()
referralCode := "SOUL" + strings.ToUpper(openID[len(openID)-6:])
nickname := "微信用户" + openID[len(openID)-4:]
// openID 可能为空/短值(微信异常回包),统一走尾部安全截断避免 panic
openIDLast6 := tail(openID, 6)
openIDLast4 := tail(openID, 4)
if openIDLast6 == "" {
openIDLast6 = strings.ToUpper(randomSuffix())
}
if openIDLast4 == "" {
openIDLast4 = strings.ToUpper(randomSuffix())
}
referralCode := "SOUL" + strings.ToUpper(openIDLast6)
nickname := "微信用户" + openIDLast4
avatar := ""
hasFullBook := false
earnings := 0.0
@@ -68,22 +82,48 @@ func WechatPhoneLogin(c *gin.Context) {
if countryCode != "" && countryCode != "86" {
phone = "+" + countryCode + " " + phoneNumber
}
user = model.User{
ID: userID,
OpenID: &openID,
SessionKey: &sessionKey,
Nickname: &nickname,
Avatar: &avatar,
Phone: &phone,
ReferralCode: &referralCode,
HasFullBook: &hasFullBook,
PurchasedSections: &purchasedSections,
Earnings: &earnings,
PendingEarnings: &pendingEarnings,
ReferralCount: &referralCount,
created := false
for i := 0; i < 5; i++ {
userID := "user_" + randomSuffix()
curReferralCode := referralCode
if i > 0 {
suffix := strings.ToUpper(tail(randomSuffix(), 3))
curReferralCode = "SOUL" + strings.ToUpper(tail(openIDLast6+suffix, 6))
}
user = model.User{
ID: userID,
OpenID: &openID,
SessionKey: &sessionKey,
Nickname: &nickname,
Avatar: &avatar,
Phone: &phone,
ReferralCode: &curReferralCode,
HasFullBook: &hasFullBook,
PurchasedSections: &purchasedSections,
Earnings: &earnings,
PendingEarnings: &pendingEarnings,
ReferralCount: &referralCount,
}
if err := db.Create(&user).Error; err != nil {
// 并发场景:若另一请求已创建同 open_id直接回查复用避免 500
if strings.Contains(strings.ToLower(err.Error()), "duplicate") {
var existed model.User
if qErr := db.Where("open_id = ?", openID).First(&existed).Error; qErr == nil {
user = existed
isNewUser = false
created = true
break
}
continue
}
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "创建用户失败"})
return
}
created = true
break
}
if err := db.Create(&user).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "创建用户失败"})
if !created {
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "创建用户失败,请稍后重试"})
return
}
} else {
@@ -91,7 +131,10 @@ func WechatPhoneLogin(c *gin.Context) {
if countryCode != "" && countryCode != "86" {
phone = "+" + countryCode + " " + phoneNumber
}
db.Model(&user).Updates(map[string]interface{}{"session_key": sessionKey, "phone": phone})
if err := db.Model(&user).Updates(map[string]interface{}{"session_key": sessionKey, "phone": phone}).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "更新用户失败"})
return
}
user.Phone = &phone
}
@@ -130,7 +173,11 @@ func WechatPhoneLogin(c *gin.Context) {
if user.VipExpireDate != nil {
responseUser["vipExpireDate"] = user.VipExpireDate.Format("2006-01-02")
}
token := fmt.Sprintf("tk_%s_%d", openID[len(openID)-8:], time.Now().Unix())
tokenSeed := tail(openID, 8)
if tokenSeed == "" {
tokenSeed = tail(randomSuffix(), 8)
}
token := fmt.Sprintf("tk_%s_%d", tokenSeed, time.Now().Unix())
c.JSON(http.StatusOK, gin.H{
"success": true,
@@ -143,6 +190,17 @@ func WechatPhoneLogin(c *gin.Context) {
})
}
func tail(s string, n int) string {
if n <= 0 {
return ""
}
r := []rune(strings.TrimSpace(s))
if len(r) <= n {
return string(r)
}
return string(r[len(r)-n:])
}
func strVal(p *string) string {
if p == nil {
return ""