홈으로 돌아가기
PortOne logo

포트원(아임포트) v1 PortOne(Iamport) v1

PortOne/Iamport v1 결제 시스템

포트원(아임포트) v1은 통합 PG 결제 서비스입니다. Merchant ID를 입력하면 실제 결제 모듈을 테스트해볼 수 있습니다.

API 키 설정

실시간 데모

API 키를 입력하면 실시간 데모를 확인할 수 있습니다.

설정 가이드

1

PortOne 회원가입

PortOne 웹사이트에서 계정을 생성하세요.

2

Merchant ID 확인

PortOne 관리자 페이지에서 Merchant ID를 확인하세요.

3

PG사 설정

사용할 PG사(이니시스, KCP 등)를 설정하세요.

4

웹사이트에 적용

아래 코드를 웹사이트에 추가하세요.

TypeScript 지원

TypeScript를 사용하는 경우 iamport-typings 패키지를 설치하면 PortOne v1 API의 타입 정의를 사용할 수 있어 개발 경험이 향상됩니다.

npm install -D iamport-typings

옵션 1: Next.js Script 컴포넌트 (권장)

Next.js의 Script 컴포넌트를 사용하여 최적화된 스크립트 로딩을 구현합니다.

TypeScript 타입 설치 (선택사항)

bash
npm install -D iamport-typings

Next.js Script 컴포넌트 사용법

tsx
'use client';

import { useState } from 'react';
import Script from 'next/script';
import type { RequestPayResponse } from 'iamport-typings'; // 타입스크립트 사용 시

declare global {
  interface Window {
    IMP: any;
  }
}

function PaymentPage() {
  const [impReady, setImpReady] = useState(false);

  const handleScriptLoad = () => {
    console.log('Iamport 스크립트 로드 완료');
    if (window.IMP) {
      window.IMP.init('YOUR_MERCHANT_ID');
      setImpReady(true);
    }
  };

  const handleScriptError = () => {
    console.error('Iamport 스크립트 로드 실패');
  };

  const requestPay = () => {
    if (!window.IMP || !impReady) {
      alert('결제 모듈이 아직 준비되지 않았습니다.');
      return;
    }
    
    window.IMP.request_pay({
      pg: 'html5_inicis', // PG사
      pay_method: 'card', // 결제수단
      merchant_uid: 'merchant_' + new Date().getTime(), // 주문번호
      name: '상품명',
      amount: 14000,
      buyer_email: 'buyer@example.com',
      buyer_name: '구매자',
      buyer_tel: '010-1234-5678',
      buyer_addr: '서울특별시 강남구',
      buyer_postcode: '12345'
    }, (response: RequestPayResponse) => {
      if (response.success) {
        // 결제 성공
        alert(`결제 성공: ${response.imp_uid}`);
        
        // 서버 검증 API 호출
        // fetch('/api/payments/verify', {
        //   method: 'POST',
        //   headers: { 'Content-Type': 'application/json' },
        //   body: JSON.stringify({
        //     imp_uid: response.imp_uid,
        //     merchant_uid: response.merchant_uid
        //   })
        // });
      } else {
        // 결제 실패
        alert(`결제 실패: ${response.error_msg}`);
      }
    });
  };

  return (
    <>
      {/* Next.js Script 컴포넌트로 최적화된 로딩 */}
      <Script
        src="https://cdn.iamport.kr/v1/iamport.js"
        strategy="afterInteractive" // 페이지 인터랙티브 후 로드
        onLoad={handleScriptLoad}
        onError={handleScriptError}
      />
      
      <div className="p-6">
        <h2 className="text-xl font-bold mb-4">결제 테스트</h2>
        <button
          onClick={requestPay}
          disabled={!impReady}
          className={`px-6 py-3 rounded-lg font-medium transition-colors ${
            impReady 
              ? 'bg-blue-600 text-white hover:bg-blue-700' 
              : 'bg-gray-300 text-gray-500 cursor-not-allowed'
          }`}
        >
          {impReady ? '결제하기' : '로딩중...'}
        </button>
      </div>
    </>
  );
}

옵션 2: React 스크립트 로딩

useEffect 훅을 사용하여 동적으로 스크립트를 로드하는 방식입니다.

React 스크립트 로딩 방식

tsx
'use client';

import { useEffect, useState } from 'react';
import type { RequestPayResponse } from 'iamport-typings'; // 타입스크립트 사용 시

declare global {
  interface Window {
    IMP: any;
  }
}

function PaymentComponent() {
  const [impLoaded, setImpLoaded] = useState(false);

  useEffect(() => {
    // 이미 로드된 경우 스킵
    if (window.IMP) {
      window.IMP.init('YOUR_MERCHANT_ID');
      setImpLoaded(true);
      return;
    }

    const script = document.createElement('script');
    script.src = 'https://cdn.iamport.kr/v1/iamport.js';
    script.async = true;
    script.onload = () => {
      if (window.IMP) {
        window.IMP.init('YOUR_MERCHANT_ID');
        setImpLoaded(true);
      }
    };
    script.onerror = () => {
      console.error('Iamport 스크립트 로드 실패');
    };
    
    document.head.appendChild(script);

    // 클린업
    return () => {
      const existingScript = document.querySelector('script[src="https://cdn.iamport.kr/v1/iamport.js"]');
      if (existingScript) {
        existingScript.remove();
      }
    };
  }, []);

  const requestPay = () => {
    if (!window.IMP) {
      alert('결제 모듈이 아직 로드되지 않았습니다.');
      return;
    }
    
    window.IMP.request_pay({
      pg: 'html5_inicis',
      pay_method: 'card',
      merchant_uid: 'merchant_' + new Date().getTime(),
      name: '상품명',
      amount: 14000,
      buyer_email: 'buyer@example.com',
      buyer_name: '구매자',
      buyer_tel: '010-1234-5678'
    }, (response: RequestPayResponse) => {
      if (response.success) {
        alert(`결제 성공: ${response.imp_uid}`);
      } else {
        alert(`결제 실패: ${response.error_msg}`);
      }
    });
  };

  return (
    <button 
      onClick={requestPay} 
      disabled={!impLoaded}
      className={impLoaded ? 'bg-blue-500 text-white' : 'bg-gray-300 text-gray-500'}
    >
      {impLoaded ? '결제하기' : '로딩중...'}
    </button>
  );
}

중요 안내

위의 두 옵션 중 하나만 선택해서 사용하세요. 두 방식을 동시에 사용하면 스크립트가 중복 로드될 수 있습니다.