payout resource done

This commit is contained in:
Ricardo Espinoza 2019-11-26 11:59:27 -05:00
parent 08c95f989c
commit eaa33e0a8d
4 changed files with 150 additions and 57 deletions

View file

@ -14,49 +14,18 @@ import {
export async function paypalApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, endpoint: string, method: string, body: any = {}, query?: IDataObject, uri?: string): Promise<any> { // tslint:disable-line:no-any export async function paypalApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, endpoint: string, method: string, body: any = {}, query?: IDataObject, uri?: string): Promise<any> { // tslint:disable-line:no-any
const credentials = this.getCredentials('paypalApi'); const credentials = this.getCredentials('paypalApi');
let tokenInfo; const env = getEnviroment(credentials!.env as string);
if (credentials === undefined) { const tokenInfo = await getAccessToken.call(this);
throw new Error('No credentials got returned!'); const headerWithAuthentication = Object.assign({ },
}
// @ts-ignore
const env = {
'sanbox': 'https://api.sandbox.paypal.com',
'live': 'https://api.paypal.com'
}[credentials.env as string];
const data = new Buffer(`${credentials.clientId}:${credentials.secret}`).toString(BINARY_ENCODING);
let headerWithAuthentication = Object.assign({},
{ Authorization: `Basic ${data}`, 'Content-Type': 'application/x-www-form-urlencoded' });
let options: OptionsWithUri = {
headers: headerWithAuthentication,
method,
qs: query,
uri: `${env}/v1/oauth2/token`,
body,
json: true
};
try {
tokenInfo = await this.helpers.request!(options);
} catch (error) {
const errorMessage = error.response.body.message || error.response.body.Message;
if (errorMessage !== undefined) {
throw errorMessage;
}
throw error.response.body;
}
headerWithAuthentication = Object.assign({ },
{ Authorization: `Bearer ${tokenInfo.access_token}`, 'Content-Type': 'application/json' }); { Authorization: `Bearer ${tokenInfo.access_token}`, 'Content-Type': 'application/json' });
const options = {
options = {
headers: headerWithAuthentication, headers: headerWithAuthentication,
method, method,
qs: query, qs: query || {},
uri: uri || `${env}/v1${endpoint}`, uri: uri || `${env}/v1${endpoint}`,
body, body,
json: true json: true
}; };
try { try {
return await this.helpers.request!(options); return await this.helpers.request!(options);
} catch (error) { } catch (error) {
@ -69,35 +38,74 @@ export async function paypalApiRequest(this: IHookFunctions | IExecuteFunctions
} }
} }
function getEnviroment(env: string): string {
// @ts-ignore
return {
'sanbox': 'https://api.sandbox.paypal.com',
'live': 'https://api.paypal.com'
}[env];
}
async function getAccessToken(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions): Promise<any> { // tslint:disable-line:no-any
const credentials = this.getCredentials('paypalApi');
if (credentials === undefined) {
throw new Error('No credentials got returned!');
}
const env = getEnviroment(credentials!.env as string);
const data = Buffer.from(`${credentials!.clientId}:${credentials!.secret}`).toString(BINARY_ENCODING);
const headerWithAuthentication = Object.assign({},
{ Authorization: `Basic ${data}`, 'Content-Type': 'application/x-www-form-urlencoded' });
const options: OptionsWithUri = {
headers: headerWithAuthentication,
method: 'POST',
form: {
grant_type: 'client_credentials',
},
uri: `${env}/v1/oauth2/token`,
json: true
};
try {
return await this.helpers.request!(options);
} catch (error) {
const errorMessage = error.response.body.message || error.response.body.Message;
if (errorMessage !== undefined) {
throw errorMessage;
}
throw error.response.body;
}
}
/** /**
* Make an API request to paginated intercom endpoint * Make an API request to paginated paypal endpoint
* and return all results * and return all results
*/ */
export async function intercomApiRequestAllItems(this: IHookFunctions | IExecuteFunctions, propertyName: string, endpoint: string, method: string, body: any = {}, query: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any export async function paypalApiRequestAllItems(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, propertyName: string, endpoint: string, method: string, body: any = {}, query?: IDataObject, uri?: string): Promise<any> { // tslint:disable-line:no-any
const returnData: IDataObject[] = []; const returnData: IDataObject[] = [];
let responseData; let responseData;
query.per_page = 60; query!.page_size = 1000;
let uri: string | undefined;
do { do {
responseData = await paypalApiRequest.call(this, endpoint, method, body, query, uri); responseData = await paypalApiRequest.call(this, endpoint, method, body, query, uri);
uri = responseData.pages.next; uri = getNext(responseData.links);
returnData.push.apply(returnData, responseData[propertyName]); returnData.push.apply(returnData, responseData[propertyName]);
} while ( } while (
responseData.pages !== undefined && getNext(responseData.links) !== undefined
responseData.pages.next !== undefined &&
responseData.pages.next !== null
); );
return returnData; return returnData;
} }
function getNext(links: IDataObject[]): string | undefined {
for (const link of links) {
if (link.rel === 'next') {
return link.href as string;
}
}
return undefined;
}
export function validateJSON(json: string | undefined): any { // tslint:disable-line:no-any export function validateJSON(json: string | undefined): any { // tslint:disable-line:no-any
let result; let result;

View file

@ -21,8 +21,18 @@ export const payoutOpeations = [
{ {
name: 'Get', name: 'Get',
value: 'get', value: 'get',
description: 'Show payout item details',
},
{
name: 'Get All',
value: 'getAll',
description: 'Show payout batch details', description: 'Show payout batch details',
}, },
{
name: 'Delete',
value: 'delete',
description: 'Cancels an unclaimed payout item, by ID.',
},
], ],
default: 'create', default: 'create',
description: 'The operation to perform.', description: 'The operation to perform.',
@ -276,7 +286,7 @@ export const payoutFields = [
}, },
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* payout:get */ /* payout:getAll */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
{ {
@ -290,7 +300,7 @@ export const payoutFields = [
'payout', 'payout',
], ],
operation: [ operation: [
'get', 'getAll',
], ],
}, },
}, },
@ -300,14 +310,14 @@ export const payoutFields = [
displayName: 'Return All', displayName: 'Return All',
name: 'returnAll', name: 'returnAll',
type: 'boolean', type: 'boolean',
required: false, default: false,
displayOptions: { displayOptions: {
show: { show: {
resource: [ resource: [
'payout', 'payout',
], ],
operation: [ operation: [
'get', 'getAll',
], ],
}, },
}, },
@ -328,7 +338,7 @@ export const payoutFields = [
'payout', 'payout',
], ],
operation: [ operation: [
'get', 'getAll',
], ],
returnAll: [ returnAll: [
false, false,
@ -337,4 +347,47 @@ export const payoutFields = [
}, },
description: 'If all results should be returned or only up to a given limit.', description: 'If all results should be returned or only up to a given limit.',
}, },
/* -------------------------------------------------------------------------- */
/* payout:get */
/* -------------------------------------------------------------------------- */
{
displayName: 'Payout Item Id',
name: 'payoutItemId',
type: 'string',
required: true,
displayOptions: {
show: {
resource: [
'payout',
],
operation: [
'get',
],
},
},
description: 'The ID of the payout item for which to show details.',
},
/* -------------------------------------------------------------------------- */
/* payout:delete */
/* -------------------------------------------------------------------------- */
{
displayName: 'Payout Item Id',
name: 'payoutItemId',
type: 'string',
required: true,
displayOptions: {
show: {
resource: [
'payout',
],
operation: [
'delete',
],
},
},
description: 'The ID of the payout item to cancel.',
},
] as INodeProperties[]; ] as INodeProperties[];

