JustFlows

Shop / Integrations

Extend Shop from another plugin

Another plugin can add payment gateways and shipping carriers with two filters. Register them in activate(); they disappear when that plugin is deactivated.

ts
ctx.hooks.filter("justflows.shop.payments.gateways", (gateways) => [
  ...gateways,
  {
    id: "acme-pay",
    name: "Acme Pay",
    manual: false,
    managed: false,
    capabilities: ["intent", "capture", "refund", "webhooks", "sandbox"],
    fields: [
      { id: "publicKey", label: "Public key", secret: false },
      { id: "secretKey", label: "Secret key", secret: true },
    ],
  },
]);

ctx.hooks.filter("justflows.shop.shipping.carriers", (carriers) => [
  ...carriers,
  {
    id: "acme-post",
    name: "Acme Post",
    origins: ["NL", "BE"],
    services: [{ id: "standard", label: "Acme Standard" }],
    capabilities: ["rates", "tracking"],
  },
]);
FieldRules
idLower-kebab (acme-pay). Duplicates are dropped.
nameRequired, up to 80 characters.
manual (gateway)true for offline methods such as bank transfer. Manual gateways may not have secret fields.
managed (gateway)true for a managed account from a companion plugin, such as Justflows Payments.
capabilities (gateway)Any of intent, confirm, authorize, capture, partial_capture, void, refund, partial_refund, webhooks, reconcile, tokenize, pending, disputes, fees, sandbox.
fields (gateway)Settings shown on the Payments page. secret: true values go to plugin secrets and are never sent to the browser.
origins (carrier)ISO country codes the carrier collects from. Empty means any origin.
capabilities (carrier)Any of rates, labels, tracking, pickup, returns, customs, address.

Filter rules

Append, don't replace. The list you return replaces Shop's list, so dropping entries hides the built-in gateways or carriers. Invalid entries are dropped silently. Shop only calls the APIs of its built-in providers; calling your provider is your plugin's job.

Products are ordinary content, so core webhooks already notify other systems when a product is created, updated, published, unpublished, or deleted. Act only on events where data.type is product. Shop also sends its own versioned events through core webhooks, with HMAC signatures, retries, and delivery history: justflows.shop.order.created, .paid, .payment_failed, .cancelled, .refunded, .shipped, and .delivered; justflows.shop.subscription.started, .renewed, .payment_failed, .updated, and .ended; and justflows.shop.stock.low. Payload types are exported from justflows.shop/contracts.

More filters let other plugins add commerce features: justflows.shop.tax.providers (tax rates per address from an outside service; checkout stops instead of charging the wrong tax when it does not answer), justflows.shop.discounts.promotions (promotions applied like Shop's own discounts), and justflows.shop.catalog.product_types (types such as tickets or bookings, with an optional check before an item can be bought). Carrier adapters can supply rates, createLabel, and track, and justflows.shop.subscriptions.entitlements reports when a plan's resources are given or taken back.

Another plugin can bill through Shop with POST /api/shop/orders/unpaid: it sends lines of { title, quantity, unitMinor } in the store currency and gets back orderId, number, and paymentUrl. Staff with Create orders can name the customer (customerUserId); a signed-in customer can open an order only for themselves. The order, its invoice, and its payment stay in Shop. Mollie has to be on. See the Shop developer reference for the v1 API, events, and extension points.