Mental GrowthРуководство
Элементы
MENTAL GROWTH / РУКОВОДСТВО

Как работает оплата

Preview / Stable, test_mode / prod_mode, US / WW и multicurrency — порядок выбора и запасные варианты.

Проверено по редактору:

Оплата определяется последовательностью: префикс /test в адресе → платёжный режим → региональный провайдер → валюта и цены каждого пути → подтверждение. На каждом этапе используются результаты предыдущего.

Например: /preview/cosmiciq → prod_mode → US → stripe_us → USD. Но для того же посетителя из US результатом может стать stripe → EUR, если US-настройки в Production не заполнены, а у WW-пути доступна только базовая цена в евро.

Ниже подробно разобрана оплата подписки через Simple Plans + Checkout или Composite. Особенности One Click и Cancellation приведены в конце страницы.

Какие настройки за что отвечают

ПонятиеНа что влияет
Preview / StableКакое содержимое воронки открыто; независимо от режима оплаты
test_mode / prod_mode/test включает test_mode; без него prod_mode. Какие пути плана, API платёжного сервиса и ключ Stripe используются
US / WWКакой региональный провайдер и его Payment App выбираются
MulticurrencyКакая готовая цена из выбранного пути подходит стране посетителя
Intro offerЕсть ли вводная цена в той же валюте, что и подписка
ЛокализацияЯзык и форматирование текста; язык сам по себе не выбирает платёжную валюту

Здесь WW означает общий провайдер Stripe (stripe), а US — Stripe US (stripe_us). В редакторе вкладки называются Stripe и Stripe US. Страна берётся из IP lookup посетителя; региональный провайдер и валюта выбираются раздельно.

1. Адрес → test_mode или prod_mode

В header редактора доступны три ссылки. Обе Preview-ссылки открывают текущий выбранный экран одной и той же версии воронки.

СсылкаАдресСодержимоеНастройки и ключ StripeAPI оплатыРегистрация
Link to stable/cosmiciqStableprod_mode, prod_mode_publishable_keypay.mentalgrowth.app/api/v1Production URL
Link to preview prod/preview/cosmiciq?step=Welcome+1Previewprod_mode, prod_mode_publishable_keypay.mentalgrowth.app/api/v1Production URL
Link to preview test/test/preview/cosmiciq?step=Welcome+1Previewtest_mode, test_mode_publishable_keydev.pay.mentalgrowth.app/api/v1Staging URL

Режим определяется только ведущим сегментом /test, независимо от домена staging или production. Обычный Preview теперь использует боевые настройки. Например, https://dev.constructor.youth-app.com/preview/cosmiciq — это prod_mode, а тот же адрес с /test/preview/ — test_mode.

Preview / Stable выбирают содержимое и опубликованный renderer. Они не выбирают платёжный режим. В редакторе вкладки Test mode и Production выбирают редактируемые настройки; режим посетителя задаёт его ссылка. Публикация не преобразует тестовые priceId в боевые.

Префикс сохраняется при переходах по экранам, перезагрузке и возврате на старт. Cancellation и Manage Subscription работают по тому же правилу: например, /test/preview/manage-subscription/<alias>. Preview на телефоне из редактора открывается в тестовом режиме. Тестовая идентификация клиента и Stripe не подставляются в Preview prod.

2. Страна → US или WW

Префикс test выбирает test_mode; без него prod_mode. Для страны US выбирается stripe_us при заполненном Payment App и наличии US priceId в активном режиме; иначе выбирается stripe, WW.
Сначала фиксируется режим, затем проверяется региональная конфигурация именно этого режима.На узком экране схему можно прокручивать по горизонтали.Открыть схему в полном размере ↗

Stripe US выбирается, только когда одновременно выполнены три условия:

  1. Страна посетителя — US.
  2. У коллекции заполнен Payment App для Stripe US.
  3. У выбранного плана есть хотя бы один непустой US priceId в активном режиме.

Во всех остальных случаях выбирается WW / Stripe. Для других стран Stripe US не выбирается, даже если он полностью настроен. Если страна неизвестна, используется WW и далее базовая валюта пути.

Матрица четырёх конфигураций

В таблице US-ветка предполагает, что её условия выше выполнены.

Режим ссылкиВыбранный провайдерКакие пути читаютсяОбщий Payment App
С /testWW / StripepaymentPaths.test_mode.stripeproviderSettings.stripe.appName
С /testUS / Stripe USpaymentPaths.test_mode.stripe_usproviderSettings.stripe_us.appName
Без /testWW / StripepaymentPaths.prod_mode.stripeproviderSettings.stripe.appName
Без /testUS / Stripe USpaymentPaths.prod_mode.stripe_usproviderSettings.stripe_us.appName

У коллекции два общих Payment App — Stripe и Stripe US. Каждый используется в обоих режимах. Пути и цены внутри плана разделены на четыре конфигурации из таблицы. Изменение Payment App во вкладке Test mode также меняет общий App для Production этого провайдера.

Выбранный Payment App связывается с интеграцией проекта по app_name; из неё берётся ключ нужного режима. При отсутствии подходящей интеграции или ключа текущий клиент использует встроенный тестовый ключ. Для Production необходимо явно настроить совпадающий App и production-ключ: заполненные пути сами по себе этого не гарантируют.

Где заканчивается переход US → WW

Переход на WW происходит при выборе провайдера, если US App или US-пути не заполнены. Затем проверяется каждый путь уже выбранного провайдера.

Если Stripe US выбран, но у одного из его путей неправильная сумма, нет совместимой валюты или не хватает intro-цены, оплата получает blocked. Автоматического перехода на WW после такой ошибки нет. Также нет перехода с prod_mode на test_mode при незаполненных Production-путях.

3. Multicurrency → валюта и сумма

Multicurrency использует сохранённые цены каталога для выбранного priceId. В клиенте нет пересчёта по курсу обмена: сумма USD, EUR или CAD берётся из соответствующей настройки цены.

При выборе Subscription редактор загружает дополнительные валюты и сохраняет их в currency_options текущего пути. Для Intro Offer ID отдельно загружаются introOfferCurrencyOptions. Во время запроса виден индикатор Fetching multicurrency.... Каталог запрашивается для выбранного Payment App и режима; загрузка валют для Test mode не заполняет Production.

Порядок выбора цены

  1. Страна сопоставляется с валютой по таблице клиента: например, US → USD, DE → EUR, CA → CAD, GB → GBP, JP → JPY.
  2. В currency_options ищется подходящая цена этой валюты.
  3. Если её нет или она не подходит, проверяется опция базовой валюты path.currency, затем базовая path.price.
  4. При включённом intro offer проверяется совместимость двух цен по схеме ниже.
  5. Итоговый код валюты и сумма подписки валидируются до подготовки оплаты. Отсутствие подходящей цены блокирует попытку.

Любая другая доступная валюта не выбирается случайно. Например, наличие только CAD в дополнительных опциях не означает, что посетителю из US покажут CAD: будет использована подходящая базовая цена либо оплата заблокируется.

Цена валюты страны или базовая цена → проверка intro offer в той же валюте → при необходимости совместимая базовая пара → проверка суммы → оплата или blocked.
Этот выбор выполняется для каждого платёжного пути. Режим и провайдер на данном этапе уже выбраны и не меняются.На узком экране схему можно прокручивать по горизонтали.Открыть схему в полном размере ↗

Intro offer должен совпасть по валюте

Допустим, подписка имеет цену USD 29.99 и базовую EUR 24.99, а intro offer существует только в EUR 1.99. Для посетителя из US сначала находится USD-подписка, но USD intro отсутствует. Тогда проверяется базовая пара, и весь путь переходит на EUR 24.99 + EUR 1.99.

Если подходящей базовой пары тоже нет, результат — blocked. Клиент не смешивает USD-подписку с EUR intro и не убирает включённое вводное предложение, чтобы провести оплату по обычной цене.

US не гарантирует USD, а WW не означает EUR. И US-, и WW-путь могут содержать несколько валют. Выбор провайдера отвечает за платёжную конфигурацию; выбор валюты — за совместимые цены внутри неё.

Суммы из unit_amount_minor приводятся к денежным единицам с учётом валюты: например, 1999 → USD 19.99, а 3000 → JPY 3000. Число minor units нельзя всегда делить на 100. Сумма подписки должна быть положительной; для настроенного intro offer допускается нулевая цена.

Примеры прохождения схемы

Цены ниже условные, для объяснения правил. Во всех строках предполагаются корректные данные клиента и ключи интеграций.

СитуацияЧто выберетсяПочему
Preview test, страна US; тестовый US-путь заполнен и содержит USDtest_mode → stripe_us → USDПроверяются US-настройки Test mode
Stable, страна US; US заполнен только в Test mode; Production WW содержит USDprod_mode → stripe → USDТестовый US-путь не участвует в prod_mode
Stable, страна DE; оба провайдера заполнены, WW содержит EURprod_mode → stripe → EURДля страны DE выбирается WW
Stable, страна CA; WW не содержит CAD, базовая USD корректна, intro выключенprod_mode → stripe → USDИспользуется базовая цена WW-пути
Stable, страна US; US-путь заполнен, USD-подписка без USD intro; есть базовая пара EURprod_mode → stripe_us → EURМеняется валюта, провайдер остаётся US
Stable, страна US; US выбран, но совместимой пары подписка + intro нетblockedПоздняя ошибка не переключает оплату на WW
Stable; выбранный Production-провайдер не содержит корректного путиblockedНастройки Test mode не подставляются

Для каждого плана и режима проверьте отдельные сценарии US, другой страны, отсутствующей валюты и несовпадающего intro offer. Каждый дополнительный платёжный путь разрешает свою валюту отдельно; ошибка любого пути блокирует подготовку всей попытки.

Как настройки доходят до Checkout

Simple Plans сохраняет выбор посетителя. Связанный Checkout читает этот выбор из указанного источника. Composite объединяет обе роли. В обоих случаях Payment App принадлежит коллекции, а платёжные пути и действия после результата — выбранному Payment Plan.

Редактор → CMS → воронка. Воронка обращается к платёжному сервису, подтверждает оплату через Stripe.js и обрабатывает результат.
Место платёжной конфигурации в общей схеме системы.На узком экране схему можно прокручивать по горизонтали.Открыть схему в полном размере ↗

До подготовки оплаты нужны идентификатор и email зарегистрированного клиента. После готовности данных клиента и определения местоположения runtime проверяет конфигурацию и фиксирует параметры попытки. Неполный Payment App, отсутствующий путь или неподходящая сумма/валюта блокируют подготовку.

Воронка обращается к платёжному сервису напрямую. CMS backend хранит и отдаёт конфигурацию воронки и интеграции проекта. Внутренняя обработка платёжного сервиса, webhooks и дальнейшие автоматические продления подписок находятся за границей этой схемы.

Настройки блоков и записи интерфейса собраны в разделе Платёжные элементы.

Как проходит Checkout

Ниже показан успешный сценарий. Первый платёжный путь создаёт основную подписку; остальные, если они есть, выполняются последовательно как дополнительные подписки.

Выбор плана → подготовка основной подписки → подтверждение через Stripe → дополнительные подписки → действие успеха.
Успешный сценарий Checkout / Composite. При ошибке цепочка останавливается на текущей операции.На узком экране схему можно прокручивать по горизонтали.Открыть схему в полном размере ↗
  1. Выбор и подготовка. Checkout получает выбранный план и вызывает subscriptions/init. В ответ приходят данные для подтверждения оплаты. Подготовка сама по себе не является командой подтверждения списания.
  2. Подтверждение посетителем. Для карты сначала создаётся Payment Method, затем вызывается подтверждение Stripe. Для Apple Pay / Google Pay открывается нативное окно кошелька и подтверждается тот же платёж. Доступность кошельков зависит от устройства и окружения.
  3. Фиксация результата. Успех основной операции требует статуса succeeded и идентификатора PaymentIntent. После подтверждения отправляются события покупки и устанавливается защита от повторной оплаты в этой вкладке.
  4. Дополнительные пути. Каждый следующий путь вызывает subscriptions/add. Подтверждённые операции отмечаются выполненными. Если очередной путь завершается ошибкой, уже выполненные автоматически не повторяются и не откатываются.
  5. Действие экрана. Настроенное paymentSucceeds выполняется после успеха всех операций. Подтверждение основной подписки ещё не означает завершение всей цепочки.

