-
-
Notifications
You must be signed in to change notification settings - Fork 929
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sagepay server and redirectionURL #255
Comments
NOTE: the notification URL is now set with If you are using SagePay Server, then you need to provide a notification URL, which is usually known as a callback (the "returnUrl" in OmniPay, which is a total misnomer - it translates to the "NotificationURL" on SagePay, which is a more accurate name). That URL is where SagePay will send the results of the authorisation, which you store, and then tell SagePay where to send the user next. That notification is called outside of the user's session, so the transaction and results must be stored in your database for it to be accessed between the callback and the user pages. So, it looks like you have that, with the callback being handled by In addition:
I generally send the user to the same URL for confirm/invalid/success and then read the final status of the payment from the database (as stored in the callback) then take appropriate action based on that. SagePay may seem unusual, but - trust me - it is a hell of a lot more secure than many other gateways, but ONLY if implemented correctly. |
Just to highlight what may be confusing many people - the The name |
@judgej thanks for pointing that out. I think it's definitely a point of confusion. I'm adding it tot he list of things we need to specifically document for this gateway. |
Thank you for your help judgej. I will tidy up the handling of the Sagepay responses once I can get it working, am still trying to get past that error at the moment! Some useful tips about the correct process thank you. It's not getting past the |
@JoSquiders yes, sorry, I forgot another important step. When you first register the transaction, you must get the In the callback, you must pass this transaction reference, along with the transaction ID, to the This is what mine looks like, with $sagepay_transaction being the saved transaction ORM record:
I have omitted the saving of the updated transaction with the results, logging etc. for clarity. |
I have another issue open to try to remove that exception, so this can be handled a lot more cleanly. |
@kayladnls I have a note in my (v3) list to suggest standardising on a |
Is it worth moving this issue to the omnipay-sagepay repository? I found this online tool that seems to be able to do it: https://github-issue-mover.appspot.com/ It was referenced from here: holman/ama#413 |
@judgej Thank you so much - you've no idea how much I've been pulling my hair out over this! I've got past the error now so hopefully I can sort it out from here, it was just knowing what to pass where and what functions to call. I couldn't find any useful code examples to work from either so you've been a great help :) |
Glad it was useful. Let us know how it all works out in the end - there may be other little things that need tweaking. |
Thank you @judgej. I'm just tweaking some bits but I have something along these lines:
I haven't worked on the error handling yet though I have some code in there for it. Have cut the code down to basics to make it easy for someone else to follow. |
That looks like it covers most stuff. The Checking that order number is the same as in the user's session is essential. I've seen examples of sites (e.g. some WooComnmerce and Drupal gateways) where this check is not done. What happens is that people make a tiny purchase with a valid card, and catch the final page URL without going there. Then they make a massive purchase with an invalid card, but then go to the final page URL they caught before, and it marks the larger payment as successful. This stuff does happen, is a well-known technique, so you can be sure someone will try it on your site. |
I have added in that check and yes makes perfect sense. Have updated my code above to make that clear and to take out some of the unnecessary |
Totally :-) The more we get this sorted out, together, the easier it will be to use, and the more people will use it, and so the more people there are to help maintain it and take it to levels we would not have dreamt of. It's a virtuous circle. |
I am getting the same issue as documented here, and I have re-read this thread several times hoping I had missed something but can't see what, please help! This is the code I have so far:
|
I wouldn't put the transaction ID in the final confirm URL - keep that in the session where the user cannot mess with it. That is one vulnerable place where hackers can switch the IDs of small and large partial orders around, and end up getting a big purchase for a small amount, if you have not taken other steps to prevent this. You can use Is the "23" in your notify URL the transaction ID? It is also available through $request = $this->gateway->completePurchase([...]);
$transaction_id = $request->getTransactionId(); You will need it to retrieve your order payment from the database, but you don't need to pass it into Beyond that, where is it actually failing? You can write messages to the log file in the "update" notify handler to see what is happening in there ( |
I can't get inside the update method at all, I can get to I have put log calls in, but I omitted them from the code for clarity, but SagePay doesn't hit my endpoint : ( |
Have you checked the HTTP logs? Is it really not getting there? |
I'm running on Digital Ocean, I have checked the error and access logs for nginx and there is nothing there to suggest that SagePay has come back |
Hmm, I can get to the URL, so something is up there. If you provide a complete invalid URL - just some random characters - does it get as far through the process? If SagePay did not think you had given it a URL, then it would not have reported a success at the first stage, so you should in theory not get a redirect. I need to get home now, but I'll do a few tests tonight in case it is anything that has changed at the SagePay end. |
Same here, hopefully some fresh eyes tomorrow will help. |
Can't remember off the top of my head, but is Sagepay one of the merchants that requires you to add in your IP address to an allowed list? Just a thought that you might want to check that! ** thinking about it, I think it gives you an invalid IP address error. Ignore me! |
I've done that, and it would return an Invalid IP response if it wasn't allowed, thanks though! |
@JoSquiders yes it is. The IP address is the only way SagePay knows it is really your server that is sending the request. Other gateways use certificate-based hashing of that data, but SagePay does not (at the initial registration, at least). However, it would be rejected right at the start if the IP was not right. I'm wondering, is SagePay really returning a valid "go ahead" response to that initial registration? If it is, then it is certainly happy with the details that it has been given, and happy with the IP address. So after redirecting to SagePay, exactly what happens next? You should get a screen with a list of credit card icons. Click one of those and it takes you to the pre-filled personal details page. Only after completing that does SagePay try to contact your server. Is that the sequence that is being seen here? |
Had forgotten it returns the IP invalid error! Also missed that it is getting to the SagePay redirect, think I read that as it wasn't! |
@judgej I'm getting to the SagePay screen, I can select a card, and fill in the form, and then it goes to a confirmation screen; when I confirm, a progress bar appears, and then the 5006 error pops up after a while, not sure if it is timing out, I read in the SagePay docs it tries up to 10 times and then continues to retry but with a failed response instead. I also read somewhere, that, sometimes, you need to allow access to the site via the firewall on your server, but I can't find the IP addresses I need to add anywhere. I pinged the site, but got 100% packet loss so wasn't sure if that was the right IP and I couldn't see that IP in my access log. |
@judgej Just following up to see if you were able to think of anything that could be causing this issue? |
Yes, SagePay does try multiple times in rapid succession. I've seen that with a script returning a 500, in the HTTP logs. There are just a few seconds between each retry, for the first few at least. It will try again later, maybe five minutes or so, before it times out and sends a final "timed out" message to your notification URL. So your problem: SagePay calls a URL and does not get a response it expects. It is either not calling the right URL, or your handler is not returning the correct response. Not sure if I've already asked, but is there anything in the HTTP or HTTPS access logs that show SagePay trying to access the notification URL? If not, could there be a firewall stopping it (I could access those URLs from my browser, so I would guess not). If access attempts are in those logs, then it narrows it down to what your script is actually doing. If you are using HTTPS, then try HTTP. IIRC SagePay does not have a problem with self-signed SSL certificates (some gateways do - Authorize.Net hates them). But it is worth trying HTTP as a long-shot. |
I don't have SSL installed yet. I have tried several times whilst tailing the access log for nginx and nothing appears, we had an issue recently regarding HHVM, which we have installed on the server, have you heard of any conflicts between the OmniPay, SagePay, and HHVM? I'm wondering whether HHVM is interfering with the request at all? The firewall isn't an issue, it should accept the calls from SagePay. |
No, no experience with that. SagePay is firing off notifications to the URL you give it. It is getting through to your server, or it isn't. There should be some log files somewhere on your server that tell you what is coming in over HTTP. This is what you primarily need to find out. The SagePag test admin panel should also allow you to drill down to the response it gets. I'm sure I've seen that feature, but it's well hidden in the interface (you need to select failed transactions and there are some no-too-intuitive links through from that). |
For anyone who might read this in future, I uninstalled HHVM and this seemed to fix the problem, not sure what inside HHVM made this fail, but this is how I got round it. |
Thanks @judgej for your help! |
Could there have been a layer of front-end caching? The notify is a POST message so I can't see how, but clutching at straws here. It would be nice to know the root reason for this problem, because I'm certain it won't be the last we see of it. Thanks for letting us know. |
I don't think so, I cleared the cache a couple of times between tries to ensure javascript scripts were up to date, and the result was still the same. I think the problem here was in the HHVM config, but I don't know enough about servers to really debug it. |
Hi JudJ you seems like a real expert on this subject and I was wondering if you can help me please. Thanks so much in advance. After changing my website over to shared SSL, I have been trying to solve this 5006 error for the past few days with a developer. The error happened in the final stage after the 3D secure password. When my woocommerce site was http it seems fine, only when I made it https with a valid https certificate, I am getting this error 5006 and 500. http://www.mywebsite.com/?wc-api=woocommerce_sagepayserver I would advise on investigating the URL in question to see if it is active and responsive." When I click on the above link I get this: All my plugin were fine and working, only when switch over to https. Can you help me and pinpoint the actual place where I have to put this url in? I mean should it be automatic? I never created this url. Ensure you have opened ports 80 and 443 on your Servers to allow posts from Sage Pay. |
@thaithai21 Do you have any security plugins installed on your WP installation. Sometimes they can block URLs from some sources but not others, and that may be affected by the use of SSL. Sage Pay is happy to respond to non-SSL URLs and self-signed URLs (other gateways are not happy to do this). Just something to bear in mind, in case the policy changes. The status message you get back looks fine. Can you confirm the response - even with the error message - is a HTTP 200 and not a 40X? Sage Pay Server always expects a 200 response, no matter what the status. Could you try a POST to that same notify URL. You should get the same result as with the GET. Sage Pay will send a POST. Firebug, or some online tools will be able to do that for you. I've seen security plugins treat GET and POST to the same URL differently before. |
Hi @judgej, Thanks for the reply. I manage to solve the problem last night. Finally got through to blue host as I have site lock on. So yes you are right it is some kind of security issue. They also re-validate my SSL certificate when I moved over to their wordpress hosting server. Not sure exactly what they have done but it seems to wok now. Thanks so much for the response anyway, the stuff that you know you should be a partner of sagepay ;-) |
I'm closing this as the original issue has been resolved. The details will hang around and should probably go into documentation at some point. |
Hi @judgej, Thanks for your post. Here is my code in Python: @http.route('/payment/sagepay/complete', type='json', auth="public", methods=['POST', 'GET']) def sagepay_complete(self, **post):
@http.route('/payment/paysage', type='http', auth="none", methods=['POST', 'GET']) def sagepay_complete_redirect(self, **post):
Here first url '/payment/sagepay/complete' is the NotificationURL. I got response to this url. I returned the response with RedirectURL '/payment/paysage'. But it always gives the error 5006. Please guide me if I am missing something. |
This probably isn't the place to be asking Python questions, but I'll try to answer generically. Sage have offloaded their main developer support questions to Stack Overflow (the cheapskates) so that is where you will find the best Sage Pay answers. Please move the question over to there if there are specific technical questions. When you first set up the Sage Pay Server transaction, you give the gateway the notification URL to send the results to. You can set any URL you like, SSL or not, and that can include GET parameters and a path to give your notification handler some context. In your notification handler you must tell Sage Pay (using the format you have already identified in your post above) where to send the user next. IMO that URL should be the same place regardless of the status of the transaction (OK, FAILED or ERROR) - don't put anything into that URL that can be used as an attack vector if the end user fiddles with it. So what is that URL? That is up to you. In your handler you have:
This information will be enough to be able to construct a URL to send the user to. When the user to returned to the site front end (through that URL) the first thing to look at is the session - you should have stored the state of the transaction there (your internal session ID), so on return your application knows where to pick up from. Then you can use that to fetch the transaction result that was stored in the database in the notification handler. That, in a nutshell, is how the notification handler for Sage Pay Server is used. Sage Pay Direct (needing more PCI certification) and Sage Pay REST (a very new gateway which only came out of beta this week) do not use a notification handler. |
Had this issue as well, my problem lied in the fact we had just installed an SSL onto the domain, and hadn't changed; $strPost=$strPost . "&NotificationURL=https://" . $_SERVER['HTTP_HOST'] . "/sagepay"; Why not have the system detect if it's http or https itself, eliminates this kind of problem |
I'm getting error: 5006 Unable to redirect to Vendor's web site. The Vendor failed to provide a RedirectionURL.
I'm trying to connect to Sagepay Server and am setting 'returnUrl' but it is never hitting the URL I specify here. It does successfully connect to Sagepay and I go through the test payment all okay. I receive the error when clicking pay now. I know Sagepay works a bit different from the other gateways but I don't know what I'm missing.
My code looks like:
I have cut out some of it to make it readable but the $orderNo and 'card' parameters are set (I've only put firstName here but I do send all the details). I initiate the Omnipay Sagepay server instance in the __construct.
The text was updated successfully, but these errors were encountered: