基于Nest JS的支付服务:如何按支付方式动态注入仓储依赖
在NestJS中实现支付服务的动态仓储依赖注入
1. 标准化抽象仓储契约
先明确抽象仓储的统一接口(TypeScript接口无法用于NestJS依赖注入,因此用抽象类),确保所有具体实现遵循同一规范:
// src/payment/repositories/payment.repository.ts export abstract class PaymentRepository { abstract createPixCharge(data: any): Promise<string>; // 返回巴西银行通用支付码 abstract createBoletoCharge(data: any): Promise<string>; abstract createCreditCardCharge(data: any): Promise<string>; }
2. 实现网关-specific仓储类
针对每个支付网关,创建对应仓储实现,直接调用你已开发的createPixCharge等服务:
PagSeguro仓储实现
// src/payment/repositories/pagseguro-payment.repository.ts import { Injectable } from '@nestjs/common'; import { PaymentRepository } from './payment.repository'; import { createPixCharge, createBoletoCharge, createCreditCardCharge } from '../services/pagseguro.services'; @Injectable() export class PagSeguroPaymentRepository implements PaymentRepository { async createPixCharge(data: any): Promise<string> { return createPixCharge(data); } async createBoletoCharge(data: any): Promise<string> { return createBoletoCharge(data); } async createCreditCardCharge(data: any): Promise<string> { return createCreditCardCharge(data); } }
PayPal仓储实现(示例)
// src/payment/repositories/paypal-payment.repository.ts import { Injectable } from '@nestjs/common'; import { PaymentRepository } from './payment.repository'; import { createCreditCardCharge } from '../services/paypal.services'; @Injectable() export class PayPalPaymentRepository implements PaymentRepository { async createPixCharge(data: any): Promise<string> { throw new Error('PayPal不支持PIX支付'); } async createBoletoCharge(data: any): Promise<string> { throw new Error('PayPal不支持Boleto支付'); } async createCreditCardCharge(data: any): Promise<string> { return createCreditCardCharge(data); } }
3. 用工厂模式实现动态注入
在NestJS模块中通过useFactory定义动态提供者,根据请求上下文或配置参数选择对应仓储实例:
// src/payment/payment.module.ts import { Module, Provider } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; import { Request } from 'express'; import { PaymentRepository } from './repositories/payment.repository'; import { PagSeguroPaymentRepository } from './repositories/pagseguro-payment.repository'; import { PayPalPaymentRepository } from './repositories/paypal-payment.repository'; const PaymentRepositoryProvider: Provider = { provide: PaymentRepository, useFactory: (request: Request) => { // 从请求体/参数中获取用户选择的网关标识 const { gateway } = request.body; switch(gateway) { case 'pagseguro': return new PagSeguroPaymentRepository(); case 'paypal': return new PayPalPaymentRepository(); default: throw new Error('不支持的支付网关'); } }, inject: [REQUEST], // 注入请求对象实现请求级动态选择 }; @Module({ providers: [ PaymentRepositoryProvider, // 注册你已开发的各网关支付服务 ], exports: [PaymentRepository], }) export class PaymentModule {}
4. 关联业务服务与仓储
在核心业务服务中直接依赖抽象仓储,NestJS会自动注入对应网关的具体实现:
// src/payment/services/payment.service.ts import { Injectable } from '@nestjs/common'; import { PaymentRepository } from '../repositories/payment.repository'; @Injectable() export class PaymentService { constructor( private readonly paymentRepository: PaymentRepository, ) {} async createCharge(paymentMethod: string, data: any): Promise<string> { switch(paymentMethod) { case 'pix': return this.paymentRepository.createPixCharge(data); case 'boleto': return this.paymentRepository.createBoletoCharge(data); case 'credit_card': return this.paymentRepository.createCreditCardCharge(data); default: throw new Error('不支持的支付方式'); } } }
可选:按支付方式拆分仓储优化扩展性
如果后续需要更细粒度的扩展,可按支付方式拆分抽象仓储(如PixRepository、BoletoRepository),用自定义token注册不同网关的实现,再通过工厂动态选择,进一步降低耦合。
内容的提问来源于stack exchange,提问作者Felipe Leal
相关产品推荐
相关产品推荐

