npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@seaart/payment-checkout-embed

v0.1.5

Published

SeaArt embeddable payment checkout Web Component

Readme

@seaart/payment-checkout-embed

可嵌入的 SeaArt 收银台 Web Component,负责支付方式展示、支付 SDK 挂载、3DS、跳转支付和订单状态轮询。

它不负责计算商品价格、读取宿主的 Cookie/localStorage,也不会推断用户、商品或权益信息。建单支持两种明确模式:payment-hub 交易模式和主站商品驱动模式。

选择接入模式

| 模式 | 适用场景 | 是否传 transactionId | 建单时机 | | --- | --- | --- | --- | | openPaymentCheckout | 调用方已有 payment-hub transaction | 是 | 由 payment-hub 处理 | | openBusinessPaymentCheckout | 宿主先创建 payment-hub transaction | 业务页不传,Adapter 返回 | 打开收银台前 | | openMainSitePaymentCheckout | SeaArt 主站商品、订阅、算力、礼包等 | 否 | 用户选择支付方式并确认后 |

安装

npm install @seaart/payment-checkout-embed

该包仅能在浏览器中运行。SSR 项目请在客户端动态导入,或放在 ClientOnly 中渲染。

主站商品驱动方式

主站当前 PaymentForm 不是先创建 payment-hub transaction:它会先加载支付策略,随后根据商品类型、支付渠道、试用、数量和来源创建订单。因此主站接入请使用 openMainSitePaymentCheckout,不要把 goodsId、主站订单号或任意业务 ID 填入 transactionId

import { openMainSitePaymentCheckout } from '@seaart/payment-checkout-embed';

const checkout = openMainSitePaymentCheckout({
  businessContext: {
    productType: 'computing',
    goodsId: 'calculate_1000',
    quantity: 1,
    productInfo,
    purchParams: { discount_type: 'recommend_calculate' },
    pageFrom: 'VipComputingDialogV3',
    dotFrom: 'vip_computing_recommend',
  },
  // 每次打开都生成新的关联号,用于 success / unsuccess / close 生命周期关联。
  checkoutReference: crypto.randomUUID(),
  runtimeConfig: {
    baseUrl: window.location.origin,
    credentials: 'include',
  },
  adapter: {
    // 复用主站已确认的 init-context / 支付策略聚合逻辑,返回收银台上下文。
    loadCheckoutContext: (context, signal) => loadMainSiteCheckoutContext(context, signal),
    // 复用主站 PaymentParamsBuilder + PaymentAPIManager 的商品类型分流逻辑。
    createPayment: (context, paymentParams, signal) => createMainSiteOrder(context, paymentParams, signal),
    getOrderStatus: (context, orderId, signal) => getMainSiteOrderStatus(context, orderId, signal),
    checkThreeDs: (context, params, signal) => checkMainSiteThreeDs(context, params, signal),
  },
  language: 'zhCN',
  onSuccess: (result) => {
    refreshHostEntitlements(result);
    checkout.remove();
  },
  onClose: () => checkout.remove(),
});

checkoutReference 必须在每次打开时唯一。主站模式的 success / unsuccess 事件返回该字段和真实 orderId(成功或已建单后),不会伪造 transactionIdadapter.checkThreeDs 是必填项,即使当前商品未触发 3DS;它必须返回 { status: { code: number, msg?: string }, data?: { order_id?: string } } 完整响应壳,不能只返回 data。缺失或结构不符时公共包会报出明确配置错误,绝不回退调用 payment-hub 3DS 接口。

adapter 是业务边界,公共包不会硬编码主站内部的 /api/v1/payment/order/createcreate-subcreate-gift-order 等接口。调用方必须复用主站现有的商品参数构建和接口分流,保证试用、礼包、升级、数量、优惠和幂等规则一致。

Adapter 详细契约

adapter 的四个方法均为必填。公共包只处理收银台状态、SDK 和轮询;商品定价、支付接口选择、订单幂等与权益刷新均由主站负责。

type MainSiteCheckoutAdapter<TContext> = {
  loadCheckoutContext(context: TContext, signal?: AbortSignal): Promise<TransactionResponse>;
  createPayment(
    context: TContext,
    params: CreatePaymentParams,
    signal?: AbortSignal,
  ): Promise<CreatePaymentResponse>;
  getOrderStatus(context: TContext, orderId: string, signal?: AbortSignal): Promise<OrderStatus>;
  checkThreeDs(
    context: TContext,
    params: CheckThreeDsParams,
    signal?: AbortSignal,
  ): Promise<CheckThreeDsResponse>;
};

