skip to Main Content

After a PayPal order is complete, it sends a webhook to a google script URL. Before information is sent, it has to validate the signature. Down below is a link to a Java example.

https://developer.paypal.com/docs/api-basics/notifications/webhooks/notification-messages/#

How to validate a PayPal webhook signature for Google Script?

I’ve looked through the google-apps-script and PayPal tags for a solution, but it only provides IPN solutions. From my understanding that’s an older method. Perhaps that’s the only way. I don’t know. I’m new to API handling, so I may be wording the problem incorrectly.

EDIT: Did some more digging and was able to receive and process a paypal webhook.

function doPost(e) {
    var params = JSON.stringify(e.postData.contents);
    params = JSON.parse(params);
    var myData = JSON.parse(e.postData.contents);

    SpreadsheetApp.flush();
    return HtmlService.createHtmlOutput("post request received");
}

The next problem is setting up the PayPal Smart button to send the correct webhook. The correct webhook event would be "Checkout order completed" (tested via PayPal’s Webhooks simulator). This webhook contains the order information. The examples over at PayPal Smart Button Demo calls onAuthorize as a webhook. This webhook does not contain the information I want. I’ll make a separate post about this.

onAuthorize: function(data, actions) {
        return actions.payment.execute().then(function() {
            window.alert('Payment Complete!');
        });
    }

So I guess no validation is required for webhooks, maybe.

2

Answers


  1. Chosen as BEST ANSWER

    After a lot of trial and error, I got a semi-working system.

    function doPost(e) {
        SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Debug').getRange('A1').setValue("Recieved doPostCommand");
    
        var myData = JSON.parse(e.postData.contents);
    
        try {
            if (myData.event_type == 'PAYMENTS.PAYMENT.CREATED') {
                var email = myData.resource.payer.payer_info.email
                var name = myData.resource.payer.payer_info.first_name + " " + myData.resource.payer.payer_info.last_name
                var payID = myData.resource.id
      
                SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Debug').getRange('A3').setValue(email);
                SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Debug').getRange('A4').setValue(name);
                SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Debug').getRange('A5').setValue(payID);
            } else if (myData.event_type == 'PAYMENT.SALE.COMPLETED'){
                var payID = myData.resource.parent_payment
    
                SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Debug').getRange('A7').setValue(payID);
            } 
        } catch (e) {
            SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Debug').getRange('E1').setValue("Error: " + e);
        }
    
      SpreadsheetApp.flush();
      return HtmlService.createHtmlOutput("post request received");
    }
    

    I found the webhooks to work some of the time. Sometimes they failed while other times they are received. When they are received, the webhooks don't necessarily arrive in a specific order.

    So to confirm a payment complete, append the customer details (including PayPal ID) to a "customer" sheet. To a separate "confirmed payment id" sheet, append the PayPal IDs. From there, add a listener to when a PAYMENTS.PAYMENT.CREATED or a PAYMENT.SALE.COMPLETED webhook is received, check if there are matching PayPal IDs. The "confirmed payment id" sheet will act as a buffer. From there set the payment completed column to true for the correct customer and delete the PayPal ID from the buffer sheet.

    That's how I would do it, but webhooks seem to be trash atm. I'll have to resort to some eCommerce service. I hope someone finds this useful. Cheers


  2. IPN is a much older solution that is separate to webhooks.

    Regarding webhook verification, you linked to a page for DIY verification, where you calculate whether the signature matches. The example is in Java, but can conceivably be adapted to any language (with some considerable work)

    The alternative way to verify a webhook is via the webhooks API, posting the message back using this API call: https://developer.paypal.com/docs/api/webhooks/v1/#verify-webhook-signature

    Avoid using the PayPal-*-SDKs, since that documentation was written before those SDKs were deprecated

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search