支付管理与会员体系
收费配置、会员类型、会员套餐、支付商户 DSL、支付通道、订单与回调日志的完整配置流程。
「支付管理」把「内容收费」和「在线支付」串成闭环:用户在前台充值、开通会员、升级会员或单片购买 → 系统按金额筛选可用支付通道 → 通道绑定支付商户向支付平台下单 → 支付平台异步回调 → 订单入账,会员/余额/观影券发放。
步骤章节(点击跳转)
演示 支付管理 的收费配置、会员类型、会员套餐、提供商与通道配置、订单与回调日志的排查入口。
订阅提示
内容付费与会员体系属于需要订阅授权的功能(详见角色与权限中的订阅功能表)。未订阅的实例页面仍可打开,但高级能力不可保存或不会生效。
菜单与推荐配置顺序
「支付管理」下共 8 个页面:
| 页面 | 作用 | 前端路由 |
|---|---|---|
| 收费配置 | 付费总开关、全站收费、单片价格、试看/预览、充值金额与档位 | /payManage/pay-config |
| 弹窗配置 | 播放页付费弹窗(智能弹窗/自定义 HTML) | /payManage/dialog-config |
| 会员类型 | 定义会员等级(名称、权限值、每天价值、角标) | /payManage/membership-type |
| 会员套餐 | 用户能买什么:时长、价格、赠送 | /payManage/membership-plan |
| 提供商配置 | 对接支付平台(即「支付商户」)(下单地址 + DSL + 回调白名单) | /payManage/provider-settings |
| 通道配置 | 前台支付弹窗里展示的支付方式 | /payManage/channel-config |
| 订单管理 | 查订单、人工回调 | /payManage/order-manage |
| 回调日志 | 查看支付平台回调内容与验签/处理结果 | /payManage/callback-log |
推荐按下面顺序配置,每一步都点击「保存配置」:
- 提供商配置:先把支付平台接通(预编译 + 调试);
- 通道配置:创建用户可见的支付方式并绑定商户;
- 会员类型:创建会员等级;
- 会员套餐:创建月卡/季卡/年卡并绑定会员类型;
- 收费配置:打开付费模式,配置试看/预览、充值范围与档位;
- 到「视频管理」或分类里设置访问权限(免费/会员/单片付费);
- 前台用测试账号小额真实走一遍,确认回调入账。
收费配置

该页采用「改完统一保存」:切换开关、改金额、维护档位后,点击右上角「保存配置」才生效。
收费总控
| 配置项 | 说明 |
|---|---|
| 开启当前付费模式 | 前台付费能力是否整体生效。关闭后,无论视频、分类或全站如何设价,前台都按免费处理 |
| 启用全站收费模式 | 付费模式开启后才有意义。视频和分类都选「继承」时:关闭=按免费,开启=按全站收费兜底 |
| 开启单片收费 | 「零价格视频默认收费」是否生效 |
| 零价格视频默认收费(元) | 继承到全站收费、且没有单独价格的视频,使用的默认单片价 |
| 美元兑人民币汇率 | 多语言前台金额展示和输入换算(1 美元 = X 人民币) |
规则总结:
- 付费模式关 → 全站免费;
- 付费模式开、全站收费关 → 只有视频/分类单独配置为付费时才收费;
- 付费模式开、全站收费开 → 视频和分类都继承时走全站收费兜底;兜底下若没开单片收费,用户通常需要开通会员;开了单片收费并填了默认价,用户可以单片购买或开通会员。
试看与预览
| 配置项 | 说明 |
|---|---|
| 试看功能总开关 | 每日试看名额是否启用 |
| 每天可以试看多少部视频 | 同一用户设备每天最多试看的视频数,到上限后当天不再给试看 |
| 是否支持预览 | 未获得完整权限的付费视频,购买前可预览指定秒数 |
| 付费视频可以预览多少秒 | 预览时长 |
| 未开启预览时是否允许进入播放页 | 仅关闭预览时生效;不允许时,没有权限的用户会在进入播放页前被拦截 |
「试看」像每日体验名额,「预览」像付费前的片段试看,两者可单独或同时开启。
充值金额与推荐档位
- 最低充值金额 ≥
0.01元,最高充值金额必须大于最低; - 每个推荐档位金额必须在最低-最高之间,且不能重复;
- 档位字段:是否启用、充值金额、档位类型(通用/人民币/美元)、名称(多语言,简体中文必填)、赠送金额、赠送观影券类型与数量;
- 用户选推荐档位充值成功后,发放赠送金额和观影券;自定义金额不享受赠送;
- 赠送的观影券需要先在活动配置的观影券管理里创建并启用。
四种典型站点配置
| 站点类型 | 付费模式 | 全站收费 | 单片收费 | 其他 |
|---|---|---|---|---|
| 免费站点 | 关 | 关 | 关 | 试看/预览可关闭 |
| 会员制 | 开 | 开 | 关 | 建议开预览,充值档位配合套餐价 |
| 单片付费 | 开 | 开 | 开 | 填默认单片价,档位覆盖常见价格(1 部/3 部/5 部) |
| 混合付费 | 开 | 视情况 | 开 | 试看/预览开启,档位兼顾套餐价 |
会员类型

