PayPal Instant Update API not working on HTTPS - ruby-on-rails

We are building an online store that is based on Spree and hosted on Heroku. We want to make the checkout as easy as possible so we decided to use PayPal Express Checkout, and Instant Update API to determine the shipping cost.
When we tested the checkout process over HTTP, everything works perfectly - when the user enters his shipping address, PayPal queries our server in the background and obtains the shipping costs.
However when we switched to SSL, the shipping cost just doesn't update and reverts to the default flat-rate. I cannot figure out what is wrong because everything is the same, except this time the app is accessed through HTTPS, i.e. https://myapp.herokuapp.com
I have check the logs and I see that PayPal's server did make the query, but the shipping cost just don't update on PayPal's checkout page.
Any thoughts on what's wrong?
Update:
After further testing, it seems PayPal is not obeying the timeout set in the transaction setup. We added a simple "sleep(x)" to the callback method to artificially induce some delay (by x seconds), and even over normal HTTP, just 1 second delay is enough to caused PayPal to ignore the response.
The max timeout is supposed to be 6 seconds, but in reality it doesn't seem to be the case at all. And couple that with HTTPS (which take longer to establish a connection), it is probably why the callback was failing in the first place.
I have submitted a ticket to PayPal, but I'm not sure if they will respond or do anything about it...

It appears there are many reasons that PayPal could ignore the returned shipping options from the callback.
I'd like to see something on PayPal's site that would keep a history of recent calls to the callback with the returned response and reasons for rejection - somewhat similar to the useful IPN history.

I'm glad you posted your real domain name here because you've pretty much confirmed my suspicions.
I'm pretty convinced the problem is that you have a wildcard SSL (I see your certificate is issued to *.herokuapp.com) and not just an SSL for a single domain.
I am having the same problem with a UCC certificate for www.MicroPedi.com which is a 5 name UCC certificate. PayPal just flat out refuses to even make any calls to it (I have logging and nothing is coming through except when using the sandbox).
To confirm this I have a previous Express checkout implementation that is working just fine (with a single SSL) and I pointed my new application to that old URL and it magically started working again. That is a single name SSL - in fact it's one of those expensive green bar certificates.
I've written directly to PayPal support, but right now the only thing I can think of doing as a workaround is writing some kind of proxy page that will just redirect from the good domain to my UCC domain.

Related

Sign in with apple "invalid_client" on the first redirect to apple of the Oauth2 code grant flow using service identifier

At this point I might be missing something really obvious in the configuration panel for apple, but after spending a day on this with several other people and reverting back to vanilla node (no third party dependencies).
We had 2 app identifiers in our account with Sign in with Apple and Push Notifications checked. I added at some point a service identifier to one of them and whitelisted a redirect URI. Everything went fine locally.
I got to production, and I kept getting wrong redirect uri for the exact same config, although the uri was whitelisted. I thought it might be because there's 2 uris, so I deleted the one that worked in the hopes that the one in production will start working.
None of them work anymore.
I have added a new set of app id + service id + secret key to use for the whole flow and I never get passed the "invalid_client" during the very first redirect to apple.
Code:
const url = new URL("https://appleid.apple.com/auth/authorize");
url.searchParams.append("state", "fdbd287b1f");
url.searchParams.append("response_type", "code");
url.searchParams.append("scope", "name email");
url.searchParams.append("response_mode", "form_post");
url.searchParams.append(
"redirect_uri",
"https://raiseitupdev.com/auth/apple/redirect",
);
url.searchParams.append("client_id", "com.myname.auth");
return res.redirect(url.toString());
We got this resolved by going into the More > Configure and adding our domain, making sure the SPF tick is green (if its not green, do a quick google to find out how to fix it for your config). After this, we stopped getting invalid_client errors.
The thing that made us stumble on this was it didn't appear important on account of it saying it was for the emails - we skimmed over it thinking we could come back to it later..

PayPal not redirecting to the IPN notify_url in an MVC system