loadCheckoutContext

打开收银台时调用一次。它负责调用主站的支付初始化接口,并适配为收银台上下文;不能在公共包中硬编码主站接口。

最小返回结构如下,payment_strategy 中的支付方式决定展示内容和可用渠道:

return {
  price: product.price,
  product_name: product.name,
  local_price: {
    price: product.localPrice,
    code: product.currency,
    currency: product.currency,
    price_old: product.originalPrice,
  },
  country_code,
  payment_strategy,
  adyen_payment_methods,
  adyen_config,
  adyen_card: cardList.find((item) => item.channel_type === 9) || null,
  payermax_card: cardList.find((item) => item.channel_type === 1) || null,
  payermax_params_by_purchase_type,
  subscription: isSubscription ? { period: 'month', period_amount: renewalAmount } : null,
};

payment_strategy.sub_payment_method_items 代表可订阅的支付方式,single_payment_method_items 代表一次性支付方式。支付条目应保留后端的 idnametypeinteraction_typelogochannel_idchannel_typeprev_pay_type

主站商品驱动模式会隐藏 Airwallex 支付方式;payment-hub 模式严格按后端 payment_strategy 展示,不做该渠道过滤。

createPayment

用户点击支付后调用。context 是调用方传入的商品业务上下文;params 是公共包根据当前渠道生成的支付参数:

{
  transactionId,   // 主站模式中是 checkoutReference,仅用于前端生命周期关联
  from,
  thirdPlatType,   // 渠道类型,例如 1=PayerMax、9=Adyen
  usePayType,      // 例如 VISA、scheme、paypal
  origin,
  oneClick,
  thirdExtra,      // Adyen payment_method/browser_info;PayerMax payment_token/session_key
}

主站必须根据 context.productType、试用、升级、礼包、数量和优惠,复用现有的 createcreate-sub 等业务建单逻辑;并透传渠道所需的 thirdExtra。不要将 params.transactionId 当作主站订单号提交,也不要记录 payment_tokensession_key 等敏感字段。

返回值必须统一为:

{
  order_id: '主站真实订单号',
  payment_url: '可选,跳转或 3DS 地址',
  result: '可选,Adyen action 的 JSON 字符串',
  check_three_ds2: false,
}

order_id 是进入等待支付和轮询的必要字段。没有 order_id 时应视为建单失败,不能只返回 payment_url

getOrderStatus

外部跳转、3DS 和关闭前确认都会调用。必须按传入的真实 orderId 查询,并返回:

{
  id: orderId,
  status: 1 | 0 | -1, // 1=成功,0=待支付,-1=失败
  status_desc: '可选状态说明',
  price: 5.99,        // 可选,成功回调金额
}

checkThreeDs

仅 Adyen 3DS 流程调用。必须将 three_ds_resultorder_id 和可选的 adyen_payment_method 传给主站的 3DS 校验接口,并保留完整响应壳:

{
  status: { code: 10000, msg: 'ok' },
  data: { order_id: '主站真实订单号' },
}

不能只返回 data,也不能在主站模式下回退请求 payment-hub 的 3DS 接口。

主站接口字段映射

以下映射对应主站当前已封装的接口,Adapter 应在宿主侧调用这些函数后再转换返回值。公共包不会直接请求这些 URL。

初始化上下文:loadCheckoutContext

| 主站接口 | 请求字段 | 响应字段 | 映射到公共包上下文 | | --- | --- | --- | --- | | POST /api/v1/payment/init-context | country_code | payment_strategy | payment_strategy | | 同上 | - | payment_methods / adyen_payment_methods | adyen_payment_methods | | 同上 | - | card_listchannel_type === 9 | adyen_card | | 同上 | - | card_listchannel_type === 1 | payermax_card | | 主站商品信息 | 商品名、价格、币种、续费金额 | - | product_namepricelocal_pricesubscription | | POST /api/v1/payment/order/pre-pay | 主站现有预支付请求参数 | common_client_keycommon_session_key | payermax_params_by_purchase_type.common.client_key/session_key | | 同上 | - | sub_client_keysub_session_key | payermax_params_by_purchase_type.sub.client_key/session_key |

