백엔드 25일차

이동현·2023년 4월 14일
0

코드캠프 백엔드

목록 보기
20/29

결제 기능 구현하기

1. 결제 프로세스

PG사랑 계약을 하면 알아서 카드사와 카드 결제를 가능하게 해줌

2. 아임포트

현재는 포트원이라고 바뀜

3. 결제 실습하기

  1. 브라우저에서 결제하기
  2. 받은 데이터를 백엔드를 통해 db에 저장하기
//pointTransaction.entity.ts

export enum POINT_TRANSACTION_STATUS_ENUM {
  PAYMENT = 'PAYMENT',
  CANCEL = 'CANCEL',
}

// enum을 graphql용으로 사용하기
registerEnumType(POINT_TRANSACTION_STATUS_ENUM, {
  name: 'POINT_TRANSACTION_STATUS_ENUM',
});

@Entity()
@ObjectType()
export class PointTransaction {
  @PrimaryGeneratedColumn('uuid')
  @Field(() => String)
  id: string;

  @Column()
  @Field(() => String)
  impUid: string;

  @Column()
  @Field(() => Int)
  amount: number;

  @Column({ type: 'enum', enum: POINT_TRANSACTION_STATUS_ENUM })
  @Field(() => POINT_TRANSACTION_STATUS_ENUM)
  status: POINT_TRANSACTION_STATUS_ENUM;

  @ManyToOne(() => User)
  @Field(() => User)
  user: User;

  @CreateDateColumn()
  @Field(() => Date)
  createdAt: Date;
}
// jwt-social-google.strategy.ts

export class JwtGoogleStrategy extends PassportStrategy(Strategy, 'google') {
  constructor() {
    super({
      clientID: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
      callbackURL: 'http://localhost:3000/login/google',
      scope: ['email', 'profile'],
    });
  }

  validate(accessToken, refreshToken, profile) {
    console.log(accessToken);
    console.log(refreshToken);
    console.log(profile);

    return {
      user: profile.displayName,
      isPhone: 'false',
      email: profile.emails[0].value,
      password: '1234',
      phone: '0108222',
      user_id: 'dldl',
      birthday: '960204',
      payment: 'card',
    };
  }
}
//pointsTransactions.module.ts

@Module({
  imports: [
    TypeOrmModule.forFeature([
      PointTransaction, //
      User,
    ]),
  ],
  providers: [
    PointsTransactionsResolver, //
    PointsTransactionsService,
  ],
})
export class PointsTransactionsModule {}
//pointTransactions.resolver.ts

@Resolver()
export class PointsTransactionsResolver {
  constructor(
    private readonly pointsTransactionsService: PointsTransactionsService,
  ) {}

  @UseGuards(GqlAuthGuard('access'))
  @Mutation(() => PointTransaction)
  createPointTransaction(
    @Args('impUid') impUid: string, //
    @Args({ name: 'amount', type: () => Int }) amount: number,
    @Context() context: IContext,
  ): Promise<PointTransaction> {
    const user = context.req.user;
    return this.pointsTransactionsService.create({ impUid, amount, user });
  }
}
//posintsTransactions.service.ts

@Injectable()
export class PointsTransactionsService {
  constructor(
    @InjectRepository(PointTransaction)
    private readonly pointsTransactionsRepository: Repository<PointTransaction>,

    @InjectRepository(User)
    private readonly usersRepository: Repository<User>,
  ) {}

  async create({
    impUid,
    amount,
    user: _user,
  }: IPointsTransactionsServiceCreate): Promise<PointTransaction> {
    // this.pointsTransactionsRepository.create(); // 등록을 위한 빈 객체 생성,db랑 상관없음
    // this.pointsTransactionsRepository.insert(); // 등록은 가능, 결과는 못받아오는 등록방법
    // this.pointsTransactionsRepository.update(); // 결과는 못 받는 수정방법

    // 1. PointTransaction 테이블에 거래기록 1줄 생성
    const pointTransaction = this.pointsTransactionsRepository.create({
      impUid: impUid,
      amount: amount,
      user: _user,
      status: POINT_TRANSACTION_STATUS_ENUM.PAYMENT,
    });
    await this.pointsTransactionsRepository.save(pointTransaction);

    // 2. 유저의 돈 찾아오기
    const user = await this.usersRepository.findOne({
      where: { id: _user.id },
    });

    // 3. 유저의 돈 업데이트
    await this.usersRepository.update(
      { id: _user.id },
      { point: user.point + amount },
    );

    // 4. 최종결과 브라우저에 돌려주기
    return pointTransaction;
  }
}

4. Graphql 실체

Graphql도 rest-api의 확장된 버전이며, rest-api와 아예 다른 것이 아니다!!

rest-api는 각 요청을 할때마다 함수를 계속 실행 시켜줘야 하고 앤드포인트고 계속 늘어나는 under-feching문제점과 모든내용을 받아야만 하는 over-feching문제점이 있있는데, 묶어서 한번에 실행시켜주고 받고 싶은 것만 받는 방법이 없을까?에서 Graphql이 생겨남

Graphql에 매칭되는 3개의 함수를 만들어 놓은후 앤드포인트를 단일화해서 나머지 3개의 함수중에 하나를 골라서 실행시키게 함
또한 바디에 객체 형식으로 함수를 넣어 앞서 말한 3개의 함수중 하나를 고를 수 있게 했다.
=> under-feching문제를 해결했다.

그러므로 graphql은 rest-api에 post형식이다!

하지만 Graphql의 단점도 있다.

  • 아직까진 회사에 REST-API 하는 사람이 더 많음
  • 오픈API는 대부분이 REST-API임
  • 그래프뷰엘은 캐시(임시저장)이 어렵다.
    (앤드포인트가 /graphql로 통일되어 있어 캐싱하기에 난해하다)

0개의 댓글