msPayPalAlt

Оплата PayPal через JavaScript SDK прямо в оформлении заказа
Автор дополнения
Артур Шевченко
Пакетов
31
Закачек
3 607
Обычно отвечает в течение суток
Автор дополнения
Пакетов
31
Закачек
3 607
Обычно отвечает в течение суток
Версия 1.1.9-rc
Дата выпуска 12.11.2026
Загрузки 0
Внимание, этот компонент несовместим с MODX 3.
Что делает
  • Выводит кнопки оплаты PayPal прямо в форме оформления заказа — покупатель подтверждает платёж во всплывающем окне и остаётся на вашем сайте.
  • Работает на официальном JavaScript SDK PayPal, оплата подтверждается на стороне провайдера.
  • Статус заказа miniShop2 меняется по результату платежа.
Особенности
  • Шаблоны, где показывать кнопки, задаются настройкой — на остальных страницах SDK не грузится.
  • Место вывода кнопок вы определяете сами одним контейнером в шаблоне оформления заказа.
  • Идентификатор и секрет продавца, а также ID способа оплаты — в системных настройках MODX.
Требования
  • MODX Revolution 2.5+, PHP 7.4+
  • miniShop2
  • Бизнес-аккаунт PayPal с доступом к API

1.1.9-rc

  • БЕЗОПАСНОСТЬ: вебхук PayPal больше не принимается на веру. Раньше любой запрос на webhook.php с нужным event_type и номером заказа PayPal переводил заказ в «Оплачен». Теперь перед сменой статуса пакет сам спрашивает PayPal: GET /v2/payments/captures/{id} ключами того контекста, где оформлен заказ; платёж должен принадлежать этому заказу PayPal и быть в статусе, который заявляет событие (COMPLETED — для оплаты, DECLINED/FAILED — для отказа). Если в контексте задана настройка msppa_webhook_id (ID вебхука из кабинета PayPal), дополнительно проверяется подпись через /v1/notifications/verify-webhook-signature. Не прошедший проверку вебхук получает ответ 400, статус заказа не меняется, в mxLogger пишется ошибка; при недоступности PayPal — 503, PayPal повторит доставку.
  • БЕЗОПАСНОСТЬ: поиск заказа по номеру PayPal — подготовленный запрос, номер проверяется по формату (латиница и цифры). Раньше номер из тела вебхука подставлялся в SQL как есть. Текст SQL в журнал больше не пишется.
  • Вебхук берёт ключи PayPal из контекста заказа, а не из web: у контекста может быть свой аккаунт PayPal.
  • БЕЗОПАСНОСТЬ: оплата засчитывается, только если сумма и валюта платежа PayPal совпадают со стоимостью заказа (msppa_currency_code контекста). Заказ PayPal создаётся по корзине на момент нажатия кнопки, и раньше дешёвый платёж мог закрыть более дорогой заказ. При расхождении статус не меняется, в mxLogger пишется ошибка — заказ разбирает человек.
  • БЕЗОПАСНОСТЬ: action.php выполняет только createOrder и capturePayment; прочие публичные методы сервиса по имени из запроса больше не вызываются.

1.1.8-rc

  • Сбои оплаты видны в mxLogger с тегом payment независимо от настройки msppa_debug. Раньше при отключённом логировании в журнал не попадало ничего, и ошибку PayPal API или вебхука можно было заметить только по жалобе покупателя. Теперь ошибки пишутся всегда: отказ или исключение PayPal API при создании и подтверждении платежа, пустой или битый ответ, вебхук без номера заказа или с неизвестным заказом, неудачная смена статуса заказа. Отладочные записи по-прежнему включает msppa_debug. Без установленного mxLogger поведение прежнее: ничего не пишется и в журнал MODX ничего не добавляется.
  • В записях об ошибках есть контекст: номер заказа PayPal и заказа магазина, HTTP-код и фрагмент ответа API, без ключей и подписей.
  • Ожидаемое не считается ошибкой: повторный вебхук для заказа, уже находящегося в нужном статусе, финальный или зафиксированный статус заказа и отказ банка покупателя при списании пишутся как info и warning.
  • Если клиент PayPal не создан или в сессии нет номера заказа PayPal, createOrder() и capturePayment() сразу возвращают ошибку, а не падают дальше. Исключение SDK при создании заказа возвращается ошибкой, а не фатальной.

1.1.7-rc

  • PayPal получает итог заказа с налогом сайта. Сумма бралась из события msOnGetOrderCost, а сайт может доначислить налог уже после него: на sleepandglow налог сверху цены (gb — VAT 20 %, can — GST/HST) прибавляется в обработчике заказа, и окно PayPal показывало сумму без налога. Теперь createOrder() берёт итог у miniShop2 (order->getCost(true, true)) — тот же, что ложится в стоимость заказа при оформлении; если итог не получен, остаётся сумма из события. Контексты, где налог уже в цене, не меняются.
  • Сумма уходит в PayPal строкой с точкой и двумя знаками (у HUF, JPY, TWD — без дробной части), а не числом, запись которого зависела от настроек PHP.

1.1.6-rc

  • Колбэк Order.submit.before и кнопки PayPal ждут загрузки miniShop2 без лимита waitTimeout. Если сайт подгружает miniShop2 позже 10 секунд после скрипта пакета (на sleepandglow его подключает модуль Libraries), гард не регистрировался и общая кнопка снова создавала заказ без оплаты.

1.1.5-rc

  • Колбэк Order.submit.before регистрируется сразу после загрузки miniShop2, не дожидаясь SDK PayPal. Раньше клик «Оформить» с выбранным PayPal до загрузки SDK создавал заказ без оплаты.
  • При отмене отправки кнопки формы заказа снова активны. Системный submit.before miniShop2 выключал их, а включает только при ответе с ошибкой — после отмены «Оформить» оставалась неактивной даже при переключении на другой способ оплаты.

1.1.4-rc

  • Общая кнопка оформления заказа при выбранном PayPal больше не создаёт неоплаченный заказ. Форму miniShop2 отправлял только onApprove, но обычный submit ничем не перехватывался: заказ создавался, capturePayment() без PayPal-ордера в сессии возвращал ошибку, а покупатель уходил на страницу успеха (прод-тест 06.10.2026, ch, где PayPal отмечен по умолчанию). Теперь колбэк Order.submit.before блокирует отправку, пока PayPal не подтвердил оплату, и прокручивает страницу к кнопкам PayPal.

1.1.3-rc

  • Локаль PayPal следует языку, выбранному на сайте, а не только культуре контекста. В мультиязычном контексте (ch: fr/de/it, can: en/fr) язык переключается в рантайме через setOption('cultureKey'), а resolveLocale() читал cultureKey из настроек контекста — немецкоязычный покупатель видел PayPal на французском. Теперь берётся cultureKey текущего запроса.
  • Коннектор action.php работает в API-режиме, где переключатель языка не отрабатывает: страница передаёт в запросе свою локаль (jsSdkParams.locale), сервис принимает её опцией конструктора ['locale' => ...] и приводит к списку PayPal (normalizeLocale()). Приоритет: msppa_locale → локаль запроса → cultureKey запроса.

1.1.2-rc

  • Исправлено создание заказа: createOrder() считал успехом только статус CREATED, а PayPal с блоком payment_source.paypal в запросе отдаёт PAYER_ACTION_REQUIRED («заказ создан, ждём подтверждения покупателя»). Метод возвращал ошибку msppa_order_create_failed и не клал id заказа в $_SESSION['msppa']['paypalOrderId'], из-за чего capturePayment() потом не находил заказ и деньги не списывались. Теперь созданием считаются оба статуса (self::ORDER_CREATED_STATUSES). Регрессия 1.1.0-rc: до неё payment_source в запросе не было, и статус всегда был CREATED.

