I am building a (small) subscription box business and I now need to focus on the web app. I already built stripe-based websites so I have a decent knowledge.
However, the issue I faced when building these previous sites is that the API was called TOO OFTEN. It slowed everything down.
How to build this subscription-based website, only with stripe, and making calls to Stripe API only when required (create/edit a customer, plan, subscription, etc.) while still making sure information is reconciled and up-to-date on the website for both admin and clients?
Check out the Stripe Webhook API here: https://stripe.com/docs/webhooks
You can store the user's information in the database and only update those fields if the user makes a UI action and you can make an assumption on what to update (like a subscription plan ID) or using a webhook handler, which you can use as a sanity check as well.
To be even more specific, I can give some examples as you will still need to make API calls when a user does an action such as: creates an account, removes their subscription, subscribes to a different subscription. You will store when their subscription expires in the database. When the user makes a request you do not make an API call to check when their subscription expires, but check the database field. When the subscription renews itself you will then have a webhook handler to update the expiration date in the database.
Essentially how it works is Stripe will make a request to YOUR service only when it needs to, instead of your service calling to Stripe on every request.
For WordPress specifically you can user the User Meta Data to cache/store the user's information and only make calls to your database for faster transactions. http://codex.wordpress.org/Function_Reference/get_user_meta
Related
I have a paid membership site which takes payments via Stripe Checkout (server integration). When a user registers, they are redirected to the Stripe checkout (with their ID passed as the 'client_reference_id') where they enter their card details. For the checkout fulfillment, I have a webhook setup that is linked to the event 'checkout.session.complete'.
Everything is working fine, the webhook triggers and the endpoint processes the data and marks the corresponding account as activated, sends an email to the account holder as well as the site admin to let them both know the account has been created and a payment has been successful.
However, if a payment fails, I don't know what event to attach to the webhook to detect failed payments via Stripe Checkout. The only checkout event documented is 'checkout.session.complete', there isn't one for something like 'checkout.session.failed'. There's 'invoice.payment_failed' but this is used in subscriptions not one-off checkout payments.
We're wanting to basically notify the site admin when a payment fails so they are aware an account has been created but it still awaiting payment.
Is there a checkout event I'm missing or another way to go about finding failed checkout transactions?
To charge a credit or a debit card, you create a Charge object. You can retrieve and refund individual charges as well as list all charges. Charges are identified by a unique, random ID.
-- From the Stripe API Documentation.
You can then detect a webhook response of charge.failed to show that an attempted use of a charge object has failed.
Stripe used to be very cleanly documented, but they've lost their way a little, recently.
Stripe card payments ALWAYS use Charge objects, sometimes these are set by you (invoices, subscriptions, etc.) and sometimes these are set behind the scenes by Stripe ("Checkout Process", etc) -- but they are always set, so your webhook can always detect a charge.failed event.
Addendum
This does work, however, since the client_reference_id is not in the charge.failed data, I can't link the failed payment to a specific account anyway. But in regards to my actual question, this event does work and is the correct answer, just unfortunate that it doesn't solve my specific situation.
To solve this; either using the Stipe interface or by coding:
1) Create a Customer object and keep some sort of record of this customer Id.
2) When the Stripe Charge runs, an associated $charge->customer is set. This is available to your webhook.
3) When the webhook result appears, use this (typically) $event->data->object->customer value to cross reference the charge with the correct customer on your server.
4) As mentioned in comments, Stripe Webhook Testing does not populate the webhooks with example data such as ->customer... :-(
I know this is a bit late for a reply - but I have a working solution!!
When I create a "Session" in Stripe, I make sure to fill out the SessionCreateOptions so that the PaymentIntentData.Metadata field is setup to have my customer's ID and stuff in it. When I do that, the metadata not only shows up in payment_intent.created and payment_intent.succeeded webhooks, but it ALSO shows up in charge.succeeded/failed!
This means that when a payment fails I can look up the attempted payment that I keep track of and email them back letting them know that it failed and why, and I can also log it for myself for reference when I go look up that customer in my customer service tools.
It's not clear from the documentation and I spent a lot of time grokking how it works, so I hope this will save you some time.
The checkout session CANNOT fail (!)
A Checkout Session can have one of 3 states: "open" is an active session which can be paid, "completed" is paid ("happy path"), and "expired" if within the expiration time the session was not completed.
A session can only expire with two options:
After 24 hours if not paid (or sooner, if you set a shorter expiration time https://stripe.com/docs/api/checkout/sessions/create#create_checkout_session-expires_at)
Manually by calling https://stripe.com/docs/api/checkout/sessions/expire
A session's URL can be accessed unlimited number of times for payment attempts until it is either paid or expires. This is by design, so a user can have a couple of failed attempts to pay until she actually pays. With a session, you do not care about those attempts, and in most cases you do not need to track them.
So one option for your workflow can be the following, for example:
For creating a new order, create a new session, save it's ID in the order's record in the DB, and redirect the user to the session's URL
On the back-end, listen for "session completed" event, which is the happy path - everything is paid (watch out for the async payments, if you accept any! See herehttps://stripe.com/docs/payments/checkout/fulfill-orders#delayed-notification)
Also listen for "session expired" event. This will tell you that the user bailed and hasn't paid the order. You can send them a "failed payment, try again" email in this case (see below for Recovery workflow)
If the user returns to your website before paying for the order, you can display "NOT PAID, TRY AGAIN" message next to the unpaid order.
Attention: it is perfectly safe for the user to open a dozen of the session's URL and attempt to pay as Stripe won't allow the double payment after card information is submitted.
So you are thinking about creating expiring the old session and creating a new one for this unpaid order? Wrong! You can retrieve it by ID (you saved it in the DB, right?) and send the same URL to the user.
However, if the retrieved session is "expired", there will be no URL to send, so you will be forced to create a new session, save it in DB, and the whole cycle repeats.
Another possibility is for the repayment workflow to happen in rare state between the payment and "session is completed" webhook event (the user already paid in another tab, but you haven't received the "paid" event yet), you will get that the retrieved session state is "completed", in this case you will need the capability for the front-end not only to redirect the customer to a session's URL, but instead sometimes show a message like "nope, it's already paid".
As you can see, there is no "failed" state for the checkout session.
Now, another thing for recovering the unpaid and expired sessions is the Recovery workflow (https://stripe.com/docs/payments/checkout/abandoned-carts). The gist of it is the following:
When creating a session, you set "recovery" to true, so if the session expires, you will have access to a special URL that will "revive the same session with the same parameters" that will be active for 30 days after the original session expiration. You then send this URL to users with possibly some discount to recover their abandoned cart. Also, you can track whether the session is "original" or "revived". However, I did not use this way, and instead opted to simply creating a new session manually if the old one is expired.
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 creating a site in which a user must pay in order to access certain parts of the site. I understand how to make certain pages available to certain users, but I would like to know how I can automatically give them access once their payment has been processed.
ex.) A user sets up a account, during the process it will ask for credit card or other payment info(I would like it to be through Paypal). Once the payment has been processed it will add the user to my database and then they can access the site.
I am new to eCommerce and would like to know what tools I can use so that when a purchase on my site has been processed, I allow the user to access the website.
note: My site is being built with PHP.
I would recommend using Instant Payment Notification (IPN) for that.
It's basically a script that sits on your server listening for data. Any time your PayPal account has a transaction that takes place it will automatically push data to your listener script in real-time. Within that script you can update your database, send out email notifications, etc.
Here's a PHP template for IPN that I developed years ago. It's a little rudimentary, but still very useful and will get you up-and-running with IPN within minutes. Then all you would need to do is make some basic additions to update your users table accordingly, but the template comes with a nice database class that makes that very simple as well (assuming you install the IPN template solution to the same DB as your users table.)
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 site with a members area that I've set up and want to make it so when people register, they need to subscribe to paypal, and only then the user is created in the database.
I don't know much how paypal works. Does anyone have any pointers? How or where do I start?
Basically I need to somehow redirect the visitor to paypal after he presses the "Register" button, make the payment, and then make Paypal return to my site and tell it that the payment was processed, so the user can be created...
Paypal IPN is the Paypal deployment for this kind of requirement.
IPN (Instant Payment Notification) allows you to delegate an endpoint URL that the payment gateway will send postdata to when a payment is completed successfully.
Most of the time this requires utilizing some kind of database to save the registration state while the user is forwarded over to Paypal for the payment process, making use of their SSL encryption and payment logic. When the process is completed, your application is notified with post data containing a unique identitfier generated by your app and passed with the original redirect in order to identify the user's session that has completed payment.
You will want to generate a unique id either using PHP uniqueid() function or by hashing a timestamp. This will be passed along to paypal in your redirect, and paypal will send it along with success/fail flags when the payment is processed. When the user fills out their form and is redirected to Paypal, save a boolean value for IsPaid in your database associated with their ID (i'd recommend using both a primary key as well as this unique transaction id mentioned earlier.) Your IPN script can then listen for the post data, parse it out and change the false IsPaid boolean for that id to true.
There are numerous good tutorials available. I've only used this in MVC deployments, so if you're doing procedural, googling around will help a great deal. Paypal's documentation has the most up to date parameter guides but there are other great, if a bit old, tutorials available independent of them.
http://www.web-development-blog.com/archives/easy-payments-using-paypal-ipn/
http://net.tutsplus.com/tutorials/php/using-paypals-instant-payment-notification-with-php/
Look at the Paypal IPN API, this is used in most paid membership scripts:
https://cms.paypal.com/uk/cgi-bin/?cmd=_render-content&content_ID=developer/library_code