Что происходит при ошибке

РезультатПоведение
Успех · succeededВсе операции завершены; выполняется действие успеха
Отказ · failedПри ошибке выполнения запускается настроенное действие ошибки; допустима явная повторная попытка
Отмена · cancelledПосетитель или Stripe отменил подтверждение; выполняется настроенное действие отмены, повторная попытка допустима
Нет сети · offlineДо отправки запрос не ставится в очередь. После восстановления связи требуется явная попытка
Неопределённый результат · unknownЗапрос мог выполниться, но окончательный результат не получен. Повтор заблокирован до выяснения статуса
Блокировка · blockedНе хватает настроек/данных клиента либо сработала защита после подтверждённой оплаты. Сначала нужно устранить причину

При offline, unknown и blocked действия успеха и ошибки не запускаются. Ошибка подготовки subscriptions/init также не запускает действие экрана и допускает повтор: подтверждение списания ещё не начиналось. Для команды списания обрыв связи, HTTP 408/5xx или нечитаемый/неокончательный ответ означают unknown.

Повтор в рамках текущей попытки продолжает невыполненные операции. Перезагрузка страницы не является способом восстановить платёж: Stripe-ссылки на клиента и подписку хранятся только в памяти, а отметка о подтверждённой оплате в текущей вкладке блокирует новую попытку. Автоматического восстановления спорного результата через backend в этом клиентском потоке пока нет.

После основной оплаты

One-Click Button

Кнопка выполняет только первый настроенный платёжный путь и использует Stripe-данные, полученные в текущей сессии оплаты.

Связь Preview / Stable с режимом и правило выбора US сохраняются. Но настройки One Click имеют собственную структуру paymentMethods[provider][mode]: Payment App и пути находятся внутри выбранной пары провайдер + режим. Правило об общем App коллекции к этой отдельной структуре не относится.

ТехникаДействиеЧто требуется
oneTimeРазовый платёжStripe customer ID
additionalSubscriptionДополнительная подпискаStripe customer ID
modifyИзменение подписки с выбранным правилом перерасчётаStripe subscription ID

onPress выполняется только после успеха операции. Если изменение подписки прошло без списания, отправляется subscription_modified, а не событие покупки. При нехватке Stripe-данных после перезагрузки операция блокируется.

Отмена и заморозка

Cancellation — отдельный сценарий: по email и user_id из ссылки он запрашивает список подписок, применяет отмену или заморозку к доступным для действия подпискам и обновляет их статус. Отмена действует в конце оплаченного периода; заморозка задаётся на 1–365 дней. Итоговое действие экрана зависит от общего результата запросов.

Здесь US / WW — уже буквальные секции cancellationConfig.us и cancellationConfig.ww. Для страны US выбирается US-секция, если заполнены оба поля app и projectSlug; иначе используется заполненная WW-секция. Выбора нового priceId и multicurrency в отмене нет. Хост API по-прежнему зависит от Preview / Stable.

Manage Subscription имеет отдельный вход с проверкой email. Сам по себе этот вход не запускает Cancellation и не восстанавливает данные One Click.

Запросы к платёжному сервису

Хост выбирается по варианту воронки из таблицы выше.

ОперацияМетод и путь
Подготовка основной подпискиPOST /api/v1/constructor/stripe/subscriptions/init
Дополнительная подпискаPOST /api/v1/constructor/stripe/subscriptions/add
Разовый платёжPOST /api/v1/constructor/stripe/payments/one-time
Изменение подпискиPOST /api/v1/constructor/stripe/subscriptions/modify
Получение подписокGET /api/v3/status_subscription
ОтменаPOST /api/v1/constructor/stripe/subscriptions/cancel
ЗаморозкаPOST /api/v1/constructor/stripe/subscriptions/freeze

На этой странице