会员类型只定义等级本身,不设置售卖价格。
| 配置项 | 说明 |
|---|---|
| 启用该会员类型 | 关闭后不能被套餐、视频权限、分类权限、用户会员等级使用 |
| 会员名称 / 标签文案 / 类型说明 | 简体中文必填,多语言可分别填写 |
| 权限值 | 大于 0 的整数,数值越大等级越高,不能重复 |
| 每天价值(元/天) | 大于 0,最多 2 位小数,用于会员升级场景的价值展示和差价参考 |
要点:
- 权限值建议留间隔:默认会员
10、黄金20、钻石30、至尊40,以后好插入「白银」「铂金」; - 系统默认会员类型必须保持启用,不能删除;
- 删除会员类型前,确认没有被套餐、视频/分类权限、礼品卡、兑换码或用户会员等级引用;
- 每天价值应与套餐价格体系大致一致,高等级高于低等级。
会员套餐

| 配置项 | 说明 |
|---|---|
| 绑定会员类型 | 购买成功后授予的等级,需先建好 |
| 套餐名称 | 前台标题,如「黄金月卡」「钻石年卡」 |
| 套餐时长 | 购买后会员有效期 |
| 现价 / 原价 | 实付价 / 对比价,原价不能小于现价 |
| 赠送金额 / 观影券权益 | 购买成功后额外赠送 |
| 角标 | 如「热销」「限时」 |
| 启用 / 排序 | 控制是否展示、可购买及顺序 |
页面分两组:套餐列表是个人中心开通会员、付费视频弹出会员窗口时展示的常规套餐;单片购买优惠套餐会在用户打开单片购买窗口时同时出现,用「更便宜的会员」引导用户从单片购买转为开通会员。新增、编辑、删除、排序后同样需要「保存配置」。
弹窗配置(播放页付费弹窗)

用户在播放页遇到需要付费的视频时弹出的窗口:
| 模式 | 说明 |
|---|---|
| 智能弹窗 | 系统默认逻辑,按当前视频权限、登录状态、是否支持单片购买、是否需要会员自动决定展示内容 |
| 自定义 HTML 弹窗 | 先展示你写的 HTML,你可在里面放按钮引导用户打开单片购买、会员套餐等 |
自定义 HTML 的规则:系统只提供遮罩和定位外壳,标题栏、关闭按钮、背景、边框、内边距都要在 HTML 里自己设计;不执行任意 JavaScript,请使用 HTML、内联样式和系统识别的受控属性;内容为空时不能保存;选择「智能弹窗」时下方 HTML 不参与展示。
提供商配置(支付商户 DSL)

