I am currently developing an E-Comm site that uses Paypals express check out system. The express checkout system works fine, I send the payments amount, the user logs in to confirm the shipping details, and returns back to my page where I confirm it and the payment is completed. The main issue I am having is that I have the username (email) saved in the session. Once the user clicks checkout with paypal and confirms his/her paypal account, my session is cleared. So I cannot keep a record of who purchased what item (unless I use the users paypals email address which could be different from the one the user used on my site).
So my question is, is there any way that I can preserve the session state throughout this confirmation action? Or is there another way to keep the users information? is this a documented problem (I have not seen it anywhere)?
If any more detail is required let me know.
Thanks for your time.
No, once the user leaves your domain the session will terminate.
Instead you can store the email address in a table before user leaves your site and pass the ID of the inserted record to paypal. As this ID is a custom field it will be returned in the call back url once the user completes the payment. You can get the ID from URL and retrieve the corresponding email from database.
Even if your PHP session didn't terminate (there is likely a different reason for it closing), it still isn't a good idea to depend on the session being unmodified between the time the user leaves for PayPal and returns. Consider a user with multiple tabs that starts poking around your website in another tab before finishing Express Checkout.
Instead, store everything that is important to your checkout completion in a database, and pass a unique identifier through the Express Checkout process via the CUSTOM or INVNUM parameters. Those will be juggled through the checkout process. Once the callback returns to your site, you can very easily identify which "incomplete" order in your database it is referring to and mark it "paid."
Related
Well, I was wondering if it is possible to automatically logins the user in paypal everytime they checks out?
Given the scenario a new user registers in my site.
New User->Logins to paypal->get permissions(etc..)->approve->gets back to my site
So, everytime the user checks-out it automatically logins in paypal.
I would like to link his paypal account to his profile in my site thus easier check out
I saw the documents but it is just too much for me to comprehend.
It sounds like you are referring to reference transactions. With PayPal you can create a billing agreement, and you would save the billing agreement ID to the local user record in your database.
In the future when they are logged in and checking out on your site you can pull the billing agreement ID and pass that into a reference transaction request to PayPal. This will immediately process the new payment without any approval necessary, so you can simply display the order complete page to the user.
Their experience would be choosing their saved payment method, clicking to buy, and the complete page would show up immediately. No checkout forms or login (other than logging in to your site) necessary.
Depending on whether you're working with the Classic API or REST the specific calls would be different, but "reference transactions" and "billing agreements" are the terms you're looking for.
I've built a web application and I am looking to integrate cardsave's direct payment API into the application. I was wondering if anyone had any advise on the best way to do this.
Cardsave provide standard code for integrating: Download Gateway Integration Pack ZIP file
When a payment is made I need to store the CrossPaymentsReference and payment amount in my database, the rest I will leave to cardsave's api I have thought of a couple of solutions which should potentially work:
1) Using Views for all of the code and on sucessful payment and use Ajax to update the database with the crossPaymentReference and payment amount on sucessfull completion, because it involves minimal editing of the code, but does have a minor security risk because it sends the reference at the client end.
2) Create a library with the payment system class, put the preprocess payments and process payment code into a controller and copy the form into a view, and just a have a small model to update the database on sucessfull payment's. (I'm guessing this is the best way.)
3) Edit everything and build an MVC version of the code
My latest project runs on CI 2.0. I’ve integrated a payment system such as Card Save with success (in my case I use Ogone, which is a Belgian company).
Below I’ve detailed a bit how I implemented the order and payment system.
The advice I can give you is the following.
Keep your products, orders and payments in separate tables.
Link products to orders via a reference table (don’t store e.g. a list of product ID’s in a field in the order)
Allow that a payment can only have one order, but an order can have multiple payments (but only one paid). This way when a payment fails (e.g. the user pressed cancel on Card Saves payment page), you can just create a new payment on your side and let the user retry (unless Card Save accepts that you do 2 payment request with the same payment ID).
Make a separate library (not controller) that handles successfully paid orders. This library would e.g. activate a subscription that the user bought, or make a work order for someone to ship the products. By keeping it in a separate library you can extend its functionality (e.g. if for a specific product you would need to do something new) without touching at your payment logic (thus preventing heavy retesting).
Generate hashes when posting data, or redirecting users to checkout pages, pages that prepare the payment and recalculate the hashes each time to prevent that someone tampered with the data you posted or that is in the URL.
Make sure everything works without AJAX and add AJAX afterwards.
Basically the ordering process I came up with is divided as follows:
User adds services (I don’t sell physical products) to basket (using a modified version of CI’s shopping cart)
When done user clicks “Order products” which does a POST to the controller Place_order. The controller Place_order does the following things:
Check if the user is still logged in (in my case everyone needs to register before)
Get the products that are in the shopping cart and checks if they actually exist in the database (you never know)
Create a new order in the database and add the products to the order in the DB
Place_order doesn’t output anything, but redirects the user on success to a controller Checkout. Here I don’t use POST. This way you can reuse the URL (e.g. if the user decides to stop, he can continue the payment later). The URL contains the order ID and a hash.
The Checkout controller does the following
Recalculate the hash to see if no one tampered with the URL
Check if the order exists and isn’t paid yet
Check if the order belongs to the user logged in
Create the payment if it doesn’t exist yet
Show a view with a button “Cancel order” and “Pay order”. This is actually a form that contains in a hidden field the payment ID and a hash of the payment ID.
When clicking “Pay order”, a POST is done to a controller Pay_order. I don’t use GET, because I want that users only come on this page by posting data that was set by the Checkout controller. If they use GET to come on the page an error is thrown. This controller does the following:
Recalculate the hash to see of no one tampered with the posted data
Check if the payment exists and is not yet paid
If all is OK, compose the view that contains the necessary info to be posted to the payment service
Show the view.
When the user presses “Go to payment service” all data is posted to Ogone where the user executes the payment
When the payment is completed (correct or not) Ogone redirects the user back to me to a controller Payment_successfull or Payment_other (for errors etc). In the Payment_succesfull I call a library Purchase_activator which takes the payment ID as input. This one looks up the order and activates the services the user just paid. In the other case (on error) the user is shown a view with the correct error message and an option to retry or cancel.
One of the web applications I recently developed works like this:
User picks a subscription level
User enters various custom/personal data on the site as well as picking out certain options
User confirms their data
The system stores this data in an array with a flag set specifying that the data is incomplete
The user is directed to PayPal to pay
PayPal makes an IPN request and we grab the row ID containing their information and complete the rest of the fields, effectively completing the process.
Now, obviously there are a few problems with this approach.
1. These rows are created whenever a user visits the form and can quickly add up
I solved this issue by adding a last_touched column which is a timestamp, and I routinely delete records older than 48 hours (more than enough time to complete a PayPal transaction).
2. Because of the above, it's possible that a user could checkout successfully with PayPal and there is no row in the database
I transmit the essential information such as the ID of the subscription package with the PayPal custom field, and if the row doesn't exist when I'm doing my IPN request, I fill in the blanks using the data supplied to PayPal and from the custom field.
3. The username the user entered could theoretically be taken by the time they checkout
I've solved this by checking to see if the username is taken and if it is, I add a number to it and keep incrementing the number until I get an available username.
I'm not sure if this is the best way to handle the given situations or if there is a better alternative (Not involving PayPal Payments Pro). At which point would the potential issues with a system like this outweigh the cost of PayPal Payments Pro?
Your best bet is to store all account information on your database as if the user created the account before sending them to PayPal.
So store everything including the username before allowing them to proceed to the checkout. This enables you to validate their information and username before they go to PayPal. Then you cache it all for 48 hours just to make sure they don't lose the username while checking out. You could also take advantage of PHP's session support to track the user if they happen to come back the next day to make the purchase. As long as they didn't clear their cookies/cache and your session lifetime hasn't expired the session server-side, they should be able to resume the session right where they left off and go straight to PayPal.
I would still send all vital data to PayPal just in case the user somehow manages to sit on PayPal's payment page for a week and then decides to put in CC info.
You could also use this system to "check" if the user has already started paying. Perhaps ask them to enter an email address first. Associate all data to that email and the user's IP address ($_SERVER['REMOTE_ADDR']). If you don't have session concurrency for a user, but they enter an email address already in the database. Check their IP (and maybe even browser too if you want to be really anal about it) and if it's a match, tell the user "looks like you started checking out before and never finished. want to continue?" and let them pick up where they left off. Obviously don't store any sensitive information this way, and only cache it in the temp table for paypal stuff so it only lasts for 2 days at best.
This way the user can click "Yes" and they don't have to choose their subscription again and go through all that picking/deciding a second time. If the user says "No, I'd like to start over" then just delete the row in the temp table and make a new one for them.
I'm trying to write an IPN that, upon successful transaction, modifies a database entry (like as to increment a currency (like Envato does for their prepaid deposits)).
I've looked over the IPN variables a few times and I can't figure out how to track a user transaction, except for the payer's email (but this relies on the fact that the registered account's email is the same as the payer email (which is not always true).
I'd like to track it using an account ID, but while the IPN will reply with a custom variable, I can't transmit a dynamic variable (using the Buy Now button) for it to send back (like an account ID).
My question is, how can I send a dynamic variable with these buttons or track it an already established way?
You can transmit custom data via Paypal. Look at the custom variable.
So the scenario is this:
user logs in;
in the page which is before payment page, you either have hidden input having custom field set to user id or form it dynamically with Javascript;
custom field is not even shown to the payer when he/she confirms the payment;
when transaction happens, custom field is stored (so you can always look it up in Paypal website);
IPN notification sends you the custom field value (amongst other ones) which you can use for identifying the user.
I have got similar scenario working on a production system.
I've implemented a paypal transaction before but this one has a twist that I'm not quite sure what's the best way to handle it.
The basic idea is I want to create an account for the user when he provides some details and makes a payment via PayPal. Until BOTH the user details are filled out correctly AND the payment is made correctly, I shouldn't create an account for the user.
The setup I've done before was simply a paypal button that the user clicks, makes a payment, and gets forwarded back to just a generic page "your order will be processed and shipped" so there was no pre-order form involved.
This one is different though because
before PayPal, I need to collect initial user data
after PayPal, I need to create the new user account and use in it the user data collected from the pre-paypal form
I'm sure there's a logical way to implement this, but I'm not quite sure what's the flow I should follow to do it.
I use the Zend framework by the way, which shouldn't matter but just in case Zend has an easier way to help me with what I'm trying to do.
I do the following (though I do this in ASP.NET):
User fills out form
Info is saved in Order table in db with a unique invoice number
Invoice number is passed to PayPal, along with the IPN Notify URL, when you do the redirect
User is sent to Paypal to pay and then comes back to a generic Success page
Behind the scenes, Paypal makes a call to the IPN Notify url once processing is complete. This page receives your invoice number which PP returns with its call, and then does the account creation processing for that order after retrieving the details from the db. [This is a page with no UI, since only PP is hitting it.]
An email is sent from that process which notifies the customer that their account has been created and gives them the details.
This is a simplified version of the process, but hits the highlights. You can check out PayPal's page about IPN, and do a search on google for IPN integration with PHP.