Files
kami_backend/.qoder/repowiki/zh/content/API端点参考/风控限制API/IP限制API.md
danial 96ed936079 docs(api): 添加详细Apple卡密管理API文档
- 新增API端点参考文档,涵盖权限、卡密、订单、商户、监控、限制等模块
- 详细说明Apple卡密充值处理流程,包括提交、查询、回调和轮询接口
- 描述充值订单状态机及生命周期,支持超时重试和状态迁移
- 介绍签名验证、幂等控制及重复卡密防刷单策略
- 增加商户配置管理、历史记录查询和错误处理机制说明
- 提供API使用示例代码及客户端实现指导
- 删除过时的.drone.yml.bak文件,清理无用配置
- 添加.dockerignore忽略指定目录和文件
2025-10-08 20:13:40 +08:00

14 KiB
Raw Blame History

IP限制API

**本文档引用文件** - [restriction_v1_check_ip_allowed.go](file://internal/controller/restriction/restriction_v1_check_ip_allowed.go) - [restriction.go](file://internal/service/restriction.go) - [restriction.go](file://internal/logic/restriction/restriction.go) - [v_1_restrict_ip_order_access.go](file://internal/dao/v_1_restrict_ip_order_access.go) - [v_1_restrict_ip_record.go](file://internal/dao/v_1_restrict_ip_record.go) - [entity.go](file://internal/model/entity/v_1_restrict_ip_order_access.go) - [do.go](file://internal/model/do/v_1_restrict_ip_order_access.go) - [restriction.go](file://internal/model/restriction.go) - [restriction.go](file://internal/consts/restriction.go) - [cache.go](file://utility/cache/cache.go)

目录

  1. 简介
  2. 核心功能
  3. IP访问控制端点
  4. IP匹配算法
  5. 缓存策略
  6. 数据库设计
  7. 错误处理
  8. 性能优化
  9. 集成关系
  10. 客户端调用示例
  11. 常见问题

简介

IP限制API提供了一套完整的IP访问控制机制用于管理系统对特定IP地址的访问权限。该系统支持基于商户部署策略的多维度限制包括IP、设备、卡密和代理检测等多种控制方式。系统通过Redis缓存和数据库持久化相结合的方式实现了高性能的IP状态管理。

核心功能

IP限制系统提供以下核心功能

  • IP白名单/黑名单管理
  • 基于省份的区域访问控制
  • 设备级访问限制
  • 卡密关联的访问控制
  • 代理使用检测
  • 访问记录持久化存储

IP限制核心功能组件关系图

graph TD
A[API控制器] --> B[服务接口]
B --> C[业务逻辑]
C --> D[数据访问层]
D --> E[数据库]
C --> F[Redis缓存]
G[商户部署策略] --> C
H[IP匹配算法] --> C
I[访问记录] --> D

图示来源

IP访问控制端点

端点信息

  • HTTP方法: POST
  • URL模式: /api/restriction/v1/check_ip_allowed
  • 认证机制: 基于商户部署ID的认证
  • 权限控制: 通过商户部署策略配置的限制规则

请求参数

请求体包含以下字段:

  • orderNo: 订单号
  • ip: 待检查的IP地址
  • deviceId: 设备ID
  • cardPass: 卡密
  • merchantDeployID: 商户部署ID

响应结构

响应体包含以下字段:

  • isAllowed: 布尔值表示IP是否被允许访问

访问控制流程

flowchart TD
Start([开始]) --> GetStrategy["获取商户限制策略"]
GetStrategy --> StrategyValid{"策略有效?"}
StrategyValid --> |否| ReturnError["返回内部错误"]
StrategyValid --> |是| CheckCardPass["检查卡密限制"]
CheckCardPass --> CardPassRestricted{"卡密受限?"}
CardPassRestricted --> |是| ReturnFalse["返回不允许"]
CardPassRestricted --> |否| CheckDevice["检查设备限制"]
CheckDevice --> DeviceRestricted{"设备受限?"}
DeviceRestricted --> |是| ReturnFalse
DeviceRestricted --> |否| CheckProxy["检查代理使用"]
CheckProxy --> ProxyUsed{"使用代理?"}
ProxyUsed --> |是| ReturnFalse
ProxyUsed --> |否| CheckPublicIP["检查公网IP"]
CheckPublicIP --> IsPublic{"公网IP?"}
IsPublic --> |是| CheckIPExist["检查IP是否受限"]
IsPublic --> |否| CheckInternalIP["检查内网IP策略"]
CheckInternalIP --> RestrictInternal{"限制内网IP?"}
RestrictInternal --> |是| ReturnFalse
RestrictInternal --> |否| ReturnTrue["返回允许"]
CheckIPExist --> IPExist{"IP受限?"}
IPExist --> |是| ReturnFalse
IPExist --> |否| CheckArea["检查区域限制"]
CheckArea --> AreaConfigured{"配置区域?"}
AreaConfigured --> |是| CheckAreaAllowed["检查IP是否在允许区域"]
AreaConfigured --> |否| ReturnTrue
CheckAreaAllowed --> AreaAllowed{"在允许区域?"}
AreaAllowed --> |是| ReturnTrue
AreaAllowed --> |否| ReturnFalse
ReturnTrue --> End([结束])
ReturnFalse --> End

图示来源

本节来源

IP匹配算法

算法实现

IP匹配算法主要通过CheckIPIsAllowedIsInProvince方法实现,其核心逻辑如下:

flowchart TD
Start([开始]) --> ParseIP["解析IP地址"]
ParseIP --> IsPublicIP["判断是否为公网IP"]
IsPublicIP --> |否| ReturnTrue["返回允许"]
IsPublicIP --> |是| GetIPRecord["获取IP记录"]
GetIPRecord --> RecordExist{"记录存在?"}
RecordExist --> |否| ReturnFalse["返回不允许"]
RecordExist --> |是| IsPublic{"公网地址?"}
IsPublic --> |否| ReturnFalse
IsPublic --> |是| CheckProvince["检查省份"]
CheckProvince --> IsAlpha{"英文省份?"}
IsAlpha --> |是| ConvertToPinyin["转换为拼音"]
IsAlpha --> |否| CompareProvince["直接比较"]
ConvertToPinyin --> CompareProvince
CompareProvince --> InProvince{"在允许省份?"}
InProvince --> |是| ReturnTrue
InProvince --> |否| CheckOverseas["检查海外"]
CheckOverseas --> IsOverseas{"是海外?"}
IsOverseas --> |是| ReturnTrue
IsOverseas --> |否| ReturnFalse
ReturnTrue --> End([结束])
ReturnFalse --> End

图示来源

省份匹配逻辑

系统支持34个省级行政区的匹配包括

  • 23个省
  • 5个自治区
  • 4个直辖市
  • 2个特别行政区

匹配时支持中文和拼音两种格式,系统会自动进行转换和匹配。

本节来源

缓存策略

Redis缓存实现

系统使用Redis作为缓存层通过utility/cache/cache.go文件中的Cache结构体实现缓存操作。

classDiagram
class Cache {
+*gcache.Cache
+Incr(ctx, key, duration)
+Decr(ctx, key, duration)
+GetPrefixKeyNum(ctx, key)
+SaveTrace(ctx, key)
+GetTrace(ctx, key)
+GetTraceID(ctx)
+DeleteTrace(ctx, key)
}
class PrefixEnum {
+RedeemType
+RedeemWithPaymentType
+RedeemAppleAccountLimitedType
+AccountLimiterType
+JDAccountQueryCache
+JDAccountQueryBalanceWithCookie
+WalmartAccountQueryCache
+WalmartAccountQueryBalanceWithCookie
+AppleMachineAccount
+AppleDuplicatedOrder
+PrefixTrace
+Key(key)
}
Cache --> PrefixEnum : "使用"

图示来源

缓存键设计

系统采用前缀+键的设计模式,主要缓存键包括:

  • redeem_type: 兑换类型缓存
  • account_limiter_type: 账户限流类型
  • jd_account_query_cache: 京东账户查询缓存
  • walmart_account_query_cache: 沃尔玛账户查询缓存
  • apple_duplicated_order: 苹果重复订单
  • trace: 追踪信息

本节来源

数据库设计

核心表结构

系统使用两个核心表来存储IP限制相关信息

限制IP记录表 (restrict_ip_record)

字段名 类型 描述
id uint 主键
ip string IP地址
ip_province string IP所在省份
is_public bool 是否为公网地址
raw_data string 原始数据
created_at *gtime.Time 创建时间
updated_at *gtime.Time 更新时间
deleted_at *gtime.Time 删除时间

IP订单访问表 (restrict_ip_order_access)

字段名 类型 描述
id uint 主键
restrict_ip_id int 关联的IP地址
order_no string 订单号
card_pass string 卡密
ip string IP地址
status int 状态
restrict_strategy string 限制策略
device_id string 设备ID
created_at *gtime.Time 创建时间
updated_at *gtime.Time 更新时间
deleted_at *gtime.Time 删除时间

表关系

erDiagram
V1RestrictIpRecord ||--o{ V1RestrictIpOrderAccess : "包含"
V1RestrictIpRecord {
uint id PK
string ip
string ip_province
bool is_public
string raw_data
*gtime.Time created_at
*gtime.Time updated_at
*gtime.Time deleted_at
}
V1RestrictIpOrderAccess {
uint id PK
int restrict_ip_id FK
string order_no
string card_pass
string ip
int status
string restrict_strategy
string device_id
*gtime.Time created_at
*gtime.Time updated_at
*gtime.Time deleted_at
}

图示来源

本节来源

错误处理

错误处理机制

系统采用统一的错误处理机制,主要通过errHandler包实现。

sequenceDiagram
participant Client as "客户端"
participant Controller as "控制器"
participant Service as "服务层"
participant Logic as "业务逻辑"
Client->>Controller : 发送请求
Controller->>Service : 调用服务
Service->>Logic : 执行业务逻辑
alt 执行成功
Logic-->>Service : 返回结果
Service-->>Controller : 返回结果
Controller-->>Client : 返回成功响应
else 执行失败
Logic--xService : 抛出错误
Service--xController : 包装错误
Controller-->>Client : 返回错误响应
end

图示来源

错误码

系统定义了以下错误码:

  • gcode.CodeInternalError: 内部错误,当获取限制策略失败时返回

本节来源

性能优化

事务处理

系统在添加IP限制记录时使用数据库事务确保数据一致性

err = config.GetDatabaseV1().Ctx(ctx).Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
    // 事务内的操作
    return nil
})

