Help with paddle webhook authentication

In Node.js I have setup the required webhooks to update account details within a remote db.
However I am stuck on implementing the described authenication process.

    • I have created the array with the value {{$_POST}}, but dont know how to remove the last array value from the array.
    • I have used $_POST.sort in the server data binding. Is this correct?
    • Not got there yet so don’t know if that’s straight forward…

Any help would be realy appreciated :slight_smile:

After trying and failing to create/manipulate arrays server side I have decided on a different approach.
Can anyone tell me if this could work?

-A webhook comes in from paddle
-I save the POST values to the db
-I run a query with all the post values but exclude the signature

How do I use the query results as an array, sort it, as 5 above, serialise and sign it as 6 above?


From the looks of it, you need custom module to do the verification stuff.
The custom module would easily take care of sorting & removing signature & then doing an SHA1 to generate new signature.

Ok Sid thankyou

Never used or created a custom module so again I dont know where to start…any advice?

Just read Patricks post PREVIEW: Writing Custom Modules and Formatters (NodeJS) See if I can get my head round that…

That link is the seconds doc you should refer. Here’s the frist one: PREVIEW: Wappler Extensibility - Writing Custom Modules and Formatters for Server Connect

Apart from this, we have created a few free custom formatters & one paid. You can find those posts in community.

Ok looked at the tutorial and examples but still not able to work out how to do this.
I have found the node.js code for the authentication process.

// Node.js & Express implementation
const crypto = require('crypto');
const Serialize = require('php-serialize');
const express = require( 'express' );
const bodyParser = require("body-parser");
const app = express();

// Parses urlencoded webhooks from paddle to JSON with keys sorted alphabetically ascending and values as strings
app.use(bodyParser.urlencoded({ extended: true }));

// Webhook request handling"/", (req, res) => {
  if (validateWebhook(req.body)) {
  } else {

app.listen( 8080, () => console.log( 'Node.js server started on port 8080.' ) );

// Public key from your paddle dashboard
const pubKey = `-----BEGIN PUBLIC KEY-----

-----END PUBLIC KEY-----`

function ksort(obj){
    const keys = Object.keys(obj).sort();
    let sortedObj = {};
    for (let i in keys) {
      sortedObj[keys[i]] = obj[keys[i]];
    return sortedObj;

function validateWebhook(jsonObj) {
    // Grab p_signature
    const mySig = Buffer.from(jsonObj.p_signature, 'base64');
    // Remove p_signature from object - not included in array of fields used in verification.
    delete jsonObj.p_signature;
    // Need to sort array by key in ascending order
    jsonObj = ksort(jsonObj);
    for (let property in jsonObj) {
        if (jsonObj.hasOwnProperty(property) && (typeof jsonObj[property]) !== "string") {
            if (Array.isArray(jsonObj[property])) { // is it an array
                jsonObj[property] = jsonObj[property].toString();
            } else { //if its not an array and not a string, then it is a JSON obj
                jsonObj[property] = JSON.stringify(jsonObj[property]);
    // Serialise remaining fields of jsonObj
    const serialized = Serialize.serialize(jsonObj);
    // verify the serialized array against the signature using SHA1 with your public key.
    const verifier = crypto.createVerify('sha1');

    const verification = verifier.verify(pubKey, mySig);
    // Used in response if statement
    return verification;

How would I convert this into a module?
I have created a webhook api which would get the returned verification value before updating the database.

Simplistic instructions with visual guidance would be so helpful at this stage :slight_smile:

Sorry, but can’t help you here.

I myself just tinkered around with the articles I sent to you… and other extensions in the community to figure out how all of this works. Hope someone else can help you better.

1 Like

Thanks Sid for answering hopefully somone else can give some guidance.

I always knew this going to be tricky so It this last bit in my first Wappler project before it’s completed… :slight_smile: