Accepting payment best practices - php

I am creating an ecommerce site that uses the payment gateway DPS. The payment gateway just takes a users details and returns whether the payment was successful or not.
I am just wondering if anyone has any good resources for how to make a really robust payments page that can handle large volumes of transactions safely. Are there well tested techniques and strategies for high volume payments pages?

You'll want to design your code in such a way as took keep your data in a valid state.
The big liability you face is that you send data off for Auth/Capture, and then, for whatever reason, something on your end fails. You've charged your customer, but for whatever reason, you don't know this fact! Eventually, some irate customer is going to start shouting at you over the phone. That's a bad time.
The general idea is to put some safeguards in place so you can identify these kinds of problems. The problem should be very rare, if it even ever happens, so fixing the mess will probably be a manual process.
Here's what I would do:
Design a database table that tracks payments (let's call it "payment"), and relate it to your "order" table (so payment.order_id references order.id).
When it's time to interact with your gateway, set up a new payment record, containing any non-sensitive data you're about to pass to the payment gateway. Have a "status" column in your payment table, and set it to "pending"
Attempt the auth/capture transaction with your gateway. Upon receiving a response, update the payment record status to "approved", "declined", or "error" and save any relevant metadata (decline reasons, transaction ID, etc). If the gateway times out, that's probably just a kind of "error", though you might retry once or twice.
Run a cron job every now and then looking for payment records that are "pending", and older than, say, 30 seconds. If you find any, panic and tell a developer/operations person.
There are certainly other things that could go wrong, but this is the big one that comes to mind, and the strategy I've described is one I've used on multiple occasions to mitigate the risk.

I'm not an expert on payment processing and developing ecommerce applications, but some of my (commonsense) guidelines are:
Force HTTPS for the submission of CC information from users (pretty much all payment processing gateways force the use of SSL when communicating with their gateway);
Do not store Credit Card information in the database after processing;*
Follow general security guidelines (e.g. don't save plain-text passwords or e-mail passwords);
*Note:
PCI does allow for the storage of credit card details after processing, but you need PCI-compliant hosting, which is usually quite expensive. And even then you're running a huge risk. So if you decide to give your customers that option (and I know it's very tempting since big sites like Amazon all offer "one-click" checkout), you better make sure your application and server are locked down tight.
I don't know much about scalability issues with payment processing as I have no experience in that area. All of my applications only process about 5-25 orders a day.

Use SagePay (formerly Protx) it supports PayPal and allows you to take card payments. It also integrates into the Sage Suite (an accoutants dream) it can automate a lot of time consuming data entry.
www.sagepay.com
As others are saying - Sometimes for smaller sites it's not worth taking the risk of storing cards yourself. I prefer paying on websites where I'm redirected to a well known payment service (such as paypal, sagepay or google checkout) as i know that a lot of money is spent on securing this software. If you're a website that i'm using for the first time, well I'm going to be put off.

Related

Is mirroring Stripe (Subscriptions, Invoices, Coupons...) in your own local database efficient?

Is mirroring Stripe with your own local database is a good thing?
Mirroring using both API calls (create a new plan, coupon, subscription, etc.) and webhooks (new invoice or charge generated, payment failed.) so you can store all data (literally have similar tables with columns matching the stripe objects) locally and work with it faster.
If not, what data do you save locally and what do you request?
Thank you.
Typically, saving the same data in two different places is not a good idea. By avoiding data duplication, you save a lot of time and prevent possible issues like data being out of sync.
That being said,
You do not control data saved on Stripe's side. If it disappears for any reason, you are in trouble. Even though such an event is highly unlikely, I would recommend to store locally the most critical information.
In my apps I typically store Stripe's customer ID and which plan a user is subscribed to. Obviously, I also have all plans in my code since they determine what a user can do within an app.
You may want to store some data locally for performance reasons, but a call to your own database is not necessarily faster than an API call. More importantly, even if there is a difference of a few hundred milliseconds, users will not notice it. And most users access such data (list of their invoices, etc.) very infrequently.
Like Andrei said, it is nice to not have to worry about data duplication issues. Their API is plenty fast for most use cases, but if you need to make it faster, you can create temporary caches using redis or memcached. This is especially important if Stripe's API has any unexpected downtime.
Most SaaS companies like Stripe recommend backing up your data as an extra precaution. So if some of your Stripe data is accidentally deleted, or a Salesforce contact is changed, etc... then you can always recover it from a backup. This also covers you in the very unlikely event that Stripe's data is compromised.
Seems unlikely but you never know if you don't control it yourself. Capital One was hacked last year and I would've never thought it would happen.
The strategy you're describing is exactly the one I am using.
Basically, using Stripe is a bidirectional thing: sometimes you initiate the request (when creating a new customer for example), sometimes they do (when canceling a subscription because a credit card is failing for example).
In the first case I save the Stripe response (which is a JSON) in my database. In the second case, I save the Stripe webhook (which is a JSON too) in my database too.
In order not to choose which customer or subscription fields to save in DB, I save the whole JSON in PostgreSQL using a JSONB field. There is almost no performance overhead, and it is very simple to query the data.
Doing this you have the best of both worlds:
Speed (since you are reading local data instead of remote data)
Ease of development (you don't have to think to much about which Stripe data you are going to save)
You're safe in case of disaster on the Stripe side
You data is always up to date
I actually even wrote an article about that, in case it helps:
https://juliensalinas.com/en/storing-stripe-payment-data-database/

Keeping accounts restricted to 1 per user - PHP

The website that I am currently designing has run into a bit of a snag - basically my client has mad it clear that he needs a one person = one account feature, now I'm not the best at analytic's (despite my programming background) so I could really use some suggestions.
We are programming in PHP, and I'm 100% aware that there isn't a solution that would 100% prevent the problem, but I need as close to the 100% as I can get and so far I have tried...
Placing cookies to the users browser. Workaround - Switch browser.
Tracking IP. Workaround - change IP, reset router etc. (Also, more than one user per IP is permitted).
Using analytic's to try and track actions such as Account A being logged out, then a minute later account B logging in from the same IP. (This seemed to be the most effective, but it took a few people to keep it going so I'd like to automate it as much as possible or if possible eliminate the need for manual monitoring.
The problem is that the users of my clients site will be paid depending on different actions and my client has already decided on a $10 minimum withdraw amount, and payments will be handled via PayPal.
So basically multiple account usage could cost my client a lot of money if the site goes live without these features.
I would also like to keep this back-end (possible cron-tab). Just to be clear.
Any help/input/suggestions at all will be massively appreciated.
Tah
PS- I have already checked out this question (Account verification: Only 1 account per person) which is where I got the idea for point 3 from.
The only way to really prevent a person from signing up for multiple accounts would be to ask them for personal information specific to them. I ran into this issue and ended up having to track social security numbers to prevent multiple accounts. Granted, the project I was working on was for a school and the school already had this information. Also, for a new user signing up, it wasn't unusual to them to give this information.
Reading some of the comments, I can say that even if PayPal had a way to track duplicate accounts, it is highly unlikely that you would be granted access to this information, even just to say "yes this is a duplicate" or "no it is not a duplicate".
I really think SSN would be your best bet.
AFAIK iovation uses a set of tracking methods, including Flash cookies and browser fingerprinting to track the users and the devices used. Although budget-wise it might not be your best option, you may consider the techniques themselves.
I'd suggest the business to create incentives for using a single account, which might pay off better than (costly?) fancy tracking software.

How to allow users to accept payment from other users?

I am working on an apartment CRM of sorts and I would like to allow renters to be able to pay bills online. My issue is that I don't know how you would implement a system that would work in this case. I would both need to accept payment from landlords/owners for providing a service to them and also allow them to collect rent from their renters(users). Any tips on setting up something like this? For the accepting payments from landlords/owners part, that is pretty straightforward as I would just need to integrate some payment gateway but the other part has me stumped.
For security and accountability reasons I don't want to be responsible for moving funds myself from the rents collected to each individual owner. I would like to keep each payment relationship (landlords and renters) separate if that makes any sense.
In case it matters, I am using the PHP framework CodeIgniter for this.
Here's the challenge...when you're talking about removing yourself from the money moving game, I believe you're talking about multiple merchant accounts. Now I'm sure that there's some sort of discount out there for running multiple accounts, but generally the merchants aren't your friend unless you're doing some serious traffic--the last merchant account I worked on did about $1million USD/year and we still didn't feel like we were very high on the totem pole with customer service or negotiating position for merchant fees. You'll be talking about $30/month (give or take) plus a percentage of the transaction as the cost to operate the merchant account.
Fees add up in a hurry. Not a problem if you're doing volume, but if you're only talking 25 renters and then only a portion of them use the service, you may get hit harder that you can justify with them spread amongst multiple sites.
Consider some already done options out there:
https://www.erentpayment.com/Default.aspx
http://www.landlord.com/rent_collection_online.htm
http://www.rentmatic.com/
Obviously, I don't know the specifics of your situation, so these may not be a great option. Regardless, it never hurts to explore alternatives if only to learn what UI patterns they used to achieve the goal you're shooting for.
You'll have to set up some sort of payment gateway account for each owner. You can save their settings for the gateway in your database.

Church Retreat Online Registration/Payment

I was given the task of creating a registration page for an upcoming church retreat. Design-wise, it will consist of fields for name, sex, phone number, email, and grade. We need a way for the end user to put their credit/debit card info and have it charge them for the retreat.
After some searching I found that Braintree offers a good service (37 signals likes them). The down side is that I have no clue on how to implement this sort of system into my site. So we are going to apply for a merchant account using their service. I also found documentation on how to implement it with PHP.
My question is, do I have to do anything else? I've always heard of https but I don't know if that's something I should implement. What security measures should I put in place? Should credit card numbers be stored in a database as plain text or encrypted? Has anyone used Braintree and can let me know what to expect after getting a merchant account?
Edit: I was looking through the PHP documentation code and was lost at this:
Braintree_Configuration::environment('sandbox');
Braintree_Configuration::merchantId('your_merchant_id');
Braintree_Configuration::publicKey('your_public_key');
Braintree_Configuration::privateKey('your_private_key');
I'm guessing the environment is set to sandbox for testing but is a merchantId provided to you after you make an account? Also, I have no idea what a public or private key is.
Hire someone with ecommerce experience to do this. If you don't know what https is then you shouldn't be handling sensitive information like credit card numbers or processing payments. The implications of a poor implementation are huge and lives can literally be ruined from it.
Do not store the credit card information in a database. This is a bad idea for numerous reasons listed many places on the Interwebs. PCI Compliance being the most commonly cited one. It is a really, really, really bad idea.
Https, by the way, is the secure version of the http protocol and allows for http traffic to be encrypted between clients (usually a browser and server but not always). It is implemented by the installation of an SSL certificate.
Your best bet is to use a merchant account and a payment gateway service like Authorize.Net's SIM API which handles the order form for you. That way you hand the handling of sensitive data to them.
You may want to read Merchant Accounts 101 and Ecommerce 101 before proceeding. Disclaimer, I wrote those articles.
You should not and cannot store any credit card information in your database. Mostly any payments service like Braintree will handle entering sensitive data, HTTPS and all other things. All you need to do is to give correct request to payment gateway and process answer.
A second reason to consider a site such as Google Checkout, Amazon, or Paypal is because the big merchants charge a set fee by the month plus transaction fee. If this is a one-time deal, the registration fees aren't that significant, or you don't plan to use it year-round, it's likely not worth going this route, even with a professional doing the work. I do a lot of work with quite a few smaller non-profits and the only way they can afford to do merchant accounts is via grouping of resources...but that brings up several tricky accounting questions.
Even easier than doing all the work yourself, consider a simple online registration site such as Active.com (or many multiples of others out there--I'd bet there's even one specifically for church groups) Their business is online event registration, and they do this for hundreds of smaller parks and rec type registrations, so they certainly would have the capability to do something like this. Trust me, having built several registration systems, there's nothing worse than the first bug popping up that makes 50 registrants show up unregistered or charging someone 4 times.
Unless there's some good reason for you to roll your own, use a third-party service to handle registrations for you. Among the others mentioned, some of my friends who put on shows and improptu classes use eventbrite.com and brownpapertickets.com
Both will tack on a small service fee

An online free-trial anti-abuse system design

I am currently selling time based access passes to an online service at micro payment prices.
After payment the customer gets a set of credentials that is only valid for the purchased period. When the access pass expires the customer has to buy a new set of credentials.
So basically the credentials are one-time(period) use only.
I would like to offer a free-trial of x minutes to this service so potential customers can realise it works fine, possibly increasing total sales.
My question is, how would you stop abusers?
That is, people should only be allowed to try for free once, and if that is not possible at least make them go through a process/test which (as in shareware) is too cumbersome or annoying for them to keep trying it.
Obviously there is always someone who will bypass it. I am looking for a solution for the majority of people who are either not IT savvy, time constrained, or simply too lazy to bother abusing it, instead of simply paying the tiny fee.
I have some approaches in mind but would like to be inspired by other people too.
The service is developed with LAMP.
Put a cookie in their browser. Force a small delay before they can re-use your service, or make them go to the trouble of deleting the cookie. If they block cookies, politely ask them to allow them. You might have more business success if you allow several trials, with a minimum of hassle.
If you look around, everybody who gives out free trials binds them to a credit card - not to charge them, but to verify the user's identity. That's about the only feasible way to prevent abuse I can think of.
Any other idea will depend on the kind of service you are offering. StackExchange for example can offer a 45 day trial without a credit card no problem, simply because the effort to build a SE site is so huge, starting multiple trial periods (and having to configure a new site and build a new community every time) just wouldn't work.
Something similar could be unique login names that you can register during your trial period, and would have to give away if you don't convert it into a pay subscription, things like that. Really depends on the nature of your service.
The users who want to try your product again via a trial are highly convertible users because they already know the value of the product.
The challenge is detecting them and then converting them to paying users.
Detecting can be done using a variety of signals including:
IP
Cookies
Device fingerprints
Credit card or payment information
Email verification and validation
Each individual signal has its challenges eg. IPs can change and are legitimately shared among large audience such as via carrier grade nat.
SMS verification is good in most markets but adds friction and potentially cost for you and your users.
Something like Upollo.ai solves all the hard parts for you so worth a look for people facing these problems in future
I ended up using the smallest possible payment amount for a short time span, but enough to get the user satisfied at very low monetary risk.
In the time past since I asked I actually seriously considered using Flash cookies which very few people know (even that they exist) how to remove.
The other simple (although not-free) is using a SMS confirmation option which binds the user's mobile phone number. As a mobile phone number you just do not throw away like you do with email addresses then this is also a safe limitation method.

Categories