缓存优化

系统通过Redis缓存频繁访问的数据减少数据库查询次数。

并发处理

在省份匹配时,系统使用并发处理提高性能:

slice.ForEachConcurrent(allProvinceListCopier, func(index int, item string) {
    allProvinceListCopier[index] = gstr.ToLower(pinyin.NewDict().Convert(item, "").None())
}, 5)

本节来源

集成关系

系统集成架构

graph TD
A[前端应用] --> B[API网关]
B --> C[IP限制API]
C --> D[商户部署服务]
C --> E[订单服务]
C --> F[Redis缓存]
C --> G[数据库]
D --> H[配置中心]
E --> I[支付服务]
G --> J[备份系统]
subgraph "核心服务"
C
D
E
end
subgraph "数据存储"
F
G
J
end

图示来源

依赖服务

IP限制API依赖以下服务

  • 商户部署信息服务:获取限制策略
  • 订单服务:更新订单状态
  • Redis服务缓存IP状态
  • 数据库服务:持久化存储访问记录

本节来源

客户端调用示例

Go语言调用示例

// 创建请求
req := &v1.CheckIPAllowedReq{
    OrderNo:         "ORDER123456",
    Ip:              "192.168.1.1",
    DeviceId:        "DEVICE789",
    CardPass:        "CARDPASS001",
    MerchantDeployID: 1,
}

