Skip to content

fix: Fix Paypal subscription form data attachment bug by improving handshaking...

fix: Fix Paypal subscription form data attachment bug by improving handshaking between donation form data and webhook messages

During donate-neo-to-civicrm data handoff testing, it became clear that, while new recurring donations using Paypal were able to be made on staging, and that donation would be logged in CiviCRM, the donation form data was not being properly attached to the for-CiviCRM Resque message, even though it was being collected.

This is due to the changes made in !108 (merged) - we attempted to ensure that, of vars being passed to CiviCRM via Resque, trxn_id always referred to a transaction's unique ID, and recurring_contribution_transaction_id always referred to a recurring donation's subscription ID.

While that MR was made successfully, it made the assumption that all donations had unique IDs available for use at two points in time - once as the server was handing its completed donation object off to the vendor JS library for processing, and again as the server's webhook handler processes the message indicating the success of that donation. In the first of those cases, we use the ID as a key to temporarily store stringified form data in Redis as a key-value pair. In the second of those cases, we getdel that data, using that same ID from the webhook to recreate the Redis entry's key.

It is usually possible to use trxn_id for this purpose, and historically we have done so. However, it is not actually available in the moment where we hand off form data to CiviCRM - the one value which can be used for this purpose is the subscription ID.

So: Until !108 (merged), when processing Paypal subscriptions, we simply set trxn_id to the value of that subscription ID, but that meant that multiple CiviCRM donations would receive the same ID, which causes downstream problems. With !108 (merged), we fixed those downstream problems by setting trxn_id to a unique per-donation value, but that broke webhook message handshaking.

==========

That brings us to now, and to this commit, which provides a solution to these myriad inconsistencies brought about by Paypal's API: args["handshake_id"].

When we now process an incoming webhook message, and as we compile the object args, adding values to it which will be useful to CiviCRM, we now add one purely for ourselves: args["handshake_id"]. It is usually set to the same value as args["trxn_id"], but when we're processing the webhook message for successful Paypal subscription billing, it contains the same value as args["recurring_contribution_transaction_id"].

Adding a value to this object with a custom value in this way means that we solve several problems at once:

  • We have a variable dedicated to this specific purpose, rather than overloading the function of another variable
  • We don't complicate any existing methods - aside from the handful of places we set args["handshake_id"], the only other change across the entire codebase is that civi.report_donation() now calls civi.retrieve_donation() with the contextually-sensible handshake_id instead of trxn_id
  • Most importantly - we ensure CiviCRM properly receives user form data when processing Paypal subscription initial payments.

Merge request reports