跳转到主要内容
listen(...)input(...)waitPay(...) 会阻塞当前插件运行,直到收到匹配事件、超时或用户发送退出口令。支付类插件建议把超时、取消和金额不匹配都显式处理。

listen(waitTime, recallTime?, scope?)

等待同一会话、同一账号下的下一条用户输入。超时返回空字符串 ""
waitTime
number
必填
等待时间,单位毫秒。运行时会归一化:默认 60000 ms,最小 1000 ms,最大通常为 900000 ms。
recallTime
number | 'group'
默认值:"0"
收到输入后延迟撤回用户消息的毫秒数。若第二个参数直接传 'group',SDK 会把它识别为 scope,并把 recallTime 置为 0
scope
'group' | string
'group' 时,允许同群任意成员回答;不传时只等待当前用户。
await sender.reply('请在 60 秒内发送验证码')
const code = await sender.listen(60000)

if (!code) {
  await sender.reply('已超时,请重新开始。')
} else {
  await sender.reply(`收到:${code}`)
}

input(waitTime, recallTime?, scope?)

input(...)listen(...) 的别名,参数和返回值一致。
await sender.reply('请群内任意成员在 60 秒内确认,回复 y')
const answer = await sender.input(60000, 0, 'group')

if (answer !== 'y') {
  await sender.reply('未确认。')
}
如果等待到的是带媒体的消息,input(...) 返回文本内容;媒体从 sender.getMediaItems() 读取。
const { downloadAdapterFile } = require('./middleware.js')

await sender.reply('请发送一个 CSV 文件')
const text = await sender.input(60000)
const items = await sender.getMediaItems()
const csv = items.find((item) => item.type === 'file')

if (!csv) {
  await sender.reply(`没有收到文件,收到文本:${text || '空'}`)
  return
}

const saved = await downloadAdapterFile(csv, { path: 'imports' })
await sender.reply(`已保存:${saved.file_name},大小:${saved.file_size} bytes`)

waitPay(exitcode, timeout, amount?)

等待支付事件或退出口令。它会使用当前运行上下文里的 IM、账号、会话和用户来注册支付等待;如果支付配置不可用,会退化为 legacy 等待支付事件。
exitcode
string
必填
退出口令。等待期间用户发送完全相同文本时,方法返回该字符串并结束等待。传空字符串时表示不启用用户退出口令。
timeout
number
必填
等待时间,单位毫秒。运行时会按输入等待上限归一化,通常最大 900000 ms。
amount
string | number
期望收款金额。SDK 会把它作为 expected_amount 发送给运行时;undefinednull 或空字符串不会发送该字段。

amount 会改变什么

传入有效 amount 后,运行时会:
  1. 把金额写入支付等待元数据 ExpectedAmount
  2. 在启用支付存储时,把金额写入支付记录的 expected_amount
  3. 支付成功返回对象时,追加 expected_amountamount_matched
  4. 对强制支付宝转账链接场景,把转账链接金额设置为该期望金额;未传金额时使用默认 0.01
amount 不是所有支付通道的通用硬过滤条件。不同通道可能仍会把支付事件投递给等待流程。发货、开通权限或发卡前,你应检查返回对象里的 amount_matched === true

amount 不会改变什么

  • 超时仍返回字符串 "timeout"
  • 并发冲突仍返回字符串 "busy"
  • 用户发送 exitcode 仍返回该退出口令字符串。
  • 没有成功支付对象时,不会凭空返回 expected_amountamount_matched

返回值

"timeout"
等待时间耗尽时返回。你应该提示用户重新发起流程。
money
number | string
收到的付款金额。运行时会兼容补充 Money 字段;如果事件只有 received_amount,会用它补 money / Money
Money
number | string
兼容旧插件的大写金额字段,通常与 money 相同。
received_amount
number | string
支付事件中的实际收款金额。不是所有通道都会返回该字段。
expected_amount
number
仅当 amount 归一化后大于 0 时返回。表示本次等待期望收到的金额。
amount_matched
boolean
实收金额与期望金额是否匹配。运行时按 moneyexpected_amount 比较,误差小于 0.001 视为匹配;缺少任一金额或金额小于等于 0 时为 false
order_id
string
等待支付流程生成或通道返回的订单号。启用支付配置时通常形如 pay_<hex>
trade_no
string
支付通道交易号。是否存在取决于通道事件。

安全处理模板

const result = await sender.waitPay('q', 120000, 19.8)

if (result === 'timeout') {
  await sender.reply('支付已超时,请重新发起。')
  return
}

if (result === 'busy') {
  await sender.reply('当前已有支付等待,请稍后再试。')
  return
}

if (result === 'q') {
  await sender.reply('已取消支付。')
  return
}

if (!result || typeof result !== 'object') {
  await sender.reply('没有收到有效支付结果。')
  return
}

if (result.expected_amount && result.amount_matched !== true) {
  await sender.reply(`金额不匹配,应付 ${result.expected_amount},实付 ${result.money || result.received_amount || '未知'}。`)
  return
}

await sender.reply('支付成功,正在发货。')

常见问题

只有支付成功并返回对象时,才会看到 expected_amountamount_matched。如果返回 "timeout""busy" 或退出口令字符串,返回体不变。
可以。运行时会把数字、数字字符串、带 ¥ / 前缀或逗号分隔的金额归一化为数字。JS helper 只要发现 amount 不是 undefinednull 或空字符串,就会发送 expected_amount;运行时无法解析或解析后小于等于 0 时,不会在成功对象中追加有效 expected_amount
不要这样假设。它会记录期望金额并在成功返回对象里给出 amount_matched。部分通道或下单方式可能用期望金额辅助匹配,但插件业务仍应在发货前检查 amount_matched

atWaitPay()

判断当前运行时是否存在等待支付流程。
方法参数返回
atWaitPay()Promise<boolean>
if (await sender.atWaitPay()) {
  await sender.reply('已有支付等待中,请稍后。')
}

下一步

事件和媒体项

查看等待输入后如何读取用户上传文件。

支付插件权限和配置

查看 manifest header 和参数声明。
Last modified on June 3, 2026