Skip to content
  1. Extras
  2. MiniShop3
  3. Manager interface
  4. Settings
  5. Payments

Payment methods ​

Managed via Extras → MiniShop3 → Settings → Payments.

For the store owner ​

  1. Create a payment method: name, description, logo, active flag.
  2. Link it to the needed deliveries. Without a link the customer cannot pick the pair on the storefront.
  3. For pay-on-delivery leave the class field empty. The order simply stores the selected payment_id.
  4. For online payment install a payment extra from the catalog (for example msp3YooKassa, mspTBank, msp3Sberbank) and set the handler class in class as in that package's docs.
  5. Check the post-payment redirect: ms3_order_success_page_id and the Thanks page with msGetOrder.

Surcharge in the price field:

  • 100: fixed amount added to the order
  • 3%: percent of the total

Payment fields ​

FieldTypeDescription
namestringPayment method name
descriptiontextDescription for the customer
pricestringSurcharge (amount or percent)
logostringImage path
positionintSort order
activeboolActive
classstringPHP payment handler class
propertiesJSONHandler settings

Delivery linkage ​

Edit links on the delivery card. Typical sets:

  • Pickup: cash, card on delivery
  • Courier: cash, card, online
  • Post: cash on delivery, online

Payment handlers ​

Built-in handlers ​

ClassDescription
(empty)No online payment, only records the method

Creating a handler ​

A payment extra implements PaymentProviderInterface and registers the class on the payment method. The sketch below is for your own package. Prefer documented extras for production; do not ship this skeleton as-is.

php
<?php
namespace MyComponent\Payment;

use MiniShop3\Controllers\Payment\PaymentProviderInterface;
use MiniShop3\Model\msPayment;
use MiniShop3\Model\msOrder;

class YooKassaPayment implements PaymentProviderInterface
{
    protected $modx;
    protected $payment;

    public function __construct($modx, msPayment $payment)
    {
        $this->modx = $modx;
        $this->payment = $payment;
    }

    /**
     * Redirect to payment
     * Called on order submit with online payment
     */
    public function send(msOrder $order): array
    {
        $properties = $this->payment->get('properties');
        $shopId = $properties['shop_id'] ?? '';
        $secretKey = $properties['secret_key'] ?? '';

        // Create payment in YooKassa
        $client = new \YooKassa\Client();
        $client->setAuth($shopId, $secretKey);

        $payment = $client->createPayment([
            'amount' => [
                'value' => $order->get('cost'),
                'currency' => 'RUB',
            ],
            'confirmation' => [
                'type' => 'redirect',
                'return_url' => $this->modx->makeUrl(
                    $this->modx->getOption('ms3_payment_return_id')
                ),
            ],
            'description' => 'Order #' . $order->get('id'),
            'metadata' => [
                'order_id' => $order->get('id'),
            ],
        ], uniqid('', true));

        // Save payment ID on the order
        $order->set('payment_link', $payment->getConfirmation()->getConfirmationUrl());
        $order->save();

        return [
            'success' => true,
            'redirect' => $payment->getConfirmation()->getConfirmationUrl(),
        ];
    }

    /**
     * Payment notification (webhook)
     */
    public function receive(msOrder $order): array
    {
        // Handle webhook from payment system
        $source = file_get_contents('php://input');
        $data = json_decode($source, true);

        if ($data['event'] === 'payment.succeeded') {
            return [
                'success' => true,
                'message' => 'Payment received',
            ];
        }

        return [
            'success' => false,
            'message' => 'Payment not confirmed',
        ];
    }

    /**
     * Payment cost calculation (fee)
     */
    public function getCost(msOrder $order, float $cost): float
    {
        $price = $this->payment->get('price');

        if (str_ends_with($price, '%')) {
            $percent = (float)rtrim($price, '%');
            return $cost * ($percent / 100);
        }

        return (float)$price;
    }
}

Registering a handler ​

Set the class in the payment method class field:

text
MyComponent\Payment\YooKassaPayment

Additional settings ​

The properties field stores JSON with payment system settings:

json
{
  "shop_id": "123456",
  "secret_key": "live_xxx...",
  "test_mode": false,
  "success_status": 2,
  "fail_status": 5
}

These settings are available in the handler via $this->payment->get('properties').

Payment notifications (webhook / callback) ​

MiniShop3 core has no ready-made payment/handler.php. The payment extra sets the notification URL (for example webhook.php / callback.php under assets/components/{ns}/). See the gateway docs (msp3YooKassa, mspTBank, etc.).

The payment class implements send() / notification handling and changes the order status. The payment link in emails and msGetOrder is built via PaymentLinkResolver.

API ​

Deliveries and payments in the order draft ​

Public lists (no token): GET /api/v1/delivery/list, GET /api/v1/payment/list. There is no separate GET /api/v1/order/payments.

Draft:

http
GET /api/v1/order/get

data.order holds order fields, including delivery_id / payment_id and address_*. Change method: POST /api/v1/order/add or POST /api/v1/order/set with keys payment_id / delivery_id. The Fenom storefront can render the choice via msOrder.

Payment cost ​

http
GET /api/v1/order/cost/payment?payment_id=2

Response:

json
{
  "success": true,
  "data": {
    "cost": 150.00
  }
}

Full totals (cart + delivery + payment): GET /api/v1/order/cost. Web API map: Checkout.

Thank-you page and emails get the payment URL from PaymentLinkResolver (ms3_payment_link_resolver):

  • in msGetOrder — snippet parameter payStatus (CSV of status IDs);
  • in notifications — setting ms3_payment_link_statuses, empty falls back to ms3_status_new;
  • link is hidden for final statuses and the paid status.

The payment handler must return a URL from its payment method (see the send() example above). Details: msGetOrder.