Php – Integrating with a payment provider; Proper and robust OOP approach

designpaymentPHP

History

We are currently using a so called redirect model for our online payments (where you send the payer to a payment gateway, where he inputs his payment details – the gateway will then return him to a success/failure callback page). That's easy and straight-forward, but unfortunately quite inconvenient and at times confusing for our customers (leaving the site, changing their credit card details with an additional login on another site etc).

Intention & Problem description

We are now intending to switch to an integrated approach using an exchange of XML requests and responses. My problem is on how to cater with all (or rather most) of the things that may happen during processing – bearing in mind that normally simplicity is robust whereas complexity is fragile.

Examples

  • User abort: The user inputs Credit Card details and hits submit. An XML message to the provider's gateway is sent and waiting for response. The user hits "stop" in his browser or closes the window.
    • ignore_user_abort() in PHP may be an option – but is that reliable?
    • might it be better to redirect the user to a "please wait"-page, that in turn opens an AJAX or other request to the actual processor that does not rely on the connection?
  • Database goes away
    • sounds over-complicated, but with e.g. a webserver in the States and a DB in the UK, it has happened and will happen again: User clicks together his order, payment request has been sent to the provider but the response cannot be stored in the database. What approach could I use, using PHP to sort of start an SQL like "Transaction" that only at the very end gets committed or rolled back, depending on the individual steps? Should then neither commit or roll back have happened, I could sort of "lock" the user to prevent him from paying again or to improperly account for payments – but how?
  • And what else do I need to consider technically? None of the integration examples of e.g. Worldpay, Realex or SagePay offer any insight, and either my search engine or my search terms weren't good enough to find somebody else's thoughts on this.

Thank you very much for any insight on how you would approach this!

Best Answer

As a developer working almost exclusively with payments I perhaps can give you some pointers about where the possible pitfalls are. I'm working for a site with high traffic, ~40 active payment service providers (PSPs) and dealing with tens of thousands transactions per day. And trust me, the sh*t will always hit the fan and all you can do is prepare as much as possible for dealing with the situation from that point.

Log, log and log some more...

This is the most important part in your payment process, make sure you have a record of everything. Ask yourself the questions "could this piece of information help me once in a million transactions?". If the answer is yes, log it!

Our setup is that the main point of logging is the database. Every initiated, failed, settled, redirected, etc transaction is stored per PSP in tables. If the PSP uses an API, all API-calls are logged (both requests sent and responses). All callbacks are logged in tables as well. And so forth..

When we encounter an unexpected event or exception we log it to the PHP log file with a certain format to make it searchable and easily found based on transaction ID, user ID, etc.

You will be grateful that you have all the data if you get sued for example.

Monitoring and alerts

Build in monitoring logic with some simple tests that will alert you through email when something goes wrong. For example, if 3 callbacks in a row fails for a PSP. All of these small things that can make you work on resolving issues quickly instead of reacting to them after your customers have made you aware of them (which doesn't always happen) is very important.

Database transactions

If you have the luxury of setting up or changing your database structure to support database transactions, for example use InnoDB on MySQL. Take a look at this answer on how to handle it in the code. You should make sure that every step of a transaction is completed or none is, having partially completed transactions is just a burden on you and your system. For example: 1) User completes transaction, 2) User gets rewarded somehow. If not both step 1 and 2 are met here, the transaction should not be set as complete in step 1.

Technical people to contact

When you have a technical issue, make sure you have someone technical to contact immediately. Having an account manager is pretty useless, especially if that person decides to mediate between you and their technician.

Live world example that happened to me: one PSP all of the sudden stops working, nothing in our code had changed and they say they haven't changed anything as well. After sending debug information back and forth with them (through their account manager), one of their technicians catches that the WSDL-schema fetches seems off. Then they realize they updated their WSDL-schema and after some debugging I realize that PHP cached the old WSDL-schema. This could've been caught sooner as resolved if I just had a technical person on Skype to contact directly. Or if they just admitted to changing their WSDL-schema, but it's often hard to get a confession out of the PSPs when something goes wrong..

Final words...

Prepare all you can and assume that ANYTHING can happen :)

Not sure this was exactly the kind of answer you were after, but I'm trying to provide a real world example of payments and how you can prevent the biggest traps and pitfalls. Let me know if there's something you would like me to elaborate on or if you're interested in another topic.

Related Topic