Simple Commerce Documentation

website·Indexed 32 days ago

https://simple-commerce.duncanmcclean.com/

Documentation for Simple Commerce, including PHP API references, payment gateway integration for Stripe, PayPal, and Mollie, and guides for handling donations, static caching, and multi-site setups. Includes comprehensive upgrade guides from v2.2 through v8.0 and migration information to Cargo.

Tokens
27.4K
Snippets
181
Records
228
Agent score
61%

What's inside Simple Commerce

  1. Overview of Simple Commerce customer drivers

    Simple Commerce supports three customer storage options:

    1. Entries: Customers are stored as normal collection entries (Default).
    2. Users: Customers are stored as users, enabling login and order history access (Requires Statamic Pro).
    3. Database: Customers are stored in the database, used specifically in conjunction with the Database Orders feature.
  2. Understand Simple Commerce data architecture

    Simple Commerce treats products, orders, and customers as standard Statamic entries. This allows developers to leverage native Statamic features such as front-end routing, multi-site localization, and search capabilities. As a site scales, customers and orders can be migrated from the filesystem into the database.
  3. Understand the Stripe Payment Flow

    Since v5.x, Stripe is treated as an off-site gateway. The process is as follows:

    1. Customer enters payment info on the Checkout page.
    2. Payment is confirmed by Stripe upon submission.
    3. Stripe sends a webhook to the server to notify Simple Commerce of the payment.
    4. Stripe redirects the customer to a Simple Commerce URL, which then redirects them to a 'checkout success' page.
  4. Choose a payment gateway for Simple Commerce

    Simple Commerce provides out-of-the-box integrations for several popular payment gateways to facilitate quick setup. For development and demo purposes, a 'Dummy Gateway' is available that accepts all card details for testing. If a required gateway is not natively supported, developers can build a custom gateway integration.
  5. Implement an off-site payment gateway flow

    Off-site gateways redirect customers to a third-party website to complete payment.

    1. Redirecting the Customer Use the {{ sc:checkout:gatewayName }} tag to trigger the redirect. Specify the success and error redirect paths as parameters.

    2. Handling Webhooks Payment processors notify Simple Commerce of status changes via a webhook. The webhook URL follows this pattern: /!/simple-commerce/gateways/YOUR_GATEWAY_NAME/webhook. Implement a webhook(Request $request) method to verify the payment status and update the order.

    3. Handling the Callback When the customer is redirected back to your site, the callback(Request $request) method is executed. It should return a boolean: true to redirect the user to the success page, or false to redirect to the error page. Because callbacks may arrive before webhooks, it is recommended to verify the payment status via the gateway's API directly within this method.

    {# Example: Redirecting to Mollie gateway #}
    {{ sc:checkout:mollie redirect="/thanks" error_redirect="/payment-error" }}
    // Example Webhook implementation
    public function webhook(Request $request)
    {
        $mollieId = $request->get('id');
        $payment = $this->mollie->payments->get($mollieId);
    
        if ($payment->status === MolliePaymentStatus::STATUS_PAID) {
            $order = OrderFacade::query()
                ->where('data->mollie->id', $request->get('id'))
                ->first();
    
            if (! $order) {
                throw new OrderNotFound("Order related to Mollie transaction [{$mollieId}] could not be found.");
            }
    
            if ($order->paymentStatus() === PaymentStatus::Paid) {
                return;
            }
    
            $this->markOrderAsPaid($order);
        }
    }
    
    // Example Callback implementation
    public function callback(Request $request): bool
    {
        $this->setupPayPal();
        $order = OrderFacade::find($request->get('_order_id'));
    
        if (! $order) {
            return false;
        }
    
        $paypalOrder = $order->get('paypal')['result'];
        $request = new OrdersGetRequest($paypalOrder['id']);
        $response = $this->paypalClient->execute($request);
    
        return $response->result->status === 'APPROVED';
    }
  6. Add a specific product variant to the cart

    To add a variant to the cart, use the {{ sc:cart:addItem }} action. You must provide the product ID and the specific key of the variant option selected by the user via a form input named variant.
    {{ sc:cart:addItem }}
      <input type="hidden" name="product" value="{{ id }}">
    
      <select name="variant">
        <option disabled>Variant</option>
        {{ product_variants:options }}
          <option value="{{ key }}">{{ variant }} {{ price }}</option>
        {{ /product_variants:options }}
      </select>
    
      <select name="quantity">
        <option disabled>Quantity</option>
        {{ loop from="1" to="5" }}
          <option value="{{ value }}">{{ value }}x</option>
        {{ /loop }}
      </select>
    
      <button type="submit">Add to cart</button>
    {{ /sc:cart:addItem }}
  7. Implement dynamic pricing for product variants in Simple Commerce

    For products with variants, use the SimpleCommerce::productVariantPriceHook method to register a callback. This allows you to determine the price based on the specific product variant being used. Like the standard product hook, this must return an integer and only affects line item calculations (e.g., adding to cart), not the stored product price or the initial display price.
    use DuncanMcClean\SimpleCommerce\Contracts\Order;
    use DuncanMcClean\SimpleCommerce\Contracts\Product;
    use DuncanMcClean\SimpleCommerce\Products\ProductVariant;
    use DuncanMcClean\SimpleCommerce\SimpleCommerce;
    
    SimpleCommerce::productVariantPriceHook(function (Order $order, Product $product, ProductVariant $variant) {
        if (now()->isWeekend()) {
            return 1750;
        }
        return 1500;
    });
  8. Enable Digital Products in v6.0

    v5-x-to-v6-0
    In v6.0, the 'Digital Products' tab has been replaced. To enable digital product fields, you must now toggle the Product Type field to Digital on the product blueprint. As part of the upgrade process, ensure all existing digital products have their Product Type set to Digital.
  9. Migrate Digital Products addon to Simple Commerce Core

    v5-x-to-v6-0
    Digital Product support is now built into the Simple Commerce Core. You must uninstall the standalone addon and update the notification namespace in your configuration.
    composer remove doublethreedigital/sc-digital-products
    // In simple-commerce.php
    'notifications' => [
        'digital_download_ready' => [
            \DuncanMcClean\SimpleCommerce\Notifications\DigitalDownloadsNotification::class => [
                'to' => 'customer',
            ],
        ],
    ],
    
  10. Migrate from Simple Commerce to Cargo

    Simple Commerce has been replaced by Cargo. While Simple Commerce v8 remains compatible with Statamic 5 and 6, users are encouraged to migrate to Cargo to access a redesigned Control Panel UI, a pre-built Checkout Page, a reworked carts and orders system for better reliability, and an overhauled discounting system that supports both automatic site-wide discounts and traditional coupons.
  11. Manage order line items

    Order line items can be retrieved as an Illuminate Collection from an Order instance. You can add, update, or remove items individually or clear the entire list.
    // Get all line items
    $lineItems = $order->lineItems();
    
    // Access properties of a line item
    $item = $lineItems->first();
    $itemId = $item->id();
    $product = $item->product();
    $variant = $item->variant();
    $qty = $item->quantity();
    $total = $item->total();
    $tax = $item->tax();
    
    // Add a new line item
    $order->addLineItem([
        'product' => 'product-id',
        'quantity' => 1,
        'total' => 1500,
    ]);
    
    // Update a specific line item
    $order->updateLineItem($lineItemId, [
        'quantity' => 2,
    ]);
    
    // Remove a specific line item
    $order->removeLineItem($lineItemId);
    
    // Clear all items
    $order->clearLineItems();