====== Subscription and Recurring Billing with FoxyCart ====== ===== Related Documentation ===== * [[..:cheat_sheet#subscription_product_options|Subscription Product Options]] * [[..:api|The API]] * [[..:subscription_xml_datafeed|Subscription XML Datafeed]] * [[:integration:subscription_datafeed|PHP Subscription XML Datafeed Processor]] (to create automated billing reminder emails, etc.) * [[:v:2.0:products:subscriptions:subscription_step_by_step|Subscription Non-Tech Step-by-Step Topics]] ===== How Subscriptions Work in FoxyCart ===== FoxyCart allows merchants to process subscription and recurring-billing types products in a secure and flexible way, without relying on gateway-specific solutions with are often costly and less flexible for the merchant and the customer. To do this, FoxyCart securely stores the customer's payment information, and provides access to subscriptions to the merchant through the [[https://admin.foxycart.com/|FoxyCart admin]], to the developer through [[..:api|the API]], and to the customer through a variety of link possibilities (included in the email receipts by default). Recurring revenue streams can be a game-changing business decision, but it is important to understand a few things. - Recurring billing //will fail// with some regularity. Credit cards methods expire, become overdrafted, are canceled due to fraud or identity theft, and more. If you have 100 customers on a monthly billing arrangement, it is completely natural for at least a handful to error in any given month. If you want to get paid, you will need to monitor errors and followup with customers. Often times customers simply need a reminder to update their payment information. - FoxyCart does not send customers emails //by default//, though this functionality ("dunning") can be configured in the advanced settings page of your store admin. You may also perform more advanced customizations and integrations using the [[..:subscription_xml_datafeed|Subscription XML Datafeed]] and something like [[:integration:subscription_datafeed|PHP Subscription XML Datafeed Processor]]. If you have questions please post in [[http://forum.foxycart.com/|our forum]]. - Some gateways may have additional steps to allow FoxyCart to process subscriptions. Please see the notes below for explanation, and **//always test, test, test//** before going live. Custom shipping snippets do not work for subscriptions. The reason for this is because the snippets are done as Javascript modifications and run in the browser, while subscriptions run completely on the server side and never touch the browser. Subscriptions will always calculate on the server side based on how the category is configured. ==== When Do Subscriptions Process? ==== Subscriptions //start// processing daily at 0500 Pacific Time (America/Los_Angeles, US). Different FoxyCart versions process subscriptions at different times, but they are all scheduled near those windows. Note that depending on a number of factors, we cannot guarantee that subscriptions //finish// processing by specific times, though we do try to ensure all subscriptions finish by noon US Eastern Time. Any automated re-attempts or reminder emails (if configured for your store) are processed a little later in the day, starting around 1300 US Pacific Time. You can see [[#subscription_billing_cancellation_management_dunning|more information about the automated dunning functionality below on this page]]. //**We Eat Our Own Dog Food**// FoxyCart uses FoxyCart's subscription processing functionality to bill for FoxyCart services, and we have from day 1. So if you're wondering how robust it is, you can take comfort in the fact that if it messes up, we lose money ourselves. ===== Will It Work With Your Gateway? ===== //**Required Reading!**// Handling subscriptions through FoxyCart may not work with all gateways, particularly with your default settings. **READ THIS SECTION** if you're using subscriptions. By default, most gateways require the [[wp>Card_security_code|CSC]] (card security code, also called the CVV2, CVC2, or CCID) to be sent with the payment details. Because storing the CSC is prohibited per [[wp>PCI_DSS|PCI DSS]], FoxyCart sends the subscription transactions //without// the CSC. If your gateway is set to require the CSC, the transaction will fail, effectively rendering FoxyCart's subscription functionality useless. Depending on your gateway provider and account settings you may be able to configure this yourself, or you may need to ask your gateway's support to change your account for you. Please review the notes for [[:gateways:start|your gateway]]. Even if there are no notes specific to subscription handling on our wiki, you should still dig into the CSC settings on your gateway. And //**test**// to ensure recurring payments process correctly. Worth noting is that for all regular transactions through FoxyCart the CSC is required on checkout. The only way the CSC will //not// be sent to your gateway by FoxyCart is for a subscription transaction. ===== Subscription-Related Product Options ===== Please see [[..:cheat_sheet|the cheat sheet]] for the complete list of product options. Subscription-specific options are included below for your reference. {{section>..:cheat_sheet#subscription_product_options&noheader&noeditbutton&permalink&footer&nodate}} ===== Common Subscription Product Configurations ===== For details on how to create add-to-cart links and forms for your products, we'd recommend first familiarizing yourself with the [[.:|general product documentation]]. ==== Future starting subscription ==== If you need to offer a subscription that doesn't start immediately, you can simply set a ''sub_startdate'' parameter that is in the future, either by offering a specific day or date, or by setting it to a certain time range: For example, ''&sub_startdate=20251210'': to start on the 10th of December, 2025, ''&sub_startdate=10'': to start on the next 10th of the month, or ''&sub_startdate=2m'': to start two months from today. ==== Subscription with a set number of payments ==== Sometimes you only need to capture a certain number of payments - for example, a product is normally $200, but you can also offer it in 4 payments of $50 spread out over a year. To achieve that, you'll make use of the ''sub_enddate'' parameter, to set the subscription to end after a specific length of time. Continuing the example of 4 payments of $50 - that would be a ''sub_frequency'' of ''3m'', and assuming the subscription starts today, a ''sub_enddate'' of ''13m'', and in an add to cart link would look like ''&sub_frequency=3m&sub_enddate=13m''. Note the ''sub_enddate'' parameter is the month after the last required renewal - if the end date falls on the same day that the subscription would normally be renewed - it will be cancelled without taking any charge. By setting it to the following month, it ensures that a total of 4 payments are taken, but not any more. Also worth noting - the ''sub_enddate'' parameter is based on todays date - so if your subscription is set to start in the future, you need to adjust a relative end date value accordingly. ==== Subscription with an Initial Setup or One-Off Fee ==== For offering a subscription that includes an initial fee (like a set-up fee), you would make use of our [[.:#product_grouping_bundling_ensembles|bundled product functionality]] to link to products together. The main product will be your subscription, but you will bundle with it the second normal one-off product to act as the fee. By bundling the two products together, the customer is unable to remove the one-off product individually to avoid the fee. On the initial purchase, the customer will pay for both the one-off product and the subscription (assuming it starts today), but moving forward, the one-off product will not be included with the subscription renewals; only the subscription product will remain. The bundled product documentation goes into detail for how to set it up, but as an example, let's assume you have a $20 monthly subscription, but want to charge a $5 set up fee: ?name=Subscription&price=20&code=mysub&sub_frequency=1m&2:name=Setup+Fee&2:price=5&2:parent_code=mysub&2:quantity_min=1 You could also use this approach to set a different price for the first period of the subscription compared to the continuing renewals. To achieve that, you would simply add a ''sub_startdate'' parameter to the subscription which matches the frequency. In the example above, that would be ''sub_frequency=1m'', which would make the initial month $5, with all future months $20. ==== Discounted subscription cost for only a certain number of renewals ==== You may need to be able to offer customers a special offer of receiving their subscription at a discounted price for the first X renewals, before the subscription becoming full price again. To achieve that, you would make use of [[..:coupons_and_discounts|our coupons functionality]] and the setting to limit the number of uses per customer for the coupon. This restriction is based on the customers email address, so if you need to allow the customer to receive the first 3 payments on their subscription at a discounted rate, you would set the limit per customer to be ''3''. For the customer to receive the discount, they would need to enter the coupon code on the cart or checkout. If you wanted them to receive the discount automatically, you could include the ''coupon'' parameter as part of the add to cart for your subscription, like ''coupon=my_coupon_code'' ===== Testing ===== Testing is a **REQUIRED STEP** when using subscriptions with FoxyCart. Check [[..:getting_started:testing|the testing page]] for more details. Important to note is that while your FoxyCart store is in test mode, any subscriptions you process will be set to "active", and will be processed once you switch over to the Live Servers. Before you switch over to the Live Servers, make sure that you set all the subs you have created while on the Test Servers to inactive. You can do that by using the [[v:2.0:api|API]] or by changing them individually. To change them individually, go to the Manage Subscriptions section in the FoxyCart admin, click on the Edit link of the desired subscription, deactivate the sub by unchecking the **Active?** checkbox and then update the subscription. It's recommended to create a separate store for testing and one for production so that you wouldn't need to deactivate all the test subs when you switch over to a Live Store. ===== Subscription Billing & Cancellation Management (Dunning) ===== ==== An Overview of Subscription Management with FoxyCart ==== As mentioned above, FoxyCart does not send automatic emails to customers when their payments fail or if their payment method is soon to expire **//by default//**, though this can be configured. FoxyCart does provide a "customer portal" where customers can view active subscriptions, update billing info, cancel subscriptions, and (optionally) change next dates and frequency (useful for "auto-ship" merchants). ==== Using FoxyCart's Native Dunning Functionality ==== In your store's advanced settings page, there is a section named "Recurring Billing Settings". In this section are options to re-attempt failed transactions, send email reminders about subscriptions in an error state, and cancel a subscription after a period of time. All of the following options are on the "advanced settings" page in your FoxyCart admin. === Customer Portal Subscription Modification URL === If you are using ''foxy-items-form'' in the customer portal, you can specify a **modification url** here to show an **Edit** link on their subscription in the portal that will send the subscriber to this URL with their subscription pre-loaded. === Toggling Email Receipts For Subscription Renewals === By default, FoxyCart will send an email receipt to the customer for all transactions - which for subscriptions include the initial purchase as well as each successful renewal. If you want to prevent email receipts from being sent for renewals, you can uncheck the checkbox for "send emails for automated subscription renewals" on your store's advanced settings. Unchecking the checkbox will just stop subscription renewal emails - email receipts for subscription modifications or cancellations will still be sent. If the store is set to receive a BCC of the transactions in the [[https://admin.foxycart.com/admin.php?ThisAction=EditTemplate&template=email|email]] settings and you have this dunning setting enabled, the store will also receive a copy of this email. === Customising How Past Due Amounts Are Handled === As part of the advanced settings, you can dictate how a past due amount is handled against a subscription when it fails to renew correctly. Currently you can either have the subscription past due amount "Increased by the missed payment amount" (so with each renewal it will increase the total amount due) or "Replaced with the latest missed payment amount" (meaning the subscription will only have a past due from the most recent renewal failure). === Charge Past Due Amounts === If checked, the past due amount will be included in automatic subscription processing, and will be included in the cart if a customer attempts to update their subscription. If unchecked, any successful subscription payment (automatic or customer-initiated) will clear out the past due amount. NOTE: Even if this is not checked, you can still effectively collect past due amounts with the ''sub_restart=auto'' flag on sub_token links. === Requiring Past Due Amounts Before Customers Can Modify or Cancel Subscriptions === By checking the "prevent customer-initiated modification, replacement, and cancellation if past-due is present" checkbox in the advanced settings, a customer will be required to pay any past due amounts present on their subscription before they can manually cancel it, and also before they can use the ''sub_modify=replace'' behavior. If unchecked, a customer will be able to modify or cancel their subscription even if they have a past due amount present. === End Dates on Cancellations === When a customer uses the ''sub_cancel=true'' functionality, the "when a subscription ends, set the end date to" setting determines whether the enddate should be set to "tomorrow" or to the next transaction date. If you have a membership service where a customer pays for the year or the month at the beginning of the period, this should generally be set to "next transaction date", as they've already paid for that time period. This can be useful if you're relying on Foxy subscription data to determine access to a 3rd party site. === Resetting A Subscription's Next Renewal Date When A Payment Is Made === When a customer makes a successful payment on a subscription (either via the ''sub_restart=true'' or a "past due" mount), by default it's next renewal date will remain as it already was. If you check the "reset the next transaction date on past due makeup payment" checkbox, when they pay the past due amount, their subscription's next date will be set to be one frequency ahead of the day that the transaction is processed. For example, if you have a monthly subscription that renews on the 1st of every month - and the customer pays a past due amount for that subscription on the 18th of a month - the subscription would ordinarily still renew on the 1st of the following month. With this checkbox checked, it would instead update to have a new renewal date of the 18th of the following month - one month from todays date. For "auto-ship" merchants, you'll almost always want to set this to reset the next date. === Failed Transactions Reattempt Schedule === This field accepts a comma-separated list of numbers. Each number represents the number of days after the initial failure that a reattempt should be made. For example, a setting of 1, 3, 5, 15, 30 would direct FoxyCart to attempt to collect the past-due amount on the 1st, 3rd, 5th, and 15th days after the initial transaction. Emails are not sent when the reattempt occurs unless the transaction is successful. === Reattempt Bypass Logic & Strings === These two fields work in conjunction with the reattempt schedule, and limit when a transaction should be reattempted. The "strings" field accepts a comma-separated list of strings containing text strings that should prevent or allow (based on the above setting) a rebilling attempt. For example, setting the logic to "skip if the string is present" with a value for the "strings" field of ''Code: 8, DO NOT HONOR'' would instruct FoxyCart to not initiate the rebilling process if the last error (logged in the [[https://admin.foxycart.com/admin.php?ThisAction=ErrorLog|error log]] in your FoxyCart admin) contained either ''Code: 8'' or ''DO NOT HONOR'', but to attempt the rebilling in all other cases. Note that error messages and codes are different from gateway to gateway. === Expiring Soon Payment Method Email Schedule === Similar to the "transactions reattempt schedule", this field accepts a comma-separated list of numbers. Each number represents the number of days before the end of the month that the customer's card is set to expire in that an email notification should be sent to the customer. This only happens for customers who have active subscriptions, and if the card is updated, no further reminders will be sent. The email will let the customer know that their card is about to expire, and include a link to allow them to proceed to the checkout and enter a new payment method. Emails are sent using the normal store email receipt template, with a Twig variable of ''is_expiring_payment_reminder'' used to display content specific to this reminder notification. The following language strings are also utilised for this email: ''email_text_message_expiring_payment_reminder'', ''email_html_message_expiring_payment_reminder'', ''email_subject_expiring_payment_reminder''. The store will also get a copy of this email if BCC to the store is set up in your [[https://admin.foxycart.com/admin.php?ThisAction=EditTemplate&template=email|email]] settings. === Reminder Email Schedule === Again, similar to the "transactions reattempt schedule", this field also accepts a comma-separated list of numbers. Each number represents the number of days after the initial failure that an email notification to the customer should be sent. This only happens for active subscriptions which still have a past due amount. If a reattempt is successful, no additional reminder email will be sent. Emails are sent using the normal email template. Take a look at the default template (search for the ''is_subscription_dunning_reminder'', ''is_subscription_dunning_cancellation'', or other bits with ''dunning'' in them) to see how the logic is structured, and where to inject your own messaging to your users. You can also look at the ''days_since_first_failed_transaction'' value, which will allow you to change the message depending on how long it's been since the error. If you've set your store to receive a BCC of the transactions in your [[https://admin.foxycart.com/admin.php?ThisAction=EditTemplate&template=email|email]] setting and you've set up a schedule here, a copy of the reminder emails will also be sent to your store email address. === Cancellation Schedule === This field accepts a single number representing the number of days after the initial failure that a subscription should be set to cancel (assuming a successful payment hasn't been made in the meantime). For example, if a subscription is set to process on the 1st of the month and this value is 35, on the 5th of the next month (which is 35 days later, assuming the first month had 30 days), the subscription will be cancelled. (The end date will be set to that day, and it will be set to inactive.) As before, look at the default email template to see what will be sent to your customers when this triggers. If the store is set to receive a BCC of your transactions (as set up in the store's [[https://admin.foxycart.com/admin.php?ThisAction=EditTemplate&template=email|email]] settings) and you have a cancellation schedule set up, your store will also receive a copy of the email that's sent to your customers when the subscription is cancelled. === Example Email Customization === If you wanted to change the text of your email based on the number of days since the failed payment (to increase the urgency and warn of impending cancellation, for example), it'd look something like this (replacing the ''if sub'' block of the default plain text email template): {% set sub = subscriptions|first %} {% if sub %} {% if days_since_first_failed_transaction < 15 %} This email is a reminder that your subscription is currently {{ days_since_first_failed_transaction }} days past due. To bring your subscription up to date, use the link below and complete your transaction: {{ sub_token_url }}&empty=true&cart=checkout {% elseif days_since_first_failed_transaction > 15 and days_since_first_failed_transaction < 28 %} This email is a reminder that your subscription is currently {{ days_since_first_failed_transaction }} days past due. **Your subscription will be cancelled automatically, and access removed, in {{ 30 - days_since_first_failed_transaction }} days.** To bring your subscription up to date, use the link below and complete your transaction: {{ sub_token_url }}&empty=true&cart=checkout {% elseif days_since_first_failed_transaction == 29 %} This email is a reminder that your subscription is currently {{ days_since_first_failed_transaction }} days past due. **Your subscription will be cancelled TOMORROW unless you click the link below to update your payment information.** {{ sub_token_url }}&empty=true&cart=checkout {% endif %} {% endif %} ===== Managing Subscriptions ===== ==== Customer Subscription Management by Email ==== {{:v:2.0:products:manags_subscription_links.png?direct&250 |}} The easiest way for most stores to provide customers with the means to update or cancel their subscriptions is to provide links in each and every receipt email sent to the customer. At left is an example of what we ourselves use, which is provided by default in FoxyCart's default email templates. Notice that links are provided to update the customer's billing information, to transfer the subscription to a new billing contact, and to cancel the subscription. Because these links are included in each and every receipt sent for a given subscription, it is an easy and effective way for customers to manage their own subscriptions. Also, because of the flexibility FoxyCart provides, these links can be customized as desired, removed, or extended to provide additional functionality. ==== Administrator Subscription Management ==== If you need to modify a subscription on behalf of a customer you can accomplish this in one of three ways: - By using [[..:unified_order_entry|Unified Order Entry]] (aka "the superpassword") to act as a customer without knowing their password, either through the checkout or customer portal. - Through the FoxyCart admin, by editing the subscription. (For advanced edits you can edit the raw XML.) - Through [[..:api|the API]]. The Unified Order Entry method allows you to take advantage of the ''sub_token'' methods outlined below, as if you were the customer. See [[..:unified_order_entry|Unified Order Entry]] for details, but the basic idea is to use the ''sub_token'' to modify the subscription as necessary, then use the UOE superpassword to process the subscription on behalf of the customer. You can modify the subscription product and customer information by following these steps: - Login to your store [[https://admin.foxycart.com/admin.php|admin]] - Take note of the Unified Order Entry Password from the FoxyCart admin on the “Advanced” page: https://admin.foxycart.com/admin.php?ThisAction=EditAdvancedFeatures - Go to the [[https://admin.foxycart.com/admin.php?ThisAction=ManageProductSubscriptions|Manage Product Subscriptions]] page and click on [+] (plus sign) next to desired subscription and click the **Sub Token URL** link - In the same window (or tab), go to your website and add the donation campaign you want to replace the current one with. You should see a message in the cart that says "You are currently modifying a subscription." - Remove the previous subscription, then proceed to the checkout page - The customer’s email address will be pre-loaded. For the password, input the Unified Order Entry Password from Step 2 to auto-populate the Customer Billing, Shipping, and Payment information - Select the new credit card information (other than the Use saved card option) and fill in the updated credit card information - Complete order and the customer will receive a receipt via email ==== The ''sub_token'': What It Is and How To Use It ==== Every subscription in a FoxyCart store has a unique ''sub_token'', which is used both to identify the subscription (independent of customer or transaction) and to load the subscription into a customer's cart (to modify or cancel). This token is available in the [[..:subscription_xml_datafeed|Subscription XML Datafeed]], from [[..:api|the API]], and also in your FoxyCart admin subscriptions page, within the expanded details of a given subscription (right-click and copy the URL from the "Sub Token URL" link), or from the edit page of a subscription. When the ''sub_token'' parameter is passed to the cart, it will blow away any previous cart data and load in a "template" of what the subscription is. There are a few common use cases for this: === Changing Billing Information or Paying Past Due Amounts === The ''sub_token'' can be combined with a ''cart=checkout'' directive to send the customer straight to the checkout screen (bypassing the cart), and indeed this is how the default receipt email includes the ''sub_token''s. When the customer lands on checkout the email address will be pre-filled with the current billing email address. At that point the customer can enter their password and complete the payment or information update as normal, or the customer can enter a new email address and take over the subscription from the previous billing contact. It's worth noting that customers may update their billing information without the ''sub_token'' by using the ''cart'' parameter ''updateinfo'', but for the purposes of this discussion it's likely more useful to include the ''sub_token''. That said, if you need to allow customers to update their payment information and you don't have the ''sub_token'' available, you can use ''cart=updateinfo''. More info is available at the [[..:cheat_sheet|cheat sheet]] and the [[..:checkout#update_info_requests|documentation here]]. If you're using PayPal Express (non-Reference Transactions), we do not support modifying subscriptions via the ''sub_token''. We strongly recommend using the "Reference Transaction" option for PayPal Express Checkout (selected in the admin). === Automating Subscription Billing Reattempts on Errors === **NOTE:** The best way to automate this now is by using the native dunning functionality, described above. If a subscription has had a billing error and has a past due amount, you can tell FoxyCart to attempt to collect the past due amount by passing in the ''sub_token'' to the ''process_past_due_subscription'' endpoint at your store's domain, like this: ''https://example.foxycart.com/process_past_due_subscription&sub_token=foobar'' The response is JSON like this: { "result": "OK", // "OK" if successful. "ERROR" if unsuccessful. "transaction_id": "", // int "processor_response": "", // string "processor_response_details": "", // string "receipt_url": "", // URL } === Manually Reattempting / Charging a Failed Subscription === If a subscription failed to process but you'd like to reattempt it, these are the steps. {{ https://www.evernote.com/shard/s1/sh/4ba4b87c-7224-4352-a0b0-440f32bf89fc/d0281a659c0075128a53a853caf61dd2/deep/0/Admin%20-%20FoxyCart.png?250}} - If [[..:unified_order_entry|UOE]] isn't already enabled, go to your store's Advanced settings and enable it. Use something like [[http://passphra.se/|Passphra.se]] to generate a random but memorable and secure password. - Load up the subscriptions in the FoxyCart admin and expand the subscription in question. - Find the "Sub Token URL" link, as noted in the image to the right. Control+Click that to open it in a new tab. - The cart will load with that subscription present. Click to continue to the checkout. - The customer's email will be loaded already. Enter the UOE password, and the checkout will complete with their payment info. Modify if necessary. Notice that the past due amount is set to be charged. - Complete the transaction. If it succeeds, the customer will receive an email receipt. If it isn't successful, you'll see the error describing the reason why. (For more on interpreting errors, [[:primer:errors|see this page]].) === Loading the Subscription to be Modified === {{ :v:2.0:products:sub_token.png?direct&300|}}If a customer desires to change his or her subscription, you could pair the ''sub_token'' with a ''redirect'' parameter to redirect the customer to a page on your website with links or forms for new subscriptions, or to view their cart. The customer could then add or remove items from their subscription, change quantities, or etc. Once the customer is satisfied with their new subscription they can proceed through checkout to update their subscription. Visual indication is provided to the customer on the cart and checkout page if a ''sub_token'' is active, as shown in the image at right. Note that any new subscriptions added to the cart will automatically have the ''sub_startdate'' set to the next scheduled date for the subscription to run on, which will prevent a user from modifying a subscription that ran yesterday (for example) and being charged again for today. For example, if you have a subscription for "Chocolate of the Month" set to run on the 15th of each month, and you load the ''sub_token'' on the 25th and add a "Wine of the Month" subscription product to your cart, the ''sub_startdate'' will be set to the 15th of the next month (unless manually overridden). Once a user completes the checkout from the ''sub_token'' that new transaction will replace the previous subscription. === Canceling a Subscription === Similar to the modification approach above, a subscription can be loaded to be canceled if the ''sub_token'' is passed in with a ''sub_cancel'' attribute set to either ''true'' or ''next_transaction_date''. This will change the notification to something like "You are about to set this subscription to end on 2010-10-01", and //upon checkout// the subscription will be set to end. It is generally a good idea to include the ''cart=checkout'' parameter to ensure the cancellation goes straight to checkout. When a subscription is set to cancel, it effectively sets the ''sub_enddate'' to either tomorrow or it's next normal transaction date (depending on which value you pass for ''sub_cancel''), at which point the subscription will not be processed (even if the ''sub_enddate'' falls on a normal billing date), and the cancellation will be included in the [[..:subscription_xml_datafeed|Subscription XML Datafeed]]. If you have set your store to require that customers pay any past due amount before they can cancel their account, then a customer will not be able to use the link to cancel until they pay that amount. This setting can be found on the "advanced" setting page, labelled "prevent customer-initiated cancellation if past-due is present". If a customer needs to cancel a subscription with a past due balance you will have to do this for them through the subscription page in the FoxyCart admin, or clear their past due amount by editing their subscription.