Skip to content

Commit

Permalink
fix(pagarme): Read transaction on pagar.me API when webhook signature…
Browse files Browse the repository at this point in the history
… not verified

Overwrite transaction object and status, ignoring received invalidated webhook body
  • Loading branch information
leomp12 committed Aug 2, 2024
1 parent 2dc23c9 commit 69246a3
Showing 1 changed file with 30 additions and 18 deletions.
48 changes: 30 additions & 18 deletions packages/apps/pagarme/src/pagarme-webhook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { createHmac } from 'node:crypto';
import api from '@cloudcommerce/api';
import * as functions from 'firebase-functions/v1';
import config, { logger } from '@cloudcommerce/firebase/lib/config';
import axios from 'axios';
import Pagarme from 'pagarme';
import qs from 'qs';
import { parsePagarmeStatus } from './pagarme-utils';
Expand Down Expand Up @@ -35,51 +36,63 @@ export const pagarme = {
}

// https://docs.pagar.me/docs/gerenciando-postbacks
const pagarmeTransaction = req.body && req.body.transaction;
if (pagarmeTransaction && pagarmeTransaction.metadata) {
// const storeId = parseInt(pagarmeTransaction.metadata.store_id, 10);
let pagarmeTransaction = req.body?.transaction;
if (pagarmeTransaction?.metadata) {
const orderId = pagarmeTransaction.metadata.order_id as ResourceId | undefined;
if (typeof orderId === 'string' && /^[a-f0-9]{24}$/.test(orderId)) {
let pagarmeStatus = req.body.current_status || pagarmeTransaction.status;
logger.info(`Order ${orderId}`);
let isVerified = false;
if (`${process.env.PAGARME_WEBHOOK_SKIP_SIG}`.toLowerCase() !== 'true') {
logger.info(`Validating ${orderId} webhook signature`);
const urlSig = req.query.sig;
if (urlSig && typeof urlSig === 'string') {
const notificationSig = createHmac('sha256', process.env.PAGARME_TOKEN)
.update(orderId).digest('hex');
if (notificationSig !== urlSig) {
isVerified = notificationSig === urlSig;
if (!isVerified) {
logger.warn('?sig argument is received with invalid hash');
res.sendStatus(401);
return;
}
} else {
// validate Pagar.me postback
// https://github.com/pagarme/pagarme-js/issues/170#issuecomment-503729557
const headerSig = req.headers['x-hub-signature'];
if (!headerSig || typeof headerSig !== 'string') {
res.sendStatus(403);
return;
isVerified = false;
} else {
const verifyBody = qs.stringify(req.body);
const sigHeader = headerSig.replace('sha1=', '');
isVerified = !!(Pagarme.postback
.verifySignature(process.env.PAGARME_TOKEN, verifyBody, sigHeader));
}
const verifyBody = qs.stringify(req.body);
const sigHeader = headerSig.replace('sha1=', '');
if (
!Pagarme.postback
.verifySignature(process.env.PAGARME_TOKEN, verifyBody, sigHeader)
) {
}
}
if (!isVerified) {
try {
const { data } = await axios({
url: `https://api.pagar.me/1/transactions/${pagarmeTransaction.id}`,
method: 'get',
data: { api_key: process.env.PAGARME_TOKEN },
});
pagarmeTransaction = data;
if (pagarmeTransaction?.metadata?.order_id !== orderId) {
res.sendStatus(401);
return;
}
pagarmeStatus = pagarmeTransaction.status;
} catch {
res.sendStatus(401);
return;
}
}

try {
const order = (await api.get(`orders/${orderId}`)).data;
if (order && order.transactions) {
// add new transaction status to payment history
const transaction = order.transactions?.find(({ intermediator }) => {
return intermediator
&& intermediator.transaction_id === String(pagarmeTransaction.id);
return intermediator?.transaction_id === String(pagarmeTransaction.id);
});
const pagarmeStatus = req.body.current_status || pagarmeTransaction.status;
const bodyPaymentHistory = {
date_time: new Date().toISOString(),
status: parsePagarmeStatus(pagarmeStatus),
Expand All @@ -92,7 +105,6 @@ export const pagarme = {
if (req.body.old_status) {
bodyPaymentHistory.flags.push(`old:${req.body.old_status}`.substring(0, 20));
}
// return appSdk.apiRequest(storeId, resource, method, body);
await api.post(`orders/${orderId}/payments_history`, bodyPaymentHistory);
res.status(200).send('OK');
return;
Expand Down

0 comments on commit 69246a3

Please sign in to comment.