跳到正文

集成

本页内容

JavaScript Low-Code SDK

给任何网页添加可配置的支付按钮,自选金额来源和主题,无需搭建后端表单即可打开 Paymos 收银台。

Low-Code SDK 让你把支付按钮直接嵌入网站。客户点击时,SDK 解析付款金额,用你的公开 SDK key(pk_...)创建账单,并打开收银台表单——iframe 弹窗整页重定向

Low-Code SDK 是 POST /v1/invoicespayment_url 返回的那个托管收银台页面的便捷封装;iframe 模式下它以 ?embed=true 打开该收银台。原始重定向和手动 iframe 契约见 托管收银台

底层上,SDK 向 https://paymos.io/public/v1/sdk 发 POST——与提供 paymos-widget.js 的同一来源——你的 key 放在 X-Sdk-Key 请求头。

如果没有可用金额且你传了 pos_url,按钮改为打开 Terminal 页面——一个手动输入金额的数字键盘。没有 pos_url 时,无金额可解析的点击会抛错并发出 paymos:error

工作流程

  • 01在页面中加入 SDK 脚本和挂载点
  • 02调用 PaymosWidget.mount(),传入 api_keyproject_id 和选项
  • 03客户点击按钮
  • 04SDK 解析金额(静态值、回调或输入框选择器)
  • 05有金额——SDK 创建账单并打开收银台
  • 06无金额且设了 pos_url——SDK 打开该 URL 的 Terminal 数字键盘
  • 07无金额且无 pos_url——SDK 抛错并发出 paymos:error
  • 08付款被处理——webhook 发送到你注册的 webhook URL

安装

<script src="https://paymos.io/v1/paymos-widget.js"></script>
<div id="paymos-widget"></div>

解析金额

SDK 在按钮被点击的那一刻解析付款金额,按以下顺序取第一个可用来源:

  • 01amount——配置中传入的固定十进制字符串。适合单商品页或固定价格条目。
  • 02get_amount()——返回十进制字符串金额的回调函数。总额动态计算(如购物车)时使用。
  • 03amount_selector——指向 <input> 元素的 CSS 选择器。SDK 在点击时读取它的 .value。适合客户自己输入金额的场景。

如果以上都返回不了有效的正数十进制字符串,SDK 打开你 pos_url 指向的 Terminal——一个手动输入金额的数字键盘。如果没设 pos_url,该点击抛出 PaymosWidget requires an amount, amountSelector, or price_id.,收银台不会打开。

// Fixed price (price_id) — RECOMMENDED for fixed products.
// Create the price once in the dashboard; the server resolves the amount and
// currency from it, so a buyer cannot change them in DevTools. No amount in the embed.
PaymosWidget.mount('#paymos-widget', {
  api_key: 'YOUR_PUBLIC_KEY',
  price_id: 'price_YOUR_PRICE_ID'
});

// Fixed amount — client-supplied (editable in the browser; use for donations / free-amount)
PaymosWidget.mount('#paymos-widget', {
  api_key: 'YOUR_PUBLIC_KEY',
  project_id: 'prj_YOUR_PROJECT_ID',
  amount: '25.00',
  currency: 'USD'
});

// Dynamic amount — computed at click time
PaymosWidget.mount('#paymos-widget', {
  api_key: 'YOUR_PUBLIC_KEY',
  project_id: 'prj_YOUR_PROJECT_ID',
  get_amount: () => calculateCartTotal().toFixed(2),
  currency: 'USD'
});

// Input selector — reads value from an <input> element
PaymosWidget.mount('#paymos-widget', {
  api_key: 'YOUR_PUBLIC_KEY',
  project_id: 'prj_YOUR_PROJECT_ID',
  amount_selector: '#donation-amount',
  currency: 'USD'
});

两种集成模式

SDK 暴露两个入口。按页面需要任选其一:

mount(selector, opts)——SDK 渲染按钮

SDK 把一个完整样式、开箱即用的支付按钮注入目标元素(文字来自 label 选项,默认 "Support with crypto")。适合单商品页、简单落地页、捐赠挂件——任何你不想写 CSS 的地方。

