Repository navigation
Plugin Extension Points
扩展点是内核和插件之间的能力注入机制。插件通过 ctx.registerExtension() 向扩展点注册实现,内核或其他插件通过 ctx.getExtensions() 读取。
下表的「消费方」指谁调用 ctx.getExtensions(pointId):内核自己消费的即 KERNEL_EXTENSION_POINTS,其余由 store 插件(或预留)消费。
| 扩展点 ID | 用途 | 接口类型 | 消费方 |
|---|---|---|---|
auth.provider |
认证提供者 | AuthProvider |
内核 |
payment.provider |
支付提供者 | PaymentProvider |
内核 |
payment.settlement |
支付结算 | PaymentSettlementHandler |
内核 |
commerce.operations |
商业域操作(商品/订单/交付物) | CommerceOperations |
内核 |
seo.provider |
站点 SEO 输送(sitemap/feed 等) | SeoProvider |
内核 |
web.nav |
导航项 | NavItem |
内核 |
ui.admin.dashboard |
管理面板 Widget | AdminDashboardWidgetMeta |
内核 |
fulfillment.provider |
履约/交付物提供方 | FulfillmentProvider |
store |
store.productType |
商品类型插件(类型定义+本地履约) | ProductTypeProvider |
store |
upstream.product.source |
上游商品数据源(商品表单关联) | UpstreamProductSource |
store |
notification.channel |
通知外部渠道(预留,无消费方) | 插件实现,监听 notification.created
|
— |
routes |
预留(路由已改为声明式 routes) |
PluginRoute |
— |
event.listener |
预留(监听已改为声明式 eventListeners) |
PluginEventListener |
— |
onActivate(ctx) {
// 注册导航项
ctx.registerExtension('web.nav', {
surface: 'admin',
label: '商品管理',
href: '/admin/my-plugin',
});
// 注册 Dashboard Widget
ctx.registerExtension('ui.admin.dashboard', {
id: 'my-widget',
title: '销售统计',
description: '销售数据概览',
});
}registerExtension 返回一个取消注册函数。通常不需要手动调用——插件停用时会自动清理。
onActivate(ctx) {
const providers = ctx.getExtensions<AuthProvider>('auth.provider');
for (const provider of providers) {
ctx.logger.info(`认证提供者: ${provider.id} (${provider.name})`);
}
}第三方认证提供者(如 WowID):
interface AuthProvider {
readonly id: string;
readonly name: string;
authorizeUrl?(
state: string,
options?: { codeChallenge?: string; nonce?: string },
): string | undefined;
authenticate(credential: unknown): Promise<AuthIdentity | null>;
}
interface AuthIdentity {
externalId: string;
email?: string;
displayName?: string;
}内核编排 OAuth 舞蹈:authorizeUrl 构建授权 URL,authenticate 交换凭证并返回身份。内核负责创建/匹配本地用户和签发 session。
外部支付提供者(如易支付):
interface PaymentProvider {
readonly id: string;
readonly name: string;
readonly mode: 'gateway' | 'manual';
readonly callbackPath: string; // 如 '/callbacks/epay'
getMethods(): PaymentMethod[];
createPayment(
request: ExternalPaymentRequest,
config?: unknown,
): Promise<ExternalPaymentInitiationResult>;
closePayment?(request: { merchantOrderNo: string; externalId?: string | null }): Promise<boolean>;
}createPayment 返回 ExternalPaymentInitiationResult:网关型返回 { externalId, paymentUrl, expiresAt? },手工型返回 { mode: 'manual', instructions }(银行转账/二维码等买家指引)。callbackPath 是提供者插件自己注册的回调路由路径,用于接收支付网关的异步通知。
支付结算处理器,由业务插件(如 store 的订单域)注册,内核在结算时同步调度:
interface PaymentSettlementHandler {
settle(
payment: ResolvedPaymentSettlement,
): Promise<{ applied: boolean; purpose: 'ORDER' | 'TOP_UP' }>;
release?(payment: ResolvedPaymentSettlement): Promise<{ applied: boolean }>;
}- 调度方是内核
PaymentService(ctx.payments.settle),不再是支付提供者插件。 - 网关插件(epay/zjmf)回调验签后调
ctx.payments.settle,不直接调用本处理器。 -
TOP_UP目的由内核直接入账钱包,不经过处理器;ORDER目的按注册顺序调度, 取第一个成功者。 - 处理器必须幂等——同一笔结算重复调用不应产生副作用。
- 内核还提供
ctx.payments的create/release/cancel/sweepExpired与ctx.wallet的credit/debit/adjust/listLedger等平台能力,供任意插件使用。 - 支付与钱包属于内核服务,不由某个插件实现:网关插件只负责发起支付与回调验签,
结算由内核
PaymentService统一编排。
导航项注入到平台导航:
interface NavItem {
surface: 'public' | 'account' | 'admin';
label: string;
href: string;
}GET /nav/:surface 端点会聚合内核默认导航和插件注入的导航项。
管理面板 Dashboard Widget:
interface AdminDashboardWidgetMeta {
id: string;
title: string;
description?: string;
}GET /admin/ui/widgets 端点返回所有激活插件贡献的 Widget,包含 pluginId。Widget 的渲染组件需在插件 frontend 包的 ui.adminWidgets 中以 Widget id 为键声明。
插件可以在 manifest 中声明 provides 和 consumes,用于激活时的依赖校验:
{
"provides": ["my-plugin.widget"],
"consumes": [{ "pluginId": "store", "extensionPoint": "payment.provider", "optional": true }]
}-
provides:本插件向其他插件提供的扩展点 ID -
consumes:本插件需要消费的扩展点。optional: true表示即使目标未提供也不阻止激活
详见 插件依赖。
核心开发
插件开发
主题开发
前端包开发
RESTful API