
Payment methods
Managed via Extras → MiniShop3 → Settings → Payments.
For the store owner
- Create a payment method: name, description, logo, active flag.
- Link it to the needed deliveries. Without a link the customer cannot pick the pair on the storefront.
- For pay-on-delivery leave the
classfield empty. The order simply stores the selectedpayment_id. - For online payment install a payment extra from the catalog (for example msp3YooKassa, mspTBank, msp3Sberbank) and set the handler class in
classas in that package's docs. - Check the post-payment redirect:
ms3_order_success_page_idand the Thanks page withmsGetOrder.
Surcharge in the price field:
100: fixed amount added to the order3%: percent of the total
Payment fields
| Field | Type | Description |
|---|---|---|
name | string | Payment method name |
description | text | Description for the customer |
price | string | Surcharge (amount or percent) |
logo | string | Image path |
position | int | Sort order |
active | bool | Active |
class | string | PHP payment handler class |
properties | JSON | Handler 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
| Class | Description |
|---|---|
| (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
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:
MyComponent\Payment\YooKassaPaymentAdditional settings
The properties field stores JSON with payment system settings:
{
"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:
GET /api/v1/order/getdata.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
GET /api/v1/order/cost/payment?payment_id=2Response:
{
"success": true,
"data": {
"cost": 150.00
}
}Full totals (cart + delivery + payment): GET /api/v1/order/cost. Web API map: Checkout.
Payment link (payment_link)
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 toms3_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.
