1
This commit is contained in:
@@ -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 ""
|
||||
|
||||
Reference in New Issue
Block a user