| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- package services
- import (
- "app/commons/config"
- "app/commons/core"
- "app/commons/core/redisclient"
- "app/commons/model/entity"
- "bytes"
- "context"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "net/http"
- "time"
- )
- // TgPlatformService 平台API客户端服务(调用Vitiens平台接口)
- type TgPlatformService struct {
- CommonService
- }
- // ---- 请求/响应结构体 ----
- // oauthLoginRequest OAuth登录请求
- type oauthLoginRequest struct {
- Provider string `json:"provider"`
- OpenId string `json:"openId"`
- Nickname string `json:"nickname"`
- Avatar string `json:"avatar"`
- InviteCode string `json:"inviteCode,omitempty"`
- }
- // platformAPIResponse 平台API通用响应
- type platformAPIResponse struct {
- Code int32 `json:"code"`
- Msg string `json:"msg"`
- Data json.RawMessage `json:"data"`
- Time int64 `json:"time"`
- }
- // oauthLoginData OAuth登录响应data
- type oauthLoginData struct {
- Token string `json:"token"`
- User oauthUserInfo `json:"user"`
- IsNew bool `json:"isNew"`
- }
- // oauthUserInfo 用户信息
- type oauthUserInfo struct {
- Id int64 `json:"id"`
- Uid string `json:"uid"`
- Nickname string `json:"nickname"`
- Avatar string `json:"avatar"`
- Phone string `json:"phone"`
- Email string `json:"email"`
- }
- // walletInfoData 钱包信息响应data
- type walletInfoData struct {
- Balance float64 `json:"balance"`
- FrozenBalance float64 `json:"frozenBalance"`
- TotalRecharge float64 `json:"totalRecharge"`
- TotalWithdraw float64 `json:"totalWithdraw"`
- TotalTaskIncome float64 `json:"totalTaskIncome"`
- }
- // ---- 核心方法 ----
- // RegisterAndBind 一键注册并绑定
- // 1. 检查是否已绑定 → 已绑定直接返回
- // 2. 调用Vitiens平台OAuth接口注册/登录
- // 3. 在本地创建绑定记录
- func (s *TgPlatformService) RegisterAndBind(telegramId int64, username string, firstName string) (userId int64, isNew bool, err error) {
- bindService := &TgBindService{}
- // 检查是否已绑定
- bound, existUserId := bindService.IsUserBound(telegramId, username)
- if bound {
- return existUserId, false, nil
- }
- // 调用平台OAuth接口
- apiURL := s.getPlatformAPIURL()
- if apiURL == "" {
- return 0, false, errors.New("平台API地址未配置")
- }
- // 构造请求
- nickname := firstName
- if nickname == "" && username != "" {
- nickname = username
- }
- if nickname == "" {
- nickname = fmt.Sprintf("TG_%d", telegramId)
- }
- reqBody := oauthLoginRequest{
- Provider: "telegram",
- OpenId: fmt.Sprintf("%d", telegramId),
- Nickname: nickname,
- }
- reqBytes, err := json.Marshal(reqBody)
- if err != nil {
- return 0, false, fmt.Errorf("序列化请求失败: %w", err)
- }
- // 发起HTTP请求
- url := fmt.Sprintf("%s/dt/auth/oauth/login", apiURL)
- core.Log.Infof("一键注册 - 调用平台API: %s, telegramId: %d", url, telegramId)
- httpReq, err := http.NewRequest("POST", url, bytes.NewBuffer(reqBytes))
- if err != nil {
- return 0, false, fmt.Errorf("创建请求失败: %w", err)
- }
- httpReq.Header.Set("Content-Type", "application/json")
- client := &http.Client{Timeout: 10 * time.Second}
- resp, err := client.Do(httpReq)
- if err != nil {
- return 0, false, fmt.Errorf("请求平台API失败: %w", err)
- }
- defer resp.Body.Close()
- body, err := io.ReadAll(resp.Body)
- if err != nil {
- return 0, false, fmt.Errorf("读取响应失败: %w", err)
- }
- core.Log.Infof("一键注册 - 平台API响应: %s", string(body))
- // 解析响应
- var apiResp platformAPIResponse
- if err := json.Unmarshal(body, &apiResp); err != nil {
- return 0, false, fmt.Errorf("解析响应失败: %w", err)
- }
- if apiResp.Code != 200 {
- return 0, false, fmt.Errorf("平台注册失败: %s", apiResp.Msg)
- }
- var loginData oauthLoginData
- if err := json.Unmarshal(apiResp.Data, &loginData); err != nil {
- return 0, false, fmt.Errorf("解析用户数据失败: %w", err)
- }
- if loginData.User.Id <= 0 {
- return 0, false, errors.New("平台返回的用户ID无效")
- }
- // 创建本地绑定记录
- bind := &entity.TgUserBind{
- UserId: loginData.User.Id,
- TelegramId: telegramId,
- TelegramUsername: username,
- TelegramFirstName: firstName,
- BindStatus: 1,
- BindTime: time.Now(),
- }
- if err := s.DB().Create(bind).Error; err != nil {
- core.Log.Errorf("一键注册 - 创建绑定记录失败: %v", err)
- return 0, false, fmt.Errorf("绑定失败: %w", err)
- }
- // 设置Redis绑定缓存
- ctx := context.Background()
- rdb := redisclient.DefaultClient()
- cacheKey := fmt.Sprintf("tg_bind_cache:%d", telegramId)
- rdb.Set(ctx, cacheKey, fmt.Sprintf("%d", loginData.User.Id), 1*time.Hour)
- core.Log.Infof("一键注册 - 成功, telegramId: %d, userId: %d, isNew: %v",
- telegramId, loginData.User.Id, loginData.IsNew)
- return loginData.User.Id, loginData.IsNew, nil
- }
- // GetUserBalance 查询用户余额(通过平台API)
- func (s *TgPlatformService) GetUserBalance(platformToken string) (*walletInfoData, error) {
- apiURL := s.getPlatformAPIURL()
- if apiURL == "" {
- return nil, errors.New("平台API地址未配置")
- }
- url := fmt.Sprintf("%s/dt/wallet/info", apiURL)
- httpReq, err := http.NewRequest("GET", url, nil)
- if err != nil {
- return nil, fmt.Errorf("创建请求失败: %w", err)
- }
- httpReq.Header.Set("Authorization", "Bearer "+platformToken)
- client := &http.Client{Timeout: 10 * time.Second}
- resp, err := client.Do(httpReq)
- if err != nil {
- return nil, fmt.Errorf("请求失败: %w", err)
- }
- defer resp.Body.Close()
- body, err := io.ReadAll(resp.Body)
- if err != nil {
- return nil, fmt.Errorf("读取响应失败: %w", err)
- }
- var apiResp platformAPIResponse
- if err := json.Unmarshal(body, &apiResp); err != nil {
- return nil, fmt.Errorf("解析响应失败: %w", err)
- }
- if apiResp.Code != 200 {
- return nil, fmt.Errorf("查询失败: %s", apiResp.Msg)
- }
- var walletData walletInfoData
- if err := json.Unmarshal(apiResp.Data, &walletData); err != nil {
- return nil, fmt.Errorf("解析钱包数据失败: %w", err)
- }
- return &walletData, nil
- }
- // GetUserGrabRecords 查询用户抢红包记录(本地数据库)
- // limit <= 0 时返回全部记录
- func (s *TgPlatformService) GetUserGrabRecords(telegramId int64, limit int) ([]entity.TgRedPacketRecord, error) {
- var records []entity.TgRedPacketRecord
- query := s.DB().Where("telegram_id = ?", telegramId).Order("grabbed_at DESC")
- if limit > 0 {
- query = query.Limit(limit)
- }
- err := query.Find(&records).Error
- if err != nil {
- return nil, err
- }
- return records, nil
- }
- // getPlatformAPIURL 获取平台API地址
- func (s *TgPlatformService) getPlatformAPIURL() string {
- telegramConfig := config.EnvConf().Telegram
- if telegramConfig != nil && telegramConfig.PlatformAPIURL != "" {
- return telegramConfig.PlatformAPIURL
- }
- return ""
- }
|