| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- import { Injectable } from '@nestjs/common';
- import { InjectConnection } from '@nestjs/typeorm';
- import { ConfigArg, ConfigArgType, UpdatePaymentMethodInput } from '@vendure/common/lib/generated-types';
- import { omit } from '@vendure/common/lib/omit';
- import { ID, PaginatedList } from '@vendure/common/lib/shared-types';
- import { assertNever } from '@vendure/common/lib/shared-utils';
- import { Connection } from 'typeorm';
- import { UserInputError } from '../../common/error/errors';
- import { ListQueryOptions } from '../../common/types/common-types';
- import { getConfig } from '../../config/config-helpers';
- import { ConfigService } from '../../config/config.service';
- import {
- PaymentMethodArgs,
- PaymentMethodArgType,
- PaymentMethodHandler,
- } from '../../config/payment-method/payment-method-handler';
- import { Order } from '../../entity/order/order.entity';
- import { PaymentMethod } from '../../entity/payment-method/payment-method.entity';
- import { Payment, PaymentMetadata } from '../../entity/payment/payment.entity';
- import { ListQueryBuilder } from '../helpers/list-query-builder/list-query-builder';
- import { getEntityOrThrow } from '../helpers/utils/get-entity-or-throw';
- import { patchEntity } from '../helpers/utils/patch-entity';
- @Injectable()
- export class PaymentMethodService {
- constructor(
- @InjectConnection() private connection: Connection,
- private configService: ConfigService,
- private listQueryBuilder: ListQueryBuilder,
- ) {}
- async initPaymentMethods() {
- await this.ensurePaymentMethodsExist();
- }
- findAll(options?: ListQueryOptions<PaymentMethod>): Promise<PaginatedList<PaymentMethod>> {
- return this.listQueryBuilder
- .build(PaymentMethod, options)
- .getManyAndCount()
- .then(([items, totalItems]) => ({
- items,
- totalItems,
- }));
- }
- findOne(paymentMethodId: ID): Promise<PaymentMethod | undefined> {
- return this.connection.manager.findOne(PaymentMethod, paymentMethodId);
- }
- async update(input: UpdatePaymentMethodInput): Promise<PaymentMethod> {
- const paymentMethod = await getEntityOrThrow(this.connection, PaymentMethod, input.id);
- const updatedPaymentMethod = patchEntity(paymentMethod, omit(input, ['configArgs']));
- if (input.configArgs) {
- const handler = this.configService.paymentOptions.paymentMethodHandlers.find(
- h => h.code === paymentMethod.code,
- );
- if (handler) {
- updatedPaymentMethod.configArgs = input.configArgs;
- }
- }
- return this.connection.getRepository(PaymentMethod).save(updatedPaymentMethod);
- }
- async createPayment(order: Order, method: string, metadata: PaymentMetadata): Promise<Payment> {
- const { paymentMethod, handler } = await this.getMethodAndHandler(method);
- const result = await handler.createPayment(order, paymentMethod.configArgs, metadata || {});
- const payment = new Payment(result);
- return this.connection.getRepository(Payment).save(payment);
- }
- async settlePayment(payment: Payment, order: Order) {
- const { paymentMethod, handler } = await this.getMethodAndHandler(payment.method);
- return handler.settlePayment(order, payment, paymentMethod.configArgs);
- }
- private async getMethodAndHandler(method: string): Promise<{ paymentMethod: PaymentMethod, handler: PaymentMethodHandler }> {
- const paymentMethod = await this.connection.getRepository(PaymentMethod).findOne({
- where: {
- code: method,
- enabled: true,
- },
- });
- if (!paymentMethod) {
- throw new UserInputError(`error.payment-method-not-found`, { method });
- }
- const handler = this.configService.paymentOptions.paymentMethodHandlers.find(h => h.code === paymentMethod.code);
- if (!handler) {
- throw new UserInputError(`error.no-payment-handler-with-code`, { code: paymentMethod.code });
- }
- return { paymentMethod, handler };
- }
- private async ensurePaymentMethodsExist() {
- const paymentMethodHandlers: Array<PaymentMethodHandler<PaymentMethodArgs>> = this.configService
- .paymentOptions.paymentMethodHandlers;
- const existingPaymentMethods = await this.connection.getRepository(PaymentMethod).find();
- const toCreate = paymentMethodHandlers.filter(
- h => !existingPaymentMethods.find(pm => pm.code === h.code),
- );
- const toRemove = existingPaymentMethods.filter(
- h => !paymentMethodHandlers.find(pm => pm.code === h.code),
- );
- const toUpdate = existingPaymentMethods.filter(
- h => !toCreate.find(x => x.code === h.code) && !toRemove.find(x => x.code === h.code),
- );
- for (const paymentMethod of toUpdate) {
- const handler = paymentMethodHandlers.find(h => h.code === paymentMethod.code);
- if (!handler) {
- continue;
- }
- paymentMethod.configArgs = this.buildConfigArgsArray(handler, paymentMethod.configArgs);
- await this.connection.getRepository(PaymentMethod).save(paymentMethod);
- }
- for (const handler of toCreate) {
- let paymentMethod = existingPaymentMethods.find(pm => pm.code === handler.code);
- if (!paymentMethod) {
- paymentMethod = new PaymentMethod({
- code: handler.code,
- enabled: true,
- configArgs: [],
- });
- }
- paymentMethod.configArgs = this.buildConfigArgsArray(handler, paymentMethod.configArgs);
- await this.connection.getRepository(PaymentMethod).save(paymentMethod);
- }
- await this.connection.getRepository(PaymentMethod).remove(toRemove);
- }
- private buildConfigArgsArray(handler: PaymentMethodHandler, existingConfigArgs: ConfigArg[]): ConfigArg[] {
- let configArgs: ConfigArg[] = [];
- for (const [name, type] of Object.entries(handler.args)) {
- if (!existingConfigArgs.find(ca => ca.name === name)) {
- configArgs.push({
- name,
- type,
- value: this.getDefaultValue(type),
- });
- }
- }
- configArgs = configArgs.filter(ca =>
- handler.args.hasOwnProperty(ca.name),
- );
- return [...existingConfigArgs, ...configArgs];
- }
- private getDefaultValue(type: PaymentMethodArgType): string {
- switch (type) {
- case ConfigArgType.STRING:
- return '';
- case ConfigArgType.BOOLEAN:
- return 'false';
- case ConfigArgType.INT:
- return '0';
- default:
- assertNever(type);
- return '';
- }
- }
- }
|