- 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
At this point in the series, we have a payment form that allows for users to submit a one-time or recurring payment, but it’s not very flexible. The payment amount is currently hard coded into our plugin, which makes almost useless for people that want to have multiple payment forms for different amounts. In this part of the series, we are going to look into expanding this a little bit to allow a price to be defined by an attribute in the short code. We are also going to add an option to our settings page that will allow you define the Stripe plan ID for recurring payments.
When finished, we will be able to do this:
[payment_form amount=20]
The first thing we need to do is modify our short code function to allow a parameter that will act as the payment amount. Open includes/shortcodes.php and replace its contents with 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 | function pippin_stripe_payment_form($atts, $content = null) {
extract( shortcode_atts( array(
'amount' => ''
), $atts ) );
global $stripe_options;
if(isset($_GET['payment']) && $_GET['payment'] == 'paid') {
echo '<p class="success">' . __('Thank you for your payment.', 'pippin_stripe') . '</p>';
} else { ?>
<h2><?php _e('Submit a payment of $10', 'pippin_stripe'); ?></h2>
<form action="" method="POST" id="stripe-payment-form">
<div class="form-row">
<label><?php _e('Card Number', 'pippin_stripe'); ?></label>
<input type="text" size="20" autocomplete="off" class="card-number"/>
</div>
<div class="form-row">
<label><?php _e('CVC', 'pippin_stripe'); ?></label>
<input type="text" size="4" autocomplete="off" class="card-cvc"/>
</div>
<div class="form-row">
<label><?php _e('Expiration (MM/YYYY)', 'pippin_stripe'); ?></label>
<input type="text" size="2" class="card-expiry-month"/>
<span> / </span>
<input type="text" size="4" class="card-expiry-year"/>
</div>
<?php if(isset($stripe_options['recurring'])) { ?>
<div class="form-row">
<label><?php _e('Payment Type:', 'pippin_stripe'); ?></label>
<input type="radio" name="recurring" value="no" checked="checked"/><span><?php _e('One time payment', 'pippin_stripe'); ?></span>
<input type="radio" name="recurring" value="yes"/><span><?php _e('Recurring monthly payment', 'pippin_stripe'); ?></span>
</div>
<?php } ?>
<input type="hidden" name="action" value="stripe"/>
<input type="hidden" name="redirect" value="<?php echo get_permalink(); ?>"/>
<input type="hidden" name="amount" value="<?php echo base64_encode($amount); ?>"/>
<input type="hidden" name="stripe_nonce" value="<?php echo wp_create_nonce('stripe-nonce'); ?>"/>
<button type="submit" id="stripe-submit"><?php _e('Submit Payment', 'pippin_stripe'); ?></button>
</form>
<div class="payment-errors"></div>
<?php
}
}
add_shortcode('payment_form', 'pippin_stripe_payment_form'); |
First note that our function now accepts two parameters:
$atts, $content = null
This is the standard for short codes that have attributes. We will be defining our price with this amount=XX, where XX stands for the price is US dollars. We use the extract() function to get the price value, like this:
1 2 3 | extract( shortcode_atts( array( 'amount' => '' ), $atts ) ); |
The amount will now be stored in a variable named $amount, which means we can output it in a hidden form element like this:
1 | <input type="hidden" name="amount" value="<?php echo base64_encode($amount); ?>"/> |
Notice that we are not just echoing $amount into the value of the form input, instead we are echoing it after we encode it with base64_encode(). This is just a security measure that we use so that it’s harder for someone to change the price before submitting the form.
We now need to open includes/process-payment.php. Place this around line 11, just after the require_once():
1 | $amount = base64_decode($_POST['amount']) * 100; |
This will decode our payment amount and convert it to cents, which is required by Stripe. And now we need to replace the ‘amount’ variable in our Stripe_Charge function to reflect our new variable:
1 2 3 4 5 6 | $charge = Stripe_Charge::create(array( 'amount' => $amount, // amount in cents 'currency' => 'usd', 'card' => $token ) ); |
That’s it! Our form now accepts a variable price. Note, however, that this price only reflects one time payments. It does not effect recurring payments, and that’s because those must be created in Stripe before hand. To make that part of the plugin a little better, we will now add a new option to our Stripe Settings page where we can define the plan ID that we have created in Stripe.
Open includes/settings.php and add this to the bottom of the settings area:
1 2 3 4 5 6 7 8 9 10 | <tr valign="top"> <th scope="row" valign="top"> <?php _e('Plan ID', 'pippin_stripe'); ?> </th> <td> <input id="stripe_settings[plan_id]" name="stripe_settings[plan_id]" class="regular-text" type="text" value="<?php echo $stripe_options['plan_id']; ?>"/> <label class="description" for="stripe_settings[plan_id]"><?php _e('Enter the ID of the recurring plan you have created in Stripe', 'pippin_stripe'); ?></label> </td> </tr> |
Your settings should now look like this:
We now need to replace “your_stripe_plan_id” in process-payment.php with our option. To do that, update the Stripe_Customer call to this:
1 2 3 4 5 | $customer = Stripe_Customer::create(array( 'card' => $token, 'plan' => $stripe_options['plan_id'] ) ); |
The complete code for part three can be download below.
Download Plugin


Awesome! Just what I was looking for. Thanks!!
I was also looking to have the plan be variable as well so that the plugin could be used for different payment options. For example, I wanted to have a couple different levels of monthly subscription plans.
I used your example of how you made the prices variable and made the plan variable. Now I can use this shortcode to define the price and plan:
[payment-form amount=X planid=X) //Replace X with the appropriate variable.
I’m not much of a programmer, so it may not be the best but here is what I did:
In /shorcodes.php
Add this code just above: global $stripe_options;
extract( shortcode_atts( array(
‘planid’ => ”
), $atts ) );
Near the bottom, with the hidden inputs add:
<input type="hidden" name="planid" value="”/>
In /process-payment.php
Change to this:
$customer = Stripe_Customer::create(array(
‘card’ => $token,
‘plan’ => $planid
The only other thing that needs to done is create the plans in your Stripe dashboard.
One other thing: The line in shortcodes still heads the form with “Submit a payment of $10″. I changed that to “Submit a payment’ and then enter text to identify the plan and payment in the post title or the area above the shortcode.
How this is useful. Thanks for all your work on this plugin.
Now if Stripe would only add a Quarterly option in their recurring payment……
Fantastic! Thanks for adding all of this. One thing you need to make sure is that you have both “planid” and “amount” in your short code extract() function.
I’ve been hoping for quarterly payments from Stripe for a long time now. According to support, it is not likely to happen soon, unfortunately.
Yeah, I wasn’t sure how to add both shortcodes in the same extract () function. It worked doing two separate ones. What is the proper way?
Supposedly, you can create a quarterly payment by doing a $0 recurring payment and then setting up an invoice that creates and charges every three months. Apparently, the invoice will charge automatically. I’m trying to learn how to do this and maybe it can be integrated into the plugin somehow.
This is how you want to do it:
Yeah, they told me that as well, but it seems kind of messy.
**Disclaimer: Limited Programming Skills**
I love this tutorial, and it provides excellent step by step instructions. I am implementing this into our business model as a means to introduce a recurring monthly massage maintenance plan. It is my goal to have this form be for administrative use only, and not open to outside customers. I really like the inclusion of the variable plan_id into the shortcode for the charge form. My question is, is it easy or possible to have a selection list of plan_id that drive the variable cost so I only have to use one form. So the process would be:
Enter Name
Enter Card Information
Select Plan and Pricing
As I understand it now, it looks as though I would have to build separate forms for each of the different monthly subscription variations that I have. Reason I am looking to develop this into my wordpress site, is I have 3 employees that will need to have access to make charges, however I do not wish to grant them the access to the strip.com account.
Sorry for the long question/post, any way to incorporate a Name for the card we are entering?
That is absolutely possible. What you would need to do is build a drop down that automatically populates the options with plans pulled from Stripe. I think this sounds like a great idea for part 4
I just wanted to say that this plug-in was/is extremely useful. Not to mention the excellent tutorial to go along with it. I am a WordPress and Stripe newby, but this jump started my project in the matter of a few hours.
I’ll need to incorporate some extra fields(name, address, etc.) and set the plan type according to the option my user selects on a previous page no the current drop down. But that is small potatoes compared to what you’ve got going here.
My payday will be your payday too.(donation-wise I mean)
Cheers Pippin.
Double post, sorry.
I intended to have my comment on part 4 of the tutorial.
Feel free to appropriately moderate me!
Ha, no worries. There will be more parts to this series, so it’s not complete yet
This is an EXCELLENT tutorial series, thank you so much!
I am interested in what Stripe calls METERED BILLING — so the amount charged to a customer each month can vary. It seems to be based on setting up Invoices and Invoice Items, to be added to the base amount of the Subscription. (It can be a negative amount, too.)
But i’m unclear how my site (on WordPress) would trigger these invoice-item api calls. I assume it’d need either cron, or a manual click by the site admin. But wouldn’t i need to send a separate api call for each customer? This sounds like re-building the recurring-billing engine in wp. I must be missing something here. If you have any experience with that, i’d love to learn more. Thanks!
Can you describe the exact billing types you need? I believe what you’re going to want to do is setup a recurring payment and then alter it by adding invoice items to the customer. Each time you add an invoice item, the next payment the subscriber makes will reflect that invoice item. The next payment after the invoice was paid will revert back to the normal amount.
I’m trying to create a form that allows for a recurring monthly donation at an amount set by the user. On the one hand, this seems like Stripe doesn’t support it. I would have to offer a limited set of defined options instead of allowing the user to define the amount. On the other hand, I saw this post on the Stripe support page that seems to suggest what I want is possible.
https://support.stripe.com/questions/recurring-billing-for-online-donations
What do you make of it?
Michael, it is possible, but it’s pretty tricky. Basically what you need to do is dynamically create a plan in Stripe for the donation amount each time a donation is submitted. Are you comfortable enough with PHP to do that?
Not really, no. If you happen to make this the next part of your tutorial, I would be grateful.
Also, I want to offer “suggested” monthly donations as well as the monthly donation of your choice, would the user-generated plans show up in the pre-populated list each time one is generated?
I will definitely consider it for an additional part to the series.
All plans would show up in the list, regardless of how they were created.