背景
我有一个RESTful API通过域http://restapi.com
访问
我有一个使用http://restapi.com
的客户端应用程序。客户端应用程序具有域http://myapp.com
我设置HAEOAS的方式是API在没有域的情况下呈现URI。因此,它不包含http://restapi.com/some/resource
,而是包含指向类似/some/resource
的资源的链接。下面的示例API json资源:
{"_links":{"self":{"href":"/some/resource"}}}
这样做的好处是API不需要了解客户端应用程序,客户端应用程序只需做很少的事情就可以从API获得正确的资源,并且不必重新格式化资源中的所有URI。例如,在客户端应用程序中,浏览器http://myapp.com/some/resource
将使用以下URI。当应用程序获得请求时,它需要调用API来获得资源,并简单地交换域,即http://restapi.com/some/resource
。
迄今为止,这是成功的,并允许不同的客户端使用API具有很大的灵活性,所需的唯一知识是API的初始端点(域(。它还将API与客户端应用程序完全解耦。
我遇到的问题是,我已经开始使用一些外部服务(特别是PayPal自适应支付(,我需要为取消的支付和成功的支付提供重定向URL。例如,浏览器导航到http://myapp.com/payment
。http://restapi.com/payment
返回的资源提供了到PayPal的链接。不需要过多的细节,API必须要求PayPal提供支付ID,然后可以使用该支付ID创建到PayPal支付的链接,例如http://paypal.com?PayId-123456
。创建过程的一部分要求提供URL,以便在付款取消或成功时重定向。同样,我不想详细说明,但当从PayPal请求PayId时,重定向URL会作为变量发送到PayPal,我猜PayPal会根据创建的特定PayId存储它们。
浏览器导航到资源中返回的链接http://paypal.com?PayId-12345
。付款后,PayPal根据需要使用重定向URL重定向回我的应用程序,例如,在成功完成付款后,PayPal应重定向到http://myapp.com/paymentcomplete
。注意:我意识到这不是一个完全命名的URI,但它简化了对我的问题的描述
问题
我现在的问题可能是显而易见的。我需要重定向回http://myapp.com/paymentcomplete
,但它是API,提供了到PayPal的重定向URL。它不了解客户端应用程序。由于PayPal是一项外部服务,因此必须提供完整的URL。API能做的最好的事情是发送http://restapi.com/paymentcomplete
作为重定向URL,但如果PayPal重定向到该URL,则得到的响应将是JSON字符串(我的API的输出格式(,而不是客户端应用程序格式良好的页面。
我的问题是,什么是正确提供重定向URL到PayPal的好方法?
我的一个想法是让客户应用程序处理创建PayPal PayId,但我不喜欢这个选项,因为我想在API一侧保留PayPal支付ID的创建。它还要求每个客户端应用程序都提供自己的实现,这也是我不想要的。
我认为的另一个选择是要求客户端在请求中提供其域。目前,客户端获取带有PayPal链接的资源的请求是GET http://restapi.com/payment
,但我可以使用POST http://restapi.com/payment
,客户端提供其域作为参数。API然后可以使用它来构造正确的重定向URL。我也不太喜欢这个想法,因为它看起来有点过时,而且还需要应用程序知道必须填写这个字段,即人类用户不会填写域输入。
非常欢迎其他解决方案或想法。
正如您已经提到的,PayPal是一个需要此附加参数的外部api,您无法控制它。看起来客户端是唯一可以提供重定向URI信息的一方。
我想到了几个主意。
-
客户端可以通过头将重定向uri发送到restapi,从而保持你的休息网址完好无损。这是一个灰色地带,并不违反restful api在我看来。(再说一遍,这只是我的看法(。
-
restapi可以返回带有占位符的响应客户端在渲染前填写。这样API就不需要知道关于重定向uri和责任留给客户端其具有该信息。
如果您可以通过在浏览器上对Javascript代码执行几行来填充占位符来实现选项2,那就更好了。这很容易。最终,这个事务只有2个端点知道重定向uri-browser&贝宝。
这缓解了您的大部分担忧。处理PayPal id的工作将继续留在您的API。
您应该能够使用Referer标头来确定客户端的完整URI。它可能会自动为您填充。如果没有,你可以自己添加。URI类具有为您拉出客户端主机的方法。当API构建PayPal URI以返回到客户端时,它可以包括客户端的主机。
请注意,referer
并不总是包含在内,有时会被中介剥离,如wiki页面上所述。既然在这种情况下您同时控制客户端和服务器,那么您应该能够告诉每个人要玩得很好。
我会保留GET http://restapi.com/payment
并通过客户端域传递查询参数
GET http://restapi.com/payment?domain=http://myapp.com (of course, the "http://myapp.com" needs to be encoded)