import { Injectable } from '@nestjs/common' import { HttpService } from '../http' import { N2BPayments } from '../../typings/global' import { CancelSubscriptionParams, CardParams, GenerateSubscriptionParams, RefundParams } from './params' import { Payment, Refund, Subscription } from './types' import { N2BPaymentsProviders } from './enums' type PaymentResult = { subscription: Subscription success: boolean } type RefundResult = { refund: Refund success: boolean } type ChargeInstallmentArgs = { subscriptionId: number; installmentNumber: number; card?: CardParams } @Injectable() export class N2BPaymentsService { private get environment(): N2BPayments { return globalThis.secret.n2b_payments } constructor(protected readonly httpService: HttpService) {} async generateSubscription(data: GenerateSubscriptionParams): Promise { return { subscription: await this.requestGenerateSubscription(data), success: true } } async generateSubscriptionAndChargePayment(data: GenerateSubscriptionParams): Promise { const subscription = await this.requestGenerateSubscription(data, true) return { subscription, success: subscription.invoice.installments[0]?.payments?.[0]?.amount > 0 } } async askRefund(data: RefundParams): Promise { return { refund: await this.requestRefund(data), success: true } } async refund(data: RefundParams): Promise { const refund = await this.requestRefund(data, true) return { refund, success: refund?.amount > 0 } } async askCancelSubscription(data: CancelSubscriptionParams): Promise { return { subscription: await this.requestCancelSubscription(data), success: true } } async generateClientSession(provider: N2BPaymentsProviders): Promise { const request = await this.sendData( {}, `payment-providers/${provider}/client-session`, ) return request?.clientSession } async chargeInstallment( originalTransactionId: number | string, installmentNumber: number, card?: CardParams, ): Promise { return this.sendData( { subscriptionId: +originalTransactionId, installmentNumber, card }, 'subscription/charge-installment', ) } private async requestGenerateSubscription( data: GenerateSubscriptionParams, waitPaymentCharging = false, ): Promise { data.card = { ...data.card, token: this.environment.card_simulate && data.card?.token === 'mock' ? this.environment.card_simulate : data.card?.token, } return this.sendData(data, 'subscription/generate', waitPaymentCharging) } private async requestRefund(data: RefundParams, waitPaymentCharging = false): Promise { return this.sendData(data, 'invoice/refund', waitPaymentCharging) } private async requestCancelSubscription( data: CancelSubscriptionParams, waitPaymentCharging = false, ): Promise { return this.sendData(data, 'subscription/cancel', waitPaymentCharging) } private async sendData< T = CancelSubscriptionParams | GenerateSubscriptionParams | RefundParams, R = Subscription & Refund >(data: T, endpoint: string, waitPaymentCharging = false): Promise { const url = `${this.environment.endpoint}/${endpoint}` try { const response = await this.httpService.post( url, { ...data, paymentProvider: N2BPaymentsProviders.INGENICO, waitPaymentCharging }, { headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${this.environment.token}`, }, name: this.constructor.name, timeout: 30000, returnStatusCode: true, }, ) if (![200, 201].includes(response.statusCode)) throw new Error(response.message) delete response.statusCode return response } catch (error) { if ([200, 201].includes(error.statusCode)) return throw new Error(error.message) } } }