Payment gateway: Information hash needed? - php

I'm building a payment gateway for my organization. Different apps will be able to POST data to the gateway to initialize a transaction. Some of that data will be 2 account codes, and the dollar amount.
Now my thoughts have moved to security. I'm concerned about end-users being able to change the POST information en-route to either end up paying less or having the funds deposited into the wrong account. To fix that I'm thinking of adding a hash that the app can pass.
I'm thinking each expected host will have a unique key. Along with their data they can send a hash of
a random salt + their key + the 2 account codes + the dollar amount, as well as sending their random salt. On the payment gateway I can then regenerate that hash with their passed information + unique key, to see if the data has been altered.
Will this be sufficient? Are there any problems with my theory?

This is basically what paymentserviceproviders use. The trick is that the "key" is private, so it is not one of the things you send in your post. You and the sender make the same hash, and as long as they are equal, there has been no tampering.
Another option that banks use is to make the payment separate from a post: generate a payment-request from the place that actually knows the prices (the server?) and communicate that number to your client. Then let them communicate with your payment gateway using this number instead of letting them posting any amount. There will be no tampering.
The first option is used by several payment providers I know, the second one is the one we use currently directly with our bank.
For added security of private information, let the result also contain hashes you know, so when someone (the user?) asks for the "thanks for paying" page, you can actually check it was the orgional user.

Related

Where to store dynamic data for paypal express checkout (digital goods)

Imagine a site like istockphoto or envato where the user can only purchase digital credits...
How would one implement this in the cleanest, easiest way using paypal's API's? The docs there are a bit confusing to navigate...
Aside from that general "best-practices" question, my guess was to start with the Integration Wizard at https://devtools-paypal.com/integrationwizard/ and select "Express Checkout - Digital goods"
After setting up some test accounts on the sandbox, I've kinda sorta got it working- but I'm confused how I track dynamic data across the session.
I.e. where would I securely store the "number of credits" and "userid" values so that it gets added to this user (who may not have an email address, nevermind one matching their paypal account) upon successful payment. Is a database/callback system necessary?
Assuming so for the time being, my guess is to maybe store the data in a database where the primary key is the TOKEN received at SetExpressCheckoutDG(), and prepopulated fields are the data I want to keep... and then the final confirm.php page will check the database at that token and implement that data... but something just seems strange about that, i.e. relying on a callback (could be timeouts, etc.) and I'm not sure if it's really the most secure way of doing it.
If using examples, please stick with PHP (not curl or other langs). Thanks!
You could just bounce this along with your calls. I'll use NVP for my examples
You set your digital goods in SetExpressCheckout. Inside, you pass how many credits the user is buying and set the PAYMENTREQUEST_0_CUSTOM with their user ID.
In GetExpressCheckoutDetails that data would be passed back to you so you could store it in some fashion (you would get their items and quantity, plus the user ID). Then, you finish with DoExpressCheckoutPayment.
If that still doesn't help let me know.

Credit Point Web application

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.

Processing user registration/data after payment is made?

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.

sending data to payment gateway and back - possible problems

I'm going to use one of the payment gateways and so users from my site will be redirected to gateway hosted page to provide all the CC details. Gateway will return results to the page which I specify (lets call it paymentProcessed.php). But now my worry is that:
someone might fake it. What I mean is that someone might be redirected to payment gateway, then instead of paying, will return results to my site paymentProcessed.php page with confirmation that all has been payed. This confirmation will be send by the user itself via normal POST, and my site then will deliver products to the user although there was no actually payment done. What is the common practice to avoid this kind of situation?
Someone is redirected to gateway hosted page, pays, redirects back to my site and session he was logged in with has expired. Usually I rely on sessions to see if user should be allowed access to certain parts of the site, but now do I need to implement some other sort of check for confirmation page? For now I was thinking of storing order id and randomly generated value in database, when user redirected pass it to gateway (together with total, total would be passed to gateway and then back so I could confirm that proper amount was paid). Then when confirmation comes together with order id, my randomly generated value (and total) instead of relying on session like I usually do for normal shopping cart pages, I should check this value with matching order id and change status of order as needed. What is the common practice to deal with that kind of problem?
What other possible issues I should think about?
I tried to explain as clearly as possible and I hope all above makes sense. please let me know if I need to clarify something though. btw I code in php/mysql
It's actually easier and more secure then you realize. When using a hosted payment page, like Authorize.Net's SIM API, a hash of some sort is included that only you and the processor know about. It is impossible to fake as generating it requires private information only you and the processor have. So all you need to do is verify that the hash sent to your return page by the payment processor matches the one you have for the transaction. If it does, you can be 100% sure the transaction has not been spoofed.
Sessions tend to last longer then a trip to a remotely checkout form usually takes to complete and the session does last even though a user leaves your site. But, if you are concerned about a session expiring before they return to your site, simply store the session information in a database and use a cookie to track the user. Then when they come back use the cookie to identify them and retrieve their session information from your database.
UPDATE:
Here's how you can make your session cookie last longer with PHP:
// Makes the cookie last two hours. Make it a higher number to last longer.
session_set_cookie_params(7200);
session_start();
I've implemented some payment gateways already, one thing in common with all of them is that card processor will always return the transaction status for you, some of them use a weak redirect relaying on users to accomplish, others allows you to use their webservice to authenticate transactions. Either way you will need to get processor docs to know how to authenticate the transaction on your side.
Now about the other odds to avoid sessions from expiring you might want to store all transaction data on a table, you can also have sessions to speed up the process, but you don't need to go much further to see issues with relaying only on sessions:
What if the user gets disconnected in the middle of process?
Some CC processors force you to open a popup to process, what if the user closes it?
What if the server crashes?
What if the payment method failed and user wants to retry with another type of payment?
Now some random thoughts about payment gateway implementation:
Some processors delay to authenticate the purchase, they will return to your site that the payment has been accepted but you will have to use their webservice to check the final status;
Some processors require you to capture the purchase, meaning that even if it was approved you can void or finalize it later, this is good to avoid carders from purchasing things off your site, you can check user's info to make sure it's all good them capture or void the purchase avoiding a chargeback.
If your credit card processor gives you access to a webservice or they do server to server purchase authentication this will require a valid ssl certificate, so be aware.
That's all i can recall by now.