商户对应一个支付平台的接入配置。字段:
| 配置项 | 说明 |
|---|---|
| 名称 | 后台识别名,如「人民币主通道商户」 |
| 下单地址 | 支付平台的统一下单接口完整地址 |
| DSL 配置 | 描述下单参数、返回解析、回调验签的配置脚本 |
| 回调白名单 IP | 开启后只允许填写的 IP 访问回调;多个 IP 用英文逗号分隔,如 1.1.1.1,2.2.2.2 |
| 备注 | 仅后台识别 |
列表操作:编辑、预编译(检查 DSL 能否被系统识别,每次修改都建议先执行)、调试(用测试参数真实发起一次下单)、删除(删除后仍需「保存配置」才同步到服务端)。回调白名单要先确认支付平台的回调出口 IP 固定,否则会把真实回调拦在门外。
DSL 结构
一份完整 DSL 包含 request、response、callback 三个块:
{
request {
# 如何向支付平台下单
}
response {
# 如何解析下单接口返回(需为 JSON)
}
callback {
# 如何处理支付平台的异步回调(按 JSON 解析)
}
}不会写 DSL?可以直接跳到「不会写 DSL 怎么办」,复制一段现成的提示词交给 AI 生成。
写 DSL 之前,先从支付平台文档确认:下单地址、请求方式(POST/GET)、请求格式(form/json)、字段名、金额单位、签名规则、返回字段、回调字段、回调验签规则、回调应答文本(如 success/OK)。
request:下单请求
request {
method POST
body form
field mch_id = merchant.mch_id
field channel_no = channel.channel_no
field order_no = order.order_id
field amount = fixed(amount / 100, 2)
field notify_url = merchant.notify_url
optional field subject = order.subject
sign md5 {
output sign
sort_keys true
omit_empty true
exclude sign
suffix = "&key=" + merchant.api_key
uppercase true
}
}field 字段名 = 表达式:左边是支付平台要求的参数名,右边是本系统提供的数据来源。optional field在值为空时不发送、也不参与签名;sign支持md5和sha256:output是签名写入的字段、sort_keys是否按字段名排序、omit_empty空值不参与签名、exclude不参与签名的字段、suffix签名原文末尾拼接、uppercase结果是否大写。
可用数据来源:
| 来源 | 含义 |
|---|---|
merchant.mch_id / merchant.api_key |
通道里填写的「商户号」/「Key」 |
merchant.notify_url |
系统根据通道的「前端站点地址」自动生成的异步回调地址 |
channel.channel_no |
通道里填写的「通道号」 |
order.order_id / order.subject |
本系统订单号 / 订单标题 |
amount |
订单金额,单位是分 |
金额写法:平台要求传分 → amount;要求传元 → amount / 100;要求两位小数 → fixed(amount / 100, 2)。
response:下单返回解析
response {
success when body.code == "200"
order_id = body.data.order_no
channel_order_no = body.data.trade_no
amount = to_cent(body.data.amount)
pay_url = body.data.pay_url
}success when 只表示「平台已受理并创建了支付订单」,不是支付成功;pay_url 是前台引导用户去支付的链接。平台返回金额为元时用 to_cent() 转为分。
callback:支付回调
callback {
verify_sign md5 {
field sign
sort_keys true
omit_empty true
exclude sign
suffix = "&key=" + merchant.api_key
uppercase true
}
field order_id = body.out_trade_no
field channel_order_no = body.trade_no
field amount = to_cent(body.amount)
field third_status = body.status
status_map {
"SUCCESS" => "paid"
"PAID" => "paid"
"FAIL" => "failed"
"CLOSED" => "closed"
"INIT" => "pending"
}
success when third_status == "SUCCESS" or third_status == "PAID"
ack {
when success {
body "success"
}
when fail {
body "fail"
}
}
}回调要完成:验签(verify_sign)、取出本系统订单号/第三方订单号/金额/状态、把平台状态映射为系统状态(status_map)、判断是否成功,以及用 ack 告诉平台应答什么文本。ack 文本必须符合平台要求,否则平台会反复重发回调。
不会写 DSL 怎么办:让 AI 帮你生成
不会写也没关系。把下面这段提示词和支付平台给你的对接文档(接口文档的文字内容,或文档链接)一起发给 AI(如 ChatGPT、Grok、Claude 等),让它按系统支持的写法生成 DSL。
不要把真实密钥发给 AI
只需要发「提示词 + 对接文档」。商户号、密钥(Key)、通道号这些敏感参数不要告诉 AI:提示词已要求 AI 全部用变量(merchant.mch_id、merchant.api_key、channel.channel_no)代替。你在「通道配置」里填写的商户号、通道号、Key 会在下单时自动代入。如果对接文档里带有示例密钥,发出前建议也一并删掉。
使用步骤:
- 点击下面代码块右上角的「复制」,把整段提示词复制出来;
- 发给 AI,并在最后一行「(在这里粘贴对接文档的内容或链接)」处粘贴支付平台的对接文档;
- AI 返回一份 DSL 后,到「提供商配置」新增或编辑商户,把它粘贴到「DSL 配置」,下单地址在后台单独填写;
- 点击预编译检查结构,再点击调试发起一次测试下单;失败时把后台给出的报错原文发回给 AI,让它修改;
- 商户号、通道号、Key 回到「通道配置」里自己填写。
你是一名熟悉第三方支付接口对接的工程师。请根据我随后附上的「支付平台对接文档」,为发财CMS 的「支付商户 DSL」写出一份可以直接粘贴使用的配置。
【DSL 是什么】
DSL 是一种专门描述支付接入的小型规则脚本,不是通用编程语言。它由三个块组成,三个块缺一不可,并按 request、response、callback 的顺序书写,最外层用一对大括号包住:
{
request { ...如何向支付平台下单... }
response { ...如何解析下单接口的返回... }
callback { ...如何验签并处理支付平台的异步回调... }
}
注释用 # 开头。
【request 块:下单请求】
1. method 只能是 POST 或 GET;body 只能是 form 或 json。
2. field 平台要求的参数名 = 数据来源表达式:左边是支付平台文档里的参数名,右边是系统提供的数据来源。参数名和来源不要写反。
3. optional field 用于可能为空的字段(如标题);值为空时不发送,也不参与签名。
4. 固定值直接写字符串或数字,例如 field sign_type = "MD5"。
5. 签名用 sign md5 { ... } 或 sign sha256 { ... },可用配置项:
output 签名结果写入的字段名;
sort_keys true/false 参与签名的字段是否按字段名排序;
omit_empty true/false 空值是否不参与签名;
exclude 字段1,字段2 额外不参与签名的字段(签名输出字段自动排除);
suffix = "&key=" + merchant.api_key 签名原文末尾拼接的内容;
uppercase true/false 结果是否转大写。
【系统提供的数据来源(只能用这些,不要自己发明)】
下单(request)可用:
merchant.mch_id 商户号
merchant.api_key 密钥(Key)
merchant.notify_url 系统生成的异步回调地址
channel.channel_no 通道号
order.order_id 本系统订单号
order.subject 订单标题
amount 订单金额,单位是「分」
回调(callback)可用:body(回调报文,按 JSON 对象读取)、merchant.mch_id、merchant.api_key、merchant.notify_url、channel.channel_no。
注意:除以上之外没有其他数据来源(例如没有 app_id、return_url)。如果平台要求额外的固定参数,请写成固定字符串。
【表达式规则】
只支持:字符串、数字、点路径(如 body.data.pay_url)、+ - * /、==、or,以及两个函数:
to_cent(x) 把元转成分(用于 response 和 callback 里的金额)
fixed(表达式, n) 保留 n 位小数的字符串,例如 fixed(amount / 100, 2)
不支持 and、not、!=、数组、下标、自定义函数、XML。
金额换算:平台要求分 → amount;要求元 → amount / 100;要求两位小数 → fixed(amount / 100, 2)。
【response 块:下单返回】
返回内容必须是 JSON。写法:
success when 判断表达式 (表示平台已受理下单,不是支付成功)
order_id = ... 本系统订单号
channel_order_no = ... 平台订单号
amount = to_cent(...) 金额(分)
pay_url = ... 支付跳转链接
只能使用这四个标准字段。
【callback 块:支付回调】
1. verify_sign md5 { field 回调里的签名字段名 ... }:验签,配置项与 sign 相同(sort_keys、omit_empty、exclude、suffix、uppercase);sha256 同理。
2. field 只能写四个标准字段:order_id、channel_order_no、amount(用 to_cent 转成分)、third_status(平台的原始状态值)。
3. status_map { "平台状态值" => "paid" }:把平台状态映射为系统状态,可映射到 paid、failed、closed、pending。
4. success when third_status == "平台的成功状态值":什么情况判定为支付成功,多个状态用 or 连接。
5. ack { when success { body "平台要求的成功应答文本" } when fail { body "失败应答文本" } }:按平台文档填写,例如 success、OK。
【安全要求】
配置里的商户号、密钥、通道号、回调地址都不要写真实值,一律使用上面的变量(merchant.mch_id、merchant.api_key、channel.channel_no、merchant.notify_url)。我也不会向你提供任何真实密钥;如果平台文档里出现了示例密钥,请忽略,不要写进结果。
【你需要做的事】
1. 阅读我附上的支付平台对接文档(可能是文字,也可能是链接),找出:下单地址的请求方式与格式、各参数名及含义、金额单位、签名规则、下单返回字段、回调字段、回调验签规则、回调应答文本。
2. 如果文档里缺少必要信息(例如签名规则不明确),先列出问题问我,不要猜测。
3. 严格只使用上面列出的语法和数据来源。
【输出格式】
- 只输出一份完整的 DSL(包含 request、response、callback 三个块),放在一个代码块里,方便我直接复制粘贴。
- 代码块之外只允许再写一小段说明:列出你做的关键假设,以及下单地址需要我在后台单独填写。不要输出其他解释。
【参考示例(字段名只是示意,请以我附上的文档为准)】
{
request {
method POST
body form
field mch_id = merchant.mch_id
field channel_no = channel.channel_no
field order_no = order.order_id
field amount = fixed(amount / 100, 2)
field notify_url = merchant.notify_url
optional field subject = order.subject
sign md5 {
output sign
sort_keys true
omit_empty true
suffix = "&key=" + merchant.api_key
uppercase true
}
}
response {
success when body.code == "200"
order_id = body.data.order_no
channel_order_no = body.data.trade_no
amount = to_cent(body.data.amount)
pay_url = body.data.pay_url
}
callback {
verify_sign md5 {
field sign
sort_keys true
omit_empty true
suffix = "&key=" + merchant.api_key
uppercase true
}
field order_id = body.out_trade_no
field channel_order_no = body.trade_no
field amount = to_cent(body.amount)
field third_status = body.status
status_map {
"SUCCESS" => "paid"
"FAIL" => "failed"
"CLOSED" => "closed"
}
success when third_status == "SUCCESS"
ack {
when success { body "success" }
when fail { body "fail" }
}
}
}
下面是支付平台的对接文档,请据此生成 DSL:
(在这里粘贴对接文档的内容或链接)AI 生成的内容一定要自己核对一遍再使用:金额单位(分/元)、签名规则、回调应答文本、状态值是否与文档一致。核对无误后,用小额真实支付验证回调是否入账。
常见问题
| 问题 | 常见原因 | 处理 |
|---|---|---|
| 预编译失败 | 缺少 request/response/callback 或括号不成对 |
检查三段结构与 {} |
| 下单提示字段不存在 | field 右边数据来源写错 |
改成上表中的来源 |
| 平台提示签名错误 | 排序、空值、排除字段、密钥拼接或大小写不一致 | 对照平台签名示例逐项检查 |
| 调试成功但无支付链接 | response.pay_url 路径写错 |
看调试结果里的响应内容 |
| 支付成功订单不变 | 回调地址、验签、订单号/金额字段或成功判断不对 | 看「回调日志」 |
| 平台重复回调 | ack 返回不符合平台要求 |
按平台文档改 ack |
| 金额不一致 | 分/元单位混用 | 修正 request/response/callback 三处金额 |
通道配置

