I'm developing a website (with payments) that needs to support multiple payment gateways. I'm going to use omnipay package (thanks God there is a package to handle this) but now I was wondering what is the best way to store all the payment information in the database without binding it to a specific gateway.
My first idea is to have the following tables:
gateway(gateway_id, gateway_name,...)
payment(payment_id, payment_amount,...)
transaction(transaction_id, gateway_id, payment_id, transaction_reference, transaction_type transaction_status, transaction_request_data,
transaction_response_data...).
The type can be something like 'authorize', 'purchase', 'refund', 'void', etc and the status something like 'successful', 'failed', 'pending', etc.
In this way, I can have a list of gateways (Paypal, Stripe, TargetPay, WorldPay) and each payment can have multiple transactions (a payment attempt can fail at the first time and then be attempted again and work but then voided or refunded) but one transaction belongs to a single payment. Each transaction was executed using a specific gateway and this will also be stored.
I don't know if this is the best approach (maybe it's too simple?) and I would like to hear some other ideas.
Thanks!
Your initial structure is a good start. Other things that I would include are:
responses, which would hold the response messages sent back from the gateway in response to your purchase calls
callbacks. An increasing number of gateways supply POST messages on the notify url to the caller. These indicate change of status messages from the gateway such as cancelled transactions or chargebacks
refunds and voids, which I would store in a single table.
responses to the callbacks, refunds and voids, which you could store in the same table as the regular responses if you structured it correctly
Some of the data you would probably have to store as JSON blobs because the structure of messages from each gateway would be different. Some of the data you may want to encrypt, for example if it contains data that could identify a customer or perhaps a credit card
I believe the best answer is: it depends on how close the data provided / required by the gateway provided to each other. If these are close to each other, or you can map the various status types, then store all of these in a single transactions table. If not, then you need to maintain separate tables for each payment gateways.
However, even in the latter case I would have a single transactions table that consolidates the most important and common data accross all providers, such as amount, payment status, and store only the vendor specific data in their corresponding tables.
Related
I'm developing an e-commerce website using PHP and integrating paypal for processing the credit card payments.
I found APIs in PHP that are used to make payments and capture transaction id but none of these discussed about adding adjustments to the amount that is captured.
My use cases include:
Adding tip later
Adding time extension adjustments
Returning only portion of the amount if order gets cancelled
and few more of similar kind
May anyone tell me how this kind of a task is handled with paypal and also is there any API that will provide this functionality as well?
References Transactions would work fine to charge a separate transaction for the tip, but then the customers would see two separate charges on their credit card and you'll probably get lots of questions and confused people wondering why their card was hit twice. As obvious as it seems, I've been there.
The best way to handle it would be to run an Authorization when you first run the card. Authorize it for something like 50% above the ticket total, or whatever you think it would take to cover the final total including a tip for that order.
If the order is canceled for any reason you simply Void the authorization. If you're ready to actually process the funds with a final total including tip, then you can Capture the amount that you need up to the amount that you originally authorized. I believe you may even be able to capture up to 10% more than the original authorization, but I'm not 100% sure on that.
The thing you would need to be careful about is authorizing a card for some large amount and then not voiding or capturing shortly after. The authorization is only guaranteed for 3 days. You can run a re-authorization and get an additional 3 days if you need to.
If the order gets canceled and you don't void it then you'll get complaints that a large amount is "charged" on their account. It looks like a charge until it clears back or is voided. If you don't void it then it can take up to 29 days for them to get access to those funds on their account again, so you want to avoid those types of complaints too.
You would need Payments Pro to handle credit cards directly for that sort of a system. Depending on which version of Pro they put you on you'll use either the PayFlow API, or you'll use variations of DoDirectPayment, DoVoid, DoCapture, DoReauthorization.
Reference transactions would work for what you are trying to do. Reference transactions allows you to reference a previous transaction to run another transaction on that information at a later date. Here is a link to more information on reference transactions. https://developer.paypal.com/webapps/developer/docs/classic/express-checkout/integration-guide/ECReferenceTxns/
I am developing a crowd-funding site (similar to Kickstarter) using the CodeIgniter framework.
I "successfully" implemented PayPal's adaptive payments using this library.
But, I'm just not sure how to correctly and securely check for succesfull/failed payments and witch data is important to save to database.
Note: it's a chained delayed payment, I am the primary receiver, and the secondary receiver is the crowd-funding project creator. The money is transferred to the secondary receiver after a predetermined period of time.
The flow I have right now goes like this:
User click to buy a reward.
I use the 'Pay' API operation to request payment (unique TrackingID included) and save the request in the database.
If the request is succesfull, I save some response data in the session (TrackingID, PayKey, amount, ...) and redirect to PayPal..
In this step the user can: accept payment, cancel, or just close the browser, so I dont really know what happens here... (recommendations?)
If the user accepts the payment, he is redirected back to my site and I use data I saved in the session to request a 'PaymentDetails' API operation to obtain information about the payment.
I save the result in database and check to see if the response 'amount' is equal to the request 'amount' (for security).
If everything went OK I update the database and connect the payment TrackingID with the user and the reward he bought.
Later (can be months later), the 'ExecutePayment' API operation is requested by an admin, and the money is transferred from us to the project creator, and we take a small fee (thats how crowd-funding works...)
Now, I'm sure I'm missing lot of things but I have no idea what:
What about the IPN API? I need it? Where it comes to play inside the flow and checks?
What I do if the user closes the browser window when he is in PayPay (out of my site).
I heard that the PayKey is valid for 3 hours, how can I 'ExecutePayment' after months?
How I handle the enormous amount of error types in the PayPal API?
Any tips or examples of others things I need to take care of? Security? Errors? Others?
Thank you very much, I really need your answer!
IPN will automatically POST data to your "listener" (which you'd need to develop) in order to automate post-payment procedures. For example, you could update a database, hit 3rd party web services, generate email receipts, etc. within IPN so that those events happen automatically any time you receive money in your PayPal account. You can also set it up to handle refunds, disputes, and other events. It's not required, but often very useful.
This is one reason IPN can be useful. IPN will be triggered whether the user makes it back to your site or not. If you're doing post-payment processing procedures within your thank you page or something like that, I'd recommend you move it into an IPN solution.
The PayKey is indeed valid for 3 hours when being used as a token. When you call Pay with an ActionType of CREATE, though, it sets up a delayed payment and the PayKey is then valid for up to 90 days.
The error information will always come back in the same format in the response. You can just log or display errors accordingly based on this standard response.
Sounds like you're pretty much on top of everything for the most part.
I have started working on a e-commerce website. This website will run PHP and MySQL and requires to have a credit system for the users; they will be able to pay with the credit, top it up by vouchers or regular payment, as well as withdraw.
Now I do have experience with credit cards processing APIs, so paying money in and out shouldn't be a problem; what however is a problem is how to securely store the credit information. Storing it as a single numeric field is not exactly ideal and potentially could be exposed fairly easily. What I was thinking is keep all the transactions and credit history of each user in a separate table, and every time they log in recalculate what should their credit be. Same would then apply before any transaction that they attempt to do.
I would like to hear what are your thoughts how this should be implemented.
EDIT: Just to clarify; my question is not on how to process credit cards and won't be storing credit card information. I will use a well known and secure API to process the payments (e.g. via paypal). However based on the credit card payments, I need to attribute the appropriate user points in a form of credit. These points would be a representation of funds on the website (whilst the money would be retained on the company account, until the user tried to make a payment/withdrawl) and would be used to make payments and withdraw funds. Again for the actual payment processing I would use secure API, however I am not sure how to implement the credit points properly from structural point of view in the application itself. I don't want to use a simple one field point system, as that I would consider very dangerous.
I hope that clears it up a bit.
Cheers
This might not be the answer you are looking for but here are my 2 cents.
In my personal opinion unless you have someone monitoring your dedicated servers 24/7 you should never in any format store credit card numbers in your database, it is just too risky.
A very nice solution I came across last year was BrainTree http://www.braintreepayments.com/. You can set up a very nice credit card payment system without taking on any liability yourself. Their API allows server to server and transparent redirect (form posts to their site and they redirect back to your site) transactions. At the same time their Vault service allows you to store credit cards on their end and you just use a token in the server to server API to process a payment. You can store the last 4 digits (which they provide in the transaction detail) in your DB along with the CC type and the token, with this you can display a drop down for the user to select which card they want to use and you just use the token when talking to their API.
The API is very nicely documented with full examples. I think you should look into them.
Edit:
I believe you should have a table as you have suggested to store all the history and 'totals' field in the users table, which can be used to display in various places. Each time a transaction a made calculate the total and cache it in this field for ready usage. However it is a good idea to re-calculate this in certain crucial places to make sure everything is in order. Even though this field is exposed but you have a full log which can help you re-calculate everything if needed.
I'm currently building a simple ecommerce site for a client that will use solely Paypal to take payments. I want to display orders in the CMS I'm building for them, but only transactions that are made on the site I'm building.
I have achieved this so far by using the Paypal IPN to add transactions from the site into a database table (just the transaction id) and then borrowing heavily from the TransactionSearch.php file that Paypal supply with the API.
My concern is that at the moment, I'm fetching every transaction from the account (even ones not attributed to this site) and then filtering them by matching them against an array and only displaying the ones that are stored in the DB. It would be better if I could send the array I have through to Paypal and just receive those transactions - does any body know if that is possible?
The system works as is but I would prefer to make it more efficient if possible.
Thanks
I'd say a foreach with the GetTransactionDetails API should do the trick?
https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_nvp_r_GetTransactionDetails
I have a <textarea> along with user registration information that I only want to be processed (inserted to the database) after payment (I want to keep my database clear unnecessary registrations or things like people that register but change their mind about paying for the site services)
I mean, I could use sessions but are there any other ways?
I was looking for a gateway that'll pass these variables back to me after purchase.
Or perhaps just having the gateway API.
Now, I know gateways such as paypal allow advanced processes like these but I don't want to apply to their credit checks just in case they have a reason to reject me. I don't want to depend on one gateway, is there any other gateways that guarantee not to reject my gateway needs and allow me to make advanced processes like the ones mentioned above? If anyone knows about gateways that don't need credit-type checks to be accepted I would appreciate if one could be suggested.
Note: I know some people will suggest to keep the registration data since it's only a few kilobytes even if people won't use the site or pay for the services. Call me OCD but I like my database clean and to only have relevant users/data. I will end up doing this in the end if I don't find a solution that suits my needs, so please, don't suggest it. Thanks.
If you want to use simple form based integration, you aren't going to get around having rows in your table before the users has been processed, unless you want people stealing your service. The fact you want your "database clean" is naive. Just put a registered flag and delete periodically if you are really that OCD.
You must create a auth token (random unique string), and update the database of the current user that that token belongs to that user. You then pass the user to the payment gateway and also pass along the token you have assigned to that user.
The gateway will send the user back to a url of your choosing, along with the token you have assigned to that user. At this point you update the table for that user with that token.
Only you and the gateway know about the token, the user only sees it if they get a successful charge.
If you don't do this, anyone can find the url the gateway sends on successful charge, and just load it themselves, giving them free service.
Alternatively, you can use deeper integration, were you do a web service call to the payment gateway, if it succeeds, you update your row, if it fails, you don't. This subjects you to onerous PCI compliance regulations. Trust me you don't want to delve into that. Just avoid it and do not let your systems see any CC information.