123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- /* Copyright 2015-2016 PayPal, Inc. */
- "use strict";
- var generate = require('../generate');
- var api = require('../api');
- var https = require('https');
- var crypto = require('crypto');
- var crc32 = require('buffer-crc32');
- /**
- * Exposes REST endpoints for creating and managing webhooks
- * @return {Object} webhook functions
- */
- function webhook() {
- var baseURL = '/v1/notifications/webhooks/';
- var operations = ['create', 'list', 'get', 'del', 'delete'];
- var ret = {
- baseURL: baseURL,
- replace: function replace(id, data, config, cb) {
- api.executeHttp('PATCH', this.baseURL + id, data, config, cb);
- },
- eventTypes: function eventTypes(id, config, cb) {
- api.executeHttp('GET', this.baseURL + id + '/event-types', {}, config, cb);
- }
- };
- ret = generate.mixin(ret, operations);
- return ret;
- }
- /**
- * Exposes REST endpoints for working with subscribed webhooks events
- *
- * https://developer.paypal.com/webapps/developer/docs/integration/direct/rest-webhooks-overview/#events
- * @return {Object} webhook event functions
- */
- function webhookEvent() {
- var baseURL = '/v1/notifications/webhooks-events/';
- var operations = ['list', 'get'];
- /**
- * Instead of calling this method, it is recommended that you initiate a GET request in your code for the webhook
- * event data and use the returned information from the webhook or use the updated verify() function. See
- * https://github.com/paypal/PayPal-node-SDK/wiki/Webhook-Validation
- *
- * @example
- * var paypal = require('paypal-rest-sdk');
- * function(request, response) {
- * try {
- * // Get the Webhook event id from the incoming event request
- * var webhookEventId = JSON.parse(request.body).id;
- *
- * paypal.notification.webhookEvent.get(webhookEventId, function (error, webhookEvent) {
- * if (error) {
- * console.log(error);
- * // The webhook event data could not be found.
- * // Send a HTTP 503 response status code ( http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4 )
- * // to signal to PayPal to resend the request at a later time.
- * response.sendStatus(503);
- * } else {
- * // Proceed to use the data from PayPal
- * console.log("Get webhookEvent Response");
- * console.log(JSON.stringify(webhookEvent));
- * response.sendStatus(200);
- * }
- * });
- * } catch (e) {
- * // The webhook id could not be found or any other error occurred.
- * // Send a HTTP 503 response status code ( http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4 )
- * // to signal to PayPal to resend the request at a later time
- * response.sendStatus(503);
- * }
- * }
- *
- * @deprecated
- * @param {String} body raw body of request
- * @param {Function} cb callback function
- */
- function getAndVerify(body, cb) {
- var response = false;
- var err = null;
- try {
- var webhookEventId = JSON.parse(body).id;
- api.executeHttp('GET', baseURL + webhookEventId, {}, function (error, res) {
- if (error) {
- cb(error, response);
- } else {
- cb(err, true);
- }
- });
- } catch (e) {
- err = new Error("Webhook Event Id attribute not found. Possible reason could be invalid JSON Object.");
- cb(err, response);
- }
- }
- /**
- * @param {Object} headers from request
- * @param {String} raw body of request
- * @param {String} webhook id
- * @param {Function} callback function
- */
- function verify(headers, body, webhookId, callback) {
- // In an effort not to break existing applications, accept old arguments temporarily
- if (arguments.length > 4) {
- /* jshint validthis: true */
- return verifyLegacy.apply(this, arguments);
- }
- if (typeof headers !== 'object') {
- return callback(new Error("headers is not an object"), false);
- }
- // Normalizes headers
- Object.keys(headers).forEach(function (header) {
- headers[header.toUpperCase()] = headers[header];
- });
- var webhookEventBody = (typeof body === "string") ? JSON.parse(body) : body;
- var payload = {
- 'auth_algo': headers['PAYPAL-AUTH-ALGO'],
- 'cert_url': headers['PAYPAL-CERT-URL'],
- 'transmission_id': headers['PAYPAL-TRANSMISSION-ID'],
- 'transmission_sig': headers['PAYPAL-TRANSMISSION-SIG'],
- 'transmission_time': headers['PAYPAL-TRANSMISSION-TIME'],
- 'webhook_id': webhookId,
- 'webhook_event': webhookEventBody
- };
- api.executeHttp('POST', '/v1/notifications/verify-webhook-signature', payload, callback);
- }
- function verifyLegacy(certURL, transmissionId, timeStamp, webhookId, eventBody, ppTransmissionSig, cb) {
- // Emit a warning that the arguments have changed
- if (process.env.NODE_ENV === 'development') {
- console.log('PayPal-Node-SDK: Webhook verify arguments have changed. Please check the latest documentation on https://developer.paypal.com/docs/integration/direct/rest-webhooks-overview/#event-signature.');
- }
- var headers = {
- // This is currently the default auth algorithm. If this changes, need to change. Legacy method did
- // not pass in the algorithm.
- 'PAYPAL-AUTH-ALGO': 'SHA256withRSA',
- 'PAYPAL-CERT-URL': certURL,
- 'PAYPAL-TRANSMISSION-ID': transmissionId,
- 'PAYPAL-TRANSMISSION-SIG': ppTransmissionSig,
- 'PAYPAL-TRANSMISSION-TIME': timeStamp
- };
- function legacyCallback(error, response) {
- if (error) {
- cb(error, false);
- } else {
- // Verification status must be SUCCESS
- if (response.verification_status === "SUCCESS") {
- cb(null, true);
- } else {
- cb(null, false);
- }
- }
- }
- return verify(headers, eventBody, webhookId, legacyCallback);
- }
- var ret = {
- baseURL: baseURL,
- verify: verify,
- getAndVerify: getAndVerify,
- resend: function resend(id, config, cb) {
- api.executeHttp('POST', this.baseURL + id + '/resend', {}, config, cb);
- }
- };
- ret = generate.mixin(ret, operations);
- return ret;
- }
- /**
- * Exposes REST endpoint for listing available event types for webhooks
- * @return {Object} webhook event type functions
- */
- function webhookEventType() {
- var baseURL = '/v1/notifications/webhooks-event-types/';
- var operations = ['list'];
- var ret = {
- baseURL: baseURL
- };
- ret = generate.mixin(ret, operations);
- return ret;
- }
- /**
- * Exposes the namespace for webhook and webhook event functionalities
- *
- * https://developer.paypal.com/webapps/developer/docs/api/#notifications
- * @return {Object} notification functions
- */
- function notification() {
- return {
- webhook: webhook(),
- webhookEvent: webhookEvent(),
- webhookEventType: webhookEventType()
- };
- }
- module.exports = notification;
|