|
@@ -1,25 +1,231 @@
|
|
|
package services
|
|
package services
|
|
|
|
|
|
|
|
import (
|
|
import (
|
|
|
|
|
+ "encoding/json"
|
|
|
|
|
+ "fmt"
|
|
|
|
|
+ "think-go/models"
|
|
|
"think-go/utils"
|
|
"think-go/utils"
|
|
|
"time"
|
|
"time"
|
|
|
|
|
+
|
|
|
|
|
+ "github.com/beego/beego/v2/client/orm" // 确保引入了 orm
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
// SyncDataService 提供对外同步数据调用
|
|
// SyncDataService 提供对外同步数据调用
|
|
|
type SyncDataService struct{}
|
|
type SyncDataService struct{}
|
|
|
|
|
|
|
|
-// SyncDetails 向指定外部接口同步请求详情。
|
|
|
|
|
-// 参数:
|
|
|
|
|
-// - url: 完整请求地址(支持 https)
|
|
|
|
|
-// - userid, authorization: 需要放在请求头的两个字段
|
|
|
|
|
-// - body: 要发送的自定义 JSON 参数(map 或 struct)
|
|
|
|
|
-//
|
|
|
|
|
-// 返回 HTTP 状态码、响应字节和错误。
|
|
|
|
|
|
|
+// ApiResponse 用于解析外部接口的通用外层
|
|
|
|
|
+type ApiResponse[T any] struct {
|
|
|
|
|
+ Code json.Number `json:"code"`
|
|
|
|
|
+ Msg string `json:"msg"`
|
|
|
|
|
+ Data T `json:"data"` // 利用结构体标签自动过滤掉不需要的字段
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func (s *SyncDataService) SyncDetails(url, userid, authorization string, body interface{}) (int, []byte, error) {
|
|
func (s *SyncDataService) SyncDetails(url, userid, authorization string, body interface{}) (int, []byte, error) {
|
|
|
headers := map[string]string{
|
|
headers := map[string]string{
|
|
|
"userid": userid,
|
|
"userid": userid,
|
|
|
"authorization": authorization,
|
|
"authorization": authorization,
|
|
|
}
|
|
}
|
|
|
- // 使用 15s 超时,默认校验证书
|
|
|
|
|
|
|
+ // 注意:此处如果目标服务器证书有问题,建议将最后一个参数改为 true
|
|
|
return utils.PostJSON(url, headers, body, 15*time.Second, false)
|
|
return utils.PostJSON(url, headers, body, 15*time.Second, false)
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+func (s *SyncDataService) SyncDetailsInsecure() (int, interface{}, error) {
|
|
|
|
|
+ url := "https://app-api.aiceanglobal1.com/api/v1/wallet/details"
|
|
|
|
|
+ userid := "0716d0ad7eb6404682fcaf564379e4e8"
|
|
|
|
|
+ authorization := "Bearer 09ec48ab484ea7f8b4fb1d4b125dd73e"
|
|
|
|
|
+ body := map[string]interface{}{}
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 发起请求
|
|
|
|
|
+ status, dataBytes, err := s.SyncDetails(url, userid, authorization, body)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return status, nil, fmt.Errorf("请求接口失败: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 准备两个容器:一个用于过滤入库,一个用于保存原始全量数据
|
|
|
|
|
+ var resp ApiResponse[models.HomeData] // 结构体:利用标签自动过滤多余字段
|
|
|
|
|
+ var rawMap map[string]interface{} // Map:保留所有原始键值对
|
|
|
|
|
+ err = json.Unmarshal(dataBytes, &resp)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return 201, nil, fmt.Errorf("JSON解析失败: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ // 解析原始 Map(为了返回完整数据)
|
|
|
|
|
+ if err := json.Unmarshal(dataBytes, &rawMap); err != nil {
|
|
|
|
|
+ return 201, nil, fmt.Errorf("解析原始Map失败: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ codeInt, _ := resp.Code.Int64()
|
|
|
|
|
+ // 3. 业务状态码校验
|
|
|
|
|
+
|
|
|
|
|
+ if codeInt != 200 {
|
|
|
|
|
+ return 201, resp.Msg, fmt.Errorf("业务返回错误码: %d", codeInt)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 数据加工与入库
|
|
|
|
|
+ // 这里的 wallet 已经是 models.WalletDetail 类型,多余字段已被自动过滤
|
|
|
|
|
+ wallet := resp.Data
|
|
|
|
|
+ wallet.UserId = userid // 手动补全 userId
|
|
|
|
|
+
|
|
|
|
|
+ o := orm.NewOrm()
|
|
|
|
|
+ // 执行插入
|
|
|
|
|
+ _, err = o.Insert(&wallet)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return 500, nil, fmt.Errorf("数据库入库失败: %v", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ // 5. 合并返回内容
|
|
|
|
|
+ // 创建一个大的 Map,把两个对象塞进去
|
|
|
|
|
+ combinedResult := map[string]interface{}{
|
|
|
|
|
+ "filtered": wallet, // 这是根据你的模型过滤后的干净数据
|
|
|
|
|
+ "raw": rawMap["data"], // 这是包含 aiceFeeConfig 等所有字段的原始数据
|
|
|
|
|
+ }
|
|
|
|
|
+ // 返回状态码和解析后的 Data 结构体
|
|
|
|
|
+ return status, combinedResult, nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 首页接口
|
|
|
|
|
+func (s *SyncDataService) SyncHomeData() (int, interface{}, error) {
|
|
|
|
|
+ url := "https://app-api.aiceanglobal1.com/api/v1/dashboard/home"
|
|
|
|
|
+ userid := "0716d0ad7eb6404682fcaf564379e4e8"
|
|
|
|
|
+ authorization := "Bearer 09ec48ab484ea7f8b4fb1d4b125dd73e"
|
|
|
|
|
+ body := map[string]interface{}{}
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 发起请求
|
|
|
|
|
+ status, dataBytes, err := s.SyncDetails(url, userid, authorization, body)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return status, nil, fmt.Errorf("请求接口失败: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 准备两个容器:一个用于过滤入库,一个用于保存原始全量数据
|
|
|
|
|
+ var resp ApiResponse[models.HomeData] // 结构体:利用标签自动过滤多余字段
|
|
|
|
|
+ var rawMap map[string]interface{} // Map:保留所有原始键值对
|
|
|
|
|
+ err = json.Unmarshal(dataBytes, &resp)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return 201, nil, fmt.Errorf("JSON解析失败: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ // 解析原始 Map(为了返回完整数据)
|
|
|
|
|
+ if err := json.Unmarshal(dataBytes, &rawMap); err != nil {
|
|
|
|
|
+ return 201, nil, fmt.Errorf("解析原始Map失败: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ codeInt, _ := resp.Code.Int64()
|
|
|
|
|
+ // 3. 业务状态码校验
|
|
|
|
|
+
|
|
|
|
|
+ if codeInt != 200 {
|
|
|
|
|
+ return 201, resp.Msg, fmt.Errorf("业务返回错误码: %d", codeInt)
|
|
|
|
|
+ }
|
|
|
|
|
+ // 4. 数据加工与入库
|
|
|
|
|
+ // 这里的 wallet 已经是 models.WalletDetail 类型,多余字段已被自动过滤
|
|
|
|
|
+ wallet := resp.Data
|
|
|
|
|
+ wallet.UserId = userid // 手动补全 userId
|
|
|
|
|
+
|
|
|
|
|
+ o := orm.NewOrm()
|
|
|
|
|
+ // 执行插入
|
|
|
|
|
+ _, err = o.Insert(&wallet)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return 500, nil, fmt.Errorf("数据库入库失败: %v", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ // 5. 合并返回内容
|
|
|
|
|
+ // 创建一个大的 Map,把两个对象塞进去
|
|
|
|
|
+ combinedResult := map[string]interface{}{
|
|
|
|
|
+ "filtered": wallet, // 这是根据你的模型过滤后的干净数据
|
|
|
|
|
+ "raw": rawMap["data"], // 这是包含 aiceFeeConfig 等所有字段的原始数据
|
|
|
|
|
+ }
|
|
|
|
|
+ return status, combinedResult, nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 社区发展奖励
|
|
|
|
|
+func (s *SyncDataService) SyncCommunityReward() (int, interface{}, error) {
|
|
|
|
|
+ url := "https://app-api.aiceanglobal1.com/api/v1/reward/develop/home"
|
|
|
|
|
+ userid := "0716d0ad7eb6404682fcaf564379e4e8"
|
|
|
|
|
+ authorization := "Bearer 09ec48ab484ea7f8b4fb1d4b125dd73e"
|
|
|
|
|
+ body := map[string]interface{}{}
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 发起请求
|
|
|
|
|
+ status, dataBytes, err := s.SyncDetails(url, userid, authorization, body)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return status, nil, fmt.Errorf("请求接口失败: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 准备两个容器:一个用于过滤入库,一个用于保存原始全量数据
|
|
|
|
|
+ var resp ApiResponse[models.RewardDevelopData] // 结构体:利用标签自动过滤多余字段
|
|
|
|
|
+ var rawMap map[string]interface{} // Map:保留所有原始键值对
|
|
|
|
|
+ err = json.Unmarshal(dataBytes, &resp)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return 201, nil, fmt.Errorf("JSON解析失败: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ // 解析原始 Map(为了返回完整数据)
|
|
|
|
|
+ if err := json.Unmarshal(dataBytes, &rawMap); err != nil {
|
|
|
|
|
+ return 201, nil, fmt.Errorf("解析原始Map失败: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ codeInt, _ := resp.Code.Int64()
|
|
|
|
|
+ // 3. 业务状态码校验
|
|
|
|
|
+
|
|
|
|
|
+ if codeInt != 200 {
|
|
|
|
|
+ return 201, resp.Msg, fmt.Errorf("业务返回错误码: %d", codeInt)
|
|
|
|
|
+ }
|
|
|
|
|
+ // 4. 数据加工与入库
|
|
|
|
|
+ // 这里的 wallet 已经是 models.WalletDetail 类型,多余字段已被自动过滤
|
|
|
|
|
+ wallet := resp.Data
|
|
|
|
|
+ wallet.UserId = userid // 手动补全 userId
|
|
|
|
|
+
|
|
|
|
|
+ o := orm.NewOrm()
|
|
|
|
|
+ // 执行插入
|
|
|
|
|
+ _, err = o.Insert(&wallet)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return 500, nil, fmt.Errorf("数据库入库失败: %v", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ // 5. 合并返回内容
|
|
|
|
|
+ // 创建一个大的 Map,把两个对象塞进去
|
|
|
|
|
+ combinedResult := map[string]interface{}{
|
|
|
|
|
+ "filtered": wallet, // 这是根据你的模型过滤后的干净数据
|
|
|
|
|
+ "raw": rawMap["data"], // 这是包含 aiceFeeConfig 等所有字段的原始数据
|
|
|
|
|
+ }
|
|
|
|
|
+ return status, combinedResult, nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 代理奖励
|
|
|
|
|
+func (s *SyncDataService) SyncAgentReward() (int, interface{}, error) {
|
|
|
|
|
+ url := "https://app-api.aiceanglobal1.com/api/v1/reward/range/home"
|
|
|
|
|
+ userid := "0716d0ad7eb6404682fcaf564379e4e8"
|
|
|
|
|
+ authorization := "Bearer 09ec48ab484ea7f8b4fb1d4b125dd73e"
|
|
|
|
|
+ body := map[string]interface{}{}
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 发起请求
|
|
|
|
|
+ status, dataBytes, err := s.SyncDetails(url, userid, authorization, body)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return status, nil, fmt.Errorf("请求接口失败: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 准备两个容器:一个用于过滤入库,一个用于保存原始全量数据
|
|
|
|
|
+ var resp ApiResponse[models.RewardRangeData] // 结构体:利用标签自动过滤多余字段
|
|
|
|
|
+ var rawMap map[string]interface{} // Map:保留所有原始键值对
|
|
|
|
|
+ err = json.Unmarshal(dataBytes, &resp)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return 201, nil, fmt.Errorf("JSON解析失败: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ // 解析原始 Map(为了返回完整数据)
|
|
|
|
|
+ if err := json.Unmarshal(dataBytes, &rawMap); err != nil {
|
|
|
|
|
+ return 201, nil, fmt.Errorf("解析原始Map失败: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ codeInt, _ := resp.Code.Int64()
|
|
|
|
|
+ // 3. 业务状态码校验
|
|
|
|
|
+
|
|
|
|
|
+ if codeInt != 200 {
|
|
|
|
|
+ return 201, resp.Msg, fmt.Errorf("业务返回错误码: %d", codeInt)
|
|
|
|
|
+ }
|
|
|
|
|
+ // 4. 数据加工与入库
|
|
|
|
|
+ // 这里的 wallet 已经是 models.WalletDetail 类型,多余字段已被自动过滤
|
|
|
|
|
+ wallet := resp.Data
|
|
|
|
|
+ wallet.UserId = userid // 手动补全 userId
|
|
|
|
|
+
|
|
|
|
|
+ o := orm.NewOrm()
|
|
|
|
|
+ // 执行插入
|
|
|
|
|
+ _, err = o.Insert(&wallet)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return 500, nil, fmt.Errorf("数据库入库失败: %v", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ // 5. 合并返回内容
|
|
|
|
|
+ // 创建一个大的 Map,把两个对象塞进去
|
|
|
|
|
+ combinedResult := map[string]interface{}{
|
|
|
|
|
+ "filtered": wallet, // 这是根据你的模型过滤后的干净数据
|
|
|
|
|
+ "raw": rawMap["data"], // 这是包含 aiceFeeConfig 等所有字段的原始数据
|
|
|
|
|
+ }
|
|
|
|
|
+ return status, combinedResult, nil
|
|
|
|
|
+}
|