// 调用API
res, err := controller.CheckIPAllowed(context.Background(), req)
if err != nil {
    log.Printf("检查IP失败: %v", err)
    return
}

// 处理结果
if res.IsAllowed {
    fmt.Println("IP允许访问")
} else {
    fmt.Println("IP被限制访问")
}

HTTP调用示例

curl -X POST https://api.example.com/api/restriction/v1/check_ip_allowed \
  -H "Content-Type: application/json" \
  -d '{
    "orderNo": "ORDER123456",
    "ip": "192.168.1.1",
    "deviceId": "DEVICE789",
    "cardPass": "CARDPASS001",
    "merchantDeployID": 1
  }'

本节来源

常见问题

Q1: 如何配置IP白名单

A: IP白名单通过商户部署策略中的RestrictArea字段配置系统会检查IP是否在允许的区域内。

Q2: 内网IP如何处理

A: 系统会检测IP是否为内网IP如果配置了IsRestrictInternalIp为false则允许内网IP访问。

Q3: 如何查看IP限制记录

A: 可以通过GetRestrictRecordByIP方法查询特定IP的所有限制记录。

Q4: 系统如何处理代理?

A: 系统通过CheckIsDeviceUseProxy方法检测设备是否使用代理,如果检测到使用代理且策略要求限制,则拒绝访问。

Q5: 缓存失效时间如何设置?

A: 系统使用Redis默认的缓存策略具体失效时间根据不同的缓存键而定。

本节来源