Bijan
Bijan

Reputation: 8682

PayPal Buttons and Webhook integration

I have a Paypal Button setup with the following code:

  paypal.Buttons({
      createSubscription: function(data, actions) {
        return actions.subscription.create({
          'plan_id': 'P-PLANID'
        });
      },
      onApprove: function(data, actions) {
        // Somehow pass info to Webhook
      }
  }).render('#paypal-button-container');

Is there a way to have this integrate with a webhook I have setup with BILLING.SUBSCRIPTION.ACTIVATED?

I just created the webhook but I am not sure how I connect my PayPal Buttons to it

Upvotes: 2

Views: 813

Answers (2)

Dustin Spengler
Dustin Spengler

Reputation: 7781

My example isn't exactly a webhook per-se, but it works great for me. I put a call to a Firebase Cloud Function call in the onApprove function like this:

paypal.Buttons({
  createSubscription: function(data, actions) {
    return actions.subscription.create({
      'plan_id': 'P-PLANID'
    });
  },
  onApprove: function(data, actions) {
    const orderID = data.orderID;
    let url = "myCloudFunction?orderID="+orderID;
    //this will verify the purchase and complete order on back end
    fetch(url);
    //carry on with user experince
  }
}).render('#paypal-button-container');

And then verify the purchase using the orderID in my cloud function, and update my DB or whatever else i need to do like so:

const checkoutNodeJssdk = require('@paypal/checkout-server-sdk');
const functions = require("firebase-functions");

function environment() {
   let clientId = process.env.PAYPAL_CLIENT_ID || 'yourClientID';
   let clientSecret = process.env.PAYPAL_CLIENT_SECRET || 'yourClientSecret';
   return new checkoutNodeJssdk.core.LiveEnvironment(
       clientId, clientSecret
   );
}

function payPalClient() {
   return new checkoutNodeJssdk.core.PayPalHttpClient(environment());
}

exports.completeOrder = functions.https.onRequest((req, res) => {
   const orderID = req.query.orderID;
   let request = new checkoutNodeJssdk.orders.OrdersGetRequest(orderID);
   let order;
   try {
       order = await payPalClient().execute(request);
       console.log(order);
   } catch (err) {
       console.error(err);
       res.send({response: "failed"});
   }

   if (order.result.status === 'APPROVED') {
       //update DB or whatever else needs to happen to complete order
       res.send({response: "success"});
   } else {
       res.send({response: "failed"});
   }
});

You can also verify the subscription is active by passing a subscriptionID from the data object returned in the onApprove function of the button to the cloud function. Use the following to verify the subscription:

async function verifySubscription(subscriptionID, callback) {   
   const authUrl = "https://api-m.paypal.com/v1/oauth2/token";
   const subscriptionsUrl = "https://api.paypal.com/v1/billing/subscriptions/" + subscriptionID;
   const clientIdAndSecret = "myClientID:myCLientSecret";
   const base64 = Buffer.from(clientIdAndSecret).toString('base64')
   fetch(authUrl, { 
       method: 'POST',
       headers: {
           'Content-Type': 'application/json',
           'Accept': 'application/json',
           'Accept-Language': 'en_US',
           'Authorization': `Basic ${base64}`,
       },
       body: 'grant_type=client_credentials'
   }).then(function(response) {
       return response.json();
   }).then(function(data) {
       fetch(subscriptionsUrl, { 
           method: 'get', 
           headers: {
             'Authorization': 'Bearer '+data.access_token, 
             'Content-Type': 'application/json'
           }, 
       }).then(function(response) {
           return response.json();
       }).then(function(subscriptionData) {
           console.log("subscriptionData.status: ", subscriptionData.status);
           if (subscriptionData.status === "ACTIVE") {
               callback(true);
           } else {
               callback(false);
           }
       }).catch(function(error) {
           console.log("couldnt verify subscription");
           console.log(error);
           callback(false);
       });
   }).catch(function() {
       console.log("couldnt get auth token");
       callback(false);
   });
}

Upvotes: 0

Preston PHX
Preston PHX

Reputation: 30477

You need to subscribe to webhook events using the same app/client-id as you are using for the buttons. You can subscribe manually in the Developer Dashboard, or via an API call. Here is the documentation.


This comment in your code does not make sense:

// Somehow pass info to Webhook

Subscribing to webhook event notifications is a one-time, initial setup that you do somewhere else. It is not something you do from the buttons, and it will not call nor interact with the buttons in any way; webhooks are sent and processed later, asynchronously.

If you want to store some information as part of the subscription for later reconciliation (with the user who subscribed, for example, so your backend knows what to do when it receives a webhook) -- then you can set a custom_id as part of the subscription creation.

Upvotes: 0

Related Questions