How to securely pass credit card information between pages in PHP

How do you securely pass credit card information between pages in PHP? I am building an ecommerce application and I would like to have the users to go through the checkout like this:
Enter Information -> Review -> Finalize Order
Problem is that I am not sure on how to safely pass credit information from when the user inputs them to when I process it (at the Finalize Order step). I heard using sessions is insecure, even with encryption.
Any help would be appreciated!
I wouldn't store it anywhere. It's too much of a risk and probably not ethical.
Send a request to the payment gateway by posting a form over https and store the result of the transaction only.
You probably only care if the transaction was approved or declined. Who cares what the number is?
Don't store the credit card info in the session, don't store it to a database, don't store it to a file. Instead, write the cc info back to the review page in a hidden html inputs.
So the program flow would work like this:
User posts payment and billing information to the server via an html form.
Server verifies that this information is in the correct format (i.e., credit card has the appropriate number of digits, a billing address was entered, etc.)
After verification the server writes back all the information submitted as hidden form input fields. This includes billing address, shipping address and credit card info.
The form on the review page (with the hidden input fields) has a button labeled "Finish Order" / "Complete Order". This review form posts to the finalize order script.
The finalize script stores billing/shipping info in your database and submits the credit card info to your payment gateway.
The advantages of this method are two-fold:
You save the overhead and cost of additional PCI compliance that is required when storing credit info.
This method stays within the security bounds of the SSL protocol. Meaning, encrypted credit card info will have to be submitted to your server in any instance - this method continues to rely solely on the efficacy of SSL, without introducing the complexities of persisting credit card data.
This last point raises another concern - by having a review page you're doubling the number of times the encrypted credit card data is being transmitted across the network. With this method there are 4 transmissions minimum: client to server, server to client, client to server (again) then server to gateway. Without review there are 2 transmissions minimum: client to server and server to gateway. Is the convenience of a review page worth the risk of extra transmissions? That's a decision you as a web developer (and your client) get to make.
Well, first you should be using the HTTPS protocol to ensure that the connection is encrypted.
After that, you could store the data in the $_SESSION super-global. The data is stored on your servers, so it is relatively safe.
You could do a similar technique where you insert the information into an Order database, where the key is a GUID or something else fairly random and unique. Then, when the person goes to modify/review their order, you should have the Order ID stored in the GET part of the URL (or if you're paranoid, a cookie/session variable):
https://example.com/order?orderID=akjgflkhaslasdfkjhalsdjkljahs
To provide extra security, you could also store an IP Address in the Order Table, and make sure the IP and the Order ID match.
One alternative is to use a payment profile service like Authorize.net's Customer Information Manager (there are others too). You store the payment info in a profile via their API, then use the profile ID when actually charging the card. This way you're never storing the data on your servers.
Not my area of expertise, but I think you want to store it in a session but also use a "synchro token" (or whatever the kids are calling it these days) to help avoid CSRF attacks.
Of course, you want to be using https (correctly), avoiding sensitive data in the URL and hidden fields, avoiding putting very sensitive information in any response at all, etc., etc.
I think I will have to agree. Storing creditcard numbers is too big a risk and the consequences could be far fetched.
The ideal way would be to pass the information to a third party processor and just use the result returned to mould your script logic.
if (transaction){
// code goes here
}
else{
// code goes here
}
Hope you get the point ... :)

Categories