I am using IPN to receive payment notifications in an MVC system I'm working on. After verifying certain bits and pieces, I proceed to update the database with the "subscription" and "payment details" for the particular user. I am using "notify_url" to redirect back to the system and initiate the PaymentNotification method. This was working correctly up until a few days ago, when it all of a sudden just stopped working. First I thought that the database was not being updated due to an issue within the method itself, but then I noticed that the PaymentNotification (IPN) method was not being hit at all.
Some notes:
A test from the paypal developer's page seemed to redirect correctly
into the IPN. Calling the link directly from the browser hits the method also, so it seems to be externally accessible.
I am using NGROK to make the localhost look like it's
running from a live domain. It does not work with either HTTP or
HTTPS. I am also testing on a hosted environment, with sandbox configuration, within an HTTP domain, and it is not working either.
I am debugging the hidden values in the validation form, right
before redirecting to Paypal and all the values, including:
notify_url are correctly populated. This was working but suddenly
stopped.
Some questions:
What could be the reason? Why would it work all throughout the development
stages but suddenly stop working? Of course, I can't afford to have
this stop working on the live environment!
Is this perhaps an issue
with the sandbox environment? Is IPN safe for Live systems? Can someone talk from experience?
Or
is there perhaps a better option I can look into?
I read this article, which
discusses verifying/activating the email address of the sandbox
account. Can anyone indicate what that might be? And whether the same
email addresses being used could have been working but suddenly
stopped? Do they need to be real emails? As the ones that I was using (and were also working) are not tied to real paypal accounts.
As suggested in the comment, even just for testing Paypal in Sandbox mode, since September 2016, TLS 1.2 is required for PayPal IPN processing. In my case, changing the Sandbox testing business and personal emails to real / valid emails, solved my issue with regards to testing locally using NGROK as a secure tunnel to Local host. More so, this should not be a problem when I actually use the HTTPS certificate.

"Remember this approval" when using dotNetOpenAuth and Google Apps doesn't work as expected

I'm using dotNetOpenAuth to provide SSO to my app via a user's Google Apps account. Besides just simple authentication I also ask Google to return the user's email, first name and last name. When a user first goes in they get redirected to the typical Google Accounts page telling them that the app is asking for this info and do they want to allow it. There is the checkbox there to Remember This Approval. The problem is, the approval isn't being remembered. It does remember them if they go back to the site without closing their browser. But if they close their browser and then open it later and go back in, they are again prompted to allow it.
If I look through my Google account page that shows me connected sites, apps, and services, I see my app listed multiple times. It's like it doesn't recognize that it's the same app and keeps adding it.
I know I must be missing something obvious, but I'm not sure what it is. Any ideas?
Thanks!
You can find my code here
I see several problems in your code. To first answer your direct question, the reason Google doesn't remember you on return visits is because you are passing a random GUID in as part of your Realm each time you log in. The symptom is actually much worse than you realize. It's not just that Google prompts the user on return visits, your site won't recognize the user at all on return visits because Google will give them a new claimed identifier on each visit.
The fix is that you should use the exact same Realm for every login request:
Realm realm = "http://www.yoursite.com/";
var req = openid.CreateRequest(discoveryUri, realm, URIbuilder.Uri );
Or my personal favorite:
var req = openid.CreateRequest(discoveryUri, Realm.AutoDetect, URIbuilder.Uri );
Realm.AutoDetect will work for you unless your site is available both via HTTP and HTTPS, in which case you need to lock it down to just one or the other of these so that Google recognizes your site as always the same.
You must also remember that the returnTo URL that you pass in as the 3rd parameter to CreateRequest must always be based on the realm. So if your realm is HTTPS, so must your returnTo parameter be.
I also want to call out that you seem to have some GUID code and complex URL manipulation around trying to ensure that every OpenID response you accept comes from a request you sent out. I'm not sure why you're trying to do this in the first place, although there certainly can be legitimate reasons. The way you did it is insecure and can be circumvented. I suggest you delete all this code, in favor of adding this to your web.config file:
<dotNetOpenAuth>
<openid>
<relyingParty>
<security rejectUnsolicitedAssertions="true" />
</relyingParty>
</openid>
</dotNetOpenAuth>
The library has support for requiring all responses to come from your requests built in, and it does so securely so that the security exploit I alluded to earlier isn't possible.
But if you're only trying to apply this restriction so that you know it's coming from Google, may I recommend that instead of rejecting unsolicited assertions, you instead check the IAuthenticationResponse.Provider.Uri property when you receive responses and verify that it is coming from the Google OP Endpoint? Then, if Google ever supported sending unsolicited assertions it would work on your site, and ultimately your security gate is exactly where you intended it to be anyway.

PayPal Sandbox - CreateBillingAgreement call returns Internal Error (10001)

