I've been playing with stripe recently and while i fully understand that the token hides the clients credit card details from the server. This tutorial suggests that the server should not rely on the data-amount since it can be changed by the client
Don’t Rely on the Form’s Price
A frequent mistake stems from using form data to contain the price of
the product being purchased, possibly via a hidden input. Because a
user can easily edit this input’s value, it’s unwise to depend on it.
Always fetch the price of the product from the server-side. Never rely
on the form to tell you. A simple database query is the preferred option.
Can someone explain to be why stripe does not include the data-amount value as a parameter in the token generation? Is there not a potential for a server side code to change the agreed price and overcharge the client.
The token is a placeholder of a pending charge, it does not know how much you are going to charge yet. Once you are ready to charge the card an api request will be sent to Stripe along with the token. The concern about the amount deals with relying on POST data from a form that can be manipulated by the customer.
Its up to you to set the charge amount. For example a hotel could authorize $100 to spend the night but then at check out discover that you used the minibar and then charge $150. Or the auto calculated shipping is off so when you actually purchase the shipping its $5 less and you decide to charge $5 less than your auth.
What you should be doing is calculating the amount to charge the customer, save it via a shopping cart like function in your DB (or serverside somehow) sending the checkout form to the customer then using the previously calculated amount run the auth then the charge.
Form data can easily be changed by the end user. Just open the page and right click (in chrome) and click inspect element. You can then arbitrarily change form data. So if you were using that, the user could set the price to $.01 for your $1,000.00 product.
The propose of tokenization in the PCI world is to keep sensitive data off your servers. Otherwise you would collect the PCI data yourself then send the amount off to the processor along with the PCI data. By not ever having the sensitive data touch your systems you save a ton of money and headache in PCI compliance. See this 115 page document: https://www.pcisecuritystandards.org/documents/PCI_DSS_v3-1.pdf
Hope that helps, Please comment and I'll try to help further if it doesn't.
Related
Before you ask for some code, understand that this question is about the implementation technique than code mongering.
OK, so in order to save a customer in stripe connect to charge them later or monthly, here is the prescribed process:
step 1. Use Stripe.js to get card details of the user such as card numbr, exp date, cvv etc. which will be sent to stripe.
step 2. Stripe returns a token corresponding to the card like: tok_xyz, now this token can be used to generate a customer in Stripe and you will get customer id.
step 3. Once you have customer id, you can charge them anytime.
Now I have two questions:
If I provide same card details in the step 1 above, will strip return same token everytime? I am asking it so that I may know how to handle the condition when a user enters same card details twice and I don't accidentally create multiple entries in the database for same card again and again.
It's documented in Stripe that after they issue card token (step 1 above) the CVV remains valid only for few minutes and if you don't make a charge in that time, later on the card will become invalid so do I need to charge the customer right away with a small amount like 0.01$ or something? or when I create customer (step 2 above), stripe takes care of that?
Thank you for any help in advance.
No, you will get a different token and tok_xxx ID value every time. However, there is a fingerprint property you can read from the token and compare to cards saved to the customer, to check for duplicates. There are some good answers on StackOverflow showing examples of that.
True, the CVC value is only held for a short amount of time. If you make a charge during that time, it can be checked by the bank. Creating a charge outside that time doesn't make the card invalid, but it will likely lead to more chance of a decline. Luckily this isn't an issue — when you create a customer object Stripe performs a $0 authorisation charge(as described in the blue box here). So as long as you either charge the token directly, or use it to create a customer object, as soon as you get it, you don't need to think about this.
Our site currently asks customers to provide their CC data every time they put an order. Few days later we charge the card, very often with a different amount than shown during the checkout because of merging orders, changing shipment method and so on.
We'd like to migrate to Stripe, but we'd like not to change the current behaviour. Few questions arose while we read the Stripe docs:
1) Stripe.js allows to create a Source without a customer. This seems ideal for us, but the following text from Stripe docs caught our attention:
A card source must be used within a few minutes of its creation as CVC
information is only available for a short amount of time. Card sources
do not expire, but using them after a delay can result in a charge
request that is performed without CVC information. The consequences of
this can be higher decline rates and increased risk of fraud.
So we shouldn't charge the Source few days later? If so, isn't it also a problem for Sources attached to customers, because their CVCs are forgotten as well?
2) To keep things simple, we'd prefer to avoid creating customers and managing their sources in Stripe. Stripe has the concept of single-use sources, that can be charged without attaching them to customers, but the docs say that the amount is required when they are created. We don't know the exact amount at the checkout process, so could we put a bigger number as an upper limit of what we'll charge in the future and provide the exact amount during charging the source?
So you're correct, the CVC is lost anyway but this is not the point that Stripe is trying to make. When you attach the Source to a customer, Stripe will run a $0 or $1 authorization on the card with the bank to make sure it's valid. This lets them catch expired or invalid cards immediately. This also lets them send the CVC to the bank, since they have it at that point, to catch invalid CVC which is important to combat fraud.
If you were to create a Source and not charge it for a few days, that would technically work. The risk is that when you do charge it, the bank won't see the CVC and won't be able to tell you if it was correct or not, increasing the risk of fraud.
To avoid this, Stripe recommends that you save the Source on a Customer. This is just one extra API request which lets you catch invalid cards immediately. Then, days later, when you create the charge on that customer/source, the bank might still decline it (insufficient funds for example) but you would decrease the risk of charging a bad card and catch issues immediately on tokenization. It's better for you as a business but also better for the customer in case they mistyped their CVC or expiration date, etc.
I am creating a payment processing page for use via stripe and I want to be able to have my customers manages saved cards or use a new one. I am worried about being too forthcoming with some customer information and the possibility of exposing too much card information to my servers.
If I retrieve sensitive info like last 4, exp date, etc. should I be putting some means of encryption on it or is it completely fine to display or store pieces of that information for relationships server side on my end?
EDIT: New dev here be gentle :)
The only PCI-sensitive information is the entire card number and the CVC.
The card's brand, last 4 digits and expiry date are not sensitive. If you use Stripe, you can retrieve this information the card object's attributes, e.g. exp_month and exp_year, etc.
From a PCI compliance point of view, you don't need to do anything special to handle this data since it is not considered sensitive. My recommendation would be to either simply query the information from Stripe as needed, and discard it afterwards, or store it as-is into your database (in that last case, you'll probably want to use webhooks to make sure your DB is synced with your Stripe account).
Is there a way in Stripe to automatically send an email to a customer when their credit card is about to expire?
Great news! There shouldn't be a need to notify the customer about expiration dates (or even replacement cards). Stripe's system automatically handles these changes with Smarter saved cards:
Now, when you save a customer with Stripe, their card will continue to work even if the physical card gets replaced by the bank. Stripe works directly with card networks so that your customers can continue using your service without interruption.
This feature started in early 2015, according to the article's date of 2015-01-21.
In the sense you're looking for the answer is likely no. If you're willing to pay for it, something like Stunning can do this for you. Otherwise I think you'd need to setup something on your system to periodically cycle through your customer database and ping Stripe about the status of any credit cards they have on file to see if any are expiring soon.
As Tyler mentioned, Stripe's Card Updater has changed the game when it comes to expired cards.
However, it won't automatically catch 100% of expiring cards. At best, maybe around 70%, as some international territories and card issuers are not yet covered.
Even so, this has made pre-dunning emails (notifying customers before their card expires) obsolete in the best case, and actively harmful in the worst case...triggering "payment problem" notifications to customers who will never actually have a payment problem. These notifications can burden support teams and cause unnecessary customer involvement & confusion.
If you decide not to send pre-dunning emails (we don't), you definitely do need to send dunning emails (when payments actually do fail) which will catch actual, expired cards missed by Card Updater, as well as other kinds of failures that couldn't have been caught by Card Updater.
This Stripe dunning checklist is useful in building the optimal system on top of Stripe.
Actually, now in stripe settings, you could set up the simple reminder email before the card expiration. It's inside Settings -> Prevent failed payments
No there is no such way. Stunning as mentioned by Dhaulagiri sure is a solution but its not free.
A simple alternative is:
When taking the card info by the users for the first time, add the
field for expiry date (stripe provides validation for it too).
Keep checking the card's expiry date at regular intervals (say
monthly or at the time of charging).
If the card is about to expire (in say a month or by the time of
next charge) handle that case to notify your customer.
I have a scenario where the credit card number is being sent over the wire (HTTPS) from application server to browser. Thus, doing a view source of the payment page would display the entire credit card number.
Is this really a security vulnerability ? Since the data is sent over SSL(the entire flow after login is https and the page in question is 3rd or 4th one in the flow), there is no way for man in the middle to get this information. Also,I tested for session side jacking (getting the session id when user is on http and try to impersonate...) - the application is intelligent enough to prevent this attack.
I was thinking in the lines of adding a secure cookie in addition to not sending the entire credit card number over the wire, but is that an overkill ?
HTTPS, implemented properly (most browsers do, check your server), provides complete end-to-end secure delivery of the data. There will be no man in the middle attacks.
We're also assuming your website is safe from cross site scripting attacks.
Still, it's best to show just the last four digits. This is for such cases as someone wanting to do their banking or shopping or whatever from a public location. It prevents those snooping over their shoulder from getting entire account numbers.
It's still an issue if someone want's to enter a new credit card (watch your back), but there's very little reason to show the entire credit card number once you've verified it. Let the customer name the account though, just in case they have more than one card with the same last 4 digits, plus for ease of use.