✨ 添加TypeScript实现的API签名工具,包括项目配置、命令行工具、核心库及相关文档,支持多种签名算法和环境变量配置。
This commit is contained in:
288
typescript/README.md
Normal file
288
typescript/README.md
Normal file
@@ -0,0 +1,288 @@
|
||||
# API签名工具 - TypeScript实现
|
||||
|
||||
## 项目结构
|
||||
|
||||
根据实际项目文件结构:
|
||||
|
||||
```plaintext
|
||||
typescript/
|
||||
├── src/
|
||||
│ ├── index.ts # 主模块和核心实现
|
||||
│ └── cli.ts # 命令行工具入口
|
||||
├── dist/ # 编译输出目录
|
||||
├── node_modules/ # 依赖包目录
|
||||
├── package.json # 项目配置
|
||||
├── package-lock.json # 依赖锁定文件
|
||||
└── tsconfig.json # TypeScript配置
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 安装依赖
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### 构建项目
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
### 运行命令行工具
|
||||
|
||||
```bash
|
||||
npm start -- [选项]
|
||||
```
|
||||
|
||||
或直接运行编译后的CLI:
|
||||
|
||||
```bash
|
||||
node dist/cli.js [选项]
|
||||
```
|
||||
|
||||
### 命令行选项
|
||||
|
||||
| 选项 | 描述 |
|
||||
|------|------|
|
||||
| `-a, --algorithm` | 签名算法: md5, sha1, sha256, hmac-sha256 |
|
||||
| `-u, --url` | API基础URL |
|
||||
| `-p, --param` | 请求参数,格式为key=value,可多次使用 |
|
||||
| `-k, --key` | 访问密钥ID |
|
||||
| `-s, --secret` | 密钥 |
|
||||
| `-c, --channel` | 合作渠道方ID |
|
||||
| `-h, --help` | 显示帮助信息 |
|
||||
| `-m, --mode` | 操作模式: url, params, verify |
|
||||
| `-j, --json` | 以JSON格式指定参数 |
|
||||
| `-v, --version` | 显示版本信息 |
|
||||
|
||||
### 常用命令示例
|
||||
|
||||
**基本用法**
|
||||
|
||||
```bash
|
||||
node dist/cli.js
|
||||
```
|
||||
|
||||
**自定义参数**
|
||||
|
||||
```bash
|
||||
node dist/cli.js \
|
||||
-u "https://api.example.com/user/info" \
|
||||
-p "userId=12345" -p "action=getInfo" \
|
||||
-k "YOUR_ACCESS_KEY" \
|
||||
-s "YOUR_SECRET_KEY" \
|
||||
-c "3"
|
||||
```
|
||||
|
||||
**使用JSON参数**
|
||||
|
||||
```bash
|
||||
node dist/cli.js -j '{"userId": "12345", "action": "getData"}'
|
||||
```
|
||||
|
||||
**指定签名算法**
|
||||
|
||||
```bash
|
||||
node dist/cli.js -a sha256
|
||||
```
|
||||
|
||||
**生成签名参数**
|
||||
|
||||
```bash
|
||||
node dist/cli.js -m params -p "userId=12345" -p "action=getData"
|
||||
```
|
||||
|
||||
**验证签名**
|
||||
|
||||
```bash
|
||||
node dist/cli.js -m verify -p "userId=12345" -p "action=getData" -p "AccessKeyId=test-key" -p "channelId=test-channel" -p "timestamp=1621234567890" -p "nonce=abc123" -p "sign=calculated-signature-here"
|
||||
```
|
||||
|
||||
**帮助信息**
|
||||
|
||||
```bash
|
||||
node dist/cli.js --help
|
||||
```
|
||||
|
||||
### API接口测试实例
|
||||
|
||||
使用真实API接口进行测试:
|
||||
|
||||
```bash
|
||||
# 未签名的API调用测试 - 返回错误
|
||||
curl "https://api-v1.sound-force.com:8443/p/album/single/media-url?channelId=3&singleId=381980"
|
||||
# 返回: {"code":400,"data":null,"msg":"Missing AccessKeyId","success":false}
|
||||
|
||||
# 生成访问https://api-v1.sound-force.com:8443/p/album/single/media-url的签名URL
|
||||
node dist/cli.js \
|
||||
-a md5 \
|
||||
-u "https://api-v1.sound-force.com:8443/p/album/single/media-url" \
|
||||
-p "singleId=381980" \
|
||||
-k "YOUR_ACCESS_KEY" \
|
||||
-s "YOUR_SECRET_KEY" \
|
||||
-c "3"
|
||||
|
||||
# 使用curl测试API接口
|
||||
signed_url=$(node dist/cli.js \
|
||||
-a md5 \
|
||||
-u "https://api-v1.sound-force.com:8443/p/album/single/media-url" \
|
||||
-p "singleId=381980" \
|
||||
-k "YOUR_ACCESS_KEY" \
|
||||
-s "YOUR_SECRET_KEY" \
|
||||
-c "3" | grep -A 1 "签名后的URL:" | tail -n 1)
|
||||
curl -v "$signed_url"
|
||||
```
|
||||
|
||||
请注意:
|
||||
|
||||
- 替换`YOUR_ACCESS_KEY`为实际的访问密钥ID
|
||||
- 替换`YOUR_SECRET_KEY`为实际的密钥
|
||||
- 示例使用的渠道ID为`3`,请根据实际情况调整
|
||||
|
||||
使用有效的密钥和签名后,API接口将返回成功响应(状态码200)并提供媒体URL数据。
|
||||
|
||||
### Node.js HTTP客户端测试示例
|
||||
|
||||
```javascript
|
||||
const { execSync } = require('child_process');
|
||||
const https = require('https');
|
||||
const url = require('url');
|
||||
|
||||
// 获取签名URL
|
||||
const output = execSync('node dist/cli.js -a md5 -u "https://api-v1.sound-force.com:8443/p/album/single/media-url" -p "singleId=381980" -k "YOUR_ACCESS_KEY" -s "YOUR_SECRET_KEY" -c "3"').toString();
|
||||
const lines = output.split('\n');
|
||||
let signedUrl = '';
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (lines[i].includes('签名后的URL:') && i + 1 < lines.length) {
|
||||
signedUrl = lines[i + 1].trim();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('签名生成的URL:', signedUrl);
|
||||
|
||||
if (signedUrl) {
|
||||
// 解析URL
|
||||
const parsedUrl = url.parse(signedUrl);
|
||||
|
||||
// 创建请求选项
|
||||
const options = {
|
||||
hostname: parsedUrl.hostname,
|
||||
port: parsedUrl.port,
|
||||
path: parsedUrl.path,
|
||||
method: 'GET',
|
||||
rejectUnauthorized: false // 忽略SSL证书验证,仅用于测试
|
||||
};
|
||||
|
||||
// 发送请求
|
||||
const req = https.request(options, (res) => {
|
||||
console.log(`状态码: ${res.statusCode}`);
|
||||
|
||||
let data = '';
|
||||
res.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
|
||||
res.on('end', () => {
|
||||
console.log(`响应内容: ${data}`);
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
console.error(`请求错误: ${error.message}`);
|
||||
});
|
||||
|
||||
req.end();
|
||||
} else {
|
||||
console.error('无法从输出中获取签名URL');
|
||||
}
|
||||
```
|
||||
|
||||
### 代码集成
|
||||
|
||||
```typescript
|
||||
import { ApiSigner, SignOptions, SignatureAlgorithm } from './dist';
|
||||
|
||||
// 创建签名选项
|
||||
const options: SignOptions = {
|
||||
algorithm: SignatureAlgorithm.MD5
|
||||
};
|
||||
|
||||
// 创建签名工具
|
||||
const signer = new ApiSigner(options);
|
||||
|
||||
// 准备请求参数
|
||||
const params = {
|
||||
singleId: '381980'
|
||||
};
|
||||
|
||||
// 执行签名
|
||||
const signedParams = signer.signRequest(
|
||||
params,
|
||||
'YOUR_ACCESS_KEY',
|
||||
'YOUR_SECRET_KEY',
|
||||
'3'
|
||||
);
|
||||
|
||||
// 或签名URL
|
||||
const signedUrl = signer.signUrl(
|
||||
'https://api-v1.sound-force.com:8443/p/album/single/media-url',
|
||||
params,
|
||||
'YOUR_ACCESS_KEY',
|
||||
'YOUR_SECRET_KEY',
|
||||
'3'
|
||||
);
|
||||
|
||||
console.log(signedUrl);
|
||||
```
|
||||
|
||||
### 浏览器使用
|
||||
|
||||
```html
|
||||
<script src="dist/apisign.min.js"></script>
|
||||
<script>
|
||||
const { ApiSigner, SignatureAlgorithm } = window.ApiSigner;
|
||||
|
||||
const signer = new ApiSigner({
|
||||
algorithm: SignatureAlgorithm.MD5
|
||||
});
|
||||
|
||||
const signedUrl = signer.signUrl(
|
||||
'https://api-v1.sound-force.com:8443/p/album/single/media-url',
|
||||
{ singleId: '381980' },
|
||||
'YOUR_ACCESS_KEY',
|
||||
'YOUR_SECRET_KEY',
|
||||
'3'
|
||||
);
|
||||
|
||||
console.log(signedUrl);
|
||||
|
||||
// 使用fetch API测试
|
||||
fetch(signedUrl, {
|
||||
mode: 'no-cors' // 跨域请求设置
|
||||
})
|
||||
.then(response => {
|
||||
console.log('状态码:', response.status);
|
||||
return response.text();
|
||||
})
|
||||
.then(data => {
|
||||
console.log('响应内容:', data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('请求错误:', error);
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
### 环境变量
|
||||
|
||||
该工具支持从`.env`文件加载以下配置:
|
||||
|
||||
- `ACCESS_KEY_ID`: 访问密钥ID
|
||||
- `SECRET_KEY`: 密钥
|
||||
- `CHANNEL_ID`: 渠道ID
|
||||
- `SIGN_ALGORITHM`: 签名算法
|
||||
- `API_BASE_URL`: API基础URL
|
||||
Reference in New Issue
Block a user