feat(apple): 添加通过transaction_id附加苹果交易功能
Build docker and publish / build (20.15.1) (push) Successful in 6m41s

新增通过transaction_id附加苹果交易的功能,包括:
1. 添加AttachAppleTransactionByIdRequest类型和对应路由
2. 实现AppleIAPConfig配置模型
3. 添加ServerAPI获取交易信息的实现
4. 优化JWS解析逻辑,增加cleanB64函数处理空格
5. 完善苹果通知处理逻辑的日志和注释
This commit is contained in:
2025-12-15 22:35:33 -08:00
parent 15fb9a1da5
commit 3c6dd5058b
13 changed files with 381 additions and 92 deletions
+45 -45
View File
@@ -88,26 +88,26 @@ func (l *BindDeviceLogic) createDeviceForUser(identifier, ip, userAgent string,
logger.Field("user_id", userId),
)
// enforce device bind limit before creating
if limit := l.svcCtx.SessionLimit(); limit > 0 {
if _, count, err := l.svcCtx.UserModel.QueryDeviceList(l.ctx, userId); err == nil {
if count >= limit {
l.Infow("device bind blocked by limit",
logger.Field("user_id", userId),
logger.Field("identifier", identifier),
logger.Field("count", count),
logger.Field("limit", limit))
return xerr.NewErrCodeMsg(xerr.DeviceBindLimitExceeded, "账户绑定设备数已达上限,请移除其他设备后再登录,您也可以再注册一个新账户使用,点击帮助中心查看更多详情。")
} else {
l.Infow("device bind limit check",
logger.Field("user_id", userId),
logger.Field("identifier", identifier),
logger.Field("count", count),
logger.Field("limit", limit))
}
}
}
err := l.svcCtx.UserModel.Transaction(l.ctx, func(db *gorm.DB) error {
// enforce device bind limit before creating
if limit := l.svcCtx.SessionLimit(); limit > 0 {
if _, count, err := l.svcCtx.UserModel.QueryDeviceList(l.ctx, userId); err == nil {
if count >= limit {
l.Infow("device bind blocked by limit",
logger.Field("user_id", userId),
logger.Field("identifier", identifier),
logger.Field("count", count),
logger.Field("limit", limit))
return xerr.NewErrCodeMsg(xerr.DeviceBindLimitExceeded, "账户绑定设备数已达上限,请移除其他设备后再登录,您也可以再注册一个新账户使用,点击帮助中心查看更多详情。")
} else {
l.Infow("device bind limit check",
logger.Field("user_id", userId),
logger.Field("identifier", identifier),
logger.Field("count", count),
logger.Field("limit", limit))
}
}
}
err := l.svcCtx.UserModel.Transaction(l.ctx, func(db *gorm.DB) error {
// Create device auth method
authMethod := &user.AuthMethods{
UserId: userId,
@@ -142,8 +142,8 @@ func (l *BindDeviceLogic) createDeviceForUser(identifier, ip, userAgent string,
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "create device failed: %v", err)
}
return nil
})
return nil
})
if err != nil {
l.Errorw("device creation failed",
@@ -163,28 +163,28 @@ func (l *BindDeviceLogic) createDeviceForUser(identifier, ip, userAgent string,
}
func (l *BindDeviceLogic) rebindDeviceToNewUser(deviceInfo *user.Device, ip, userAgent string, newUserId int64) error {
oldUserId := deviceInfo.UserId
oldUserId := deviceInfo.UserId
// enforce device bind limit before rebind
if limit := l.svcCtx.SessionLimit(); limit > 0 {
if _, count, err := l.svcCtx.UserModel.QueryDeviceList(l.ctx, newUserId); err == nil {
if count >= limit {
l.Infow("device rebind blocked by limit",
logger.Field("new_user_id", newUserId),
logger.Field("identifier", deviceInfo.Identifier),
logger.Field("count", count),
logger.Field("limit", limit))
return xerr.NewErrCodeMsg(xerr.DeviceBindLimitExceeded, "账户绑定设备数已达上限,请移除其他设备后再登录,您也可以再注册一个新账户使用,点击帮助中心查看更多详情。")
} else {
l.Infow("device rebind limit check",
logger.Field("new_user_id", newUserId),
logger.Field("identifier", deviceInfo.Identifier),
logger.Field("count", count),
logger.Field("limit", limit))
}
}
}
err := l.svcCtx.UserModel.Transaction(l.ctx, func(db *gorm.DB) error {
// enforce device bind limit before rebind
if limit := l.svcCtx.SessionLimit(); limit > 0 {
if _, count, err := l.svcCtx.UserModel.QueryDeviceList(l.ctx, newUserId); err == nil {
if count >= limit {
l.Infow("device rebind blocked by limit",
logger.Field("new_user_id", newUserId),
logger.Field("identifier", deviceInfo.Identifier),
logger.Field("count", count),
logger.Field("limit", limit))
return xerr.NewErrCodeMsg(xerr.DeviceBindLimitExceeded, "账户绑定设备数已达上限,请移除其他设备后再登录,您也可以再注册一个新账户使用,点击帮助中心查看更多详情。")
} else {
l.Infow("device rebind limit check",
logger.Field("new_user_id", newUserId),
logger.Field("identifier", deviceInfo.Identifier),
logger.Field("count", count),
logger.Field("limit", limit))
}
}
}
err := l.svcCtx.UserModel.Transaction(l.ctx, func(db *gorm.DB) error {
// Check if old user has other auth methods besides device
var authMethods []user.AuthMethods
if err := db.Where("user_id = ?", oldUserId).Find(&authMethods).Error; err != nil {
@@ -249,8 +249,8 @@ func (l *BindDeviceLogic) rebindDeviceToNewUser(deviceInfo *user.Device, ip, use
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update device failed: %v", err)
}
return nil
})
return nil
})
if err != nil {
l.Errorw("device rebinding failed",