通道是用户在支付弹窗里看到的支付方式(只看到名称和图标,看不到商户号/通道号/Key)。
| 配置项 | 说明 |
|---|---|
| 通道是否启用 | 关闭后仅保留配置,不参与支付 |
| 匹配对象 | 通用(所有语言)/ 人民币(中文环境)/ 美元(非中文环境) |
| 匹配商户 | 选择「提供商配置」里已配置的商户 |
| 通道名称、通道图片 | 前台展示;名称简体中文必填;图片可从图库选或上传,建议正方形 |
| 商户号、通道号、Key | 供 DSL 的 merchant.mch_id、channel.channel_no、merchant.api_key 使用 |
| 前端站点地址 | 前台站点根地址,必须以 http:// 或 https:// 开头 |
| 通道最低/最高金额(元) | 订单金额超出范围时前台不展示该通道;最低至少 0.01,最高须大于最低 |
| 固定金额 | 启用后只有金额等于列表中某值的订单才展示该通道;值需在最低-最高之间,用英文逗号或换行分隔 |
回调地址:系统为每个通道生成 前端站点地址 + /payment/callback/<通道ID>(前台服务 6166 端口提供此接口,GET/POST 都接收)。因此:
- 「前端站点地址」要填支付平台能从公网访问到的前台域名(通常是你配置好的 HTTPS 域名),不要填
127.0.0.1或内网地址; - 如果前台通过反向代理对外提供,确保
/payment/callback/路径被转发到 6166; - 启用通道必须填:匹配商户、商户号、通道号、Key、前端站点地址、最低和最高金额。
如果通道只允许固定金额,请同步调整收费配置里的推荐充值档位,避免用户选了金额却没有可用通道(此时前台提示「暂无可用支付通道」)。
订单管理与人工回调

