First, a little background about Fat Cat Fab Lab and how we use CiviCRM and Stripe. Fat Cat Fab Lab is a makerspace that pays it’s rent almost exclusively with membership dues in the West Village neighborhood of NYC. As you can imagine, rent is high in the city that arguably invented high rent. Also, we built an RFID door system that ties in with our CiviCRM database. I’ve threatened to blog about it here in the 2015 Makerfaire post. An RFID card only allows entry if the associated member is in good standing. What this means is that we’re in a fairly unique situation the in Civi-scape because of our setup. Recurring contributions have to come in, and membership renewals _must_ work flawlessly as a result of those contributions. If not, I will get urgent messages about access cards not working! That said, one of my goals is to help the Stripe CiviCRM extension become a very “membership friendly” one, making use of some of the sexy Stripe features, like subscription editing. Membership upgrade/downgrade is asked for a lot at Fat Cat Fab Lab, so this implementation strives to reduce the associated administrative load for that workflow. I dare say the extension has come a long way from not renewing memberships at all. Good times! 😛 Anyway…moving forward!
Here’s a outline of new features and changes in design/approach.
- In Webhook.php, removal of any code that cancels a subscription when an at_end_date is reached.
– Used in CiviCRM when installments are opted for in a recurring contribution, this code in case: invoice.payment.succceed became unnecessary as soon as case: customer.subscription.deleted was added. A subscription with at_end_time set naturally sends a customer.subscription.deleted event to our webhook when it expires.
- Add feature: multiple subscriptions per customer. (the initial reason for this giant commit)
– The Upgrader.php script depends on a newer version of the stripe-php library, so version 4.3.0 has been added. Now it can ask Stripe for each customers subscription id. The upgrade script supposes that organizations haven’t created any additional subscriptions for customers outside of Civi and that no subscriptions have edited. There is commented bonus code, for orgs that have made subscription edits. Method 2 should be functionally the same for orgs that haven’t edited, it’s just a more circuitous route, and therefore more prone to error.
– Now there’s a new column in the civicrm_stripe_subscriptions table to store this unique identifier.
- Switch to contribution_recurring_id exclusively as a parameter to the API call Contribution repeattransaction.
– In my experience, using original_invoice_id is unreliable in renewing a membership that has been downgraded.
As you can see from the API code for repeattransaction, when contribution_recur_id is supplied, the API Contribution getvalue is called with limit =1, and order descending. This is the _previous_ contribution associated with the recurring id! For that reason, I believe $original_invoice_id might be an unfortunate variable name here. I imagine this could cause confusion for others looking to write a payprocessor extension for CiviCRM….who knows, maybe not.– With this approach in mind, it makes sense to add column contribution_recur_id to the civicrm_stripe_subscriptions table and eventually deprecate the original_invoice_id column on installed versions 4.7.1 and earlier.- Upgrader.php will also populate the contribution_recur_id column.
- Change the default behavior of CiviDiscount on auto-renew memberships to be an introductory offer, rather than an indefinitely discounted membership. – Once I get a time to continue my work on CiviDiscount and get a PR together, if accepted, we can start paying attention to a new boolean parameter intro_offer. This would give admins the choice of behavior per discount code on an auto-renew membership or other recurring contribution.
– I’ve worked up a rough gift card implementation with CiviDiscount. This code in this commit works with it, employing a new discount_type =3 for gift cards, ( discount_type=2 is for fixed discounts). Both of these are applied to the customer the same way: though a negative balance. This is one of the recommended ways for applying a gift card to a subscription. When there is a membership involved, this means now we have to act upon a possibly null charge invoice to renew the membership. I considered adjusting the number of terms and ignoring the null charge invoice. But, I thought better of it. The fact is that this negative balance will be applied to anything the customer pays for. So if we apply the entire negative balance to multiple membership terms there could be a double spend situation…screw that!
- Implement Stripe subscription editing for recurring contributions. – What this means is that when a customers subscription has been edited to new plan in the Stripe dashboard, the existing recurring contribution is canceled and new one is started. A new pending contribution is created at the new level. In reality we don’t know the actual amount of this contribution, because Stripe prorates the remaining time at the old level and creates a new line item for the new level according to the amount of days left until the customers billing date. We’re basically waiting for the dust to settle and recording the contribution when it comes in. I had considered just editing the current recurring contribution to the new level, but as a CiviCRM site-admin, seeing a record of previous levels tells me a story and is important information. Thank you Eileen McNaughton, for letting me pester you with endless question about this and other things! – If there is a membership involved with this recurring contribution change, the members level is changed automatically. This is possible because we’re now prepending plan ids with membertype_X and adding the membership name after CiviCRM in the plan description. I don’t see any other way of making this happen…and I believe it’s worth doing if your organization depends on it’s different memberships for survival. In Stripe, plan id cannot be edited. The good news is that this code also checks to see if membertype_X- is prepended to the plan description, an attribute that can be edited. This means existing users of the extension who want the feature can retrofit their Stripe plans by looking up their member type id’s in their civicrm_membership_type table and prepending them to the corresponding plans in stripe. If existing users of this extension don’t care about the member level changing feature, they can safely ignore it.– Ultimately I see subscription editing as something initiated within CiviCRM instead of the Stripe UI. Hopefully some code can be recycled. Maybe we’d have a list of existing plans that we can change the customer to.
Thanks for reading..I hope the community finds this as useful as we do!