You are browsing a read-only backup copy of Wikitech. The primary site can be found at

Fundraising/Data and flow/Recurring

From Wikitech-static
Jump to navigation Jump to search


Recurring donations are supported via PayPal (both legacy and Express Checkout integrations), via Ingenico (Connect ), and via Adyen.

In CiviCRM, recurring donations are stored in the civicrm_contribution_recur table and each installment has an entry in civicrm_contribution with a value in the contribution_recur_id pointing to the civicrm_contribution_recur row. We store them slightly idiosyncratically - while core CiviCRM's payment processors interpret the 'Completed' status to mean that there are no more installments expected, we use 'Completed' to mean that the subscription is in a good state.


At Payments-wiki, we interpret any truthy value sent for the query string parameter 'recurring' to mean we should set up a recurring payment for the donor.


PayPal recurring donations are all driven by PayPal - that is, we indicate that we want to set up a monthly donation for a specific amount, and PayPal takes care of the scheduling, charging, and retry attempts on failed charges. For PayPal Express Checkout, we use the MAXFAILEDPAYMENTS parameter to instruct PayPal to stop trying to charge the donor after N failed attempts. Express Checkout subscriptions set up prior to October 15th, 2019 had this value set to 3, and after that date have the value set to 0, meaning to retry indefinitely. On failure, PayPal retries every 5 days. PayPal's documentation


Ingenico recurring donations are driven by us - after setting up a recurring donation, Ingenico gives us something to store and refer to in future donation attempts. We schedule the donations and make API calls to charge them once each month. Our hourly scheduled jobs check the civicrm_contribution_recur table for rows where the next_sched_contribution_date is now or before, and charge a batch of them.

Ingenico recurring donations (coded as gateway=ingenico) are tokenized. That is, we receive a payment token at the time of the setup and store it in the civicrm_payment_token table. The code to charge each monthly installment is in the CiviCRM extension org.wikimedia.smashpig, which uses the SmashPig library to interface with the Connect API. The scheduled job is configured in recurring_smashpig_charge.yaml, which runs drush cvapi job.process_smashpig_recurring.


Monthly Convert

Recurring queue

Smashpig civi extension

Failures and retry logic

If we get a failure charging a recurring contribution, we set the contribution_recur status to 'Failed', increment the failure_count column, and set a failure_retry_date. The maximum number of failures and the retry interval is configurable. For Ingenico Connect, settings are in the Civi top menu under Administer->System Settings->SmashPig Settings. For WebCollect, see the 'Recurring GlobalCollect Processor' link in the left-hand menu. Both are currently set to retry failed payments 1 day later, and to stop retrying after 3 failures.


column description
(auto) maximum failures reached cancelled automatically after three retries
(auto) un-retryable card decline reason cancelled automatically when the processor returns a decline reason that is not retryable (fraud, lost card)
(auto) Expiration notification PayPal only, we were sent a message from PayPal that the recuring is expired
(auto) User Cancelled via Gateway PayPal only, we were sent a message from PayPal that the donor cancelled their recurring
(auto) backfilled automated cancel
(auto) backfilled automated Expiration notification