This entry is part 7 of 9 in the Integrating Stripe.com with WordPress Series
- Stripe Integration Part 1 – Building the Settings and a Simple Payment Form
- Stripe Integration Part 2 – Recurring Payments
- Stripe Integration Part 3 – Variable Prices and Enhanced Plan Handling
- Stripe Integration Part 4 – Multiple Recurring Payment Options
- Stripe Integration Part 5 – Accepting Discount Codes
- Stripe Integration Part 6 – Payment Receipts
- Stripe Integration Part 7 – Creating and Storing Customers
- Stripe Integration Part 8 – Working with Invoices
- Stripe Integration Part 9 – The Stripe Button
The Stripe customer system let’s us keep track of people that have signed up for our subscriptions or purchased our products. Anytime a user signs up for a subscription, a customer is created for them in Stripe. Once a customer has been created, we can see all payments that customer has made, add or subtract charges to their account, give them discounts, and a few other things. In this part of our Stripe and WordPress integration tutorial series, we’re going to look at some of the basics of working with customers.
Before we go too far, let’s look back at some of the code we’ve already written, since we have actually already done a little work with customers. In includes/process-payment.php, we have two ways of processing payments:
- Recurring payments
- One time payments
Anytime a recurring payment is created, a customer is created. This is because a customer is required in order to setup recurring billing. We created our customer like this:
1 2 3 4 5 6 | $customer = Stripe_Customer::create(array( 'card' => $token, 'plan' => $plan_id, 'email' => strip_tags(trim($_POST['email'])) ) ); |
Pretty simple, right? There is not a lot too it, but we’re going to expand on this now.
When processing payments, we create a customer for our recurring payments, but not for the one-time payments. Let’s upgrade this so that individual payments are attributed to customers as well, which will give us a much better tracking system for our earnings.
Currently our one-time payments are created like this:
1 2 3 4 5 6 | $charge = Stripe_Charge::create(array( 'amount' => $amount, // amount in cents 'currency' => 'usd', 'card' => $token ) ); |
The Stripe Charge accepts a customer parameter that can be passed so that the payment is attributed to a customer. In order to pass that customer parameter we need to do two things:
- Check if we already have a custom ID for the current user (only if they are logged in). If we do, we will use this customer ID.
- Create a new customer if we do not have an existing customer ID and then pass the newly created ID to our charge object.
Let’s first adjust our code in process-payment.php to create a customer if needed:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | if( is_user_logged_in() ) $customer_id = get_user_meta( get_current_user_id(), '_stripe_customer_id', true ); else $customer_id = false; if( !$customer_id ) { // create a new customer if our current user doesn't have one $customer = Stripe_Customer::create(array( 'card' => $token, 'email' => strip_tags(trim($_POST['email'])) ) ); $customer_id = $customer->id; if( is_user_logged_in () ) { update_user_meta( get_current_user_id(), '_stripe_customer_id', $customer_id ); } } if( $customer_id ) { $charge = Stripe_Charge::create(array( 'amount' => $amount, // amount in cents 'currency' => 'usd', 'customer' => $customer_id ) ); } else { // the customer wasn't found or created, throw an error throw new Exception( __( 'A customer could not be created, or no customer was found.', 'pippin' ) ); } |
This first checks to see if the user is logged in. If they are, we attempt to retrieve their customer ID from the user meta table. If no meta is available, get_user_meta() will return false. If $customer_id is false, either because the user is logged out or because the customer ID didn’t exist in the meta, we go ahead and create a customer. To create the customer, all we need is the email address and card token.
Once the customer has been created, we update $customer_id with the ID number returned from Stripe, and then, if the user is logged in, store it in the user’s meta.
After the customer ID has been created or retrieved, we create the one-time charge. Note, however, that the Stripe_Chart function has been updated with a new “customer” parameter, which has replaced the “card” parameter we had before. This is because Stripe only needs the customer ID. When the customer ID is provided, it will charge the card the customer currently has on file.
In the case that no customer ID is found, and no customer can be created, we use throw new Exception to trigger the error notice, alerting us that something went wrong.
Once a payment is submitted now, you will see this in your Stripe Dashboard:
Now we have just one more modification we need to make in order for our plugin to be completely customer friendly. Since it is very feasible that a logged-in user may come back and update their subscription, let’s update the recurring portion of our payment processing to check if the current user already has a Stripe ID stored on the site.
We will use the same process for recurring payments:
- Check if the user is logged in and if they have a stored Stripe customer ID. If an ID is found, we update this customer with the new info.
- If no customer is found, we create a brand new customer and store the ID for future use, if the user is logged in.
Our updated code looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | try { if( is_user_logged_in() ) $customer_id = get_user_meta( get_current_user_id(), '_stripe_customer_id', true ); else $customer_id = false; if( $customer_id ) { // retrieve our customer from Stripe $cu = Stripe_Customer::retrieve( $customer_id ); // update the customer's card info (in case it has changed ) $cu->card = $token; // update a customer's subscription $cu->updateSubscription(array( 'plan' => $plan_id ) ); // save everything $cu->save(); } else { // create a brand new customer $customer = Stripe_Customer::create(array( 'card' => $token, 'plan' => $plan_id, 'email' => strip_tags(trim($_POST['email'])), 'coupon' => $using_discount ? trim($_POST['discount']) : null ) ); if( is_user_logged_in () ) { // store the new customer ID in the meta table update_user_meta( get_current_user_id(), '_stripe_customer_id', $customer->id ); } $customer_id = $customer->id; } // redirect on successful recurring payment setup $redirect = add_query_arg('payment', 'paid', $_POST['redirect']); } catch (Exception $e) { // redirect on failure $redirect = add_query_arg('payment', 'failed', $_POST['redirect']); } |
First we check to see if the user is logged in, and attempt to retrieve a stored customer ID if they are. If no ID is found, or the user is not logged in, $customer_id will be false.
If we have found a customer ID, we use Stripe_Customer::retrieve to grab all of the current information for the customer from Stripe. Next we use $cu->card to update the stored credit card with what the user has just entered on the page. After storing the card, we update the customer’s subscription using $cu->updateSubscription(). This allows the customer to change their subscription, even in the middle of an existing subscription. If the customer already had a subscription, the new one will be prorated if necessary.
After updating the card and the subscription, we do $cu->save() to send all of the changes to Stripe.
Now, we we did not find a customer ID, or the user isn’t logged in, then we create a new customer just like we used too. We also make sure that we store the newly created customer ID if the user is logged in.
That’s it! We now have a much more complete customer system with our Stripe billing.
One of the things that’s really great about using customer’s in Stripe, is that we, as the admin, can update or modify the customer’s subscription at any time. For example, using the invoice object, which we will look at in the next part, we can attach arbitrary fees to our customers, which will then be paid for when the customer’s next payment comes through. You can also give your customer’s discounts (or prorated amounts) in the middle of their subscription, which is something you definitely cannot do with many systems, such as PayPal.
The complete code that we have worked with in this part is below. You can also download the complete plugin (with everything we’ve done up to this point) at the bottom.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | <?php function pippin_stripe_process_payment() { if(isset($_POST['action']) && $_POST['action'] == 'stripe' && wp_verify_nonce($_POST['stripe_nonce'], 'stripe-nonce')) { global $stripe_options; // load the stripe libraries require_once(STRIPE_BASE_DIR . '/lib/Stripe.php'); $amount = base64_decode($_POST['amount']) * 100; // retrieve the token generated by stripe.js $token = $_POST['stripeToken']; // check if we are using test mode if(isset($stripe_options['test_mode']) && $stripe_options['test_mode']) { $secret_key = $stripe_options['test_secret_key']; } else { $secret_key = $stripe_options['live_secret_key']; } Stripe::setApiKey($secret_key); $using_discount = false; // check for a discount code and make sure it is valid if present if(isset($_POST['discount']) && strlen(trim($_POST['discount'])) > 0) { $using_discount = true; // we have a discount code, now check that it is valid try { $coupon = Stripe_Coupon::retrieve( trim( $_POST['discount'] ) ); // if we got here, the coupon is valid } catch (Exception $e) { // an exception was caught, so the code is invalid wp_die(__('The coupon code you entered is invalid. Please click back and enter a valid code, or leave it blank for no discount.', 'pippin'), 'Error'); } } if(isset($_POST['recurring']) && $_POST['recurring'] == 'yes') { // process a recurring payment $plan_id = strip_tags(trim($_POST['plan_id'])); try { if( is_user_logged_in() ) $customer_id = get_user_meta( get_current_user_id(), '_stripe_customer_id', true ); else $customer_id = false; if( $customer_id ) { // retrieve our customer from Stripe $cu = Stripe_Customer::retrieve( $customer_id ); // update the customer's card info (in case it has changed ) $cu->card = $token; // update a customer's subscription $cu->updateSubscription(array( 'plan' => $plan_id ) ); // save everything $cu->save(); } else { // create a brand new customer $customer = Stripe_Customer::create(array( 'card' => $token, 'plan' => $plan_id, 'email' => strip_tags(trim($_POST['email'])), 'coupon' => $using_discount ? trim($_POST['discount']) : null ) ); if( is_user_logged_in () ) { // store the new customer ID in the meta table update_user_meta( get_current_user_id(), '_stripe_customer_id', $customer->id ); } } // redirect on successful recurring payment setup $redirect = add_query_arg('payment', 'paid', $_POST['redirect']); } catch (Exception $e) { // redirect on failure $redirect = add_query_arg('payment', 'failed', $_POST['redirect']); } } else { // process a one-time payment // attempt to charge the customer's card try { if($using_discount !== false) { // calculate the discounted price $amount = $amount - ( $amount * ( $coupon->percent_off / 100 ) ); } if( is_user_logged_in() ) $customer_id = get_user_meta( get_current_user_id(), '_stripe_customer_id', true ); else $customer_id = false; if( !$customer_id ) { // create a new customer if our current user doesn't have one $customer = Stripe_Customer::create(array( 'card' => $token, 'email' => strip_tags(trim($_POST['email'])) ) ); $customer_id = $customer->id; if( is_user_logged_in () ) { update_user_meta( get_current_user_id(), '_stripe_customer_id', $customer_id ); } } if( $customer_id ) { $charge = Stripe_Charge::create(array( 'amount' => $amount, // amount in cents 'currency' => 'usd', 'customer' => $customer_id ) ); } else { // the customer wasn't found or created, throw an error throw new Exception( __( 'A customer could not be created, or no customer was found.', 'pippin' ) ); } // redirect on successful payment $redirect = add_query_arg('payment', 'paid', $_POST['redirect']); } catch (Exception $e) { wp_die($e); // redirect on failed payment $redirect = add_query_arg('payment', 'failed', $_POST['redirect']); } } // redirect back to our previous page with the added query variable wp_redirect($redirect); exit; } } add_action('init', 'pippin_stripe_process_payment'); |
[download id=”49″ format=”1″]
Hi need to send customer name from my custom form and i tried this code
Stripe.createToken({
number: $(‘.card-number’).val()
cvc: $(‘.card-cvc’).val(),
exp_month: $(‘.card-expiry-month’).val(),
exp_year: $(‘.card-expiry-year’).val(),
name: $(‘.s_name’).val()
}, stripeResponseHandler);
but when i checked my response in stripe name is null .
What is the name attribute of the input field? It will need to be “s_name” since that’s what you have in the JS.
I am using letest version of stripe . Subscription updated is not working for me.