diff --git a/paypal-commercetools-extension/src/connector/post-deploy.ts b/paypal-commercetools-extension/src/connector/post-deploy.ts index 79fa252..8966ac0 100644 --- a/paypal-commercetools-extension/src/connector/post-deploy.ts +++ b/paypal-commercetools-extension/src/connector/post-deploy.ts @@ -2,9 +2,7 @@ import dotenv from 'dotenv'; dotenv.config(); import { createApiRoot } from '../client/create.client'; -import { PAYPAL_EXTENSION_PATH } from '../routes/service.route'; -import { PAYPAL_WEBHOOKS_PATH } from '../routes/webhook.route'; -import { createOrUpdateWebhook } from '../service/paypal.service'; +import { createWebhook } from '../service/paypal.service'; import { assertError, assertString } from '../utils/assert.utils'; import { readConfiguration } from '../utils/config.utils'; import { @@ -31,9 +29,7 @@ async function postDeploy(properties: Map): Promise { await createCustomPaymentType(apiRoot); await createCustomCustomerType(apiRoot); await createCustomPaymentInteractionType(apiRoot); - await createOrUpdateWebhook( - applicationUrl.replace(PAYPAL_EXTENSION_PATH, PAYPAL_WEBHOOKS_PATH) - ); + await createWebhook(); await createAndSetCustomObject(apiRoot); } diff --git a/paypal-commercetools-extension/src/controllers/webhook.controller.ts b/paypal-commercetools-extension/src/controllers/webhook.controller.ts index c93095c..714819c 100644 --- a/paypal-commercetools-extension/src/controllers/webhook.controller.ts +++ b/paypal-commercetools-extension/src/controllers/webhook.controller.ts @@ -7,13 +7,12 @@ import { handleOrderWebhook, handlePaymentTokenWebhook, } from '../service/commercetools.service'; -import { getWebhookId } from '../service/config.service'; -import { validateSignature } from '../service/paypal.service'; +import { getWebhookId, validateSignature } from '../service/paypal.service'; import { logger } from '../utils/logger.utils'; async function verifyWebhookSignature(request: Request) { - const webhookIdField = await getWebhookId(); - if (!webhookIdField?.value) { + const webhookId = await getWebhookId(); + if (!webhookId) { throw new CustomError(500, 'WebhookId is missing'); } const verificationRequest: VerifyWebhookSignature = { @@ -23,7 +22,7 @@ async function verifyWebhookSignature(request: Request) { transmission_sig: request.header('paypal-transmission-sig') ?? '', transmission_time: request.header('paypal-transmission-time') ?? '', webhook_event: request.body, - webhook_id: webhookIdField.value, + webhook_id: webhookId, }; const response = await validateSignature(verificationRequest); logger.info(JSON.stringify(response)); diff --git a/paypal-commercetools-extension/src/service/config.service.ts b/paypal-commercetools-extension/src/service/config.service.ts index ac13eb0..3979685 100644 --- a/paypal-commercetools-extension/src/service/config.service.ts +++ b/paypal-commercetools-extension/src/service/config.service.ts @@ -58,52 +58,6 @@ export const cacheAccessToken = async ( .execute(); }; -export const getWebhookId = async () => { - try { - const apiRoot = createApiRoot(); - return ( - await apiRoot - .customObjects() - .withContainerAndKey({ - container: 'paypal-commercetools-connector', - key: 'webhookId', - }) - .get() - .execute() - ).body; - } catch (e) { - logger.warn('Failed to load stored webhookId', e); - return undefined; - } -}; - -export const storeWebhookId = async (webhookId: string, version: number) => { - const apiRoot = createApiRoot(); - return apiRoot - .customObjects() - .post({ - body: { - container: 'paypal-commercetools-connector', - key: 'webhookId', - value: webhookId, - version: version, - }, - }) - .execute(); -}; - -export const deleteWebhookId = async () => { - const apiRoot = createApiRoot(); - return apiRoot - .customObjects() - .withContainerAndKey({ - container: 'paypal-commercetools-connector', - key: 'webhookId', - }) - .delete() - .execute(); -}; - export const deleteAccessToken = async () => { const apiRoot = createApiRoot(); return apiRoot diff --git a/paypal-commercetools-extension/src/service/paypal.service.ts b/paypal-commercetools-extension/src/service/paypal.service.ts index fc1f67c..d5ec15a 100644 --- a/paypal-commercetools-extension/src/service/paypal.service.ts +++ b/paypal-commercetools-extension/src/service/paypal.service.ts @@ -30,16 +30,11 @@ import { VerifyWebhookSignatureApi, WebhooksApi, } from '../paypal/webhooks_api'; +import { PAYPAL_EXTENSION_PATH } from '../routes/service.route'; import { PAYPAL_WEBHOOKS_PATH } from '../routes/webhook.route'; import { Order } from '../types/index.types'; import { logger } from '../utils/logger.utils'; -import { - cacheAccessToken, - deleteWebhookId, - getCachedAccessToken, - getWebhookId, - storeWebhookId, -} from './config.service'; +import { cacheAccessToken, getCachedAccessToken } from './config.service'; const PAYPAL_API_SANDBOX = 'https://api-m.sandbox.paypal.com'; const PAYPAL_API_LIVE = 'https://api-m.paypal.com'; @@ -363,51 +358,22 @@ const getAPIEndpoint = () => { : PAYPAL_API_SANDBOX; }; -export const createOrUpdateWebhook = async (url: string) => { +export const createWebhook = async () => { const gateway = await getPayPalWebhooksGateway(); - const webhooks = await gateway.webhooksList('APPLICATION'); - logger.info(JSON.stringify(webhooks.data.webhooks)); - const oldWebhook = webhooks.data.webhooks?.find((webhook) => - webhook.url.endsWith(PAYPAL_WEBHOOKS_PATH) - ); - if (oldWebhook && oldWebhook?.id) { - const webhookIdField = await getWebhookId(); - if (webhookIdField?.value !== oldWebhook?.id) { - await storeWebhookId(oldWebhook?.id, webhookIdField?.version ?? 0); - } - if (oldWebhook?.url === url) { - logger.info('Webhook URL did not change'); - return oldWebhook; - } - const response = await gateway.webhooksUpdate(oldWebhook.id, [ - { - op: 'replace', - path: '/url', - value: url, - }, - ]); - logger.info(`Webhook url updated from ${oldWebhook.url} to ${url}`); - return response.data; - } const response = await gateway.webhooksPost({ - url: url, + url: getWebhookUrl(), event_types: [ { name: '*', } as EventType, ], }); - if (response?.data?.id) { - const webhookIdField = await getWebhookId(); - await storeWebhookId(response.data.id, webhookIdField?.version ?? 0); - } return response.data; }; export const deleteWebhook = async () => { const gateway = await getPayPalWebhooksGateway(); - const webhookIdField = await getWebhookId(); - const webhookId = webhookIdField?.value; + const webhookId = await getWebhookId(); if (!webhookId) { return; } @@ -421,7 +387,25 @@ export const deleteWebhook = async () => { throw e; } } - await deleteWebhookId(); +}; + +export const getWebhookId = async () => { + const webhookUrl = getWebhookUrl(); + const gateway = await getPayPalWebhooksGateway(); + const webhooks = await gateway.webhooksList('APPLICATION'); + const webhook = webhooks.data.webhooks?.find( + (webhook) => webhook.url === webhookUrl + ); + return webhook?.id; +}; + +export const getWebhookUrl = () => { + return ( + process.env.CONNECT_SERVICE_URL?.replace( + PAYPAL_EXTENSION_PATH, + PAYPAL_WEBHOOKS_PATH + ) ?? '' + ); }; export const addDeliveryData = async ( diff --git a/paypal-commercetools-extension/tests/post-deploy.spec.ts b/paypal-commercetools-extension/tests/post-deploy.spec.ts index 19c3488..90e68fe 100644 --- a/paypal-commercetools-extension/tests/post-deploy.spec.ts +++ b/paypal-commercetools-extension/tests/post-deploy.spec.ts @@ -39,11 +39,11 @@ describe('Testing post deploy', () => { })); require('../src/connector/post-deploy'); await sleep(10000); - expect(apiRoot.post).toBeCalledTimes(8); + expect(apiRoot.post).toBeCalledTimes(7); expect(apiRoot.delete).toBeCalledTimes(1); - expect(apiRoot.get).toBeCalledTimes(9); - expect(apiRequest.execute).toBeCalledTimes(18); - expect(webhooksApi.webhooksList).toBeCalledTimes(1); + expect(apiRoot.get).toBeCalledTimes(8); + expect(apiRequest.execute).toBeCalledTimes(16); + expect(webhooksApi.webhooksList).toBeCalledTimes(0); expect(webhooksApi.webhooksPost).toBeCalledTimes(1); }, 20000); }); diff --git a/paypal-commercetools-extension/tests/pre-undeploy.spec.ts b/paypal-commercetools-extension/tests/pre-undeploy.spec.ts index 12b0598..5c35c1d 100644 --- a/paypal-commercetools-extension/tests/pre-undeploy.spec.ts +++ b/paypal-commercetools-extension/tests/pre-undeploy.spec.ts @@ -18,6 +18,7 @@ const mockConfigModule = () => { })), }; apiRoot = { + customObjects: jest.fn(() => apiRoot), extensions: jest.fn(() => apiRoot), withKey: jest.fn(() => apiRoot), delete: jest.fn(() => apiRequest), diff --git a/paypal-commercetools-extension/tests/webhooks.controller.spec.ts b/paypal-commercetools-extension/tests/webhooks.controller.spec.ts index 06ea384..7ec0124 100644 --- a/paypal-commercetools-extension/tests/webhooks.controller.spec.ts +++ b/paypal-commercetools-extension/tests/webhooks.controller.spec.ts @@ -23,6 +23,7 @@ const mockConfigModule = () => { }); jest.mock('../src/service/paypal.service', () => ({ validateSignature: () => ({ verification_status: 'SUCCESS' }), + getWebhookId: () => 1, getPayPalOrder: () => ({ status: 'COMPLETED', }), @@ -37,7 +38,6 @@ beforeEach(() => { apiRequest = { execute: jest .fn() - .mockReturnValueOnce({ body: { value: 'VALUE' } }) .mockReturnValueOnce({ body: { total: 1, @@ -86,7 +86,7 @@ describe('Testing webhook controller', () => { resource_type: 'capture', resource: { id: 1 }, action: 'changeTransactionState', - executeCalls: 3, + executeCalls: 2, actionsCount: 3, }, { @@ -94,7 +94,7 @@ describe('Testing webhook controller', () => { resource_type: 'payment_token', resource: { id: 1, customer: { id: 123 }, metadata: { order_id: 2 } }, action: 'setCustomType', - executeCalls: 5, + executeCalls: 4, actionsCount: 1, }, { @@ -102,7 +102,7 @@ describe('Testing webhook controller', () => { resource_type: 'checkout-order', resource: { id: 1, intent: CheckoutPaymentIntent.Authorize }, action: 'setStatusInterfaceCode', - executeCalls: 3, + executeCalls: 2, actionsCount: 2, }, { @@ -110,7 +110,7 @@ describe('Testing webhook controller', () => { resource_type: 'authorization', resource: { id: 1 }, action: 'addTransaction', - executeCalls: 3, + executeCalls: 2, actionsCount: 3, }, ])(