使用NestJS创建调用Stripe API的GraphQL API的方法

这篇文章是GraphQL Advent Calendar 2022的第17天的文章。

Stripe数据获取基本上通过REST API完成。

然而,在GraphQL API中有一些特定的情况下进行实施是适合的,比如想要跨多个数据源(如商品和价格等)进行查询,或者只想获取所需数据的情况下。

这篇文章将介绍如何使用NestJS来创建一个能够获取Stripe数据的GraphQL API。

项目的设置

如果要创建NestJS项目,则可以使用NestJS CLI。

$ npm i -g @nestjs/cli
$ nest new project-name

准备使用Stripe SDK

接下来,让我们准备从 NestJS 调用 Stripe SDK。

$ npm install nestjs-stripe @nestjs/config

// 環境変数でStripeのシークレット/制限付きAPIキーを設定
$ echo "STRIPE_SECRET_API_KEY=rk_test_xxx" > .env.local 

有关设置详情,请阅读下面的文章。

 

GraphQL: GraphQL.

最後,安装用于实现GraphQL API的库。

$ npm i @nestjs/graphql @nestjs/apollo graphql apollo-server-express

在 app.module.ts 文件中添加设置。

让我们让安装的模块和其他工具可用。

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { GraphQLModule } from '@nestjs/graphql';
import { join } from 'path';
import { StripeModule } from 'nestjs-stripe';
import { ConfigModule, ConfigService } from '@nestjs/config';


@Module({
  imports: [
    // 環境変数の読み込み
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: ['.env.local']
    }),

    // Stripe SDKの読み込み
    StripeModule.forRootAsync({
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        apiKey: configService.get('STRIPE_SECRET_API_KEY'),
        apiVersion: '2022-08-01'
      })
    }),

    // GraphQLの読み込み
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      debug: false,
      playground: true,
      autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
      sortSchema: true
    })
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

实现GraphQL API

由于准备工作已经完成,我们将开始进行实施。

让我们创建GraphQL的数据模型

我们来创建基于GraphQL模式和NestJS实现的基础数据模型吧。

$ nest generate class model
CREATE src/model/model.spec.ts (143 bytes)
CREATE src/model/model.ts (22 bytes)

在src/model/model.ts中,我们简单地定义了产品(Product)和价格(Price)的类型。

import { Field, ID, ObjectType } from '@nestjs/graphql';

@ObjectType()
export class Price {
    @Field(type => ID)
    id: string;

    @Field({nullable: true})
    nickname?: string;

    @Field()
    currency: string;
    
    @Field()
    unit_amount: number
}

@ObjectType()
export class Product {
    @Field(type => ID)
    id: string;

    @Field({ nullable: true })
    name: string;

    @Field({ nullable: true })
    description?: string;

    @Field(() => [Price], { nullable: true})
    prices?: Price[]
}

 

创建一个调用Stripe API的服务

将调用Stripe SDK的过程作为一个服务进行分离。

$ nest generate service stripe-api
CREATE src/stripe-api/stripe-api.service.spec.ts (482 bytes)
CREATE src/stripe-api/stripe-api.service.ts (93 bytes)
UPDATE src/app.module.ts (254 bytes)

我已经添加了获取商品列表和通过商品ID获取价格的处理。

import { Injectable } from '@nestjs/common';
import { InjectStripe } from 'nestjs-stripe';
import Stripe from 'stripe';

@Injectable()
export class StripeApiService {
    constructor(
        @InjectStripe() private readonly stripe: Stripe
    ) {}

    public async listProducts() {
        return this.stripe.products.list()
    }
    public async findPricesByProductId(productId: string) {
        return this.stripe.prices.list({
            product: productId
        })
    }
}

让我们创建一个Resolver

GraphQL的API请求通过解析器进行处理。

让我们使用NestJS的CLI来创建一个Resolver。

$ nest generate resolver stripe-api
CREATE src/stripe-api/stripe-api.resolver.spec.ts (492 bytes)
CREATE src/stripe-api/stripe-api.resolver.ts (91 bytes)
UPDATE src/app.module.ts (254 bytes)

让我们从Resolver中调用先前创建的Service来实现处理。

import { Resolver, Query, ResolveField, Parent } from '@nestjs/graphql';
import { Product } from './model/model';
import { StripeApiService } from './stripe-api.service';

@Resolver(of => Product)
export class StripeApiResolver {
    constructor(
        private readonly stripeAPIService: StripeApiService
    ) {}

    @Query(() => [Product])
    async findProducts() {
        const { data:products } = await this.stripeAPIService.listProducts()
        return products
    }

    @ResolveField()
    async prices(@Parent() product) {
        const { id } = product
        const { data:prices } = await  this.stripeAPIService.findPricesByProductId(id)
        return prices
    }
}

通过使用 ResolveField,从 findProducts 查询中获取费用数据。

 

使用GraphQL Playground来验证功能

使用NestJS创建的API可以在本地环境中通过npm start:dev命令启动,就像REST API一样。

此外,对于GraphQL的情况,当访问http://localhost:3000/graphql时,将显示Playground。

スクリーンショット 2022-11-08 19.31.26.png

让我们利用Playground来确认是否成功获取了所需的数据。

完结

在本文中,我们介绍了调用Stripe API的GraphQL API实现方法。

在实际的案例中,可能会获取包括托管在AWS或GCP等平台上的其他数据库信息在内的数据。

让我们熟练运用NestJS和GraphQL的功能,推进灵活的API开发。

广告
将在 10 秒后关闭
bannerAds