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.
Related
I have website where I use PayPal NVP sandbox. Sometimes after successful payment of user, PayPal get back to my return URL very slow. Unless PayPal returns to my website with details I am unable to check whether user has completed the order (For all attempt website adds order id to the database) or not and that destroys website's work principle.
What I need is that I want to retrieve the data of transaction without transaction id if possible. Maybe with custom field or something else. If I would be able to check the transaction details without transaction id , then I would be able to handle the requests by user accordingly. Or if there is a way to get a transaction id somehow with the help of another variable that also fine as I will make checking after finding out the transaction id.
Current PayPal Checkout integrations give an immediate response of success/failure. There is no need for any redirect away from your site, and there is no need to wait for asynchronous IPN or webhook messages. Don't use such things.
Follow the PayPal Checkout integration guide and make 2 routes on your server, one for 'Create Order' and one for 'Capture Order' (see the optional step 5 in 'Add and modify the code'; you can use the Checkout-PHP-SDK). Both of these routes on your server should return/output only JSON data (no HTML or text). Inside the 2nd route, when the capture API is successful you should store its resulting payment details in your database (particularly purchase_units[0].payments.captures[0].id, which is the PayPal transaction ID) and perform any necessary business logic (such as sending confirmation emails or reserving product) immediately before forwarding your return JSON to the frontend caller.
Pair those 2 routes with the frontend approval flow: https://developer.paypal.com/demo/checkout/#/pattern/server
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 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."
So I have a multi paged checkout system that relies on sessions to store the contents of the shopping cart. I'm also using a third party system to process credit cards, which hosts the actual payment page on their servers. I just have to POST to the page the final total.
The problem I foresee is what if someone clicks to go to the hosted pay page, and then for some legitimate or nefarious reason changes the shopping cart contents in another tab. I had initially planned that when the hosted pay page redirects back to my receipt page I would then INSERT the order into my database. But, if the session is changed at that point, the order will be different from the total cost charged.
What would be a solution to this problem. I can see this sort of thing being an issue for all cart systems, so I'm wondering how they do it.
Maybe when the user clicks the button to go to the hosted paypage I can make a temporary order entry in a temp_order table in the database, and then when the payment goes through I can transfer that temp record into the permanent record table? That way I don't insert the record from the session information that has changed. But if I have to POST to the hosted pay page, where do I have the opportunity to save the shopping cart to the temp table?
Also, the temp order id must be unique across both temp and permanent tables since I don't want any overlap.
Lastly, I should want to clear the temp order table frequently as they are just temp records. Some might not go through as the user could change their mind on the hosted pay page.
I'm really confused as to what I should do!
I see no need to create a separate table. Just add one column into existing table, say, payment_in_progress and analyse it when client submits any changes to the cart.
The requirement to clear out unprocessed outdated orders remains
When the payment gateway returns just store the amount received against the shopping cart and if the amount received is less then the total, put them back onto the payment page, showing the outstanding balance left to pay.
Unless the payment system returns control to your website before final processing of the order, e.g. like PayPal Express Checkout, there is no way to stay in control of the checkout process. One-way checkout systems are really meant to be one-way. Follow-up management is manual (by a payment receipt) or handled by server to server notifications.
Posting directly to the payment site is not going to give you any control once you submit away to the other website. Probably the best case scenario is you submit the order to your website as an UNPAID order into your database, then provide a page that says "You're almost finished. Continue to payment." -- At this point, you should have also emptied the customer's cart so they cannot change anything about the order in process (which is already in your DB). When the payment system redirects back to your website, you will simply look for the unpaid order and mark it paid. It would also be a good idea to verify the payment amount, just in case the user modified the POST data in an effort to pay less.
EDIT:
You might really be in need of a payment gateway solution that gives you more control over the checkout process. Your concerns are real, but they are not typically addressed adequately using payment flows that send the user directly away from your website without first setting up the transaction server-side.
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.