<script src="https://paymos.io/v1/paymos-widget.js"></script>
<div id="paymos-widget"></div>
<script>
  PaymosWidget.mount('#paymos-widget', {
    api_key: 'pk_live_…',
    project_id: 'prj_…',
    amount: '25.00',
    currency: 'USD',
    label: 'Support with crypto'
  });
</script>

open(opts)——你渲染按钮,SDK 打开浮层

你完全掌控按钮 DOM(你的设计系统、你的 CSS、你的图标),在点击处理器里调用 PaymosWidget.open(opts)。适合多套餐定价页、购物车、自定义 UI 框架(React、Vue、Svelte 组件)。

<button id="buy-growth">Subscribe to Growth — $79/mo</button>
<script>
  document.getElementById('buy-growth').addEventListener('click', function () {
    PaymosWidget.open({
      api_key: 'pk_live_…',
      project_id: 'prj_…',
      amount: 79,
      currency: 'USD',
      client_id: 'plan:growth'
    });
  });
</script>

两种模式打同一个后端、发同样的 webhook、发同样的 window 事件。区别纯粹在按钮样式由谁负责——open() 也是控制台打开演示链接启动的方式(一个带三个独立样式按钮的定价页,全部走同一个共享浮层)。

何时用 SDK,何时用 REST API

Low-Code SDK 是浏览器侧工具——在没有后端的静态 HTML 页面上放一个支付按钮。因此它非常适合:

  • 捐赠 / 打赏(客户自选金额)
  • POS / 收银台流程(店员输入金额)
  • 自由金额挂件("你来定价")
  • 内部沙箱 / 预发布演示

凡是价格由你侧固定的场景(订阅、数字商品、实体订单、课程、许可证),记住金额就在页面里、可以从 DevTools 改——有决心的客户可以给你的 $99 套餐提交 0.01。改用你服务器上的 REST API 配 secret key。SDK 没有缺陷;这是所有客户端收银台(Stripe、LemonSqueezy、PayPal)共有的标准分工:页面上放公开 key,服务器上放 secret key。

配置

