Metadata-Version: 2.4
Name: xfcloudcard
Version: 1.0.0
Summary: 云控卡密验证客户端库 - 支持 AES+HMAC 加密通信、心跳保活、离线上报
Author: songxf
License-Expression: MIT
Project-URL: Homepage, https://github.com/songxf/xfcloudcard
Project-URL: Source, https://github.com/songxf/xfcloudcard
Project-URL: Issues, https://github.com/songxf/xfcloudcard/issues
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.25.0
Requires-Dist: pycryptodome>=3.15.0

# xfcloudcard

云控卡密验证客户端库，支持 AES-256-CBC + HMAC-SHA256 加密通信、心跳保活、离线上报、**卡密过期回调**。

## 安装

```bash
pip install xfcloudcard
```

## 快速开始

### 方式一：上下文管理器（推荐）

```python
from xfcloudcard import CardClient

def on_expire():
    print("卡密已过期！")

with CardClient(
    server_url="http://localhost:8000",
    key="your-key",
    on_expire=on_expire,   # 卡密过期时自动调用
) as client:
    result = client.verify("CARD-XXXX-XXXX-XXXX-XXXX")
    if result['success']:
        # 业务代码写这里
        pass
# 退出 with 块时自动停止心跳 + 发送离线通知
```

### 方式二：装饰器

```python
from xfcloudcard import require_card

@require_card(
    server_url="http://localhost:8000",
    key="your-key",
    on_expire=lambda: print("卡密过期！"),
)
def main():
    # 仅当卡密验证通过后才执行
    print("验证通过，执行业务逻辑...")

main()
```

### 方式三：命令行

```bash
# 交互模式
xfcloudcard

# 直接验证
xfcloudcard --card CARD-XXXX-XXXX-XXXX-XXXX

# 只验证，不启动心跳
xfcloudcard --card CARD-XXXX-... --once
```

## API

### `CardClient(server_url, key, heartbeat_interval=60, on_expire=None)`

| 参数 / 方法 | 说明 |
|------|------|
| `server_url` | 服务器 URL，默认 `http://localhost:8000` |
| `key` | 加密密钥（必须与服务器端相同） |
| `heartbeat_interval` | 心跳间隔秒数（默认 60） |
| `on_expire` | **卡密过期时的回调函数**（可选） |
| `verify(card_key)` | 验证卡密，成功后自动启动心跳 |
| `verify_only(card_key)` | 只验证，不启动心跳 |
| `close()` | 停止心跳并发送离线通知 |
| `is_online()` | 返回心跳是否运行中 |

**`on_expire` 回调行为：**
- 心跳线程检测到卡密剩余时间 `<= 0` 时自动触发
- 触发后自动停止心跳
- 回调函数抛出异常不会影响主流程

### `require_card(server_url, key, heartbeat_interval=60, exit_on_fail=True, on_expire=None)`

装饰器，在业务函数执行前自动验证卡密。

## 卡密过期处理

方案：心跳线程自动检测过期，触发 `on_expire` 回调。

```python
def my_handler():
    print("卡密已过期，请续费！")
    # 可以设置标志位让业务代码优雅退出

with CardClient(..., on_expire=my_handler) as client:
    result = client.verify("CARD-XXXX-...")
    # 业务代码正常运行
    # 到期后 my_handler 会被自动调用
```

## 依赖

- `requests >= 2.25.0`
- `pycryptodome >= 3.15.0`

## 协议

MIT
