2019-12-01 07:38:54 -08:00
import {
IHookFunctions ,
IWebhookFunctions ,
2020-10-01 05:01:39 -07:00
} from 'n8n-core' ;
2019-12-01 07:38:54 -08:00
2020-10-01 05:01:39 -07:00
import {
2019-12-01 07:38:54 -08:00
IDataObject ,
ILoadOptionsFunctions ,
INodePropertyOptions ,
2020-10-01 05:01:39 -07:00
INodeType ,
INodeTypeDescription ,
IWebhookResponseData ,
2021-04-16 09:33:36 -07:00
NodeApiError ,
NodeOperationError ,
2020-10-01 05:01:39 -07:00
} from 'n8n-workflow' ;
import {
2019-12-01 11:19:38 -08:00
payPalApiRequest ,
2019-12-01 07:38:54 -08:00
upperFist
2020-10-01 05:01:39 -07:00
} from './GenericFunctions' ;
2019-12-01 07:38:54 -08:00
2020-10-01 05:01:39 -07:00
export class PayPalTrigger implements INodeType {
2019-12-01 07:38:54 -08:00
description : INodeTypeDescription = {
2020-10-01 05:01:39 -07:00
displayName : 'PayPal Trigger' ,
name : 'payPalTrigger' ,
2021-03-25 09:10:02 -07:00
icon : 'file:paypal.svg' ,
2020-10-01 05:01:39 -07:00
group : [ 'trigger' ] ,
version : 1 ,
description : 'Handle PayPal events via webhooks' ,
defaults : {
name : 'PayPal Trigger' ,
2019-12-01 07:38:54 -08:00
} ,
2020-10-01 05:01:39 -07:00
inputs : [ ] ,
outputs : [ 'main' ] ,
credentials : [
{
name : 'payPalApi' ,
required : true ,
2020-10-22 06:46:03 -07:00
} ,
2020-10-01 05:01:39 -07:00
] ,
webhooks : [
{
name : 'default' ,
httpMethod : 'POST' ,
reponseMode : 'onReceived' ,
path : 'webhook' ,
2019-12-01 07:38:54 -08:00
} ,
2020-10-01 05:01:39 -07:00
] ,
properties : [
{
2022-06-20 07:54:01 -07:00
displayName : 'Event Names or IDs' ,
2020-10-01 05:01:39 -07:00
name : 'events' ,
type : 'multiOptions' ,
required : true ,
default : [ ] ,
2022-07-14 13:05:11 -07:00
description : 'The event to listen to. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.' ,
2020-10-01 05:01:39 -07:00
typeOptions : {
2020-10-22 06:46:03 -07:00
loadOptionsMethod : 'getEvents' ,
2020-10-01 05:01:39 -07:00
} ,
options : [ ] ,
} ,
] ,
2019-12-01 07:38:54 -08:00
} ;
methods = {
loadOptions : {
// Get all the events types to display them to user so that he can
// select them easily
async getEvents ( this : ILoadOptionsFunctions ) : Promise < INodePropertyOptions [ ] > {
2019-12-01 11:19:38 -08:00
const returnData : INodePropertyOptions [ ] = [
{
name : '*' ,
value : '*' ,
2022-05-06 14:01:25 -07:00
description : 'Any time any event is triggered (Wildcard Event)' ,
2020-10-22 06:46:03 -07:00
} ,
2019-12-01 11:19:38 -08:00
] ;
2019-12-01 07:38:54 -08:00
let events ;
try {
const endpoint = '/notifications/webhooks-event-types' ;
2019-12-01 11:19:38 -08:00
events = await payPalApiRequest . call ( this , endpoint , 'GET' ) ;
2021-04-16 09:33:36 -07:00
} catch ( error ) {
throw new NodeApiError ( this . getNode ( ) , error ) ;
2019-12-01 07:38:54 -08:00
}
for ( const event of events . event_types ) {
const eventName = upperFist ( event . name ) ;
const eventId = event . name ;
const eventDescription = event . description ;
returnData . push ( {
name : eventName ,
value : eventId ,
description : eventDescription ,
} ) ;
}
return returnData ;
} ,
} ,
} ;
2019-12-01 11:19:38 -08:00
2019-12-01 07:38:54 -08:00
// @ts-ignore (because of request)
webhookMethods = {
default : {
async checkExists ( this : IHookFunctions ) : Promise < boolean > {
const webhookData = this . getWorkflowStaticData ( 'node' ) ;
if ( webhookData . webhookId === undefined ) {
// No webhook id is set so no webhook can exist
return false ;
}
const endpoint = ` /notifications/webhooks/ ${ webhookData . webhookId } ` ;
try {
2019-12-01 11:19:38 -08:00
await payPalApiRequest . call ( this , endpoint , 'GET' ) ;
2021-04-16 09:33:36 -07:00
} catch ( error ) {
if ( error . response && error . response . name === 'INVALID_RESOURCE_ID' ) {
2019-12-01 07:38:54 -08:00
// Webhook does not exist
delete webhookData . webhookId ;
return false ;
}
2021-04-16 09:33:36 -07:00
throw new NodeApiError ( this . getNode ( ) , error ) ;
2019-12-01 07:38:54 -08:00
}
return true ;
} ,
async create ( this : IHookFunctions ) : Promise < boolean > {
let webhook ;
const webhookUrl = this . getNodeWebhookUrl ( 'default' ) ;
const events = this . getNodeParameter ( 'events' , [ ] ) as string [ ] ;
const body = {
url : webhookUrl ,
event_types : events.map ( event = > {
return { name : event } ;
2020-10-01 05:01:39 -07:00
} ) ,
2019-12-01 07:38:54 -08:00
} ;
const endpoint = '/notifications/webhooks' ;
try {
2019-12-01 11:19:38 -08:00
webhook = await payPalApiRequest . call ( this , endpoint , 'POST' , body ) ;
2021-04-16 09:33:36 -07:00
} catch ( error ) {
throw error ;
2019-12-01 07:38:54 -08:00
}
if ( webhook . id === undefined ) {
return false ;
}
const webhookData = this . getWorkflowStaticData ( 'node' ) ;
webhookData . webhookId = webhook . id as string ;
return true ;
} ,
async delete ( this : IHookFunctions ) : Promise < boolean > {
const webhookData = this . getWorkflowStaticData ( 'node' ) ;
if ( webhookData . webhookId !== undefined ) {
const endpoint = ` /notifications/webhooks/ ${ webhookData . webhookId } ` ;
try {
2019-12-01 11:19:38 -08:00
await payPalApiRequest . call ( this , endpoint , 'DELETE' , { } ) ;
2021-04-16 09:33:36 -07:00
} catch ( error ) {
2019-12-01 07:38:54 -08:00
return false ;
}
delete webhookData . webhookId ;
}
return true ;
} ,
} ,
2020-10-01 05:01:39 -07:00
} ;
2019-12-01 07:38:54 -08:00
async webhook ( this : IWebhookFunctions ) : Promise < IWebhookResponseData > {
let webhook ;
const webhookData = this . getWorkflowStaticData ( 'node' ) as IDataObject ;
const bodyData = this . getBodyData ( ) as IDataObject ;
const req = this . getRequestObject ( ) ;
const headerData = this . getHeaderData ( ) as IDataObject ;
const endpoint = '/notifications/verify-webhook-signature' ;
if ( headerData [ 'PAYPAL-AUTH-ALGO' ] !== undefined
2020-10-01 05:01:39 -07:00
&& headerData [ 'PAYPAL-CERT-URL' ] !== undefined
&& headerData [ 'PAYPAL-TRANSMISSION-ID' ] !== undefined
&& headerData [ 'PAYPAL-TRANSMISSION-SIG' ] !== undefined
&& headerData [ 'PAYPAL-TRANSMISSION-TIME' ] !== undefined ) {
2019-12-01 07:38:54 -08:00
const body = {
auth_algo : headerData [ 'PAYPAL-AUTH-ALGO' ] ,
cert_url : headerData [ 'PAYPAL-CERT-URL' ] ,
transmission_id : headerData [ 'PAYPAL-TRANSMISSION-ID' ] ,
transmission_sig : headerData [ 'PAYPAL-TRANSMISSION-SIG' ] ,
transmission_time : headerData [ 'PAYPAL-TRANSMISSION-TIME' ] ,
webhook_id : webhookData.webhookId ,
webhook_event : bodyData ,
} ;
try {
2019-12-01 11:19:38 -08:00
webhook = await payPalApiRequest . call ( this , endpoint , 'POST' , body ) ;
2021-04-16 09:33:36 -07:00
} catch ( error ) {
throw error ;
2019-12-01 07:38:54 -08:00
}
if ( webhook . verification_status !== 'SUCCESS' ) {
return { } ;
}
} else {
return { } ;
}
return {
workflowData : [
2020-10-22 06:46:03 -07:00
this . helpers . returnJsonArray ( req . body ) ,
2019-12-01 07:38:54 -08:00
] ,
} ;
}
2020-10-01 05:01:39 -07:00
}