API v1.0.0 · PX兑换枢纽 · 统一身份认证 · 语音合成 · 图片/视频生成 · 渠道商管理 · 自定义模型(BYOK) · ← 返回首页
所有 API 通过 HTTPS 访问,认证方式:Bearer Token(用户API)或 HMAC-SHA256 签名(开放平台 API)。
# Bearer Token 示例 curl -H "Authorization: Bearer <token>" \ https://platform.ciyuanfun.cn/api/v1/org/stories # HMAC-SHA256 签名(开放平台 /open/v1/*) # 参见下方"签名算法"
{"username","password","display_name"}curl -X POST https://platform.ciyuanfun.cn/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"123456","display_name":"测试"}'{"username","password"}curl -X POST https://platform.ciyuanfun.cn/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"123456"}'curl -X POST https://platform.ciyuanfun.cn/api/v1/org/voices/clone \ -H "Authorization: Bearer <token>" \ -F "audio=@sample.wav" \ -F "name=my_voice"
qwen3-tts-vc-2026-01-22curl -X POST https://platform.ciyuanfun.cn/api/v1/org/tts/synthesize \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"text":"你好世界","voice_id":"xxx"}'{"prompt","model","quality","size","category"};category 可选(general/character/scene/prop/voice),声明这张图的用途,落库进 cy_assets.category,缺省 general;seedream-5.0-flash(2k·3k·4k / 2 分,最便宜,默认)、seedream-5.0-lite(2k·3k·4k / 3 分)、seedream-4.5(2K·4K / 3 分)、seedream-4.0(标准档 / 3 分)、qwen-image-3.0(标准档 1k / 3 分,阿里百炼 DashScope);qwen-image 仍兼容,服务端归一为 seedream-5.0-flash;ceil(厂价×1.2×10),以 GET /org/pricing/image-models 实际返回为准;size 支持 1:1/4:3/3:4/16:9/9:16/3:2/2:3。返回 asset_id + 图片 URL;生成或保存失败自动退款。curl -X POST https://platform.ciyuanfun.cn/api/v1/org/generate/image \
-H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
-d '{"prompt":"海边日落","model":"seedream-4.5","quality":"2K","size":"16:9"}'page/size/type(image/audio/video)/cat(general/character/scene/prop/voice/none);data 素材数组(id/name/asset_type/file_size/tags/channel_id 等)。cat 过滤 category 列(2026-11-02 起分类独立成列,不再解析 tags JSON;AI 生成图的历史 tags 是数组,原先永远归不了类);none = category IS NULL。category 字段,前端可直接渲染分类徽标/下拉。/org/assets/file/:id 访问。<img>/<video> 直链;Range(返回 206),视频可拖进度条;application/octet-stream,服务端按扩展名兜底(如 .mp4→video/mp4),避免视频播不出来;?sig=&exp= 时按签名校验(供第三方 AI 拉图)。file 文件、name 名称、asset_type(image/audio/video,缺省按 MIME 嗅探与扩展名推断,且实际类型优先:客户端传错会被纠正,如 mp4 标成 image 会落 video)、category(general/character/scene/prop/voice,可选;不传则回退解析 tags.$.category)、tags JSON 串;data.id 与 download_url(即 /org/assets/file/:id),可直接用于分镜视频挂载;client_max_body_size 50m 限制,超限会返回 413(HTML,非 JSON)。{"name":"...","description":"...","category":"scene"};category 限 general/character/scene/prop/voice,传空串 "" 表示清除分类(回到「未分类」),传其它值返回 400;{"data":{"id":N,"category":"scene"}}。curl -X PATCH https://platform.ciyuanfun.cn/api/v1/org/assets/100 \
-H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
-d '{"category":"scene"}'2026-11-01(P192–P193)落地:把模型配置从代码搬进数据库。一条通道 = 某个模型的一条实际出路(厂商 + 接入点 + 密钥 + 协议模板 + 启停 + 优先级)。停用即拒单,不回落硬编码;新增模型时勾「自动算价」可一条龙建价。管理端入口:admin.ciyuanfun.cn → 定价/模型 → 通道管理。
kind(image/video,可选);data.list:id/kind/model_key/platform_alias/provider/mode/base_url/model_id/endpoint_id/credential_id/protocol_id/enabled/priority/price_hint/extra;platform_alias 是对外请求用的模型名(如 seedream-5.0-flash),model_key 是定价主键,两者可能不同。id 即更新,否则新增):{
"kind": "image", // 必填 image|video
"model_key": "seedream-5.0-flash", // 必填,定价主键
"platform_alias": "seedream-5.0-flash",// 对外模型名
"provider": "volc", // 必填
"mode": "native", // 缺省 native
"model_id": "doubao-seedream-5-0-flash-260915", // 必填
"endpoint_id": "ep-2026...", // 火山接入点
"base_url": "https://ark.cn-beijing.volces.com/api/v3",
"credential_id": 3,
"protocol_id": 1, // 必填,须与 kind 同模态
"enabled": 1, "priority": 0,
"price_hint": 0.12,
"extra": {"key_env":"VOLC_IMG_API_KEY_FLASH","test_quality":"2k"},
"auto_price": true, // 勾了才建价
"factory_cost": 0.12, // 厂价(元/张),auto_price=true 时必填
"pricing_name": "Seedream 5.0 Flash", // 定价表显示名
"qualities": [{"value":"2k","credits_per_image":2}]
}
自动算价:公布价(积分) = ceil(厂价(元) × 1.2 × 10),例 0.12 元→2 分、0.22 元→3 分;写入/更新定价表后返回 auto_credits。{"data":"ok","id":N,"auto_credits":2}。enabled=0,立即拒单;?purge=1:硬删除。若 cy_assets.channel_id 仍引用该通道,返回 409 并附 assets 数量,提示改为停用;{"prompt":"一只橘猫,写实摄影","ratio":"1:1","quality":"2k"};extra.test_quality,再兜底 2k —— seedream 5.0-lite / 4.5 上游要求 size ≥ 3686400 像素,写死 standard(1024²) 必被拒,会误判「通道坏了」;4.0 这类老模型则要在 extra 里写 test_quality:"standard"。kind=image,video 返回 400。id/code/name/kind/is_builtin + submit(提交 URL/方法/headers/body 模板 + 超时)、submit_parse(响应字段映射,如 data[0].url)、query/query_parse(异步查询,图片同步为空)。volc_image「火山方舟 文生图(同步)」→ {{base_url}}/images/generations。kind(image/video) 可过滤。data.list:[{code,label,base_url,protocol_code,models:[{kind,platform_alias,display_name,model_id,endpoint_id,factory_cost,published_credits,qualities,size_options,key_env,fallback_key_env,credential_note,test_quality,note}]}]pricing_rule:markup=1.2、credits_per_yuan=10、formula 与算例,前端据此实时显示「厂价 → 公布价」。qwen-image-3.0 仅登记(协议未适配)。id/name/provider/masked/enabled/created_at;不返回明文,只给 masked(如 ark-5a08****)供辨认。{"name":"volc-flash","provider":"volc","secret":"ark-xxxx"},三者必填;name 唯一:同名即覆盖并重新启用(用于轮换密钥,不必先删);MAM_VERIFY_KEK_FILE 指向的 KEK,缺失会返回 500 并提示检查该环境变量;{"data":{"name":...,"masked":...}}。密钥落库后通道按 credential_id 引用,业务代码不接触明文。三张表:cy_model_channels(路)、cy_model_credentials(密钥,secret_enc 密文 + masked 掩码)、cy_channel_protocols(协议模板)。
缓存:增删改通道后服务端自动 InvalidateChannelCache(),无需重启;但 gateway_allocations 类配置仍需重启。
seedance-2.0 / seedance-2.0-fast / seedance-2.0-mini(火山方舟,支持文生/多图参考/首尾帧)、happyhorse(阿里百炼,仅多图参考);mode: text2video文生视频(默认)/ multi_ref多图参考 / first_last_frame首尾帧;resolution 480p/720p/1080p;时长: duration 2-12 秒整数(选几秒出几秒);比例: ratio 16:9/9:16/1:1/4:3/3:4/21:9/adaptive(HappyHorse 仅固定比例,adaptive 自动转 16:9)。ref_images(公网 HTTP 图片 URL:多图参考 1-9 张;首尾帧第 1 张=首帧必填、第 2 张=尾帧可选;如素材库 /api/v1/org/assets/file/:id)。queued排队 / running生成中 / succeeded完成 / failed失败(含原因)curl -X POST https://platform.ciyuanfun.cn/api/v1/org/videos \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"prompt":"海浪拍打礁石","model":"seedance-2.0-mini","resolution":"480p","duration":4,"ratio":"16:9"}'file;文件类型由 magic bytes 判定,不认扩展名。qwen-vl-ocr(base64 data URL,prompt 固定为 "OCR");音视频 paraformer-v2(DashScope 临时 OSS 上传 + 异步任务,ffmpeg 抽 16k 单声道音轨)。{"success":true,"kind":"image|video|audio","text":"...","chars":79};无人声 {"success":true,"noSpeech":true}。UNSUPPORTED_TYPE / 413 TOO_LARGE / 400 NO_AUDIO / 429 BUSY / 429 RATE_LIMIT / 400 USE_FRONTEND_PDF。
# 图片 OCR curl -X POST https://platform.ciyuanfun.cn/api/v1/org/import/extract \ -H "Authorization: Bearer <token>" \ -F "file=@cover.png" # 视频转写 curl -X POST https://platform.ciyuanfun.cn/api/v1/org/import/extract \ -H "Authorization: Bearer <token>" \ -F "file=@clip.mp4"
word/document.xml;PDF 用 pdf.js 抽文字层,文字量 ≥20 字判定为文本 PDF。/extract,每批 10 页。"角色名"对白内容 自动拆分为分镜curl -X POST https://platform.ciyuanfun.cn/api/v1/org/stories \
-H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
-d '{"title":"新故事","script":"场景1描述...\\n\\"我\\"这是我的对白"}'video=视频文件、after=分镜序号;{"video_url":"/api/v1/org/assets/file/26","after":1},只引用 URL 不转存。video_url 仅放行 http(s):// 与站内 / 开头地址(拦截 javascript:/data:///外域),否则 400;after 指定分镜之后新建分镜并挂该视频,返回新分镜 id/panel_no/video_url。curl -X POST https://platform.ciyuanfun.cn/api/v1/org/stories/17/panels/insert-video \
-H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
-d '{"video_url":"/api/v1/org/assets/file/26","after":1}'duration(自动/5/10/15)、ratio(16:9/9:16/1:1)curl "https://platform.ciyuanfun.cn/api/v1/org/stories/17/video?duration=auto&ratio=16:9&resolution=720p" \ -H "Authorization: Bearer <token>"
panel_nos(逗号分隔的分镜序号,控制拼接顺序,如 4,3,2,1 倒序;缺省按序号升序)curl "https://platform.ciyuanfun.cn/api/v1/org/stories/22/video/concat?panel_nos=1,2,3,4" \ -H "Authorization: Bearer <token>"
把「我的作品」里的故事按系列 / 客户归入项目组。参照 aigc iw_comic_groups 的分组语义,只补分组层,不搬漫剧四步向导;一个作品只属于一个组,删除项目组只解绑,绝不删作品。P222 起项目组升级为协作单元:全站成员可自由加入,组内成员互见素材与作品,详见「🧩 项目组协作」。
cy_project_groups(group_id = cg_YYYYMMDD_xxxx、user_id、name、description、cover、status、is_deleted)+ cy_project_group_items(uk_story 唯一键保证一作品一组)+ P222 cy_project_group_members(成员关系)。不改 cy_stories 表结构,避免打断它的 _bak_* 备份表。
GET /api/v1/org/stories 新增可选 group_id / ungrouped=1 / limit≤100(默认仍 LIMIT 20),每条返回 group_id / group_name / owner_id / shared;POST /api/v1/org/stories 可带 group_id 建完直接归组(P222 放宽为「我创建或已加入的组」)。
所有查询恒带 user_id,跨用户一律 404;封面 URL 只放行站内 / 或 https。用户端入口:我的作品 → 新建项目组 / 分组条 / 卡片「移动到项目组」;后台入口:项目组(P221 起完整管理;P222 增成员查 / 加 / 移除)。
项目组由首提者建立并任组长,全站登录成员可自由选择加入;组内成员可见彼此归到该组的六类素材 + 作品(只读可见可复用,写 / 删仍限属主)。创建素材 / 故事时在编辑框里直接选归属,默认「私有」,下拉分「我的项目组」(我创建 / 已加入)与「全站项目组」(选中后自动加入)两组,右侧「+」可就地新建组;故事表单只列私有 / 项目组(作品无 global 语义)。P223 起全站正常项目组在创建弹窗里直接可选,选中即自动加入并归属。
cy_project_group_members(uk_group_user(group_id,user_id)、role=owner/member、status)独立成表,不改 cy_project_groups / cy_stories / 任何素材表;建组即补 owner 行,存量组按 user_id 幂等回填。GET /org/asset-scopes/options 的 groups 仍=我创建的 ∪ 我已加入的(供归属筛选 / 单条 / 批量弹窗消费),并返回 role;P223 新增 joinable =全站 status=1、非我创建且我未加入的组(含 member_count / owner_name),只在创建弹窗渲染。选中未加入组时前端先 POST /join(幂等+审计)再落归属,故事创建链路同样前置 join。P224 起,所有创建弹窗在打开瞬间强制刷新候选组,登录 / 建组 / 加入后的状态变化无需刷新页面即可在下拉里生效。
列表可见性 = (自己名下) OR (scope='global') OR (scope='group' AND 我 status=1 在该组成员表);作品列表按 cy_project_group_items JOIN 成员表,返回 owner_id / shared。只有 global 与 group 改变可见性,work 仍是归类筛选。文件读取对 group 素材要求属主 / 有效组员 / sig 签名链接,其余维持历史行为。
归档组不可加入、组长不可退出、组长不可被移除;退出 / 移除不删任何资产,只把当事人自己的归组映射与作品解绑。所有写操作落 audit_logs:project_group_join / leave / member_remove / member_admin_add / member_admin_remove。后台入口:🗂️ 项目组 → 成员(查 / 加 / 移除)。
素材库 6 个 tab(角色库 / 场景库 / 道具库 / 音色库 / 视频库 / 素材超市)与作品统一支持四级互斥单选归属:private 私有(默认)、global 全局(全站登录用户可见)、group 项目组、work 作品。P222 起 global 与 group 都改变可见性(global=全站登录可见;group=组内有效成员可见);work 仍是归类与筛选维度。
归属独立存 cy_asset_scopes(uk_asset(asset_kind,asset_id)),不改任何原素材表结构;无映射记录即私有,因此存量素材零改动、零曝光。存量归属由组创建者 / 属主自主决定,系统不做批量迁移。
asset_kind 六值:asset / character / scene / prop / voice / video;scope 四值:private / global / group / work。列表可见性 = (自己名下) OR (scope='global') OR (scope='group' AND 我是该组有效成员),再叠加 scope 筛选条件;子查询别名统一 ascope。
所有归属写操作落 audit_logs:asset_scope_set / asset_scope_reset / project_group_admin_create / project_group_admin_update / project_group_admin_delete。跨用户设置一律 404;group 校验「组属于该属主 或该属主已加入该组」、work 校验作品属于该属主;options 的候选组=我创建的 ∪ 已加入的。
用户端入口:素材库任一 tab → 归属筛选条 / 卡片「归属」按钮 / 批量设置(切 tab 显式重置筛选);后台入口:🎯 素材归属(清单、设为全局、下架回私有、清除映射)+ 🗂️ 项目组(组内素材、完整管理)。
gen_model、gen_ratio 外,另返回 asset_model / asset_size:按 image_url 关联 cy_assets,从资产名「摘要 · 模型 · 尺寸」解析出的实际出图模型与像素尺寸。/stories/:id/scenes)、道具(/stories/:id/props)三个列表均已返回这两个字段。库内 gen_model 是前端下拉框当时的取值,换模型生成时不会回写,曾有 7 条与实际出图模型不符(库内记 seedream-5.0-flash,实际是 qwen-image 或 seedream-5.0-lite);前端展示以 asset_model 为准,取不到(老平台链接、上传图)再退回 gen_model,仍空则不显示该行。gen_model 已按资产名落库改正(角色 38/40/41、场景 14/15、道具 13/14);② 模型名统一用正名——早期记录里的旧别名 qwen-image / qwen-image-2.0 读取时归一为 qwen-image-3.0(与定价表主键、通道 platform_alias、前端下拉同名);③ 卡片文本一律显示「✨ 提示词:…」:取值以 gen_prompt 为准,历史记录没有 gen_prompt 的退回描述字段(角色 features / 场景·道具 overview),不再出现「描述」与「提示词」两种表述混显;素材超市卡片同样统一带「提示词:」标签。date_from/date_to(YYYY-MM-DD,默认近 14 天,区间 ≤366 天);返回每日 credits_consumed 列表与 total_consumed。渠道商只看自己名下用户。{"user_id":68,"amount":10};校验用户归属,余额不足拒绝。data(待编码文本,≤512 字符)、size(80~512,默认 150);返回 image/png+Cache-Control: max-age=86400。公开接口,只把传入文本编码成图片、不读任何业务数据。api.qrserver.com 在境内实测 1540ms(本机 4.45s),抖动即空白,导致 admin 后台与渠道商面板的二维码「同时消失」。已用 jsQR 解回原文验证。page/page_size/keyword/status/reseller_id;超管可按 reseller_id 筛选(0=none 未绑定),渠道商强制只看自己名下。返回含 credits 余额与 reseller_name。{"phone":"13900000000","password":"123456","username":"可选","email":"可选","reseller_id":"超管可选"};自动生成钱包;渠道商创建自动归属自己。{"amount":100,"description":"活动赠送"};amount 为正加负扣,写 admin_adjust 流水(不计入消耗统计)。{"users":[{"phone":"13900000001","password":"123456","username":"可选","email":"可选"}]};返回 success_count/fail_list。{"name","enabled":0|1,"qualities":[...],"sizes":["1:1","16:9",...],"factory_cost","published_price"};enabled=0 停用后用户端不再显示该模型,sizes 控制生图尺寸选项。{"name","enabled":0|1,"credits_rule":{"720p":15},"sizes":[...],"modes":["text2video","multi_ref","first_last_frame"],"durations":[4..12],"factory_cost","published_price"};modes 控制该模型在视频工坊可选模式,sizes/durations 控制尺寸与时长选项,enabled 控制启用/停用。以上字段均支持独立提交(快捷启用/禁用按钮只传 enabled)。统一认证生态(MaM + PX + 各合作平台)的管理入口。渠道商体系 2026-08-16 落地:admin.ciyuanfun.cn(root=/www/wwwroot/mam-admin)→ 302 → login.html(双 tab:🏢超管 / 🔑渠道商)→ 超管跳 index.html、渠道商跳 reseller-panel.html(独立控制台)。账号存 id_auth.cy_admins(role=super|reseller),创建/改密/删除渠道商自动同步该表。nginx 对 login/reseller-panel 加 no-cache 头。
{"username","password"}。bcrypt 校验 + JWT,返回 role(super/reseller)、token、name。超管初始账号 admin/Admin@2026!。渠道商登录后仅可访问 /admin/reseller/me* 与 /admin/users*,其余 403。X-Mam-Admin-Key(超管)。ref_type='admin_adjust')。ref_type='px_exchange' 或 ref_type='admin_adjust' 且描述含"PX兑换"、amount>0),排除现金充值。供 PX 端消费进度(/api/gateway/credits/{username})调用。返回 {"success":true,"user_id":5,"px_exchange_total":2}。鉴权:X-Mam-Admin-Key。{"user_id":N,"amount":N,"description":"可选"};校验用户归属自己名下 + 渠道商积分池余额充足,不足拒绝。{"old_password","new_password"};校验旧密码,双写 cy_admins/cy_resellers。rate(默认 1 元=1 积分)。curl https://platform.ciyuanfun.cn/api/v1/wallet/recharge/plans \ -H "Authorization: Bearer <token>"
plan_id(选套餐)或 amount_fen(自定义金额,单位分)。返回 out_trade_no、code_url(二维码内容)、credits。用 code_url 生成二维码供用户扫码。curl -X POST https://platform.ciyuanfun.cn/api/v1/wallet/recharge \
-H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
-d '{"plan_id":1}'out_trade_no。返回 data.status:paid/SUCCESS=已支付,CLOSED/PAYERROR/REVOKED=失败。前端据此弹成功/失败框。curl "https://platform.ciyuanfun.cn/api/v1/wallet/recharge/status?out_trade_no=RCGxxxx" \ -H "Authorization: Bearer <token>"
balance。curl https://platform.ciyuanfun.cn/api/v1/wallet/balance \ -H "Authorization: Bearer <token>"
way_text 分为「充值 / 平台转入 / 其他转入」,含积分数值与获得时间(前端不展示人民币)。curl https://platform.ciyuanfun.cn/api/v1/wallet/account/income \ -H "Authorization: Bearer <token>"
money(充值记录:金额/到账积分/退款状态 + 充值总额/已退/可退,人民币)与 credits(当前积分余额 + 全量流水:充值/消费/退款扣回/赠送等,含余额快照)。充值页「账户详情」数据源。{"direction":"mam_to_px"|"px_to_mam","amount":N}。规则:① 双向 ② 比例 1:1(PX 1 = 人民币 1 元 = Mam 1 积分)③ 手续费 1% 以 Mam 计价,最低 1 Mam(mam_to_px 扣 amount+手续费;px_to_mam 到账 amount-手续费)④ 不做提现。底层走 PX 平台转账(平台 PX 资金池地址=market_config.platform_px_address),本地写 px_exchange 流水,转账失败自动回滚。refundable、refund_fen(可退金额/分)、refund_credits(扣回积分)、reason(不可退原因)。规则:仅已支付且未退款订单;无消费全额退;有消费扣除净消费额 15%;消费占比 ≥85% 不予退款。{"reason":"退款原因"}(必填)。微信受理成功后事务内扣回积分并写流水(type='recharge_refund');订单进入 refunding,由 60s 定时器查询微信退款单最终状态:SUCCESS→refunded,异常→自动回加积分+failed(可重试)。每单仅退一次。PX 作为统一认证生态的积分兑换枢纽/清算所:兑换(px→积分)=消费语义、无手续费;退款(积分→px)=退给自己、99% 到账、1% 手续费进 owner 资金池;支持 targetUsername 跨用户互换(对方付积分、你付 PX)。数据真相源为 users_backend.json 账本。2026-08-26 三模式路由:① api=伙伴端真实入账(MaM,调伙伴 API 真实发放积分);② gateway=平台内托管积分包(DeepSeek/文心/通义/智谱/hy3/Kimi 共 6 个大模型伙伴,scenarios 选包 → 扣 PX → 写入 gateway 托管积分 → 可在 AI 网关 /api/gateway/chat 消费);③ none=暂未接入(银行/电信/南航/麦当劳/莱美等生活积分,仅登记、暂不真实发放)。汇率口径:rate = 1 PX 兑换的目标平台 credit 数量(如 DeepSeek 1PX→30万 DS Credits、电信 1PX→100 积分);模式 C 按真实官方比例校准(中行500/电信100/南航10/麦当劳10/莱美10)。移动端"消费进度"综合 MaM 兑换 + gateway 托管积分(已获得/可用/已消费)。
id=18 已启用(rate=1.0,apiEndpoint=MaM 管理积分接口 + apiKey)。6 个大模型伙伴恢复 apiKey 并支持 gateway 积分包:DeepSeek(id=1)/文心(id=2)/通义(id=3)/智谱(id=5)/Tencent-hy3(id=15)/Kimi(id=17),scenarios 字段含可选积分包(如 ds_free: 1PX→30万 DS Credits、hy_standard: 5PX→500万 hy_credits)。{"username":"发起方","partnerId":N,"amount":N,"direction":"consume"|"refund","scenarioId":"ds_free"(仅 gateway),"targetUsername":"目标用户"}。api(配 apiEndpoint,如 MaM):跨用户时查目标方积分余额(不足拒「目标用户积分不足」)→ 扣目标方积分 → 发起方得积分 → PX 双向过户 → 记 exchange(consume);② gateway(有 scenarios 包,如 DeepSeek/hy3/Kimi):校验 PX 余额 ≥ 包 pxCost → 扣 PX → GatewayController.addCredits 写入该用户平台托管积分 → 记 exchange(direction=buy, scenarioId, credits)(失败回滚 PX);2026-09-05 起支持任意数量购买:不传 scenarioId 时按 amount × rate 折算入账(quota=floor(amount×rate)),前端"兑换数量(px)"模式;传积分包仍要求 amount 恰等于包价;③ none:返回「该积分类型暂未接入」。refund 仅 api 模式支持。curl -X POST .../api/exchange/redeem -d '{"username":"花猫妹妹","partnerId":18,"amount":5,"direction":"consume","targetUsername":"oldworker"}' 示例-买 DeepSeek 包:curl -X POST .../api/exchange/redeem -d '{"username":"王五","partnerId":1,"amount":1,"direction":"consume","scenarioId":"ds_free"}'{"success":true,"username":"王五","balance":989}。账本(users_backend.json)是运营真相源;链上余额(/api/point/balance/{addr})另作补真账轮次。PX 前端 points.js 与 MaM 端 PXBalance 均以此接口为显示口径。/api/v1/admin/users/{id}/px-exchange-total 返回已兑换 Mam 积分(usedCredits);② gateway 伙伴:读平台托管积分(gateway_allocations.json)返回 totalCredits/usedCredits/可用。返回示例:{"success":true,"username":"王五","partners":[{"partnerName":"MaM AI 漫剧","creditUnit":"Mam","rate":1.0,"usedCredits":146},{"partnerName":"DeepSeek","creditUnit":"DS Credits","rate":300000,"totalCredits":300000,"usedCredits":0}]}。移动端"消费进度"卡片数据源。direction(consume/refund)、fromUsername(发起方)、toName(目标用户)、partnerName(积分平台名)、amount(源数量)、credits(到账/获得)、rate、fee(仅退款)。入口名 alias → 上游模型 1 PX 应得 备注 DS ds → deepseek-v4-flash 13 万 套餐 ds_free(1PX)/ds_standard(5PX) WenXin wenxin/ernie → ernie-4.5-turbo-128k 38 万 千帆 v2;输出上限 cap→12288;⚠️欠费停服(9/5 起勿测) TongYi al/qwen → qwen-plus 58 万 al_free(1PX) ZhiPu gl/glm → glm-5 7 万 glm_free(1PX);推理模型小 max_tokens 时 content 空属正常 Kimi km/kimi → kimi-k2.6 4.5 万 org RPM=3 限流;moonshot-v1-8k 等已下线 Tencent hy(直连 hy3 preview) 6.6 万 hy_standard(5PX)/hy_pro(10PX) 兑换执行:gateway 积分包(带 scenarioId) 或 任意数量(不带 scenarioId → amount×rate,9/5 起) 鉴权:POST /api/gateway/allocations 需 X-Admin-Token(9/5 堵白嫖);用户购买一律走 /api/exchange/redeem 真扣 PX
开放平台 API 使用 HMAC-SHA256 签名,详见签名算法 Tab。
开放平台 API(/open/v1/*)使用 HMAC-SHA256 签名鉴权:
sign_string = METHOD + "\n"
+ PATH + "\n"
+ BODY + "\n"
+ TIMESTAMP + "\n"
+ NONCE + "\n"
+ SECRET
signature = hmac_sha256(sign_string, SECRET)
请求头:
X-App-ID: 你的应用 ID X-Timestamp: 当前 Unix 时间戳(秒) X-Nonce: 随机字符串(防重放) X-Sign: HMAC-SHA256 签名(hex)
改动落在服务端/前端时,以下口径必须同批对齐,否则两端会出现「看着都对、拼起来不对」。
split(' · ') 拆行详情摘要 · 模型 · 宽x高 例:橘猫在窗台晒太阳 · seedream-5.0-flash · 2048x2048摘要 · 模型 · 分辨率 · 时长s 例:小鹿穿过晨雾森林 · seedance-2.0 · 720p · 5s…;英文取前 6 词。description,不进 name。buildImageAssetName() / imageAssetSummary()(generate_image.go)。第三方若自建资产,建议同规则命名,前端可零适配渲染。
general / character / scene / prop / voice;未分类 = category IS NULL(列表接口用 cat=none 查)。tags.$.category,AI 生成图的 tags 是数组,$.category 取不到 ⇒ 永远归不了类,故独立成列。PATCH /org/assets/:id(只能改自己的),category="" 表示清除。
seedream-5.0-flash / seedream-5.0-lite / seedream-4.5 / seedream-4.0。qwen-image、qwen-image-2.0 仅作入参别名,服务端 canonicalImageModel() 归一为 seedream-5.0-flash。id、cy_model_channels.model_key、前端下拉 value、{characters,props,scenes}.gen_model。cost<=0 时图片返回 400、视频任务置 failed,绝不按 1 分或 25 分放行。ceil(厂价 × 12)。
#navDrawer),861px 起恢复桌面四链接。验收看 scrollWidth === innerWidth。id-auth.ciyuanfun.cn 的 location ~* \.html$ 正则优先级高于 /mam/ 前缀,会把首页罩成 30 天 immutable ⇒ 需显式 location = /mam/index.html。/mam/showcase/(首页影像窗素材,webp + 无声 mp4)走 ^~ 前缀 + 30 天 immutable;换片只改 data-items,不必升版本。?v=,否则老缓存;页面 HTML 全部 no-store。
Content-Type(入库为空或 octet-stream 时按扩展名兜底,Go 标准库不认 mp4/webm);Range 并返回 206,否则视频拖不动进度条;client_max_body_size 50m 限制,超限返 413(HTML 而非 JSON),前端需按状态码兜底提示。
kind=image)openai_image —— OpenAI Images 兼容:POST {{base_url}}/images/generations,取 data[0].url(或 data[0].b64_json)bailian_image —— 阿里百炼 DashScope 同步:POST {{base_url}}/api/v1/services/aigc/multimodal-generation/generation,取 output.choices[0].message.content[0].imagevolc_image —— 火山方舟同步(现有四个 seedream 通道在用){{base_url}} {{api_key}} {{model}} {{model_id}} {{endpoint_id}} {{prompt}} {{size}} {{size_star}} {{ratio}} {{quality}} {{provider}}{{size}} 形如 1280x720,{{size_star}} 是同一尺寸的星号写法 1280*720(百炼要求星号)。extra.size_map 按比例(其次画质)命中,未命中回落 seedream 档位;extra.size_style="generic" 表示用通用 1k 档。各家尺寸规范不同,靠全局映射必然对不上。{"size_map":{"16:9":"1280*720","1:1":"1024*1024"},"size_style":"generic"}
实测教训:百炼的 /compatible-mode/v1/images/generations 在本账号实测返回 404,必须走 DashScope 原生同步接口 —— 接新厂商一律以真跑结果为准,不以文档为准。
https;IP 直连必须是公网;域名解析后每一条 A/AAAA 都必须是公网(挡「域名指向 127.0.0.1」)。ErrUseLastResponse)⇒ 挡「公网地址 302 到 169.254.169.254」。base_url 直改成 https://127.0.0.1:58080(绕过保存校验),调用必须报「目标 127.0.0.1 解析到内网地址,已拦截」。
enabled=0 也算「已迁移」)⇒ 停用后必须拒单,不回落旧路径,否则「后台停了却仍能出图」。qwen-image 归一为 seedream-5.0-flash 时,禁止用前缀匹配 —— HasPrefix("qwen-image") 会把 qwen-image-3.0 一起吞掉,导致「配了百炼通道却拿火山 ep 出图」。别名表全项目只留一份(canonicalImageModel)。
cy_model_channels(kind=video),把命中的通道 id 落进任务的 channel_id;轮询器只认这个字段,不再靠任务号前缀判断厂商。cgt- 前缀,阿里百炼是 UUID。选 wan3.0 却拿到 cgt- 即判定走错厂商。wan3.0、展示名 wan3.0-video 时,提交入口须先归一到主键(CanonicalVideoModel:先按主键、再按名字反查),否则按展示名调 API 会被当成未知模型直接拒单。cy_user_model_channels + cy_user_model_credentials,与 cy_model_channels、cy_model_credentials 零交集。LoadChannel(kind, alias) 是带 30 秒缓存的热路径,没有用户维度;一旦混表,后台列表、测试连通、轮询器、缓存键每一处都要补 WHERE owner IS NULL,漏一处就串号。unit_price 与 service_rate 落库;之后后台调价不影响已建通道,对账时也能解释「他为什么是 0.20」。byok_pricing_mode=service_only,五哥 11-05 定):单价 = 公布价 × 5%,不叠厂价。另一档 cost_plus(厂价+服务费)保留,改配置即切、不用发版。math.Ceil(公布价取整用),拿它算 BYOK 会把 0.15 抬成 1(费率放大 6.7 倍)。判据:3×5% 必须落 0.20,不得出现 0.15 / 1 / 2.31。
扣谁的额度(P204 定案,五哥 11-06):扣使用者本人。① 模型主人自用 ⇒ 只付 5% 服务费(单价快照);② 渠道商群里的其他用户 ⇒ 按全域公布价扣他自己的积分,流水 ref_id=uc_<通道>_u<使用者>;③ 同时向渠道商收服务费 unit_price(3 分价 ⇒ 0.2 积分 = ¥0.02),扣 cy_resellers.credits,落 cy_reseller_credit_logs(service_fee / 失败退回 fee_refund)。②③ 是并行两笔,不是二选一。失败时用户与渠道商双向退回,流水 type 只有 16 字符,写超长会静默丢凭证。POST /api/v1/admin/reseller/me/models),归属落 owner_reseller_id —— 渠道商在 MaM 没有用户账号,所以 owner_user_id=0。效果:群内用户可见可用,扣用户本人积分(全域公布价);上游调用费用由渠道商自己的 Key 承担。配套接口:列表 GET .../reseller/me/models、启停 PATCH .../:id、参照族 GET .../ref-models;停用后用户端下拉立即消失。z-index=100001 —— 生图面板本身在 99999 的表单弹窗里,层级低一等就会被盖住,表现为「点了没反应」。visibility=0 仅自己;=1 同 reseller_id 的渠道商用户群。跨群用户列表看不到、按名字调用也不会命中(回落公共模型),越权改删返回 403。sk-ws-****LgSa;BaseURL 只允许 https 且必须解析到公网(Dial 层再拦一次);协议由后端按 provider 白名单指定,用户不能提供 submit JSON,否则等于开放任意 HTTP 代理。channel_id 留空 —— 它和公共通道是两套 id 空间,混写必串号;归属靠 tags 里的「私有」与流水 ref 回溯。删除通道不影响历史资产。qwen-image-3.0 档位改为 1K / 2K(厂家 size 允许 512×512–2048×2048、比例 1:8–8:1),1K 1280×1280、2K 2048×2048,同档同价。unit_price 单值存不下,故三档价写进 extra 快照:price_rule(本人自用 = 公布价 × 5%)、ref_rule(公布价,渠道商群内用户按它扣本人)。代表值 unit_price 取 720p 中间档,真实扣费一律读 price_rule[resolution]。例:参照 seedance-2.0-mini(3/6/13 积分/秒)⇒ 0.2 / 0.3 / 0.7 积分/秒;参照 seedance-2.0(5/12/30)⇒ 0.3 / 0.6 / 1.5。cy_videos / cy_story_video_tasks 增加 channel_scope(0=cy_model_channels,1=cy_user_model_channels)。两张表 id 各自自增,同一个数字是两条不同通道,轮询必须走 LoadChannelByScope(id, scope);私有通道查不到时不回落公共(回落即串号)。volc(火山方舟)与 bailian(阿里百炼),对应 volc_video / bailian_video 模板;openai_compat 没有视频协议,建通道时明确拒绝。cy_resellers.share_rate(0~1,默认 0.85),在 admin.ciyuanfun.cn → 渠道商 列表「分成」列与详情页设置,越界(<0 或 >1)直接拒绝、不夹紧。它和 5% 模型服务费是两件事:5% 是平台向渠道商收的通道服务费,share_rate 是平台与渠道商的营收分成比例。cy_video_model_pricing 里没有这一行,先查表会把合法私有模型一律判成「未启用」,BYOK 视频永远用不了(T8 端到端实测踩到);私有通道因此跳过 videoModelAvailable,该分辨率没配价时由 cost<=0 拒单,仍不兜底收费。② GET /api/v1/org/models/custom 默认 kind=image,查视频通道必须显式带 ?kind=video,否则视频 tab 恒为空。③ 分镜已支持(P209f):story.go 同样改成「先选路后校验」,vp-model 已放开自制模型,扣费按 extra.price_rule[resolution] × 时长,渠道商模型另收 5% 服务费,任务落 channel_scope=1。入口四处(P209g):① 视频工坊模型下拉末尾「+ 新建自定义模型…」② 分镜模型下拉同款 ③ 用户端「我的模型」弹窗的图片/视频两个页签 ④ 渠道商面板「+ 新建自定义模型」的模型类型下拉(参照价由 GET /api/v1/admin/reseller/me/ref-models?kind=video 给三档)。没有下拉入口=功能不存在:视频侧此前只有图片下拉带 __custom__,所以「视频自定义」在界面上等于没有。admin.ciyuanfun.cn 左侧菜单「🔌 自定义模型」,或渠道商面板 /reseller-panel.html 的卡片「渠道商自定义模型」→「+ 新建自定义模型」。卡片文案「渠道商自定义模型,群内用户可见可用,扣用户款」——扣的是使用者本人的款,不是渠道商的额度。const kind 的 TDZ 抛 ReferenceError: Cannot access 'kind' before initialization,异常发生在 fetch 之前,按钮已 disabled 却无人复位,表现为「点创建一直卡住、服务端零请求」;修完必须用 DOM 桩单测覆盖「异常后按钮是否复位」。② 新建厂商通道要看协议模板真正读哪个变量 —— 火山视频提交体的 model 填的是 endpoint_id(ep-xxx)而不是模型名;缺 ep 时通道建得成、一跑必挂,现已在创建时强校验并落 extra.endpoint_id(百炼走 model 名字,故不受影响)。③ 标注误导会伪装成权限 bug —— 渠道商模型被标「他人共享 / 归属 - /(自制)」,看起来像别人的私有模型;实测六个账号、三处数据源(列表 / 定价 / 选路)visibility=0 只本人可见,权限本身正确,改标注即可。另 弹窗状态残留=隐式默认值:mm-vis(谁能用)在打开弹窗和创建成功后不复位,选过一次「渠道商用户群」后后续模型全被误建为共享,已在两处复位为 0。iw_comic_groups 的分组语义,只读参照、不碰 aigc 代码与 inwork 库;新表一律 cy_ 前缀。分页必须用 LIMIT ? OFFSET ?(size, offset):写错成 LIMIT ?,? 会变成 offset 在前、第一页 list 恒空而 total 仍正确 ⇒ 只断言 total 会漏判,必须同时断言 list 长度(P220 实测踩到)。另 归组关系独立成表,因为 cy_stories 的 _bak_user_del / _bak_admin_del 用 INSERT ... SELECT * 备份,给它加列会整链断裂(铁律 58)。弹窗关闭也要复位按钮文案 / disabled:重命名弹窗残留「保存」会让下一次新建看起来像没生效(铁律 7,DOM 桩单测已覆盖)。ListScenes 外层别名是 s,可见性子查询也写 s 会让 s.asset_id=s.id 指向同一张表,筛选恒失效;道具库外层是 p 所以碰巧正常 ⇒ 统一改成 ascope,且六类逐条断言 list 长度和具体 id,不能只看 total / 200。② 历史文案会和新概念撞名 —— 场景/道具库 story_id=0 过去标「全局素材」(实为「不挂作品」、仍是私有),P221 引入真正全站可见的 global 后必须改成「独立素材」,否则标注误导会伪装成权限 bug(铁律 112)。③ 归属映射独立成表,别给 cy_assets 等原表加列(_bak_* 用 INSERT ... SELECT *,加列会断链,铁律 58/124)。④ 文件读取改 OptionalAuth 但要保留 sig 签名链接,否则分镜里已落库的第三方 AI 拉图 URL 会全断。⑤ 只读态别占用 busy 标志:他人 global 素材弹窗若把「不可编辑」写成 busy=true,关闭后不复位会让下次打开被守卫挡死;拆成独立 readonly 并在 close 全量复位(铁律 7/116)。⑥ admin 只能设 private/global,group/work 归属属主自决;删组必须同时把组内素材回私有,且绝不删素材或作品。api() 对 401 / 失败返回 {error} 不抛异常,asEnsureOptions 不判错就会把空候选永久缓存成 optsLoaded=true;未登录 boot → SPA 内登录不刷新页面 → 下拉永远只剩「私有 / 全局」,表现为「列表没改过来」。② 六个创建弹窗打开时只同步渲染当时的 asState,不主动拉候选(铁律 108:同功能多条链路要全覆盖,含复用 DOM 的上传弹窗与故事创作页)。③ 修法:asEnsureOptions(force) 失败即 optsLoaded=false;新增 asRefreshCreateOptions() =立即重绘+强制重拉+再重绘,七个入口逐一挂上。④ 接口单测打测试票、DOM 桩假设数据已在手,都覆盖不到「装载时序」⇒必须补页面级时序桩(未登录 boot → 登录 → 打开弹窗 → 断言 option 列表);只断渲染函数会得出「已修复」的假阳性。options.groups 只返回自己创建 / 已加入的组,其他账号下拉就只剩「私有 / 全局」,与「全站成员自由加入」相悖;修法是另给 joinable,不要把全站组塞进 groups(会污染归属筛选条 / 单条 / 批量弹窗)。② 选中未加入组必须先 join 再落归属:applyScope / CreateStory 都用 pgGroupAvailable 校验,未加入会 400;自动加入走既有 /join,不在后端偷偷写成员表。③ 同功能几条提交链路都要改(铁律 108):六类创建走 asApplyCreated,故事走 createStory → pgCreateBody,两条都要前置 join。④ join 前置放在按钮 disabled 之前,否则失败 return 会留下卡死按钮(铁律 7)。⑤ 归档组不给候选:status=0 不可加入,列了只会点了报错。⑥ 加入成功后必须 optsLoaded=false 再拉 options,否则下拉还显示旧分组。DELETE FROM cy_asset_scopes WHERE group_id=?;本轮实测 UPDATE 会清空 group_id,导致后续按组清理匹配不到、残留 6 行(判据要与结论同向:守恒要断映射表行数)。② 验证脚本的 query 拼接:已有 ? 的路径用 &scope=,没有的用 ?scope=;写错会整批 404 假阴性。③ vm DOM 桩的 select:重写 innerHTML 后没有 selected 时浏览器默认选第一项,桩必须模拟,否则「组失效回落私有」会被判成失败;asApplyCreated 成功后还会刷一次映射 GET,断言要只数 PUT。④ 同一创建功能有几条提交链路都要改(保存按钮 + 生图面板 GPregister.save,铁律 108)。⑤ gin 路由静态段不能与通配段同层:/project-groups/discover 会撞 /:groupId,改用独立路径 /project-groups-discover。⑥ 只读可见不等于可写:组员只见不改,改 / 删仍限属主+超管;退出只回收当事人自己的归属,绝不碰别人资产。cy_videos / cy_story_video_tasks 在 INSERT 时即写 channel_id/channel_scope,不再只在提交成功的 UPDATE 里补;拒单时 vch 为 nil 落 0。上游百炼 overdue-payment / Access denied 也已映射成中文可操作提示,不再直接吐英文给终端用户。cy_reseller_settlements 按「账期 + 单笔用户流水」留痕,share_rate 取生成当期快照,gross_credits =名下用户当月 AI 生成类消费净额(consume 为正、credit 退款为负;白名单只认 video_gen / image_gen / byok_* 及对应 _refund —— 排除法会把「渠道商补贴用户」的内部转账算成负营收,P213 实测踩到),reseller_credits = gross × share_rate、platform_credits = gross - reseller。状态恒为 estimated:只留痕,不改任何余额、不产生实际转账;生成接口以 source_log_id 唯一键幂等,可按月重跑。渠道商余额低于 100 积分显示「余额偏低」、为负显示「余额为负」,扣费逻辑保持「照扣、允许为负」不变。