177 lines
6.6 KiB
PHP
177 lines
6.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace paygw_moneta\privacy;
|
|
|
|
use context;
|
|
use context_system;
|
|
use core_payment\privacy\paygw_provider;
|
|
use core_privacy\local\metadata\collection;
|
|
use core_privacy\local\request\approved_contextlist;
|
|
use core_privacy\local\request\approved_userlist;
|
|
use core_privacy\local\request\contextlist;
|
|
use core_privacy\local\request\core_userlist_provider;
|
|
use core_privacy\local\request\transform;
|
|
use core_privacy\local\request\userlist;
|
|
use core_privacy\local\request\writer;
|
|
use paygw_moneta\local\order\Order;
|
|
use paygw_moneta\local\order\TransactionRepository;
|
|
|
|
/**
|
|
* Privacy API: заказы `paygw_moneta_transactions` содержат id покупателя,
|
|
* сумму, статус и снимок чека с его e-mail/телефоном.
|
|
*
|
|
* Оплаченные заказы ядро выгружает и удаляет вместе с платежом
|
|
* ({@see paygw_provider}); неоплаченные не привязаны к платежу, поэтому
|
|
* плагин обслуживает их сам в системном контексте.
|
|
*
|
|
* @package paygw_moneta
|
|
* @copyright 2026 Moneta Labs {@link https://moneta.ru/}
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
class provider implements
|
|
\core_privacy\local\metadata\provider,
|
|
\core_privacy\local\request\plugin\provider,
|
|
core_userlist_provider,
|
|
paygw_provider
|
|
{
|
|
public static function get_metadata(collection $collection): collection
|
|
{
|
|
$collection->add_database_table(TransactionRepository::TABLE, [
|
|
'userid' => 'privacy:metadata:transactions:userid',
|
|
'amount' => 'privacy:metadata:transactions:amount',
|
|
'status' => 'privacy:metadata:transactions:status',
|
|
'merchantorderid' => 'privacy:metadata:transactions:merchantorderid',
|
|
'providertransactionid' => 'privacy:metadata:transactions:providertransactionid',
|
|
'snapshot' => 'privacy:metadata:transactions:snapshot',
|
|
'timecreated' => 'privacy:metadata:transactions:timecreated',
|
|
], 'privacy:metadata:transactions');
|
|
$collection->add_external_location_link('moneta', [
|
|
'userid' => 'privacy:metadata:moneta:userid',
|
|
'fullname' => 'privacy:metadata:moneta:fullname',
|
|
'email' => 'privacy:metadata:moneta:email',
|
|
'phone' => 'privacy:metadata:moneta:phone',
|
|
'amount' => 'privacy:metadata:moneta:amount',
|
|
], 'privacy:metadata:moneta');
|
|
|
|
return $collection;
|
|
}
|
|
|
|
public static function get_contexts_for_userid(int $userid): contextlist
|
|
{
|
|
global $DB;
|
|
|
|
$contextlist = new contextlist();
|
|
if ($DB->record_exists(TransactionRepository::TABLE, ['userid' => $userid])) {
|
|
$contextlist->add_system_context();
|
|
}
|
|
|
|
return $contextlist;
|
|
}
|
|
|
|
public static function get_users_in_context(userlist $userlist): void
|
|
{
|
|
if (!$userlist->get_context() instanceof context_system) {
|
|
return;
|
|
}
|
|
$userlist->add_from_sql('userid', 'SELECT userid FROM {' . TransactionRepository::TABLE . '}', []);
|
|
}
|
|
|
|
public static function export_user_data(approved_contextlist $contextlist): void
|
|
{
|
|
global $DB;
|
|
|
|
foreach ($contextlist->get_contexts() as $context) {
|
|
if (!$context instanceof context_system) {
|
|
continue;
|
|
}
|
|
|
|
$records = $DB->get_records(
|
|
TransactionRepository::TABLE,
|
|
['userid' => $contextlist->get_user()->id],
|
|
'timecreated',
|
|
);
|
|
|
|
$orders = [];
|
|
foreach ($records as $record) {
|
|
$orders[] = self::describe(Order::fromRecord($record));
|
|
}
|
|
if ($orders !== []) {
|
|
writer::with_context($context)->export_data(
|
|
[get_string('gatewayname', 'paygw_moneta')],
|
|
(object) ['orders' => $orders],
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static function delete_data_for_all_users_in_context(context $context): void
|
|
{
|
|
global $DB;
|
|
|
|
if ($context instanceof context_system) {
|
|
$DB->delete_records(TransactionRepository::TABLE);
|
|
}
|
|
}
|
|
|
|
public static function delete_data_for_user(approved_contextlist $contextlist): void
|
|
{
|
|
global $DB;
|
|
|
|
foreach ($contextlist->get_contexts() as $context) {
|
|
if ($context instanceof context_system) {
|
|
$DB->delete_records(TransactionRepository::TABLE, ['userid' => $contextlist->get_user()->id]);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static function delete_data_for_users(approved_userlist $userlist): void
|
|
{
|
|
global $DB;
|
|
|
|
if (!$userlist->get_context() instanceof context_system || $userlist->get_userids() === []) {
|
|
return;
|
|
}
|
|
[$sql, $params] = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED);
|
|
$DB->delete_records_select(TransactionRepository::TABLE, "userid {$sql}", $params);
|
|
}
|
|
|
|
public static function export_payment_data(context $context, array $subcontext, \stdClass $payment): void
|
|
{
|
|
global $DB;
|
|
|
|
$record = $DB->get_record(TransactionRepository::TABLE, ['paymentid' => $payment->id]);
|
|
if ($record === false) {
|
|
return;
|
|
}
|
|
|
|
$subcontext[] = get_string('gatewayname', 'paygw_moneta');
|
|
writer::with_context($context)->export_data($subcontext, self::describe(Order::fromRecord($record)));
|
|
}
|
|
|
|
public static function delete_data_for_payment_sql(string $paymentsql, array $paymentparams): void
|
|
{
|
|
global $DB;
|
|
|
|
$DB->delete_records_select(TransactionRepository::TABLE, "paymentid IN ({$paymentsql})", $paymentparams);
|
|
}
|
|
|
|
/**
|
|
* Заказ в выгрузке: без внутренних идентификаторов и без данных кассы сверх контактов.
|
|
*/
|
|
private static function describe(Order $order): \stdClass
|
|
{
|
|
return (object) [
|
|
'merchantorderid' => $order->merchantOrderId,
|
|
'providertransactionid' => $order->providerTransactionId,
|
|
'amount' => $order->amount->toDecimal() . ' ' . $order->currency,
|
|
'status' => $order->status->value,
|
|
'description' => $order->snapshot->description,
|
|
'client' => $order->snapshot->receipt->client->toArray(),
|
|
'timecreated' => transform::datetime($order->timeCreated),
|
|
'timecompleted' => $order->timeCompleted === null ? null : transform::datetime($order->timeCompleted),
|
|
];
|
|
}
|
|
}
|