この記事は、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を利用する準備
続いて、Stripe SDKをNestJSから呼び出す準備をしましょう。
$ npm install nestjs-stripe @nestjs/config
// 環境変数でStripeのシークレット/制限付きAPIキーを設定
$ echo "STRIPE_SECRET_API_KEY=rk_test_xxx" > .env.local
設定内容の詳細については、以下の記事をご一読ください。
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を呼び出すServiceを作成する
Stripe SDKを呼び出す処理は、Serviceとして分離しておきましょう。
$ 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リクエストは、Resolverを通して処理されます。
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は、REST API同様にnpm start:dev
でローカル環境で立ち上げることができます。
また、GraphQLの場合、http://localhost:3000/graphql
へアクセスすると、Playgroundが表示されます。
Playgroundを利用して、意図したデータが取得できているかなどを確認しましょう。
終わりに
今回の記事では、Stripe APIを呼び出すGraphQL APIの実装方法を紹介しました。
実際のユースケースでは、AWSやGCPなどにホストされた別のデータベース情報なども含めたデータの取得を行う可能性もあります。
NestJSとGraphQLの機能を使いこなして、柔軟なAPI開発を進めましょう。