01.08.2027 335 материалов

Когда Stripe не работает: как принимать доллары и рупии без единого провайдера

Разработчик из Индии хотел принимать оплату от покупателей по всему миру и столкнулся с тем, что «просто добавь Stripe» — совет, который не работает, если ты не из США. Вот что он выстроил вместо этого и какие ошибки допустил на пути.

Когда Stripe не работает: как принимать доллары и рупии без единого провайдера

«Просто добавь Stripe» — это дефолтный совет разработчику, которому нужно принимать деньги. Он работает ровно до тех пор, пока ты — индийский продавец, которому нужно получить оплату от покупателя из Сан-Франциско и покупателя из Бангалора в один и тот же день.


Проблема, о которой забывают

Стандартный путь соло-разработчика, который хочет монетизировать продукт, хорошо известен: зарегистрировался в Stripe, подключил виджет, пошёл пить кофе. Схема работает безупречно — если ты находишься в поддерживаемой Stripe стране, твои покупатели тоже там, а валюта одна.

Мохан Венката Кришнан, разработчик маркетплейса Skill Exchange (площадка для продажи повторно используемых AI-навыков), столкнулся с ситуацией, когда ни Stripe, ни даже PayPal по отдельности не решали задачу. Он — в Индии, часть покупателей — в США, часть — дома. И простого решения не существует.

PayPal в Индии: не тот инструмент, каким кажется

Первое заблуждение, которое нужно убить сразу: PayPal — это не внутренний платёжный метод в Индии. В апреле 2021 года PayPal полностью прекратил обработку внутренних платежей India-to-India. То, что осталось, работает только трансгранично: индийский продавец может получать деньги из-за рубежа, но индийский покупатель с рупийным счётом через PayPal индийскому продавцу заплатить не может.

Разработчик обнаружил это эмпирически — подключил PayPal, попробовал заплатить самому себе со своего индийского аккаунта на свой же индийский мерчант-аккаунт и получил ничего не говорящее сообщение: «Things don't appear to be working at the moment». Без кода ошибки, без пояснения в документации — транзакция просто классифицируется как внутренняя и отклоняется. Между тем, как только покупатель — иностранец, всё работает идеально. Именно это делает баг настолько коварным при локальном тестировании.

Вывод: если хотя бы часть покупателей находится в той же стране, что и ваш PayPal-аккаунт, PayPal в одиночку вам не поможет. Нужна вторая платёжная рельса.

Два провайдера, а выбор — за покупателем

Архитектура получается из двух провайдеров, привязанных к валюте:

  • Международные покупатели → PayPal, оплата в USD
  • Индийские покупатели → Razorpay, оплата в INR через UPI — по сути, один тап, мгновенное списание, конверсия в разы выше, чем по картам в Индии

Ключевое дизайнерское решение: переключатель валюты виден прямо на чекауте и покупатель выбирает его сам. По умолчанию валюта подставляется на основе часового пояса (если Asia/Kolkata — рупии, иначе — доллары), но это именно дефолт, а не блокировка. Для индийцев за рубежом (NRI) и путешественников переключатель всегда доступен.

Не показывайте точный курс — округляйте до «родных» цен

Наивный подход — взять долларовую цену, умножить на курс и показать результат. Не делайте так. Навык за $12 при курсе ₹86/$ превращается в ₹1 032 — число, которое выглядит как баг и ощущается дорогим. Покупательная способность в Индии для цифровых товаров ниже, чем подразумевает простая конвертация.

Вместо этого разработчик использует округление до «красивых» индийских цен:

  • $5 → ₹399
  • $6 → ₹499
  • $9 → ₹799
  • $12 → ₹999
  • $15 → ₹1 299

Одна константа INR_RATE пересчитывает весь каталог разом, а округление работает как лёгкая скидка по purchasing power parity — без ручной работы над каждым лотом. Это стандартная практика: любой серьёзный продавец, работающий с Индией, использует региональные ценовые точки, а не прямой курс.

Храните валюту и комиссию на каждой транзакции — и никогда не пересчитывайте

Это та деталь, которая кусает потом, если её пропустить. Два правила:

  1. На каждой строке покупки должна быть валюта. Голый amountCents становится двусмысленным в ту секунду, когда часть из них — это paisa, а не центы.

  2. Комиссия платформы считается в момент покупки и замораживается. Если ставка комиссии меняется (у автора она упала с 10% до 5%), исторические записи должны хранить ту ставку, при которой продажа состоялась. Комиссия, пересчитываемая при чтении, — это комиссия, которую вы рано или поздно посчитаете неправильно.

Агрегаты выручки продавца тоже нужно считать в разрезе валют. Складывать центы и пайса в одно целое — верный способ получить красивое, но бессмысленное число.

Верифицируйте платёж на сервере — и только от провайдера

Оба платёжных рейса позволяют браузеру врать. Поэтому шаг подтверждения не доверяет ни сумме, ни флагу «оплата прошла» из клиентского запроса. Вместо этого сервер заново запрашивает провайдера:

  • PayPal: делается capture ордера, проверяется status === "COMPLETED" и сверяется custom_id, который был привязан к конкретному покупателю и товару при создании. Повторное использование захваченного ордера для другой покупки невозможно.

  • Razorpay: проверяется HMAC-подпись чекаута, затем ордер загружается заново и сверяется, что notes содержат правильного покупателя и товар. Сумма и валюта берутся из этого запроса к провайдеру, а не из тела клиентского запроса.

Правило едино для обоих: сумма и валюта, которые вы записываете в бухгалтерию, приходят из записи провайдера об ордере, который вы открыли и криптографически привязали к покупателю. Клиенту, сообщающему «я заплатил», доверять нельзя.

Почему это важно, даже если вы не из Индии

История Мохана Венкаты Кришнана — частный случай, но общий принцип шире. Мир, где «просто добавь Stripe» решает все проблемы, существует только внутри экосистемы поддерживаемых стран и валют. Стоит выйти за пределы — а для индийских, бразильских, нигерийских и десятков других разработчиков это не выбор, а данность — и оказывается, что приём платежей становится инженерной задачей со своими подводными камнями.

Конкретно из этого кейса можно вынести пять практических правил:

  • Если покупатель и продавец в одной стране, PayPal может не работать для внутренних платежей. Проверяйте до написания первой строки кода.
  • Разделяйте провайдеров по валюте, а не по функциям. Давайте покупателю явный выбор.
  • Конвертируйте в локальные ценовые точки, а не в точный курс.
  • Замораживайте валюту и комиссию на уровне транзакции. Агрегаты — по каждой валюте отдельно.
  • Верифицируйте платёж на сервере исключительно через API провайдера. Никогда не доверяйте клиенту.

Никакой экзотики — просто вещи, о которых никто не упоминает, пока ответом является «добавь Stripe». И все они становятся видимыми ровно в тот момент, когда ваш собственный тестовый аккаунт выдаёт первое обескураживающее «Things don't appear to be working».