Skip to content

Commit

Permalink
wip: save point
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsonogwuru committed Mar 4, 2024
1 parent c77435a commit faee9b7
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 5 deletions.
1 change: 1 addition & 0 deletions processor/src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const config = {
paypalClientId: process.env.PAYPAL_CLIENT_ID || 'xxx',
paypalClientSecret: process.env.PAYPAL_CLIENT_SECRET || 'xxxx',
paypalEnvironment: process.env.PAYPAL_ENVIRONMENT || 'test',
paypalWebhookId: process.env.PAYPAL_WEBHOOK_ID || '',

// Payment Providers config
returnUrl: process.env.RETURN_URL,
Expand Down
39 changes: 35 additions & 4 deletions processor/src/libs/fastify/hooks/paypal-webhook-verification.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,47 @@
import { PaypalAPI } from '../../../clients/paypal.client';
import { config } from '../../../config/config';
import { FastifyRequest } from 'fastify';
import { ErrorAuthErrorResponse } from '@commercetools/connect-payments-sdk';
import { NotificationPayloadDTO } from '../../../dtos/paypal-payment.dto';
import { IncomingHttpHeaders } from 'http';
import { config } from '../../../config/config';

export class WebhookVerificationHook {
constructor() {}
paypalClient: PaypalAPI;
constructor() {
this.paypalClient = new PaypalAPI();
}

public authenticate() {
return async (request: FastifyRequest) => {
const data = request.body as NotificationPayloadDTO;
// implement
if (!data.resource) {
throw new ErrorAuthErrorResponse('Unexpected payload');
}

const verifyNotificationPayload = {
auth_algo: this.verifyHeader(request.headers, 'paypal-auth-algo'),
cert_url: this.verifyHeader(request.headers, 'paypal-cert-url'),
transmission_id: this.verifyHeader(request.headers, 'paypal-transmission-id'),
transmission_sig: this.verifyHeader(request.headers, 'paypal-transmission-sig'),
transmission_time: this.verifyHeader(request.headers, 'paypal-transmission-time'),
webhook_id: config.paypalWebhookId,
webhook_event: data,
};

const validator = await this.paypalClient.verifyNotification(verifyNotificationPayload);
if (validator.verification_status === 'FAILURE') {
throw new ErrorAuthErrorResponse('Webhook signature is not valid');
}
};
}
}

private verifyHeader(headers: IncomingHttpHeaders, key: string): string {
const value = headers[key];

if (!value || Array.isArray(value)) {
throw new Error('Could not retrieve correct header');
}

return value;
}
}
4 changes: 3 additions & 1 deletion processor/src/routes/paypal-payment.route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ import {
NotificationPayload,
} from '../dtos/paypal-payment.dto';
import { PaypalPaymentService } from '../services/paypal-payment.service';
import { WebhookVerificationHook } from '../libs/fastify/hooks/paypal-webhook-verification';

type PaymentRoutesOptions = {
paymentService: PaypalPaymentService;
sessionAuthHook: SessionAuthenticationHook;
signatureAuthHook: WebhookVerificationHook;
};

export const paymentRoutes = async (fastify: FastifyInstance, opts: FastifyPluginOptions & PaymentRoutesOptions) => {
Expand Down Expand Up @@ -71,7 +73,7 @@ export const paymentRoutes = async (fastify: FastifyInstance, opts: FastifyPlugi
}>(
'/notifications',
{
preHandler: [],
preHandler: [opts.signatureAuthHook.authenticate()],
schema: {
body: NotificationPayload,
},
Expand Down
4 changes: 4 additions & 0 deletions processor/src/server/app.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { WebhookVerificationHook } from '../libs/fastify/hooks/paypal-webhook-verification';
import { paymentSDK } from '../payment-sdk';
import { PaypalPaymentService } from '../services/paypal-payment.service';

Expand All @@ -10,4 +11,7 @@ export const app = {
services: {
paymentService,
},
hooks: {
signatureAuthHook: new WebhookVerificationHook(),
},
};
1 change: 1 addition & 0 deletions processor/src/server/plugins/paypal-payment.plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ export default async function (server: FastifyInstance) {
await server.register(paymentRoutes, {
paymentService: app.services.paymentService,
sessionAuthHook: paymentSDK.sessionAuthHookFn,
signatureAuthHook: app.hooks.signatureAuthHook,
});
}
8 changes: 8 additions & 0 deletions processor/src/services/converters/notification.converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,15 @@ export class NotificationConverter {
amount: this.convertAmount(item.resource),
interactionId: item.resource.id,
};
case NotificationEventType.PAYMENT_CAPTURE_REVERSED:
return {
type: COCOTransactionTypes.CHARGE,
state: COCOTransactionStates.SUCCESS,
amount: this.convertAmount(item.resource),
interactionId: item.resource.id,
};
default:
// TODO: improve this error handling
throw new Error('Unsupported');
}
}
Expand Down

0 comments on commit faee9b7

Please sign in to comment.