|
| 1 | +import { BadRequest } from '@shared/backend' |
| 2 | +import { Logger } from 'winston' |
| 3 | +import { GateHubClient } from '../gatehub/client' |
| 4 | +import { Env } from '../config/env' |
| 5 | +import { TransactionTypeEnum } from '../gatehub/consts' |
| 6 | +import { StripeWebhookType } from './validation' |
| 7 | + |
| 8 | +export enum EventType { |
| 9 | + payment_intent_canceled = 'payment_intent.canceled', |
| 10 | + payment_intent_payment_failed = 'payment_intent.payment_failed', |
| 11 | + payment_intent_succeeded = 'payment_intent.succeeded' |
| 12 | +} |
| 13 | + |
| 14 | +interface IStripeService { |
| 15 | + onWebHook: (wh: StripeWebhookType) => Promise<void> |
| 16 | +} |
| 17 | + |
| 18 | +export class StripeService implements IStripeService { |
| 19 | + constructor( |
| 20 | + private env: Env, |
| 21 | + private logger: Logger, |
| 22 | + private gateHubClient: GateHubClient |
| 23 | + ) {} |
| 24 | + |
| 25 | + public async onWebHook(wh: StripeWebhookType): Promise<void> { |
| 26 | + this.logger.info(`received webhook of type : ${wh.type} for : ${wh.id}`) |
| 27 | + |
| 28 | + switch (wh.type) { |
| 29 | + case EventType.payment_intent_succeeded: |
| 30 | + await this.handlePaymentIntentSucceeded(wh) |
| 31 | + break |
| 32 | + case EventType.payment_intent_payment_failed: |
| 33 | + await this.handlePaymentIntentFailed(wh) |
| 34 | + break |
| 35 | + case EventType.payment_intent_canceled: |
| 36 | + await this.handlePaymentIntentCanceled(wh) |
| 37 | + break |
| 38 | + } |
| 39 | + } |
| 40 | + |
| 41 | + private async handlePaymentIntentSucceeded(wh: StripeWebhookType) { |
| 42 | + const paymentIntent = wh.data.object |
| 43 | + const metadata = paymentIntent.metadata |
| 44 | + const receiving_address: string = metadata.receiving_address |
| 45 | + const currency: string = paymentIntent.currency |
| 46 | + const amount: number = paymentIntent.amount |
| 47 | + |
| 48 | + try { |
| 49 | + await this.gateHubClient.createTransaction({ |
| 50 | + amount, |
| 51 | + vault_uuid: this.gateHubClient.getVaultUuid(currency), |
| 52 | + receiving_address, |
| 53 | + sending_address: this.env.GATEHUB_SETTLEMENT_WALLET_ADDRESS, |
| 54 | + type: TransactionTypeEnum.HOSTED, |
| 55 | + message: 'Stripe Transfer' |
| 56 | + }) |
| 57 | + } catch (error) { |
| 58 | + this.logger.error('Error creating gatehub transaction', { error }) |
| 59 | + throw new BadRequest('Failed to create transaction') |
| 60 | + } |
| 61 | + } |
| 62 | + |
| 63 | + private async handlePaymentIntentFailed(wh: StripeWebhookType) { |
| 64 | + // No need to take action on the GateHub side as no funds were transferred |
| 65 | + const paymentIntent = wh.data.object |
| 66 | + const metadata = paymentIntent.metadata |
| 67 | + const receiving_address = metadata.receiving_address |
| 68 | + |
| 69 | + this.logger.warn('Payment intent failed', { |
| 70 | + payment_intent_id: paymentIntent.id, |
| 71 | + receiving_address, |
| 72 | + error: paymentIntent.last_payment_error |
| 73 | + }) |
| 74 | + } |
| 75 | + |
| 76 | + private async handlePaymentIntentCanceled(wh: StripeWebhookType) { |
| 77 | + const paymentIntent = wh.data.object |
| 78 | + // No action needed on GateHub side as payment was canceled |
| 79 | + this.logger.info('Payment intent canceled', { |
| 80 | + payment_intent_id: paymentIntent.id, |
| 81 | + receiving_address: paymentIntent.metadata.receiving_address |
| 82 | + }) |
| 83 | + } |
| 84 | +} |
0 commit comments