Next.js 13 Express 포트원 결제 기능 구현하기

버건디·2023년 8월 31일
0

Next.js

목록 보기
47/52
post-thumbnail
post-custom-banner

가이드 링크


1 . 포트원 사이트에서 회원가입

https://portone.io/korea/ko

2 . 포트원 사이트 내에서 PG 정보 설정하기

현재 포트원에서 결제시스템 구현은 v1과 v2로 나누어져있는데, v2는 베타버전이다.

현재 v2에서는 선택할 수 있는 PG사가 제한되어있으므로, v1으로 구현해야했다.


1 . script 삽입 (layout.tsx)

import Script from "next/script";

    <html
      lang="en"
    >
      <head />
      <Script src="https://cdn.iamport.kr/v1/iamport.js" />

      </body>
    </html>

2. Payment 컴포넌트

"use client";

export default function Payments() {
  const paymentHandler = () => {
    if (!window.IMP) return;
    /* 1. 가맹점 식별하기 */
    const { IMP } = window;
    IMP.init(process.env.NEXT_PUBLIC_IAMPORT_IMP); // 가맹점 식별코드

    /* 2. 결제 데이터 정의하기 */
    const data = {
      pg: "html5_inicis.INIBillTst", // PG사 코드표 참조
      pay_method: "card",
      // 주문번호는 결제창 요청 시 항상 고유 값으로 채번 되어야 합니다.
      // 결제 완료 이후 결제 위변조 대사 작업시 주문번호를 이용하여 검증이 필요하므로 주문번호는 가맹점 서버에서 고유하게(unique)채번하여 DB 상에 저장해주세요
      merchant_uid: `mid_${new Date().getTime()}`, // 주문번호
      name: "노르웨이",
      amount: 100, // 숫자 타입
      buyer_email: "gildong@gmail.com",
      buyer_name: "홍길동",
      // notice_url: "http//localhost:3002/api/payments/webhook",
    };

    /* 4. 결제 창 호출하기 */
    IMP.request_pay(data, callback);
  };

  async function callback(rsp: any) {
    const { success, error_msg, merchant_uid, imp_uid } = rsp;

    console.log("imp_uid : ", imp_uid);

    if (success) {
      const res = await fetch("ENDPOINT", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          imp_uid: imp_uid,
          merchant_uid: merchant_uid,
        }),
      });

      const data = await res.json();

      console.log("data : ", data);
    } else {
      alert(`결제 실패: ${error_msg}`);
    }
  }

  return (
    <>
      <button onClick={paymentHandler}>
        결제하기
      </button>
    </>
  );
}

PG사 코드표

결제 창이 나오는데, 결제창에서 카드정보를 입력하고 결제 완료를 누르면

백엔드쪽의 엔드포인트로 imp_uid와 merchant_uid가 넘어간다.

- Express 코드

import { Request, Response, NextFunction } from "express";
import axios from "axios";
import * as dotenv from "dotenv";

dotenv.config();

export const completePayment = async (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  const { imp_uid, merchant_uid } = req.body;

  try {
    const getToken = await axios({
      url: "https://api.iamport.kr/users/getToken",
      method: "post", // POST method
      headers: { "Content-Type": "application/json" }, // "Content-Type": "application/json"
      data: {
        imp_key: process.env.IAMPORT_API_KEY, // REST API키
        imp_secret: process.env.IAMPORT_API_SECRET, // API SECRET 키
      },
    });
    const { access_token } = getToken.data.response;

    const getPaymentData = await axios({
      // imp_uid 전달
      url: `https://api.iamport.kr/payments/${imp_uid}`,
      // GET method
      method: "get",
      // 인증 토큰 Authorization header에 추가
      headers: { Authorization: access_token },
    });

    const paymentData = getPaymentData.data.response;

    console.log("paymentData : ", paymentData);
    
    // ... 이후 비즈니스 로직

  } catch (error) {
    console.log(error);
  }

  return res.json({ message: "message" });
};

결제가 정상적으로 완료 되면 콘솔값이 이렇게 출력되고 그 후에 자유롭게 DB에 저장해주면 된다!


결제 후에 웹훅이란것을 따로 설정해주어야하는데, 가이드 대로 ngrok을 설치해서 localhost를 포워딩 해주었는데도 잘못된 URL이라는 에러가 떴다.

포트원 쪽으로 문의를 남겼는데, Postman이나 Insomnia 같은 도구를 활용해야한다는 답변이 왔다.

테스트 연동은 일단 웹훅을 배제하고 하고 나중에 배포후에 연동 시켜주어야할 것 같다.

profile
https://brgndy.me/ 로 옮기는 중입니다 :)
post-custom-banner

0개의 댓글