Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const dotenv = require('dotenv');
const { v4 } = require('uuid');
const models = require('./models');
const { creditAccount, debitAccount } = require('./helpers/transactions');
const { hashArguments } = require('./hash');
const { checkRedisHash } = require('./redis');

dotenv.config();

Expand Down Expand Up @@ -167,6 +169,16 @@ async function transfer(sender_id, recipient_id, amount) {
error: validation.error.details[0].message,
};
}
const requestHash = hashArguments(sender_id, recipient_id, amount);

const redisCheckResult = await checkRedisHash(sender_id, requestHash);

if (!redisCheckResult.success) {
return {
success: false,
error: 'Duplicate transaction',
};
}
Comment on lines +172 to +181
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@uncoooloj this is where I used the implementation for #3.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seen it, what if transactions are just a few milli seconds apart?

That's my fear. The system won't be done with this IO so both will pass.

What do you think?

Copy link
Member Author

@OpesanyaAdebayo OpesanyaAdebayo Feb 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, @uncoooloj Redis also has implementations for transactions and optimistic locking.

I'll update it in the final version.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so quick question, what if there was a request throttling to one request per 10 ms for example? sounds like a lazy hack but that + a transaction has solves our problem no?


const t = await models.sequelize.transaction();
try {
Expand All @@ -192,6 +204,7 @@ async function transfer(sender_id, recipient_id, amount) {
metadata: {
sender_id,
},
t,
}),
]);

Expand All @@ -215,6 +228,8 @@ async function transfer(sender_id, recipient_id, amount) {
}
}

transfer(1, 2, 1000).then(console.log).catch(console.log);

/**
* @param {string} reference reference of the transaction to reverse
*/
Expand Down
29 changes: 28 additions & 1 deletion card.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ async function completeSuccessfulCharge({ accountId, reference, amount }) {
message: 'Account successfully credited',
};
}

async function chargeCard({
accountId, pan, expiry_month, expiry_year, cvv, email, amount,
}) {
Expand All @@ -78,7 +79,6 @@ async function chargeCard({
Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
},
});

const nextAction = processInitialCardCharge(charge.data);
await models.card_transactions.create({
external_reference: nextAction.data.reference,
Expand Down Expand Up @@ -302,3 +302,30 @@ async function submitPhone({
return error.response ? error.response.data : error;
}
}

async function chargeCardWithAuthorization(authorization) {
const charge = await axios.post(PAYSTACK_BASE_URL, {
authorization_code: authorization,
amount: 10000,
email: '[email protected]',
}, {
headers: {
Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
},
});
return {
success: true,
data: charge.data.data,
};
}

chargeCardWithAuthorization('AUTH_zev61rikmn').then(console.log).catch(console.log);
// chargeCard({
// accountId: 1,
// pan: '506066506066506067',
// amount: 1000000,
// cvv: '060',
// email: '[email protected]',
// expiry_month: '12',
// expiry_year: '25',
// }).then(console.log).catch(console.log);
20 changes: 20 additions & 0 deletions hash.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const crypto = require('crypto');

const key = 'mysecret key';

// create hahs
// const hash = crypto.createHmac('sha512', key);
// hash.update(text);
// const value = hash.digest('hex');

// print result
// console.log(value);

function hashArguments(...parameters) {
const concatenatedRequest = parameters.join('');
const hash = crypto.createHmac('sha512', key);
hash.update(concatenatedRequest);
return hash.digest('hex');
}

module.exports = { hashArguments };
Loading