This is an edge case to do with cancellations close to the time the first payment completes; such that the first payment actually completes after the cancellation(!)
supporter creates mandate.
GoCardless creates a payment
supporter (or admin via GoCardless website) cancels mandate
GoCardless successfully takes payment
This results in:
One Failed Contribution record
An "In Progress" Contribution Recur record.
But it should result in:
one Completed Contribution
a Cancelled Contribution Recur record.
Why it fails
When a mandate cancelled webhook is processed, the contrib. recur record is cancelled and so is any pending contribution.
When a payment confirmed webhhok is processed, it:
finds the recur record and updates it to In Progress.
looks for a pending contribution (there wasn't one because it was marked Cancelled)
looks for the first (by date) completed contribution (there wasn't one) to set as the original_contribution_id field.
calls repeat transaction API, but this will throw an exception if there isn't an original contribution. (nb if we don't provide original contribution id then the repeattransaction API looks up the last one by ID that is completed - this would result in the same thing)
solution A
Assumption: GoCardless will not create a payment if the mandate is cancelled.
Implement the payment created webhook - this would have to find the pending contrib, set its trxn_id.
Change the processing of payment confirmed webhook to look up the contribution by the trxn_id - whether that payment is Cancelled or Pending.
Only update Contrib Recur to In Progress if it is not already that, and then before making the change do a GC API lookup to check it's not been cancelled.
solution B
Change processing of the mandate cancelled webhook so that it does not cancel the pending contribution record. This would mean that the recur record showed cancelled while the payment remained pending. Presumably then GC would either send a payment confirmed event, or a payment cancelled/failed - which should both be fine.
As with solution A, it needs: Only update Contrib Recur to In Progress if it is not already that, and then before making the change do a GC API lookup to check it's not been cancelled.
I think solution B is better on the grounds that it is simpler.
This is an edge case to do with cancellations close to the time the first payment completes; such that the first payment actually completes after the cancellation(!)
This results in:
But it should result in:
Why it fails
When a mandate cancelled webhook is processed, the contrib. recur record is cancelled and so is any pending contribution.
When a payment confirmed webhhok is processed, it:
original_contribution_id
field.solution A
Assumption: GoCardless will not create a payment if the mandate is cancelled.
Implement the payment created webhook - this would have to find the pending contrib, set its
trxn_id
.Change the processing of payment confirmed webhook to look up the contribution by the
trxn_id
- whether that payment is Cancelled or Pending.Only update Contrib Recur to In Progress if it is not already that, and then before making the change do a GC API lookup to check it's not been cancelled.
solution B
Change processing of the mandate cancelled webhook so that it does not cancel the pending contribution record. This would mean that the recur record showed cancelled while the payment remained pending. Presumably then GC would either send a payment confirmed event, or a payment cancelled/failed - which should both be fine.
As with solution A, it needs: Only update Contrib Recur to In Progress if it is not already that, and then before making the change do a GC API lookup to check it's not been cancelled.
I think solution B is better on the grounds that it is simpler.