Search by

There is no license information available for the latest version (2.0.0) of this package.

Package info

github.com/DeliveryMatch/pdk

pkg:composer/deliverymatch/pdk

Statistics

Installs: 149

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

2.0.0 2026-09-17 09:49 UTC

This package is auto-updated.

Last update: 2026-09-17 09:50:18 UTC


README

The DeliveryMatch Plugin Development Kit (PDK) is built for creating easy integrations with PHP E-commerce platforms. This library is a wrapper around the SDK

Requirements

Getting Started

Install the package using Composer:

composer require deliverymatch/pdk

The PDK needs two things from your platform before it can be used:

  1. A Repository: durable storage for checkout state, keyed by a checkout reference.
  2. A CheckoutContext: tells the PDK which checkout the current request belongs to.

The checkout reference is an opaque string your platform chooses, typically the cart or quote id. It must be stable for the whole lifetime of a checkout and reproducible from server-side code (payment webhooks, order validation hooks, cron jobs), because that is where the PDK has to find the shipment id after the shopper has left the storefront.

Implement the Repository interface

Every Repository method takes the checkout reference as its first argument. Implementations store and read data per reference and must not fall back on cookies, sessions or other request-bound state to decide which checkout a call applies to. A database table is the recommended storage: it is reachable from any request, including the ones the shopper's browser is not making.

CREATE TABLE dm_checkout (
    checkout_reference VARCHAR(64) NOT NULL PRIMARY KEY,
    shipment_id        INT          NULL,
    check_id           VARCHAR(64)  NULL,
    shipping_options   LONGTEXT     NULL,
    updated_at         DATETIME     NOT NULL
);
class MyWebshopDataRepository implements \DeliveryMatch\Pdk\Common\Repository
{
    public function __construct(private readonly \PDO $db)
    {
    }

    public function setShipmentId(string $checkoutReference, int $shipmentId): void
    {
        $this->upsert($checkoutReference, ['shipment_id' => $shipmentId]);
    }

    public function getShipmentId(string $checkoutReference): ?int
    {
        $value = $this->column($checkoutReference, 'shipment_id');

        return $value === null ? null : (int) $value;
    }

    public function setShippingOptions(string $checkoutReference, array $shippingOptions): void
    {
        $this->upsert($checkoutReference, ['shipping_options' => base64_encode(serialize($shippingOptions))]);
    }

    public function getShippingOptions(string $checkoutReference): array
    {
        $value = $this->column($checkoutReference, 'shipping_options');

        return $value === null ? [] : unserialize(base64_decode($value));
    }

    public function setCheckId(string $checkoutReference, string $checkId): void
    {
        $this->upsert($checkoutReference, ['check_id' => $checkId]);
    }

    public function getCheckId(string $checkoutReference): ?string
    {
        return $this->column($checkoutReference, 'check_id');
    }

    public function flush(string $checkoutReference): void
    {
        $this->db->prepare('DELETE FROM dm_checkout WHERE checkout_reference = ?')->execute([$checkoutReference]);
    }

    private function column(string $checkoutReference, string $column): ?string
    {
        $stmt = $this->db->prepare("SELECT $column FROM dm_checkout WHERE checkout_reference = ?");
        $stmt->execute([$checkoutReference]);
        $value = $stmt->fetchColumn();

        return $value === false ? null : (string) $value;
    }

    private function upsert(string $checkoutReference, array $values): void
    {
        $values['updated_at'] = date('Y-m-d H:i:s');
        $columns = implode(', ', array_keys($values));
        $placeholders = implode(', ', array_fill(0, count($values), '?'));
        $updates = implode(', ', array_map(fn ($c) => "$c = VALUES($c)", array_keys($values)));

        $this->db
            ->prepare("INSERT INTO dm_checkout (checkout_reference, $columns) VALUES (?, $placeholders) ON DUPLICATE KEY UPDATE $updates")
            ->execute([$checkoutReference, ...array_values($values)]);
    }
}

Two things to keep in mind:

  • flush() is the platform's cleanup hook. The PDK never flushes on its own; call Pdk::flushCheckout($reference) once the shipment id has been linked to the order (see below).
  • Abandoned checkouts are never flushed, so the table grows without bound. Add a retention job that deletes rows whose updated_at is older than your longest plausible checkout (a few days is usually plenty).

Implement the CheckoutContext interface