init-contextpayment_strategy 是支付方式的唯一来源。其 sub_payment_method_itemssingle_payment_method_items 中的原始字段应原样保留,不要在 Adapter 内改写渠道类型或支付方式类型。

创建订单:createPayment

普通商品使用主站 POST /api/v1/payment/order/create,订阅商品使用 POST /api/v1/payment/order/create-sub。其他商品类型由 businessContext.productType 复用主站既有建单分支。

| 主站建单字段 | 来源 | | --- | --- | | cp_product_id | context.goodsId | | quantity | context.quantity,缺省时由主站业务规则决定 | | third_plat_type | params.thirdPlatType | | use_pay_type | params.usePayType | | payment_methodbrowser_info | params.thirdExtra,供 Adyen 使用 | | payment_tokensession_key | params.thirdExtra,供 PayerMax 使用;不得写日志 | | page_location | context.pageFrom 或调用方约定的页面来源 | | sub_source | params.oneClick ? 'one_click' : 'manual' | | os | 主站 Web 固定使用 '1' | | 试用、升级、优惠、礼包等 | context.purchParamscontext.apiParams 与主站已有参数构建器 |

主站接口返回的 ThirdOrderId / order_id 映射为 CreatePaymentResponse.order_idPaymentUrl / payment_url 映射为 payment_urlResult / result 映射为 result

订单状态:getOrderStatus

调用 POST /api/v1/payment/order/status,请求体固定为:

{ order_id: orderId }

将主站响应映射为公共包状态:is_paid === truestatus: 1,明确失败为 status: -1,其余为 status: 0;响应中的 order_id/order_no 映射为 idusd_price 映射为可选 price

3DS 校验:checkThreeDs

调用 POST /api/v1/payment/adyen/check-three-ds2,请求字段与公共包参数一一对应:

| 主站请求字段 | 公共包参数 | | --- | --- | | three_ds_result | params.three_ds_result | | order_id | params.order_id | | adyen_payment_method | params.adyen_payment_method,存在时透传 |

返回主站原始 { status, data },不能解包成 data 后返回。

主站 SDK 配置

loadCheckoutContext 除支付策略、绑卡和 Adyen 配置外,还必须返回主站已取得的渠道 SDK 配置。公共包不会自行请求主站的预支付接口,也不会推断测试或生产环境。

PayerMax 使用普通购买与订阅购买两套独立会话。主站应先调用现有的 /api/v1/payment/order/pre-pay,再将结果映射为:

return {
  // ...payment_strategy、adyen_payment_methods、adyen_config、card_list 等上下文
  payermax_params_by_purchase_type: {
    common: {
      client_key: prePay.common_client_key,
      session_key: prePay.common_session_key,
      sandbox: isDevelopment ? 1 : 0,
    },
    sub: {
      client_key: prePay.sub_client_key,
      session_key: prePay.sub_session_key,
      sandbox: isDevelopment ? 1 : 0,
    },
  },
};

公共包会根据支付策略条目来源选择会话:sub_payment_method_items 使用 subsingle_payment_method_items 使用 common。缺少某一类会话时仅隐藏该类 PayerMax 方式,不影响另一类方式或其他渠道。旧的 payermax_params 仍保留给 payment-hub 单会话模式兼容使用。

payment-hub 业务适配方式

主站及大多数业务调用方应使用 openBusinessPaymentCheckout。调用方只传递自己的商品上下文,例如 goodsId、商品类型、数量和业务来源;由宿主的 createTransaction Adapter 创建业务订单和 payment-hub transaction。

transactionId 仍是支付中心内部必需的交易标识,但不需要暴露给业务页面或用户输入。

import { openBusinessPaymentCheckout } from '@seaart/payment-checkout-embed';

const checkout = await openBusinessPaymentCheckout({
  businessContext: {
    productType: 'computing',
    goodsId: 'calculate_1000',
    quantity: 1,
    pageFrom: 'mall',
    dotFrom: 'mall_checkout',
  },
  // 该函数属于宿主业务层:先创建主站业务订单,再创建 payment-hub transaction。
  // 不能把 goodsId 或旧渠道订单号直接作为 transactionId 使用。
  createTransaction: async (context) => {
    const transaction = await createMainSitePaymentTransaction(context);
    return {
      transactionId: transaction.transactionId,
      userName: transaction.userName,
      productName: transaction.productName,
    };
  },
  language: 'zhCN',
  baseUrl: 'https://payment-api.example.com',
  runtimeConfig: {
    baseUrl: 'https://payment-api.example.com',
    credentials: 'include',
  },
  onSuccess: (result) => {
    refreshHostEntitlements(result);
    checkout.remove();
  },
  onUnsuccess: (result) => reportPaymentFailure(result),
  onClose: () => checkout.remove(),
});

