UNPKG

@lomray/microservice-payment-stripe

Version:

Stripe payment microservice based on NodeJS & inverted json.

151 lines (147 loc) 7.22 kB
'use strict'; var tslib = require('tslib'); var microserviceNodejsLib = require('@lomray/microservice-nodejs-lib'); var Event = require('@lomray/microservices-client-api/constants/events/payment-stripe'); var _ = require('lodash'); var remote = require('../../config/remote.js'); var stripePaymentMethods = require('../../constants/stripe-payment-methods.js'); var customer = require('../../entities/customer.js'); var extractIdFromStripeInstance = require('../../helpers/extract-id-from-stripe-instance.js'); var fromExpirationDate = require('../../helpers/formatters/from-expiration-date.js'); var toExpirationDate = require('../../helpers/formatters/to-expiration-date.js'); var messages = require('../../helpers/validators/messages.js'); var card = require('../../repositories/card.js'); /** * Setup intent Webhook Handler */ class SetupIntent { /** * @constructor */ constructor(manager) { this.manager = manager; this.cardRepository = manager.getCustomRepository(card); this.customerRepository = manager.getRepository(customer); } /** * Handles setup intent succeed * @description Support cards. Should be called when webhook triggers */ handleSetupIntentSucceed(event, sdk) { var _a, _b; return tslib.__awaiter(this, void 0, void 0, function* () { const { duplicatedCardsUsage } = yield remote(); /* eslint-disable camelcase */ const { id, payment_method } = event.data.object; if (!payment_method) { throw new microserviceNodejsLib.BaseException({ status: 500, message: messages.getNotFoundMessage('The SetupIntent payment method'), }); } /** * Get payment method data */ const paymentMethod = yield sdk.paymentMethods.retrieve(extractIdFromStripeInstance(payment_method), { expand: [stripePaymentMethods.CARD], }); if (!(paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.card) || !(paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.customer)) { throw new microserviceNodejsLib.BaseException({ status: 500, message: 'The payment method card or customer data is invalid.', }); } const customer = yield this.customerRepository.findOne({ customerId: extractIdFromStripeInstance(paymentMethod.customer), }); if (!customer) { throw new microserviceNodejsLib.BaseException({ status: 500, message: messages.getNotFoundMessage('Customer'), }); } const { id: paymentMethodId, billing_details: billing, card: { brand, last4: lastDigits, exp_month: expMonth, exp_year: expYear, funding, country, issuer, fingerprint, }, } = paymentMethod; const { userId } = customer; const cardParams = Object.assign(Object.assign(Object.assign({ lastDigits, brand, userId, funding, fingerprint, paymentMethodId, origin: country }, (((_a = billing.address) === null || _a === void 0 ? void 0 : _a.country) ? { country: billing.address.country } : {})), (((_b = billing.address) === null || _b === void 0 ? void 0 : _b.postal_code) ? { postalCode: billing.address.postal_code } : {})), { expired: toExpirationDate(expMonth, expYear) }); const cardEntity = this.cardRepository.create(Object.assign(Object.assign({}, cardParams), { params: { isApproved: true, setupIntentId: id, issuer, } })); /** * If we should reject duplicated cards - check */ if (duplicatedCardsUsage === 'reject') { const cardData = yield card.getCardDataByFingerprint({ userId, fingerprint, shouldExpandCard: true, }); /** * Cancel set up card if this card already exist as the payment method */ if (cardData.isExist && cardData.type === 'paymentMethod') { yield this.detachOrRenewWithDetachDuplicatedCard(paymentMethodId, cardEntity, cardData, sdk); return; } } const savedCard = yield this.cardRepository.save(cardEntity); void microserviceNodejsLib.Microservice.eventPublish(Event.SetupIntentSucceeded, savedCard); }); } /** * Detach duplicated card * @description Will detach duplicated card from Stripe customer */ detachOrRenewWithDetachDuplicatedCard(paymentMethodId, cardEntity, { entity }, sdk) { return tslib.__awaiter(this, void 0, void 0, function* () { if (!entity) { throw new microserviceNodejsLib.BaseException({ status: 500, message: messages.getNotFoundMessage('Failed to validate duplicated card. Card'), }); } /** * Card properties for renewal card that must be identical */ const cardProperties = ['lastDigits', 'brand', 'origin', 'fingerprint', 'funding', 'userId']; const existingCardPaymentMethodId = card.extractPaymentMethodId(entity); const { year: existingYear, month: existingMonth } = fromExpirationDate(entity.expired); const { year: updatedYear, month: updatedMonth } = fromExpirationDate(cardEntity.expired); /** * Update renewal card details * @description Stripe does not create new fingerprint if card was renewal with new expiration date */ if (entity.expired !== cardEntity.expired && // All other card details MUST be equal _.isEqual(_.pick(entity, cardProperties), _.pick(cardEntity, cardProperties)) && // Check expiration dates updatedYear >= existingYear && updatedMonth >= existingMonth) { entity.expired = cardEntity.expired; /** * Update card details and next() detach new duplicated card */ yield sdk.paymentMethods.update(existingCardPaymentMethodId, { card: { exp_month: updatedMonth, exp_year: updatedYear, }, }); yield this.cardRepository.save(entity); } /** * If customer trying to add identical, not renewal card * @description Detach duplicated card from Stripe customer */ yield sdk.paymentMethods.detach(paymentMethodId); yield microserviceNodejsLib.Microservice.eventPublish(Event.CardNotCreatedDuplicated, cardEntity); }); } } module.exports = SetupIntent;