CheckoutContext::currentReference() answers "which checkout does the current request belong to?". Return the same reference you would pass to the Repository for that cart, or null when the request is not attributable to a checkout: payment webhooks, CLI commands, back-office requests, or a cart that has not been persisted yet and therefore has no stable id.

class MyWebshopCheckoutContext implements \DeliveryMatch\Pdk\Common\CheckoutContext
{
    public function currentReference(): ?string
    {
        $cart = Storefront::currentCart();

        if ($cart === null || empty($cart->id)) {
            return null;
        }

        return (string) $cart->id;
    }
}

When currentReference() returns null, PDK read methods (findShippingOption(), getCachedOptions(), getShipmentId()) return an empty result and log a warning, and PDK write methods (fetchShippingOptions(), setSelectedOption(), addShippingOptionToShipment(), flushCheckout()) throw an InvalidStateException. Server-side code should therefore always pass the reference explicitly.

Create a PDK Bootstrapper

The Bootstrapper provides the PDK's dependency injection container with your Repository and CheckoutContext implementations. After creating the bootstrapper call ::setup() to initialize everything. Both bindings are resolved during setup(), so a missing one fails at bootstrap rather than at the first checkout call.

class MyWebshopPdkBootstrapper extends \DeliveryMatch\Pdk\Common\PdkBootstrapper
{
    protected function getAdditionalConfiguration(): array
    {
        return [
            \DeliveryMatch\Pdk\Common\Repository::class => \DI\autowire(MyWebshopDataRepository::class),
            \DeliveryMatch\Pdk\Common\CheckoutContext::class => \DI\autowire(MyWebshopCheckoutContext::class),
        ];
    }
}

Interact with the PDK

Once the PDK is successfully bootstrapped you can use the PDK to interact with DeliveryMatch using the \Facade\Pdk.

Check if the API connection is successful:

$isAuthenticated = \DeliveryMatch\Pdk\Facade\Pdk::checkConnection();

In the storefront

During the shopper's checkout the current cart is known, so the checkout reference can be omitted and the PDK resolves it through your CheckoutContext.

Fetch shipping options:

$rates = \DeliveryMatch\Pdk\Facade\Pdk::fetchShippingOptions($request);

Read the options fetched earlier without calling DeliveryMatch again:

$options = \DeliveryMatch\Pdk\Facade\Pdk::getCachedOptions();

Store the shipping option the shopper selected:

\DeliveryMatch\Pdk\Facade\Pdk::setSelectedOption($this->request->checkId);

Look up the selected option (for example to display it in the order summary):

$option = \DeliveryMatch\Pdk\Facade\Pdk::findShippingOption();

Server-side: link the shipment to the order

Do this from a hook that runs when the order is created or validated (order validation, payment webhook), not from the confirmation page: that page is not guaranteed to be visited. Such hooks run outside the shopper's request, so pass the checkout reference explicitly.

$cartId = (string) $order->cartId;

// Push the selected shipping option to DeliveryMatch
\DeliveryMatch\Pdk\Facade\Pdk::addShippingOptionToShipment($cartId);

// Store the DeliveryMatch shipment id with the E-commerce order
$order->dm_shipment_id = \DeliveryMatch\Pdk\Facade\Pdk::getShipmentId($cartId);
$order->save();

// The checkout is complete: remove its state from the repository
\DeliveryMatch\Pdk\Facade\Pdk::flushCheckout($cartId);

Update the shipment to new when the payment is received. You also have the option to update the order number and reference. Not all E-commerce platforms provide an order number before the checkout is completed.

\DeliveryMatch\Pdk\Facade\Pdk::updateShipmentToNew(shipmentId: $order->dm_shipment_id, orderNumber: $order->number);

Upgrading to 2.0

Version 2.0 keys all checkout state by an explicit checkout reference instead of "the current request". Every platform integration has to be updated; there is no compatibility layer. See CHANGELOG.md for the full list of changed signatures.

  1. Implement \DeliveryMatch\Pdk\Common\CheckoutContext and bind it in your bootstrapper next to Repository.
  2. Rewrite your Repository against storage keyed by $checkoutReference (database table recommended). Cookie or session based implementations cannot satisfy the new contract.
  3. Move shipment-to-order linking into a server-side hook and pass the cart id explicitly to addShippingOptionToShipment(), getShipmentId() and flushCheckout().
  4. Replace any code that pulled the Repository out of the container to read the shipment id or flush with Pdk::getShipmentId() and Pdk::flushCheckout().
  5. Pin deliverymatch/pdk:^2.0 in the same plugin release that ships the new repository.