feat: paygw_moneta 1.0.0, MONETA.Assistant payment gateway for Moodle
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace paygw_moneta\local;
|
||||
|
||||
use core\message\message;
|
||||
use core_payment\helper;
|
||||
use core_user;
|
||||
use paygw_moneta\local\order\Order;
|
||||
|
||||
/**
|
||||
* Сообщения покупателю через систему сообщений Moodle (`db/messages.php`):
|
||||
* «оплата принята» (`payment_received`) и «ссылка на оплату» (`payment_link`).
|
||||
* Плагин не выбирает канал и не шлёт почту сам: веб-уведомление и/или письмо
|
||||
* через исходящую почту сайта — по настройкам уведомлений пользователя.
|
||||
*
|
||||
* @package paygw_moneta
|
||||
* @copyright 2026 Moneta Labs {@link https://moneta.ru/}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
final class BuyerNotifier
|
||||
{
|
||||
public const PROVIDER = 'payment_received';
|
||||
public const PROVIDER_LINK = 'payment_link';
|
||||
|
||||
public function __construct(
|
||||
private readonly Logger $logger = new ErrorLogLogger(),
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Сообщение по оплаченному заказу; сбой отправки не должен ломать ответ на
|
||||
* Pay URL, поэтому ошибки только логируются.
|
||||
*
|
||||
* @return int|false id сообщения либо false, если отправка не состоялась
|
||||
*/
|
||||
public function notifyPaid(Order $order): int|false
|
||||
{
|
||||
return $this->send(
|
||||
order: $order,
|
||||
provider: self::PROVIDER,
|
||||
stringKey: 'message:paid',
|
||||
extra: static fn(Order $order): array => [
|
||||
'operationid' => (string) $order->providerTransactionId,
|
||||
'url' => helper::get_success_url($order->component, $order->paymentArea, $order->itemId)->out(false),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ссылка на оплату только что созданного заказа (настройка шлюза «Отправлять
|
||||
* ссылку оплаты на почту»): покупатель может оплатить позже, со страницы
|
||||
* `checkout.php`. Сбой отправки не мешает перейти к оплате сейчас.
|
||||
*
|
||||
* @return int|false id сообщения либо false, если отправка не состоялась
|
||||
*/
|
||||
public function notifyPaymentLink(Order $order): int|false
|
||||
{
|
||||
return $this->send(
|
||||
order: $order,
|
||||
provider: self::PROVIDER_LINK,
|
||||
stringKey: 'message:link',
|
||||
extra: static fn(Order $order): array => [
|
||||
'url' => PaymentFormPage::resumeUrl($order)->out(false),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable(Order): array<string, string> $extra поля строки сообщения сверх общих; `url` обязателен
|
||||
*/
|
||||
private function send(Order $order, string $provider, string $stringKey, callable $extra): int|false
|
||||
{
|
||||
try {
|
||||
$user = core_user::get_user($order->userId);
|
||||
if ($user === false || !empty($user->deleted) || isguestuser($user)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Значения для подстановок {$a->…} в строках message:* (имя $a задаёт get_string()).
|
||||
$placeholders = (object) ([
|
||||
'firstname' => $user->firstname,
|
||||
'fullname' => fullname($user),
|
||||
'description' => $order->snapshot->description,
|
||||
'amount' => helper::get_cost_as_string((float) $order->amount->toDecimal(), $order->currency),
|
||||
'sitename' => format_string(get_site()->fullname),
|
||||
] + $extra($order));
|
||||
$body = get_string($stringKey, 'paygw_moneta', $placeholders);
|
||||
|
||||
$bodyForHtml = get_string(
|
||||
$stringKey,
|
||||
'paygw_moneta',
|
||||
(object) (['url' => '<' . $placeholders->url . '>'] + (array) $placeholders),
|
||||
);
|
||||
|
||||
$message = new message();
|
||||
$message->component = 'paygw_moneta';
|
||||
$message->name = $provider;
|
||||
$message->userfrom = core_user::get_noreply_user();
|
||||
$message->userto = $user;
|
||||
$message->subject = get_string($stringKey . ':subject', 'paygw_moneta', $placeholders);
|
||||
$message->fullmessage = $body;
|
||||
$message->fullmessageformat = FORMAT_MARKDOWN;
|
||||
$message->fullmessagehtml = markdown_to_html($bodyForHtml);
|
||||
$message->smallmessage = $message->subject;
|
||||
$message->notification = 1;
|
||||
$message->contexturl = $placeholders->url;
|
||||
$message->contexturlname = $order->snapshot->description;
|
||||
|
||||
return message_send($message);
|
||||
} catch (\Throwable $exception) {
|
||||
$this->logger->error('Сообщение покупателю не отправлено: ' . get_class($exception));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user