- 新增API端点参考文档,涵盖权限、卡密、订单、商户、监控、限制等模块 - 详细说明Apple卡密充值处理流程,包括提交、查询、回调和轮询接口 - 描述充值订单状态机及生命周期,支持超时重试和状态迁移 - 介绍签名验证、幂等控制及重复卡密防刷单策略 - 增加商户配置管理、历史记录查询和错误处理机制说明 - 提供API使用示例代码及客户端实现指导 - 删除过时的.drone.yml.bak文件,清理无用配置 - 添加.dockerignore忽略指定目录和文件
14 KiB
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)目录
简介
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: 设备IDcardPass: 卡密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匹配算法主要通过CheckIPIsAllowed和IsInProvince方法实现,其核心逻辑如下:
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默认的缓存策略,具体失效时间根据不同的缓存键而定。
本节来源