createTransaction 必须返回:

type PaymentCheckoutTransaction = {
  transactionId: string;
  userName?: string;
  productName?: string;
};

主站 Adapter 负责将商品上下文转换为已确认的建单接口参数。价格、订单号、用户身份、国家/IP、订阅周期和幂等控制必须由宿主后端或主站既有业务接口确定,公共包不会构造这些字段。

底层方式:已有交易 ID 时调用

当调用方已通过自己的后端创建了 payment-hub transaction,可使用 openPaymentCheckout

import { openPaymentCheckout } from '@seaart/payment-checkout-embed';

const checkout = openPaymentCheckout({
  transactionId: transaction.transactionId,
  language: 'en',
  baseUrl: 'https://payment-api.example.com',
  runtimeConfig: {
    baseUrl: 'https://payment-api.example.com',
    authToken: getHostIssuedToken(),
    credentials: 'omit',
  },
  onSuccess: (result) => {
    refreshHostEntitlements(result);
    checkout.remove();
  },
  onClose: () => checkout.remove(),
});

Web Component 方式

该方式适用于已有 transactionId 的低层接入。请在元素连接前同步调用 configure

<div id="checkout-container"></div>

<script type="module">
  import './node_modules/@seaart/payment-checkout-embed/dist/seaart-payment-checkout.mjs';

  const checkout = document.createElement('seaart-payment');
  checkout.setAttribute('transaction-id', transaction.transactionId);
  checkout.setAttribute('language', 'en');
  checkout.setAttribute('base-url', 'https://payment-api.example.com');
  checkout.configure({
    baseUrl: 'https://payment-api.example.com',
    credentials: 'include',
  });
  checkout.addEventListener('success', (event) => {
    refreshHostEntitlements(event.detail);
    checkout.remove();
  });
  checkout.addEventListener('close', () => checkout.remove());
  document.querySelector('#checkout-container').appendChild(checkout);
</script>

参数说明

openBusinessPaymentCheckout

| 参数 | 必填 | 说明 | | --- | --- | --- | | businessContext | 是 | 宿主业务上下文。主站可传 productTypegoodsIdquantitypurchParamsapiParamsproductInfoisSubscriptionisFreeTryupgradepageFromdotFrom。 | | createTransaction | 是 | 宿主建单 Adapter,必须返回 { transactionId, userName?, productName? }。 | | baseUrl | 是 | payment-hub API 地址;包内不内置默认 host。 | | language | 否 | 内置语言,如 enzhCNzhTWja。 | | runtimeConfig | 否 | 请求运行配置,见下表。 | | container | 否 | 收银台挂载容器,默认 document.body。 | | onReady/onStateChange/onSuccess/onUnsuccess/onClose | 否 | 收银台生命周期回调。 |

runtimeConfig

| 参数 | 默认值 | 说明 | | --- | --- | --- | | baseUrl | 无 | payment-hub API 地址,必填。 | | authToken | 无 | Bearer Token。Cookie 鉴权时不传。 | | credentials | omit | Cookie 策略:includeomit。 | | headers | 无 | 附加请求头。不要放入业务密钥或支付凭据。 | | timeout | 20000 | 单请求超时,单位毫秒。 |

运行中的请求配置不可修改。需要刷新 token、切换 API 地址或重新建单时,请关闭并移除旧组件后重新打开。

事件

| 事件 | event.detail | | --- | --- | | ready | 无 | | statechange | 支付状态,例如 processingwaiting_redirectcompleted。 | | success | { orderId, amount, currency, transactionId } | | unsuccess | { reason, message, transactionId, orderId? } | | close | 无 |

安全边界

  • 包只使用调用方显式传入的 baseUrl、token、headers 和 Cookie 策略。
  • 包不读取 Cookie、localStoragesessionStorage,也不创建可信用户身份和价格。
  • 商品价格、主站订单、支付 transaction、用户身份、IP/国家、权益刷新和最终支付结果校验必须由宿主后端或主站业务层负责。
  • payment API 必须允许宿主来源的 CORS,并为该来源返回可用的支付 SDK 配置。

构建

pnpm --filter @seaart/payment-checkout-embed build