1.1.1-rc

  • Исправлено создание заказа: PayPal Orders v2 отвечал INVALID_REQUEST на payment_source.paypal.experience_context.locale. Туда уходил формат JS SDK (en_US), а REST валидирует значение по BCP-47 с дефисом (^[a-z]{2}(?:-[A-Z][a-z]{3})?(?:-(?:[A-Z]{2}))?$). Форматы разведены: канон внутри класса остался xx_YY и уходит в SDK-URL кнопок, для тела запроса добавлен getApiLocale() (en_US -> en-US, ja_JP -> ja-JP). Регрессия 1.1.0-rc: до неё payment_source в запросе не было вовсе.
  • Значение настройки msppa_locale теперь тоже прогоняется через normalizeLocale(). Раньше оно уходило провайдеру как есть, и запись вида en-AU или en из менеджера ломала SDK-параметр. Побочный эффект: неподдерживаемое значение молча схлопывается в en_US — как и cultureKey неизвестной культуры.

1.1.0-rc

  • В SDK-URL кнопок добавлен параметр locale: без него PayPal определял язык сам, по браузеру и IP покупателя, из-за чего в англоязычном контексте рисовались немецкие кнопки. Значение — новая настройка msppa_locale (формат xx_YY); пустая означает «взять cultureKey текущего контекста» с приведением к локали PayPal (неизвестная -> en_US).
  • Та же локаль уходит в создание заказа через payment_source.paypal.experience_context.locale — окно paypal.com/checkoutnow открывается на языке контекста, а не браузера.
  • msppa_country_code, msppa_js_sdk_url, msppa_js_path, msppa_action_url, msppa_payment_id, msppa_init_buttons_event теперь читаются с учётом контекстных настроек: раньше контекстное переопределение для них молча не работало.
  • ВНИМАНИЕ: перед сборкой настройку msppa_locale создать в менеджере (namespace mspaypalalt) — сборка тянет настройки из БД стенда.

1.0.5-rc

  • Логирование переведено с файлов (logs/*.txt) на mxLogger. Logger делегирует записи сервису mxLogger (если установлен), иначе молчит и один раз предупреждает в журнале MODX.
  • Гейты: msppa_debug (вкл/выкл) + новая настройка msppa_log_level (минимальный уровень debug|info|warning|error, по умолчанию error; единый приёмник mxLogger, включено из коробки). Консистентно с mxLogger.min_level.
  • Тэги: базовые mspaypalalt + payment, этапные create / capture / webhook. Воронка processuid = «mspaypalalt»+md5(paypalOrderId) — создание заказа, capture и вебхук одного платежа склеиваются одним процессом в mxLogger.
  • ВНИМАНИЕ: перед сборкой настройку msppa_log_level создать в менеджере (namespace mspaypalalt) — сборка тянет настройки из БД стенда.

1.0.4-rc

  • Добавил возможность указать событие, после которого начнётся инициация кнопок оплаты.
  • Оставил только один URL для переадресации после оплаты.

1.0.4-beta

  • Сделал так, захват платежа происходит в момент создания заказа в MiniShop2, а обновление статусов - после запроса на вебхук.
  • Удалил функционал возврата платежа за ненадобностью.

1.0.3-rc

  • Убрал лишний код из плагина на событие msOnGetOrderCost
  • Ужесточил проверку в плагине на событие msOnSubmitOrder

1.0.2-rc

  • Убрал из параметров ссылки на SDK параметр buyer-country

1.0.1-rc

  • Поменял стандартное расположение кнопок на вертикальное.
  • Добавил возможность указать ссылки на страницы переадресации после оплаты.

1.0.0-rc

  • Первый релиз.

1.0.0-beta

  • Первая стабильная сборка.

1.0.0-alpha

  • Первая сборка.

Последние обсуждения в сообществе MODX.pro