front/public/skills/itfx-prefix-script/SKILL.md
zzh 5a26ae0048 feat: 小红书模块迁移、登录重构与 xhs-agent-desktop 桌面 Agent
- 新增小红书前端模块(启动服务、内容分析、爆款创作、发布记录、技能卡片、拟人设置、AI 助手)

- 新增 xhs-agent-desktop 独立桌面 Agent,对接 OMS 任务调度

- 登录页重构,整合微信登录与 OMS JWT 认证

- 订单、渠道、用户中心等页面与 API 增强

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-30 16:13:13 +08:00

209 lines
8.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: itfx-prefix-script
description: >-
Generates InterfaceForward (接口通/itfx) PrefixScript C# for any signature/auth
algorithm (MD5/SHA/HMAC/RSA/custom). Maps writes to Query/Header/Body field lists
per downstream interface detail. Use for 前置脚本, PrefixScript, Natasha script.
---
# itfx 接口映射前置脚本生成(通用签名)
为 **InterfaceMap → PrefixScript** 生成 Natasha 可执行的 C# 方法体,**按用户描述的任意签名规则**实现,不限于某一服务商。
## 何时使用
- 生成/修改 **前置脚本**(非 PostfixScript)
- 第三方 API 需要签名、鉴权头、动态 token、时间戳参与计算等
- OMS「上游接口 → 映射明细 → 前置脚本」
## 执行时机
```
InParamRestructure → ReplacePlaceholder → PrefixScript ← 本 Skill
→ SerializationBody → HTTP 请求 → PostfixScript
```
| 可用 | 不可用 |
|------|--------|
| `obj.OriginalInterfaceMappedInput` | `obj.TargetInterfaceInput`(未序列化) |
| `obj.QueryFieldList` / `HeaderFieldList` / `FormFieldList` | `obj.TargetInterfaceOutput` |
| `obj.FixedFieldList` | 改 `InParamTreeList` / 映射树 |
| `obj.GetAccountFieldValueOrNull(...)` | |
## 下游接口明细 ↔ 运行时(写入位置必对齐)
| 接口明细 Tab | 运行时列表 | 典型用途 |
|--------------|------------|----------|
| Query KV | `obj.QueryFieldList` | URL 参数、签名字段 |
| Header KV | `obj.HeaderFieldList` | 请求头、Authorization |
| Body KV(FormUrlEncoded) | `obj.FormFieldList` | 表单字段 |
| Mapping Body 树 | → `OriginalInterfaceMappedInput` | 映射体(Form/None 类) |
| Request Body 树(Json/Xml) | → `OriginalInterfaceMappedInput` | JSON/XML Body |
**ContentType:** `None(0)` 无 Body;`FormUrlEncoded(1)` Body=FormFieldList;`Json(3)`/`Xml(4)` Body=序列化映射体。
## 占位符(ReplacePlaceholder 早于 PrefixScript)
| 占位符 | PrefixScript 阶段 |
|--------|-------------------|
| `$TimeStamp` / `$DateTime` / `$FromAccount` / `$Url` / `$token` | 通常已替换,直接读字段 Value |
| `$FromMappingBody` | FormUrlEncoded:可能仍为字面量;None/Json Query:通常已替换为 JSON。**签名用最终 HTTP 参数值,不要用占位符字面量** |
## 脚本技术约束
- C#,Natasha 动态编译;参数名 **`obj`**(不是 `context`)
- 仅方法体:无 `using` / `class` / `namespace` / `void Main`
- 类型 **全限定名**:`System.Security.Cryptography.HMACSHA256`、`Newtonsoft.Json.JsonConvert`
- 含 `await` 或首行 `//async` → 异步委托
---
## 通用签名生成流程(任何算法都走此流程)
用户未给全规则时,**先向用户确认**缺失项;给全则直接生成。
### 1. 从需求提取七要素
| 要素 | 问什么 |
|------|--------|
| 算法 | MD5 / SHA1 / SHA256 / HMAC-SHA1 / HMAC-SHA256 / HMAC-MD5 / RSA / 自定义 |
| 签名字符串 | 字段如何拼接、排序、分隔符、是否含 urlPath/body/secret 前缀后缀 |
| 参与字段 | 哪些 Query/Header/Form/Body JSON 字段;**排除签名字段本身** |
| 密钥 | 账户字段名(`GetAccountFieldValueOrNull`)或固定参数 |
| 输出位置 | Query / Header / Form Body / JSON Body 字段名 |
| 编码 | UTF-8;hex **大写/小写**、Base64、是否 URL 编码 |
| 特殊 | 空值是否跳过、嵌套 JSON、时间戳单位、是否 double-MD5 等 |
### 2. 对照下游接口明细
- 签名字段在哪个 Tab → 写入 `QueryFieldList` / `HeaderFieldList` / `FormFieldList` 或改 `OriginalInterfaceMappedInput`
- 参与签名的业务字段在哪个 Tab → 从**对应列表**读取 Value
- 账户字段名与服务商配置一致
### 3. 取参与签名的参数值(通用原则)
**原则:签名字符串中的每个值 = 最终 HTTP 请求里该参数的值。**
```csharp
// 按名读 Query(通用 helper 思路,可内联)
string GetQueryValue(string name) {
for (int i = 0; i < obj.QueryFieldList.Count; i++)
if (obj.QueryFieldList[i].Name == name) return obj.QueryFieldList[i].Value ?? "";
return "";
}
// Header / Form 同理遍历 HeaderFieldList / FormFieldList
// JSON Body(ContentType.Json)
string bodyJson = Newtonsoft.Json.JsonConvert.SerializeObject(obj.OriginalInterfaceMappedInput);
// 映射体 JSON:优先读已替换好的 Query/Form 字段;仍为 $FromMappingBody 时再 SerializeObject
```
**常见坑(任何服务商):**
- 签名字段(`sign`、`_aop_signature` 等)**不参与**签名字符串
- 不要读错列表(Query 参数却在 FormFieldList 里找)
- 不要对已是最终值的字段再 `SerializeObject`(字段顺序/空格会变)
- JSON 内 `"CHINA SHENZHEN"` 与 URL 编码的 `+` **不是同一字符**,签名用 JSON 原文
- FormUrlEncoded 阶段 `$FromMappingBody` 可能尚未替换,需 `SerializeObject(OriginalInterfaceMappedInput)` 或读已替换 Value
### 4. 常见算法 C# 片段(按文档选用,勿臆造)
**MD5 / SHA → hex**
```csharp
var md5 = System.Security.Cryptography.MD5.Create();
byte[] hash = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(signStr));
string sign = System.BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
// 文档要求大写则 .ToUpperInvariant()
```
**HMAC-SHA1 / HMAC-SHA256 → hex**
```csharp
using (var hmac = new System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(secret))) {
byte[] hash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(signStr));
string sign = System.BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
// HMACSHA1 替换 HMACSHA256;文档要 Base64 则 Convert.ToBase64String(hash)
```
**按键排序后 key+value 拼接(多种开放平台通用)**
```csharp
var parts = new System.Collections.Generic.List<string>();
// parts.Add("fieldA" + valueA); 排除 sign 字段
parts.Sort(System.StringComparer.Ordinal);
var sb = new System.Text.StringBuilder();
for (int i = 0; i < parts.Count; i++) sb.Append(parts[i]);
string signStr = sb.ToString(); // 或 prefix + sb + suffix,按文档
```
**secret 包裹式:`secret + params + secret`(1688 等)**
```csharp
string signStr = secret + paramString + secret;
```
**写入 Query / Header / Form(字段名按接口明细)**
```csharp
for (int i = 0; i < obj.QueryFieldList.Count; i++) {
if (obj.QueryFieldList[i].Name == "sign") {
obj.QueryFieldList[i].Value = sign;
break;
}
}
```
### 5. 生成前自检
- [ ] 算法、拼接规则、hex 大小写与**用户/文档**一致(不默认某一种)
- [ ] 读写列表与接口明细 Tab 一致
- [ ] 签名字段未参与计算
- [ ] 仅用 `obj`、全限定名、无 `using`
- [ ] 空密钥有抛错或明确处理
---
## 示例(仅参考,生成时以用户需求为准)
### 示例 A:HMAC-SHA1 + urlPath + 排序 param(阿里国际站 AOP 一类)
- 拼接:`urlPath + sort(key+value)`,不含签名字段
- 输出:Query `_aop_signature`,小写 hex
- 参数在 **QueryFieldList**;JSON 优先读 `notifyBizEventDTO` 的 Value
### 示例 B:MD5 + secret 包裹 + 排序 keyvalue(1688 一类)
- 拼接:`appSecret + key1val1key2val2... + appSecret`
- 输出:Query/Form 的 `sign`,常为大写 hex
### 示例 C:HMAC-SHA256 + Header
- Body 用 `SerializeObject(OriginalInterfaceMappedInput)` 参与拼接
- 输出:`HeaderFieldList` 的 `X-Sign` 或 `Authorization`
### 示例 D:JSON Body 内写字段
- `obj.OriginalInterfaceMappedInput["sign"] = sign;`
更多代码模式见 [examples.md](examples.md)。
---
## 输出要求
只输出一个 ```csharp 代码块(Natasha 方法体),不要额外解释。
## 禁止事项
- 不要用 `HttpClient` 再发请求
- 不要改 `InParamTreeList` / `OutParamTreeList`
- 不要用 `TargetInterfaceInput`
- 不要输出 Python/JavaScript
- 不要写 `using`;不要用 `context`
- 不要把 Query/Header 签名写到 `FormFieldList`
- **不要**在未确认文档时硬编码某一服务商的算法(如默认阿里 HMAC-SHA1)
- 不要把签名字段放进待签名字符串