View file

@ -13,7 +13,7 @@ export enum RecipientWallet {
export interface IAmount { export interface IAmount {
currency?: string; currency?: string;
value?: string; value?: number;
} }
export interface ISenderBatchHeader { export interface ISenderBatchHeader {

View file

@ -22,6 +22,7 @@ import {
import { import {
validateJSON, validateJSON,
paypalApiRequest, paypalApiRequest,
paypalApiRequestAllItems
} from './GenericFunctions'; } from './GenericFunctions';
export class PayPal implements INodeType { export class PayPal implements INodeType {
@ -69,8 +70,8 @@ export class PayPal implements INodeType {
const items = this.getInputData(); const items = this.getInputData();
const returnData: IDataObject[] = []; const returnData: IDataObject[] = [];
const length = items.length as unknown as number; const length = items.length as unknown as number;
let qs: IDataObject;
let responseData; let responseData;
let qs: IDataObject = {};
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
const resource = this.getNodeParameter('resource', 0) as string; const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string; const operation = this.getNodeParameter('operation', 0) as string;
@ -100,10 +101,10 @@ export class PayPal implements INodeType {
const payoutItem: IItem = {}; const payoutItem: IItem = {};
const amount: IAmount = {}; const amount: IAmount = {};
amount.currency = o.currency as string; amount.currency = o.currency as string;
amount.value = o.receiverValue as string; amount.value = parseFloat(o.amount as string);
payoutItem.amount = amount; payoutItem.amount = amount;
payoutItem.note = o.note as string || ''; payoutItem.note = o.note as string || '';
payoutItem.receiver = o.receiver as string; payoutItem.receiver = o.receiverValue as string;
payoutItem.recipient_type = o.recipientType as RecipientType; payoutItem.recipient_type = o.recipientType as RecipientType;
payoutItem.recipient_wallet = o.recipientWallet as RecipientWallet; payoutItem.recipient_wallet = o.recipientWallet as RecipientWallet;
payoutItem.sender_item_id = o.senderItemId as string || ''; payoutItem.sender_item_id = o.senderItemId as string || '';
@ -111,14 +112,45 @@ export class PayPal implements INodeType {
}); });
body.items = payoutItems; body.items = payoutItems;
} else { } else {
throw new Error('You must have at least one item.') throw new Error('You must have at least one item.');
} }
} else { } else {
const itemsJson = validateJSON(this.getNodeParameter('itemsJson', i) as string); const itemsJson = validateJSON(this.getNodeParameter('itemsJson', i) as string);
body.items = itemsJson; body.items = itemsJson;
} }
try { try {
responseData = await paypalApiRequest.call(this, '/payouts', 'POST', body); responseData = await paypalApiRequest.call(this, '/payments/payouts', 'POST', body);
} catch (err) {
throw new Error(`Paypal Error: ${JSON.stringify(err)}`);
}
}
if (operation === 'get') {
const payoutItemId = this.getNodeParameter('payoutItemId', i) as string;
try {
responseData = await paypalApiRequest.call(this,`/payments/payouts-item/${payoutItemId}`, 'GET', {}, qs);
} catch (err) {
throw new Error(`Paypal Error: ${JSON.stringify(err)}`);
}
}
if (operation === 'getAll') {
const payoutBatchId = this.getNodeParameter('payoutBatchId', i) as string;
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
try {
if (returnAll === true) {
responseData = await paypalApiRequestAllItems.call(this, 'items', `/payments/payouts/${payoutBatchId}`, 'GET', {}, qs);
} else {
qs.page_size = this.getNodeParameter('limit', i) as number;
responseData = await paypalApiRequest.call(this,`/payments/payouts/${payoutBatchId}`, 'GET', {}, qs);
responseData = responseData.items;
}
} catch (err) {
throw new Error(`Paypal Error: ${JSON.stringify(err)}`);
}
}
if (operation === 'delete') {
const payoutItemId = this.getNodeParameter('payoutItemId', i) as string;
try {
responseData = await paypalApiRequest.call(this,`/payments/payouts-item/${payoutItemId}/cancel`, 'POST', {}, qs);
} catch (err) { } catch (err) {
throw new Error(`Paypal Error: ${JSON.stringify(err)}`); throw new Error(`Paypal Error: ${JSON.stringify(err)}`);
} }
@ -130,6 +162,6 @@ export class PayPal implements INodeType {
returnData.push(responseData as IDataObject); returnData.push(responseData as IDataObject);
} }
} }
return [this.helpers.returnJsonArray({})]; return [this.helpers.returnJsonArray(returnData)];
} }
} }