I'd appreciate any help with this, I've run around in circles trying all sorts of combinations with the PayPal Api - but I'm hitting a brick wall on this one.
I'm looking to call the CreateBillingAgreement method but each time I do it fails and reports a 10001 'internal error' from paypal in the response.
I have a valid token and I'm using version 84.0. I've successfully called SetupExpressCheckout and DoExpressCheckout, both of which succeed and the payment goes through. I'm setting up a future payment / pre-authorisation on the SetupExpressCheckout and the user agrees to that no problems.
​Do I need to change settings on the merchant in the sandbox? Am I calling things in the wrong order maybe? (SetExpress, GetExpress, DoExpress, CreateBilling)?
​I'm looking to use this billing agreement to allow a reference transaction in the future. I'm having a test account 'pay' using paypal and not forwarding any credit card details, the payment is for a digital service with no delivery (no shipping is set, no addresses or delivery costs are involved). The overall goal is to provide a one-click re-order button, whereby no details need to be entered by the customer.
I'm using the C# api in asp.net 4, or more specifically I've created Service References from the paypal sandbox wsdl and I'm using those in asp.net.
​Any and all help is appreciated - thanks.
​Russell.
You don't need to call CreateBillingAgreement if you're specifying billingtype MerchantInitiatedBilling in your SetExpressCheckout and DoExpressCheckoutPayment API call. CreateBillingAgreement is only necessary if you don't want to call DoExpressCheckoutPayment.
If MerchantInitiatedBilling is set, DoExpressCheckoutPayment will already return a billing agreement ID, which you can use in DoReferenceTransaction.
I don't have access to an example at hand, but will update this post as soon as I've found one for you.

iphone: is there any secure way to establish 2-way SSL from an application

I need to establish a HTTPS 2-way SSL connection from my iPhone application to the customer's server.
However I don't see any secure way to deliver the client side certificates to the application (it's an e-banking app, so security is really an issue).
From what I have found so far the only way that the app would be able to access the certificate is to provide it pre-bundeled with the application itself, or expose an URL from which it could be fetched (IPhone app with SSL client certs).
The thing is that neither of this two ways prevent some third party to get the certificate, which if accepted as a risk eliminates the need for 2-way SSL (since anyone can have the client certificate).
The whole security protocol should look like this:
- HTTPS 2-way SSL to authenticate the application
- OTP (token) based user registration (client side key pair generated at this step)
- SOAP / WSS XML-Signature (requests signed by the keys generated earlier)
Any idea on how to establish the first layer of security (HTTPS) ?
Ok, so to answer my own question...
It turned out that the security has no fixed scale of measurement.
The security requirements are satisfied as long as the price for braking the system is significantly above the prize that one would get for doing so.
In my situation we are talking about e-banking system, but with somewhat low monthly limits (couple of thousands USD).
As I mentioned in my question there would be another layer of security above the HTTPS which will feature WSS XML-Signatures. The process of registering the user and accepting the his public key is also done in several steps. In the first step the user sends his telephone number together with a cod retrieved somehow from my client. Then an SMS is sent to the user with a confirmation code. The user enters the confirmation code into a OTP calculator that would produce OTP code which will identify the user. Then the public key is sent to the server together with the OTP code. From here on every request would be signed by the private counterpart of the public key sent to the server earlier.
So the biggest weakness for the whole process is that of someone reverse engineers the application and retrieves the client certificate used for the SLL. The only problem arising from this is that someone might observe users' transactions. However in order for someone to make a transaction he would need the user's private key, which is generated, encrypted and stored into the keychain. And the price for braking this security level is VERY HIGH.
We will additionally think on how to protect the users' data on a higher level (e.g. using WSS Encryption), but for the start I thing we are good with the current solution.
any opinion ?
regards
https doesn't really work this way. In a nutshell, you attach to a secure server where the certificates are signed by a well known authority.
If you use Apples (iPhone) classes for this, they will only accept 'good' certificates. By good, I mean what Apple deems as acceptable. If you don't use them (there are alternatives in the SDK), you won't be able to connect (except, maybe, in the case where you have an 'Enterprise' developers license - but I can't say that with 100% certainty as I haven't looked enough at this license to be sure)
To continue, use your https connection to your correctly signed website and then institute some sort of login with a built in username/password, or challenge/response based upon the unique ID of the iPhone (for example) and exchange keys using that connection.
Note that this means that your application will have to query for new certificates at (each connection/every X connections/every month/application specified intervals) to keep them up to date. You can then use these certificates to connect to the more secure server.
[edit]
Check this post - may have more information about what you're asking to do
[/edit]
[edit2]
Please note that the request is iphone, not OSX - app store approval is an issue
[/edit2]

Resources