Skip to content

Commit

Permalink
DASH-150 add payments job to check payment statuses from stripe and u…
Browse files Browse the repository at this point in the history
…pdate order status
  • Loading branch information
orkhan-huseyn committed Feb 2, 2023
1 parent 982b6b3 commit 1a522cc
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 21 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"lint": "eslint ./server/src ./client/src --ext js,mjs,ts,tsx",
"lint:fix": "eslint ./server/src ./client/src --ext js,mjs,ts,tsx --fix",
"server:prod": "npm run migrate && node --es-module-specifier-resolution=node server/src/index.mjs",
"scheduler": "JOB_LIST=emails,orders,txCheck,wrapStatus node --es-module-specifier-resolution=node server/src/scheduler.mjs",
"scheduler": "JOB_LIST=emails,orders,txCheck,wrapStatus,payments node --es-module-specifier-resolution=node server/src/scheduler.mjs",
"scheduler:wallet-data": "JOB_LIST=walletData node --es-module-specifier-resolution=node server/src/scheduler.mjs",
"scheduler:wrap-status": "JOB_LIST=wrapStatus node --es-module-specifier-resolution=node server/src/scheduler.mjs",
"migrate": "sequelize db:migrate",
Expand Down
8 changes: 4 additions & 4 deletions server/src/external/payment-processor/stripe.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ const STRIPE_USER_AGENT = 'Stripe/1.0';

const stripe = new StripeLib(process.env.STRIPE_SECRET);
class Stripe extends PaymentProcessor {
constructor() {
super();
}

isWebhook(hostname, userAgent) {
const checkRegex = new RegExp(`${STRIPE_USER_AGENT}`, 'i');
return checkRegex.exec(userAgent);
Expand Down Expand Up @@ -239,6 +235,10 @@ class Stripe extends PaymentProcessor {

return stripe.refunds.create(refundOptions);
}

async retrieveIntent(id) {
return await stripe.paymentIntents.retrieve(id);
}
}

export default new Stripe();
4 changes: 0 additions & 4 deletions server/src/jobs/emails.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ const CONTENT_TYPE_EMAIL_TEMPLATE_MAP = {
const OPT_IN_STATUS_SYNCED = 'OPT_IN_STATUS_SYNCED';

class EmailsJob extends CommonJob {
constructor() {
super();
}

async allowToSendBalanceChangedEmail(notification) {
const { id, userId, createdAt, data } = notification;

Expand Down
75 changes: 75 additions & 0 deletions server/src/jobs/payments.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import CommonJob from './job.mjs';

import Stripe from '../external/payment-processor/stripe.mjs';

import logger from '../logger.mjs';

import { Order, Payment, OrderItem, OrderItemStatus } from '../models';

// https://stripe.com/docs/payments/intents#intent-statuses
const STRIPE_INTENT_SUCCESS = 'succeeded';

class PaymentsJob extends CommonJob {
async execute() {
const orders = await Order.findAll({
where: {
status: Order.STATUS.PAYMENT_PENDING,
},
include: [OrderItem, Payment],
});

const t = await Order.sequelize.transaction();

try {
for (const order of orders) {
const payments = await order.getPayments({
where: { processor: Payment.PROCESSOR.STRIPE },
});
const paymentStatuses = [];
for (const payment of payments) {
const orderItemStatus = await OrderItemStatus.findOne({
where: {
paymentId: payment.id,
},
transaction: t,
});

const intentId = payment.externalId;
const intent = await Stripe.retrieveIntent(intentId);
paymentStatuses.push(intent.status);
if (intent.status === STRIPE_INTENT_SUCCESS) {
await payment.update(
{ status: Payment.STATUS.COMPLETED },
{ transaction: t },
);
await orderItemStatus.update(
{ paymentStatus: Payment.STATUS.COMPLETED },
{ transaction: t },
);
} else {
await payment.update({ status: Payment.STATUS.FAILED }, { transaction: t });
await orderItemStatus.update(
{ paymentStatus: Payment.STATUS.FAILED },
{ transaction: t },
);
}
}

const allSucceeded = paymentStatuses.some(
status => status === STRIPE_INTENT_SUCCESS,
);
if (allSucceeded) {
await order.update({ status: Order.STATUS.SUCCESS }, { transaction: t });
} else {
await order.update({ status: Order.STATUS.FAILED }, { transaction: t });
}
}
await t.commit();
} catch (error) {
logger.error(`Update transaction failed error: ${error.message}`);
await t.rollback();
}
}
}

new PaymentsJob().execute();
4 changes: 0 additions & 4 deletions server/src/jobs/tx-check.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ import logger from '../logger.mjs';
const MAX_CHECK_TIMES = 10;

class TxCheckJob extends CommonJob {
constructor() {
super();
}

async execute() {
await fioApi.getRawAbi();

Expand Down
4 changes: 0 additions & 4 deletions server/src/jobs/wallet-data.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ const returnDayRange = timePeriod => {
};

class WalletDataJob extends CommonJob {
constructor() {
super();
}

logFioError(e, wallet, action = '-') {
if (e && e.errorCode !== 404) {
if (wallet && wallet.id)
Expand Down
4 changes: 0 additions & 4 deletions server/src/jobs/wrap-status.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,6 @@ const WRAPPED_TOKEN_ABI = JSON.parse(
const UNWRAP_RETRIES_LIMIT = 3;

class WrapStatusJob extends CommonJob {
constructor() {
super();
}

handleErrorMessage(message) {
// eslint-disable-next-line no-console
console.log(message);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module.exports = {
},
createdAt: { type: DT.DATE },
updatedAt: { type: DT.DATE },
deletedAt: { type: DT.DATE },
});

return QI.sequelize.query(
Expand Down
8 changes: 8 additions & 0 deletions server/src/scheduler.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ const availableJobsParams = {
closeWorkerAfterMs:
parseInt(process.env.WRAP_STATUS_JOB_CLOSE_TIMEOUT) || 60 * 60 * 1000, // 60 min
},
payments: {
path: path.join(JOBS_PATH, 'payments.mjs'),
name: 'payments',
interval: process.env.PAYMENTS_JOB_INTERVAL || 30 * 1000, // 30 sec
timeout: 0,
closeWorkerAfterMs:
parseInt(process.env.PAYMENTS_JOB_CLOSE_TIMEOUT) || 60 * 60 * 1000, // 60 min
},
};

const jobsToLaunch = process.env.JOB_LIST;
Expand Down

0 comments on commit 1a522cc

Please sign in to comment.