参数 类型 必填 说明
api_key string 控制台中的公开 SDK key(pk_...
project_id string 是,除非提供 price_id 项目标识(prj_...
price_id string 控制台中创建的固定价格(price_...)。服务器从中解析金额和币种,买家无法修改——固定价格商品推荐用它。优先于下面所有金额来源
amount string | number 固定付款金额,十进制字符串或数字
get_amount function 点击时返回十进制字符串金额的回调
amount_selector string 含金额的输入框的 CSS 选择器
currency string 法币代码(USDEUR 等)。默认:USD
client_id string 你的内部客户 ID(附在账单上)
mode string "iframe"(默认)——弹窗浮层。"redirect"——整页跳转
label string 按钮文字。默认:"Support with crypto"
width string "auto"(默认)或 "full"(100% 宽度)
accent_color string 按钮强调色(hex)。默认:#ff6b35
text_color string 按钮文字颜色(hex)。默认:#ffffff。只有你同时传了自定义 accent_color 时才做对比度检查:你的颜色对它达到 4.5
就保留,否则 SDK 按实测对比度改用黑色或白色。用出厂强调色时不做检查,你给的值原样生效
radius number 按钮圆角,0-32 px。默认:18
frame_title string iframe 元素的无障碍标题。默认:"Paymos checkout"
aria_label string 弹窗对话框的无障碍名称。默认:"Paymos checkout"
pos_url string 你的 POS/Terminal 页面 URL。设置后,无金额可解析时按钮打开 Terminal
target string "_self"(默认)或 "_blank"(仅 redirect 模式)
auto_close_delay number 成功页在弹窗自动关闭前保持显示的毫秒数。默认:0(禁用)。弹窗内任何用户交互都会取消它
haptics boolean 在支持的平台上启用短震动反馈(Android、部分 PWA)。iOS Safari 忽略 Vibration API——那里为空操作。遵循 prefers-reduced-motion。默认:true
timeout number 账单创建请求中止前的毫秒数。必须为正数;其他值回退到默认值。默认:30000
debug boolean 向控制台输出完整 Error 对象而非仅消息。默认:false

完整示例

<script src="https://paymos.io/v1/paymos-widget.js"></script>

<div id="paymos-widget"></div>

<script>
  PaymosWidget.mount('#paymos-widget', {
    api_key: 'YOUR_PUBLIC_KEY',
    project_id: 'prj_YOUR_PROJECT_ID',
    amount: '25.00',
    currency: 'USD',
    label: 'Support with crypto',
    mode: 'iframe',
    accent_color: '#FF6B35',
    text_color: '#FFFFFF',
    radius: 20
  });
</script>

编程式 API

也可以不挂载按钮直接打开收银台:

// Open checkout programmatically (no button)
await PaymosWidget.open({
  api_key: 'YOUR_PUBLIC_KEY',
  project_id: 'prj_YOUR_PROJECT_ID',
  amount: '50.00',
  currency: 'USD',
  mode: 'iframe'
});

// Close the modal
PaymosWidget.close();

// Remove the button and clean up
PaymosWidget.destroy('#paymos-widget');

事件

SDK 在 window 上派发 CustomEvent,让你的页面响应收银台生命周期。所有负载在 event.detail 上。

事件 触发时机 event.detail
paymos:opened 弹窗已挂载且 iframe URL 已设置 { url }
paymos:closed 弹窗被移除(任何原因,包括可选的 auto_close_delay 计时器触发) { reason: 'escape' | 'iframe' | 'replaced' | 'api' | 'success' }
paymos:succeeded 客户付款达到 paidpaid_over。由 iframe 内通过 postMessage 发出 { invoiceId }
paymos:failed 终态失败(underpaidexpiredcancelled { invoiceId, reason }
paymos:error SDK 连账单都没能创建(网络/认证/CORS/超时) { message }

succeeded / failed 事件只在收银台以 iframe 模式打开时触发——由付款页调用 window.parent.postMessage 投递。SDK 只接受来自它所嵌入收银台 URL 来源、且来自该 iframe 自身 contentWindow 的消息,因此商户页面上的任何第三方都无法伪造它们。

redirect 模式的收银台在结果已知前页面已跳走,因此用你服务器上的 webhook 确认结算。

// 1. The customer paid — auto-close the modal and redirect to a thank-you page.
window.addEventListener('paymos:succeeded', (e) => {
  console.log('Paid:', e.detail.invoiceId);
  PaymosWidget.close();
  // Absolute and on your own domain: a root-relative path in a published
  // code sample gets crawled as one of OUR URLs — Googlebot did exactly that
  // and filed /thank-you?order= as a 404 against paymos.io.
  window.location.href = 'https://your-shop.example/thank-you?order=' + e.detail.invoiceId;
});

// 2. Payment failed (underpaid / expired / cancelled).
window.addEventListener('paymos:failed', (e) => {
  console.warn('Payment failed:', e.detail.invoiceId, e.detail.reason);
  // e.detail.reason: 'underpaid' | 'expired' | 'cancelled'
});

// 3. Modal lifecycle.
window.addEventListener('paymos:opened',  (e) => console.log('Opened',  e.detail.url));
window.addEventListener('paymos:closed',  (e) => console.log('Closed',  e.detail.reason));
//   e.detail.reason: 'escape' | 'iframe' | 'replaced' | 'api' | 'success'

// 4. Invoice creation failed (network down, bad config, server error).
window.addEventListener('paymos:error', (e) => {
  console.error('SDK error:', e.detail.message);
});

允许的来源

SDK 只在与你挂件设置中配置的允许的来源匹配的域名上工作。来自其他来源的请求会被拒绝。

Terminal 回退

回退是可选的:把 pos_url 指向你的 Terminal 页面。当解析不到有效金额(没有 amountget_amount() 返回 null,或 amount_selector 输入框为空)时,SDK 打开该 URL——一个手动输入金额的数字键盘。适合每笔交易金额都不同的销售点场景。

不设 pos_url 时,同样的情况改为抛出 PaymosWidget requires an amount, amountSelector, or price_id.,以 paymos:error 事件到达你的页面。