可按订单号、用户名、订单状态、订单类型、支付通道、回调状态、支付/创建时间筛选。
| 维度 | 取值 |
|---|---|
| 订单类型 | 余额充值、会员订阅、会员升级、视频购买 |
| 订单状态 | 待支付、已支付、已取消、已过期、部分退款、已退款 |
| 回调状态 | 待处理、处理成功、处理失败、人工确认 |
列表操作:查看详情(含支付/回调载荷);回调(人工回调,只对未支付且回调状态不是「处理成功」的订单可用,可填写回调备注)。典型场景:用户已付款但平台回调丢失,你在支付平台后台确认到账后,在此人工确认入账。人工回调前务必核实支付平台确实已收款,避免重复发放。
回调日志

列出每次支付回调的:回调时间、订单号、通道/商户、方法/格式、金额、客户端 IP、处理结果,并可查看详情。排查「支付成功但订单没变」时,先看这里:有没有收到回调、验签是否通过、处理结果是什么;没有记录则检查通道的前端站点地址、反向代理、防火墙和回调白名单。
上线前检查清单
- 商户:预编译通过,「调试」能拿到支付链接;
- 通道:名称、图片、匹配对象、金额范围、前端站点地址正确;
- 前台充值页:最低/最高金额、推荐档位、赠送展示正确;
- 购买会员套餐与单片视频,金额对应的通道都可用;
- 多语言站点:切换中文和非中文,人民币/美元通道展示符合预期;
- 小额真实支付一次:跳转 → 支付 → 订单变「已支付」→ 余额/会员/观影券到账;
- 回调日志中有对应记录,处理结果为成功。