REST API: предоставление URI перенаправления внешним службам с использованием домена клиентского приложения

Фон

У меня есть RESTful API, доступ к которому осуществляется через домен http://restapi.com

У меня есть клиентское приложение, использующее http://restapi.com. Клиентское приложение имеет домен http://myapp.com

Моя настройка HATEOAS заключается в том, что API представляет URI без домена. Так что вместо http://restapi.com/some/resource он содержит ссылки на ресурсы типа /some/resource. Пример ресурса API json ниже:

{"_links":{"self":{"href":"/some/resource"}}}

Преимущество этого заключается в том, что API не нужно знать о клиентском приложении, а клиентскому приложению нужно сделать очень мало, чтобы получить правильный ресурс из API, и ему не нужно переформатировать все URI в ресурсе. Например, в клиентском приложении следующий URI будет использоваться браузером http://myapp.com/some/resource. Когда приложение получает запрос, ему необходимо вызвать API для получения ресурса и просто поменять домен, т. е. http://restapi.com/some/resource.

Это было успешно и обеспечивает большую гибкость, позволяющую различным клиентам использовать API с единственным необходимым знанием, являющимся начальной конечной точкой (доменом) API. Он также полностью отделяет API от клиентских приложений.

Проблема, с которой я столкнулся, заключается в том, что я начал использовать некоторые внешние службы (в частности, адаптивные платежи PayPal), где мне нужно предоставить URL-адрес перенаправления для отмененных платежей и успешных платежей. Например, браузер переходит к http://myapp.com/payment. Ресурс, возвращенный http://restapi.com/payment, представляет собой ссылку на PayPal. Не вдаваясь в подробности, API должен запросить у PayPal идентификатор платежа, который затем можно использовать для создания ссылки на платеж PayPal, например. http://paypal.com?PayId-123456. Часть процесса создания требует предоставления URL-адресов для перенаправления при отмене или успешном платеже. Опять же, не хочу вдаваться в подробности, но при запросе PayId от PayPal URL-адреса перенаправления отправляются в PayPal как переменные, и я предполагаю, что PayPal хранит их в соответствии с конкретным созданным PayId.

Браузер переходит по ссылке, возвращенной в ресурсе — http://paypal.com?PayId-12345. Оплата производится, и PayPal затем использует URL-адреса перенаправления по мере необходимости для перенаправления обратно в мое приложение, например. после успешного завершения платежа PayPal должен перенаправить на http://myapp.com/paymentcomplete. Примечание. Я понимаю, что это не URI с спокойным названием, но это упрощает создание описания моей проблемы.

Проблема

Проблема, которая у меня есть, теперь может быть очевидной. Мне нужно перенаправить обратно на http://myapp.com/paymentcomplete, НО это API, который предоставляет URL-адрес перенаправления в PayPal. Он ничего не знает о клиентском приложении. Поскольку PayPal является внешней службой, необходимо указать полный URL-адрес. Лучшее, что может сделать API, — отправить http://restapi.com/paymentcomplete в качестве URL-адреса перенаправления, но если PayPal перенаправит на него, результирующим ответом будет строка JSON (выходной формат моего API), а не красиво отформатированная страница клиентского приложения.

Мой вопрос: как правильно указать URL-адрес перенаправления в PayPal?

Одна из моих мыслей заключалась в том, чтобы заставить клиентское приложение обрабатывать создание PayPal PayId, но мне не нравится этот вариант, так как я хотел бы сохранить создание идентификатора платежа PayPal на стороне API. Также потребуется, чтобы каждое клиентское приложение предоставляло собственную реализацию, чего я тоже не хочу.

Другой вариант, о котором я думал, заключался в том, чтобы попросить клиента указать свой домен в запросе. В настоящее время клиент делает запрос на получение ресурса со ссылкой на PayPal GET http://restapi.com/payment, но я мог бы использовать POST http://restapi.com/payment с клиентом, указывающим свой домен в качестве параметра. Затем API может использовать это для создания правильного URL-адреса перенаправления. Мне тоже не очень нравится эта идея, так как она кажется немного хакерской, а также требует, чтобы приложение знало, что оно должно заполнить это поле, то есть пользователь-человек не будет заполнять ввод домена.

Приветствуются дополнительные решения или мысли.


person Gaz_Edge    schedule 10.03.2014    source источник


Ответы (3)


Как вы уже сказали, PayPal — это внешний API, для которого требуется этот дополнительный параметр, и вы не можете его контролировать. Похоже, что клиент — единственная сторона, которая может предоставить информацию URI перенаправления.

На ум приходит пара идей.

  1. Клиент может отправить uri перенаправления в restapi через заголовок и, таким образом, сохранить ваши остальные URL-адреса нетронутыми. На мой взгляд, это серая зона, а не нарушение спокойного API. (опять же, это только мое мнение).

  2. Restapi может вернуть ответ с заполнителем, который клиент должен заполнить перед рендерингом. Таким образом, API не нужно знать об URI перенаправления, и ответственность остается за клиентом, у которого есть эта информация.

Было бы лучше, если бы вы могли реализовать вариант 2, выполнив пару строк в коде Javascript в браузере, чтобы заполнить заполнитель. Что легко. В конечном счете, только 2 конечные точки этой транзакции будут знать об uri перенаправления — браузер и PayPal.

Это снимает большую часть ваших опасений. Работа по обработке идентификатора PayPal будет по-прежнему выполняться вашим API.

person palanik    schedule 14.03.2014

Вы должны иметь возможность использовать заголовок Referer для определения полного URI клиента. Он может быть заполнен автоматически для вас. Если нет, вы можете добавить его самостоятельно. Класс URI имеет методы, чтобы вытащить хост клиента для вас. Когда API создает URI PayPal для возврата клиенту, он может включать хост клиента.

Обратите внимание, что referer не всегда включается и иногда удаляется посредниками, как подробно описано на вики-странице. Поскольку в этом случае вы контролируете и клиент, и сервер, вы должны быть в состоянии сказать всем, чтобы они играли хорошо.

person Eric Stein    schedule 13.03.2014

Я бы оставил GET http://restapi.com/payment и передал параметр запроса с клиентским доменом

GET http://restapi.com/payment?domain=http://myapp.com (of course, the "http://myapp.com" needs to be encoded)
person Simon Arsenault    schedule 12.03.2014
comment
Использование GET вместо POST лучше, потому что вы запрашиваете ресурс. Кроме того, это самое простое решение вашей текущей проблемы без серьезных изменений в дизайне вашего REST API. - person Simon Arsenault; 12.03.2014
comment
но для этого требуется, чтобы клиентское приложение знало структуру URI и знало, что ему нужно добавить свой домен к запросу - кажется немного беспокойным. - person Gaz_Edge; 13.03.2014