首页 / 用户与商业化

支付管理与会员体系

收费配置、会员类型、会员套餐、支付商户 DSL、支付通道、订单与回调日志的完整配置流程。

「支付管理」把「内容收费」和「在线支付」串成闭环:用户在前台充值、开通会员、升级会员或单片购买 → 系统按金额筛选可用支付通道 → 通道绑定支付商户向支付平台下单 → 支付平台异步回调 → 订单入账,会员/余额/观影券发放。

视频教程支付与会员:从支付商户到会员套餐 5:33
支付与会员:从支付商户到会员套餐

步骤章节(点击跳转)

空格 播放/暂停 · 方向键左右 快退/快进 5 秒 · F 全屏 · 画面由代码实时渲染,配音与配乐为 64kbps 单声道 MP3

演示 支付管理 的收费配置、会员类型、会员套餐、提供商与通道配置、订单与回调日志的排查入口。

订阅提示

内容付费与会员体系属于需要订阅授权的功能(详见角色与权限中的订阅功能表)。未订阅的实例页面仍可打开,但高级能力不可保存或不会生效。

菜单与推荐配置顺序

「支付管理」下共 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. 提供商配置:先把支付平台接通(预编译 + 调试);
  2. 通道配置:创建用户可见的支付方式并绑定商户;
  3. 会员类型:创建会员等级;
  4. 会员套餐:创建月卡/季卡/年卡并绑定会员类型;
  5. 收费配置:打开付费模式,配置试看/预览、充值范围与档位;
  6. 到「视频管理」或分类里设置访问权限(免费/会员/单片付费);
  7. 前台用测试账号小额真实走一遍,确认回调入账。

收费配置

收费配置
收费配置

该页采用「改完统一保存」:切换开关、改金额、维护档位后,点击右上角「保存配置」才生效。

收费总控

配置项 说明
开启当前付费模式 前台付费能力是否整体生效。关闭后,无论视频、分类或全站如何设价,前台都按免费处理
启用全站收费模式 付费模式开启后才有意义。视频和分类都选「继承」时:关闭=按免费,开启=按全站收费兜底
开启单片收费 「零价格视频默认收费」是否生效
零价格视频默认收费(元) 继承到全站收费、且没有单独价格的视频,使用的默认单片价
美元兑人民币汇率 多语言前台金额展示和输入换算(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 三个块:

dsl
{
  request {
    # 如何向支付平台下单
  }
  response {
    # 如何解析下单接口返回(需为 JSON)
  }
  callback {
    # 如何处理支付平台的异步回调(按 JSON 解析)
  }
}

不会写 DSL?可以直接跳到「不会写 DSL 怎么办」,复制一段现成的提示词交给 AI 生成。

写 DSL 之前,先从支付平台文档确认:下单地址、请求方式(POST/GET)、请求格式(form/json)、字段名、金额单位、签名规则、返回字段、回调字段、回调验签规则、回调应答文本(如 success/OK)。

request:下单请求

dsl
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:下单返回解析

dsl
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:支付回调

dsl
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 会在下单时自动代入。如果对接文档里带有示例密钥,发出前建议也一并删掉。

使用步骤:

  1. 点击下面代码块右上角的「复制」,把整段提示词复制出来;
  2. 发给 AI,并在最后一行「(在这里粘贴对接文档的内容或链接)」处粘贴支付平台的对接文档;
  3. AI 返回一份 DSL 后,到「提供商配置」新增或编辑商户,把它粘贴到「DSL 配置」,下单地址在后台单独填写;
  4. 点击预编译检查结构,再点击调试发起一次测试下单;失败时把后台给出的报错原文发回给 AI,让它修改;
  5. 商户号、通道号、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、处理结果,并可查看详情。排查「支付成功但订单没变」时,先看这里:有没有收到回调、验签是否通过、处理结果是什么;没有记录则检查通道的前端站点地址、反向代理、防火墙和回调白名单。

上线前检查清单

  1. 商户:预编译通过,「调试」能拿到支付链接;
  2. 通道:名称、图片、匹配对象、金额范围、前端站点地址正确;
  3. 前台充值页:最低/最高金额、推荐档位、赠送展示正确;
  4. 购买会员套餐与单片视频,金额对应的通道都可用;
  5. 多语言站点:切换中文和非中文,人民币/美元通道展示符合预期;
  6. 小额真实支付一次:跳转 → 支付 → 订单变「已支付」→ 余额/会员/观影券到账;
  7. 回调日志中有对应记录,处理结果为成功。
发财CMS 使用教程