Domanda

Background

I have a RESTful API accessed through the domain http://restapi.com

I have a client app using http://restapi.com. The client app has the domain http://myapp.com

The way I have my HATEOAS setup is that the API presents URIs without a domain. So instead of http://restapi.com/some/resource, it contains links to resources like so /some/resource. Example API json resource below:

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

The benefit this has is that the API doesn't need to know about the client app, and the client app has to do very little to get the correct resource from the API and doesn't have to reformat all the URIs in the resource. For example, in the client app, the following URI would be used by the browser http://myapp.com/some/resource. When the app gets the request, it then needs to call the API to get the resource and simply swaps the domain i.e. http://restapi.com/some/resource.

This has been successful so for, and allows a lot of flexibility to have different clients use the API with the only knowledge required being the initial end point (domain) of the API. It also completely decouples the API from the client apps.

The problem I have run into is that I have started using some external services (specifically PayPal adaptive payments) where I need to provide a redirect URL for cancelled payments and successful payments. For example, the browser navigates to http://myapp.com/payment. The resource returned by http://restapi.com/payment presents a link to PayPal. Without going into too much detail, the API has to ask PayPal for a payment ID, which can then be used to create a link to a PayPal payment e.g. http://paypal.com?PayId-123456. Part of the creation process requires that URLs are provided to redirect on payment cancellation or success. Again, don't want to go into details, but when requesting a PayId from PayPal, the redirect URLs are sent as variables to PayPal, and I guess PayPal stores them against the specific PayId created.

The browser navigates to the link returned in the resource - http://paypal.com?PayId-12345. Payment is made and PayPal then uses the redirect URLs as needed to redirect back to my app e.g. on successful completion of payment, PayPal should redirect to http://myapp.com/paymentcomplete. Note: I realise that this is not a restfully named URI, but it simplifies building up the description of my problem

Problem

The problem I have may now be obvious. I need to redirect back to http://myapp.com/paymentcomplete, BUT its the API that provides the redirect URL to PayPal. It has no knowledge of the client application. Since PayPal is an external service, the full URL must be provided. The best the API can do is send http://restapi.com/paymentcomplete as the redirect URL, but if PayPal redirects to this, the resulting response will be a JSON string (the output format of my API) not the nicely formatted page of the client app.

My question is, what is a good way to correctly provide the redirect URL to PayPal?

One thought I had was to make the client application handle creating the PayPal PayId, but I don't like this option as I would like to keep the creation of the PayPal payment ID on the API side. It would also require every client app to provide its own implementation, something I also don't want.

The other option I though of was to ask the client to provide its domain in the request. Currently the request the client makes to get the resource with the link to PayPal is GET http://restapi.com/payment, but I could use POST http://restapi.com/payment with the client providing its domain as a param. The API can then use this to construct the correct redirect URL. I don't really like this idea either as its seems a bit hackish and also requires the app to know that is must fill in this field i.e. a human user wouldn't fill the domain input in.

Additional solutions, or thoughts greatly welcomed.

È stato utile?

Soluzione

As you had already mentioned, PayPal is an external api that requires this additional parameter and you do not have control over it. Looks like the client is the only party that can provide the Redirect URI Information.

Couple of ideas come to mind.

  1. The client could send the redirect uri to restapi via header and thus keeping your rest urls intact. This is a grey area and not a violation of restful api in my opinion. (Then again, its just my opinion).

  2. The restapi could return the response with a placeholder for the client to fill in before rendering. This way the API need not know about the redirect uri and the responsibility is left to the client which has this information.

It would be nicer if you could implement option 2 with executing couple of lines on Javascript code on the browser to fill-in the placeholder. Which is easy. Ultimately, only 2 end points of this transaction would be aware of the redirect uri - browser & paypal.

This alleviates most of your concerns. The job of handling PayPal id will continue to remain with your API.

Altri suggerimenti

You should be able to use the Referer header to determine the client's full URI. It might be populated automatically for you. If not, you can add it yourself. The URI class has methods to pull out the client's host for you. When the API builds the PayPal URI to return to the client, it can include the client's host.

Note that referer is not always included and sometimes gets stripped by intermediaries, as detailed on the wiki page. Since you control both the client and the server in this case, you should be able to tell everybody to play nicely.

I would keep the GET http://restapi.com/payment and pass in a query param with the client domain

GET http://restapi.com/payment?domain=http://myapp.com (of course, the "http://myapp.com" needs to be encoded)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top