Managing PayPal IPN calls via a Workflow (node + custom extension + testing via ngrok)

This is pretty easy using a simple custom extension.

The PayPal IPN call is a fairly simple feature to install as the call itself does all the hard work. The listened needs no input and has no specific outputs; the call simple causes POST variables to be populated.

First we add a PayPal IPN npm module by going to Terminal and typing

npm install paypal-ipn

If using docker do a local deploy to ensure the extension is in the docker container

Now we create the .js in a file in the /extensions/server_connect/modules folder

I called this ipn.js

const ipn = require('paypal-ipn');

module.exports = {
    ipn: function (params) {
                ipn.verify(params, function callback(err, msg) {
            if (err) {
                console.error(err);
            } else {
                
                if (params.payment_status == 'Completed') {   
                    return true
                }
                else {
                    return false
                }
            }
        });
    }
}

and we add the hjson to manage the extension within Workflows, i call ipn.hjson

 {
    type: 'ipn',
    module : 'ipn'
       action : 'ipn',
    groupTitle : 'PayPal Extensions',
   groupIcon : 'fas fa-lg fa-table comp-data',
    title : 'IPN Handler',
    icon : 'fas fa-lg fa-table comp-data ',
    dataPickObject: true,
  }

Now create an API action, i will call it “ipn” and add the module

The module will cause POST variables to be populated so we must create them.
The IPN documentation details the data which can be captured.

For simplicity, i simply capture the first and last names

image

I create a table with corresponding fields

image

Add a simple database insert

Thats it, now for testing

The PayPal IPN simulator cannot talk to localhost so we activate ngrok proxy

The url for the API action can be found simply by viewing it in your browser

image

In this case the URL will look something like this :

https://6dff-2a00-23c6-9f08-5d01-acc1-5f6d-89b9-6a7.eu.ngrok.io/api/ipn

i go to the PayPal IPN simulator page

https://developer.paypal.com/developer/ipnSimulator
and enter the URL

and press the “Send IPN” button
image
The IPN action shoudl be verified


Checking your database table should show the data added

This simple tutorial does not deal with validation. Don’t forget the IPN call returns the payment status returned by the IPN for appropriate processing and this should be checked appropriately

image

There are a few tweaks i will make when i get time regarding further validation of the IPN receipt which I will post when complete

3 Likes

Your HJSON looks surprisingly simple :face_with_monocle:

Looking forward your next tutorial, to see if the HJSON becomes more complicated :grimacing:

This series of topics will serve as inspiration for other IPN modules

1 Like

Yes, it’s simple as there are no inputs or outputs, its effectively just a simple function call. Actually even the last line (datapicker) of the HJSON is not needed, that is left over from development

What about the returned boolean or error?

Yes, I did consider that and it could be done but i decided it served little value.
The script is called from PayPal
If the callback handshake fails then the POST variables will be blank so that can be detected.
There is no equivalent that I am aware of to signal to PayPal to stop sending so they will continue to send the IPN call intermittently for about 3 days looking for a confirmation, that’s what it does !
So ,we could capture the “return true” to know that the handshake has failed but I have no ideas as to how that could be used subsequently except perhaps an admin message to alert to the failure. Either way PayPal will continue to send

Oh, so it mutates the originally passed params… Interesting… :thinking:

Even though I won’t personally use this approach as a base for other IPN modules, I appreciate sharing it!

Kind of happened by accident, was actually looking for a new PHP IPN solution for a customer rather than a coded solution (always worried an error may expose the DB login details) and the node version sort of just happened as an aside when i spotted the paypal-ipn npm module.
I do not claim to be an expert in custom formatters/ modules but I enjoy the challenge and like to share

1 Like

Seems straight forward - integrate new billing for a small 5 item site is this weekends work plan. Haven’t dealt with Stripe and feel it might be over kill.