정기결제 연동하기


해당 가이드는 아임포트의 정기 결제 기능을 구현하는 방법을 안내합니다.아임포트의 REST API 또는 JavsScript 라이브러리로 빌링키를 발급받습니다. 그 후 REST API로 결제를 청구하고 정기 결제를 예약할 수 있습니다.
STEP1빌링키 발급받기
고객의 카드정보를 카드사에 전달하고 해당 카드에 대응하는 빌링키를 발급받는 단계입니다.

빌링키란?

구독형 정기결제, 종량제 과금결제 등 원하는 시점에 재결제를 진행할 수 있는 결제용 암호화 키 입니다. 가맹점이 고객의 카드정보를 소유할 수 없기 때문에 카드사로부터 해당 카드에 대응하는 빌링키를 발급 받습니다. 이때 발급받은 빌링키를 저장하고, 원하는 시점에 해당 빌링키로 결제를 청구할 수 있습니다. 빌링키 발급을 위해서는 카드사에 카드번호, 카드 유효기간, 생년월일(또는 사업자등록번호), 비밀번호 앞 2자리를 전달합니다.
빌링키를 발급받는 방식은 PG사에 따라 크게 두가지로 나뉩니다.
  • A. REST API를 통해 빌링키를 발급받는 방식(나이스정보통신, JTNet)
  • B. 일반결제창을 통해 빌링키를 발급받는 방식(JTNet, 이니시스, 다날-신용카드, 다날-휴대폰, 모빌리언스)

A. REST API를 통해 빌링키를 발급받는 방식

나이스정보통신을 사용하여 정기결제를 진행하는 경우에는 아임포트에서 제공하는 REST API를 통해 빌링키를 발급받습니다. 가맹점 서버가 아임포트 REST API를 사용하여 아임포트 서버에 카드정보를 전달하면, 아임포트 서버가 PG사의 API를 호출하는 방식으로 구성됩니다. 여기에서 아임포트 서버는 카드정보를 PG사에게 전달하는 역할을 담당합니다. 이 과정에서 카드정보는 기록하지 않습니다.해당 방식은 다음과 같은 특징이 있습니다.
  • 장점: 가맹점이 원하는 형태의 화면으로 카드정보 입력란을 커스터마이징할 수 있습니다.
  • 단점: 카드정보 전달과정의 보안프로세스를 구축해야하며, 개인정보 이용약관을 명시해야 합니다.
다음의 과정을 통해 REST API방식으로 빌링키를 발급받는 절차를 구현할 수 있습니다.
  1. 카드 정보 입력란 작성하기
  2. API Endpoint 생성 및 카드 정보 추출하기
  3. REST API로 빌링키 발급하기
1카드 정보 입력란 작성하기
카드 정보를 입력하는 필드를 작성합니다. 빌링키 발급을 위해 유저가 카드 번호, 카드 유효기간, 생년월일, 카드 비밀번호 앞 두자리를 입력할 수 있도록 합니다. 법인카드(단, 개인명의로 발급된 기명카드는 제외)의 경우 birth 파라메터에 사업자번호 10자리를 입력하시면 됩니다.
  <form action="https://www.myservice.com/subscription/issue-billing" method="post">
    <div>
        <label for="card_number">카드 번호 XXXX-XXXX-XXXX-XXXX</label>
        <input id="card_number" type="text" name="card_number">
    </div>
    <div>
        <label for="expiry">카드 유효기간 YYYY-MM</label>
        <input id="expiry" type="text" name="expiry">
    </div>
    <div>
        <label for="birth">생년월일 YYMMDD</label>
        <input id="birth" type="text" name="birth">
    </div>
    <div>
        <label for="pwd_2digit">카드 비밀번호 앞 두자리 XX</label>
        <input id="pwd_2digit" type="text" name="pwd_2digit">
    </div>
    <input hidden type="text" value="gildong_0001_1234" name="customer_uid">
    <input type="submit" value="결제하기">
  </form>
유저가 카드 번호, 카드 유효기간, 생년월일, 카드 비밀번호 앞 두자리를 입력할 수 있는 필드를 생성했습니다. 결제하기 버튼을 클릭하면 필드의 내용이 /subscription/issue-billing에 대해 POST요청이 생성됩니다. 이때 유저의 카드를 가르키는 값(customer_uid)을 함께 전달합니다.

customer_uid 속성

고객의 카드 정보를 통해 발급한 결제용 암호화 키인 빌링키는, 발급 후 아임포트 서버에 저장됩니다. 보안상의 이유로 가맹점은 빌링키에 직접 접근할 수 없기 때문에 customer_uid속성으로 지정한 값을 unique key로 활용하여 아임포트 서버에 저장됩니다. 즉, customer_uid값은 빌링키(카드 한 장)와 1:1로 대응합니다.

만약 고객으로부터 여러장의 카드를 등록받는 상황이라면, customer_uid를 카드 한 장에 대응하도록 값을 구성해야 합니다. 예를들어, 고객의 unique key가 gildong_0001이고 카드 뒤 네자리 번호가 1234라면, customer_uid속성의 값은 gildong_0001_1234와 같이 구성하여 특정 고객의 특정 카드를 가르킬 수 있습니다.
2API Endpoint 생성 및 카드 정보 추출하기
카드 정보를 전달받을 API Endpoint를 생성하고 요청에 담긴 카드 정보를 추출합니다.
  // "/subscription/issue-billing"에 대한 POST 요청을 처리
  app.post("/subscriptions/issue-billing", async (req, res) => {
    try {
      const {
        card_number, // 카드 번호
        expiry, // 카드 유효기간
        birth, // 생년월일
        pwd_2digit, // 카드 비밀번호 앞 두자리,
        customer_uid, // 카드(빌링키)와 1:1로 대응하는 값
      } = req.body; // req의 body에서 카드정보 추출
      ...
    } catch (e) {
      res.status(400).send(e);
    }
  });
위의 코드는 /subscription/issue-billing에 대한 POST요청을 처리하는 API입니다. HTTP request의 body에 담긴 card_number, expiry, birth, pwd_2digit, customer_uid를 추출했습니다.
3REST API로 빌링키 발급하기
https:\//api.iamport.kr/subscribe/customers/{customer_uid}에 대해 HTTP 요청을 생성하여 빌링키를 발급받습니다.
  // "/subscription/issue-billing"에 대한 POST 요청을 처리
  app.post("/subscriptions/issue-billing", async (req, res) => {
    try {
      const {
        card_number, // 카드 번호
        expiry, // 카드 유효기간
        birth, // 생년월일
        pwd_2digit, // 카드 비밀번호 앞 두자리
        customer_uid, // 카드(빌링키)와 1:1로 대응하는 값
      } = req.body; // req의 body에서 카드정보 추출
      ...
      // 인증 토큰 발급 받기
      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: "imp_apikey", // REST API키
          imp_secret: "ekKoeW8RyKuT0zgaZsUtXXTLQ4AhPFW3ZGseDA6bkA5lamv9OqDMnxyeB9wqOsuO9W3Mx9YSJ4dTqJ3f" // REST API Secret
        }
      });
      const { access_token } = getToken.data.response; // 인증 토큰
      ...
      // 빌링키 발급 요청
      const issueBilling = await axios({
        url: \`https://api.iamport.kr/subscribe/customers/\${customer_uid}\`,
        method: "post",
        headers: { "Authorization": access_token }, // 인증 토큰 Authorization header에 추가
        data: {
          card_number, // 카드 번호
          expiry, // 카드 유효기간
          birth, // 생년월일
          pwd_2digit, // 카드 비밀번호 앞 두자리
        }
      });
      ...
      const { code, message } = issueBilling.data;
      if (code === 0) { // 빌링키 발급 성공
        res.send({ status: "success", message: "Billing has successfully issued" });
      } else { // 빌링키 발급 실패
        res.send({ status: "failed", message });
      }
    } catch (e) {
      res.status(400).send(e);
    }
  });
위의 코드에서, 결제정보를 조회하기 위해 아임포트 계정에 발급되는 REST API키REST API Secret으로 인증 토큰을 발급받았습니다. 인증토큰 발급은 https:\//api.iamport.kr/users/getTokenContent-Typeapplication/json, 그리고 body에 imp_key: REST API키, imp_secret: REST API Secret을 포함하여 POST방식으로 요청을 생성했습니다.

해당 요청에 대한 응답이 오면, 응답 데이터에 담겨있는 인증토큰인 access_token을 저장합니다. 그 다음 https:\//api.iamport.kr/subscribe/customers/{customer_uid}customer_uid를 작성하고 Authorization에 발급받은 인증토큰인 access_token을 지정한 후, 카드 정보인 card_number, expiry, birth 그리고 pwd_2digit데이터와 함께 POST방식으로 요청을 생성하여 빌링키 발급 요청을 생성했습니다.

빌링키 발급 요청에 대한 응답의 code속성의 값이 0이면 빌링키 발급에 성공한 것입니다. 결과에 따라 적절한 서버응답을 생성합니다.

발급과 동시에 결제하기

아임포트 REST API인 /subscribe/payments/onetime를 활용하면 빌링키 발급과 결제 요청을 동시에 처리할 수 있습니다.

B. 일반결제창을 통해 빌링키를 발급받는 방식

JTNet, 이니시스, 다날-신용카드, 다날-휴대폰, 모빌리언스을 사용하여 정기결제를 진행하는 경우에는 PG사가 제공하는 일반결제창을 통해 빌링키를 발급받습니다. PG사의 일반 결제창에 고객이 카드정보를 입력하여 결제 프로세스가 진행됩니다.해당 방식은 다음과 같은 특징이 있습니다.
  • 장점: 카드정보가 가맹점의서버 또는 아임포트의 서버를 거치지 않고 직접 PG사로 전달되기 때문에 데이터 및 통신구간 암호화 등의 추가 보안 프로세스가 필요하지 않습니다.
  • 단점: PG사의 일반결제창을 통해 카드정보를 입력받기때문에 웹브라우저 인터페이스를 통해서만 빌링키 발급이 이루어지며, 카드정보 입력란을 커스터마이징 할 수 없습니다.
빌링키 발급을 위해 iamport.payment.jsIMP.request_pay(param, callback)와 동일한 연동방법을 사용합니다. 코드 설치 방법은 일반결제 연동 페이지에서 확인할 수 있습니다. 해당 방식은 다음의 과정을 통해 구현할 수 있습니다.
  1. 결제창 호출하기
  2. 결제 요청하기
1결제창 호출하기
IMP.request_pay(param, callback)을 호출합니다. 함수의 첫번째 인자인 param에 결제 요청에 필요한 속성과 값을 담습니다. 해당 과정을 통해 빌링키가 발급됩니다.
  // IMP.request_pay(param, callback) 호출
  IMP.request_pay({ // param
    pg: "html5_inicis",
    pay_method: "card", // "card"만 지원됩니다
    merchant_uid: "issue_billingkey_monthly_0001", // 빌링키 발급용 주문번호
    customer_uid: "gildong_0001_1234", // 카드(빌링키)와 1:1로 대응하는 값
    name: "최초인증결제",
    amount: 0, // 0 으로 설정하여 빌링키 발급만 진행합니다.
    buyer_email: "gildong@gmail.com",
    buyer_name: "홍길동",
    buyer_tel: "010-4242-4242",
    buyer_addr: "서울특별시 강남구 신사동",
    buyer_postcode: "01181"
  }, function (rsp) { // callback
    if (rsp.success) {
      // 빌링키 발급 성공
    } else {
      // 빌링키 발급 실패
    }
  });
IMP.request_pay(param, callback)을 호출하면 PC 환경에서는 지정한 pg사의 결제모듈 창이 나타납니다. 반면 모바일 환경에서는 pg사의 웹사이트로 리다이렉트하는 프로세스를 제공하는 pg사도 있습니다.

빌링키 발급을 위해 IMP.request_pay를 호출 할때에는 다음의 param속성의 조건을 만족해야합니다.
  • pay_method 속성을 card로 지정: 정기결제는 신용/직불카드로만 결제가 가능하기 때문에 card로 지정합니다.
  • amount 속성을 0으로 지정: 실제로 결제를 진행하는것이 아니고 빌링키를 발급하기 위한 것이므로 0으로 지정합니다.
  • customer_uid 속성 지정: 빌링키에 1:1로 대응하는 값으로써, 해당 속성에 지정한 값으로 반복 결제를 시도할 것이기 때문에 고유(unique)한 고객 번호를 지정합니다.

모바일 웹 환경

KG이니시스, LG U+, NHN KCP, 나이스정보통신, JTNet, KICC는 PC 환경과 달리, 모바일 웹 환경에서 각 pg사의 웹사이트로 리다이렉트되어 결제를 진행하는 프로세스를 제공합니다. 따라서 해당 pg사를 사용하는 경우에는 m_redirect_url을 지정하는 등의 추가 작업이 필요합니다. 해당 내용은 일반결제 연동하기> Step 7.모바일 웹 환경에 대응하기에서 확인할 수 있습니다.

pg사별 설정 차이

사용하는 pg사에 따라 pg사가 요구하는 param의 정책이 다르기 때문에 반드시 pg사별 예제를 참고해주세요. pg사별 예제에서 확인할 수 있습니다.
2customer_uid 및 주문 정보 전달하기
그 다음, 클라이언트에서 빌링키가 성공적으로 발급되었으면 customer_uid를 서버에 전달합니다. 서버에서는 해당 customer_uid를 통해 차후에 결제를 요청할 수 있습니다.
  // IMP.request_pay(param, callback) 호출
  IMP.request_pay({ // param
    /* ...중략... */
  }, function (rsp) { // callback
    if (rsp.success) {
      // 빌링키 발급 성공
      // jQuery로 HTTP 요청
      jQuery.ajax({
        url: "https://www.myservice.com/billings/", // 서비스 웹서버
        method: "POST",
        headers: { "Content-Type": "application/json" },
        data: {
          customer_uid: "gildong_0001_1234", // 카드(빌링키)와 1:1로 대응하는 값
        }
      });
    } else {
      // 빌링키 발급 실패
    }
  });
서버에서는 클라이언트로부터 customer_uid를 전달받는 API endpoint를 생성합니다.
  // "/billings" 에 대한 POST 요청을 처리
  app.post("/billings", async (req, res) => {
    try {
      const { customer_uid } = req.body; // req body에서 customer_uid 추출
        ...
    } catch (e) {
      res.status(400).send(e);
    }
  });
클라이언트는 빌링키에 1:1로 대응하는 customer_uid를 전달했습니다. 서버에서는 이 값을 전달받는 API Endpoint를 생성했습니다. 차후에 customer_uid를 통해 결제를 요청하고, 주문정보를 함께 담아 결제를 요청할 것입니다.
STEP2결제 요청하기
https:\//api.iamport.kr/subscribe/payments/again에 대해 HTTP 요청을 생성하여 결제를 시도합니다.
  // "/billings" 에 대한 POST 요청을 처리하는 controller
  app.post("/billings", async (req, res) => {
    try {
      const { customer_uid } = req.body; // req의 body에서 customer_uid 추출
      // 인증 토큰 발급 받기
      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: "imp_apikey", // REST API키
          imp_secret: "ekKoeW8RyKuT0zgaZsUtXXTLQ4AhPFW3ZGseDA6bkA5lamv9OqDMnxyeB9wqOsuO9W3Mx9YSJ4dTqJ3f" // REST API Secret
        }
      });
      const { access_token } = getToken.data.response; // 인증 토큰
      ...
      // 결제(재결제) 요청
      const paymentResult = await axios({
        url: \`https://api.iamport.kr/subscribe/payments/again\`,
        method: "post",
        headers: { "Authorization": access_token }, // 인증 토큰 Authorization header에 추가
        data: {
          customer_uid,
          merchant_uid: "order_monthly_0001", // 새로 생성한 결제(재결제)용 주문 번호
          amount: 8900,
          name: "월간 이용권 정기결제"
        }
      });
      ...
      const { code, message } = paymentResult;
      if (code === 0) { // 카드사 통신에 성공(실제 승인 성공 여부는 추가 판단이 필요합니다.)
        if ( paymentResult.status === "paid" ) { //카드 정상 승인
          res.send({ ... });
        } else { //카드 승인 실패 (ex. 고객 카드 한도초과, 거래정지카드, 잔액부족 등)
          //paymentResult.status : failed 로 수신됩니다.
          res.send({ ... });
        }
        res.send({ ... });
      } else { // 카드사 요청에 실패 (paymentResult is null)
        res.send({ ... });
      }
    } catch (e) {
      res.status(400).send(e);
    }
  });
먼저, 빌링키에 대응하는 customer_uid를 추출합니다.

그 다음, 인증을 위해 아임포트 계정에 발급되는 REST API키와 REST API Secret으로 인증 토큰을 발급받았습니다. 인증토큰 발급은 https:\//api.iamport.kr/users/getToken에 대해 Content-Typeapplication/json, 그리고 body에 imp_key: { REST API키 }, imp_secret: { REST API Secret }을 포함하여 POST방식으로 요청을 생성했습니다.

해당 요청에 대한 응답이 오면, 응답 데이터에 담겨있는 인증토큰인 access_token을 저장합니다. 그 다음 https:\//api.iamport.kr/subscribe/payments/again에 대해 Authorization에 발급받은 인증토큰인 access_token을 지정하고 customer_uid,merchant_uid, amount 그리고 name 데이터와 함께 POST방식으로 요청을 생성하여 결제를 요청했습니다.
STEP3결제 예약하기
고객이 카드정보를 입력하여 빌링키를 발급받고, 정기결제 상품을 구매했으면 미래의 시점에 반복적으로 결제를 청구해야 합니다. 이때 아임포트의 REST API 중 /subscribe/payments/schedule를 활용하여 미래의 특정 시점에 결제를 시도하도록 예약할 수 있습니다.
1예약 등록하기
아임포트 REST API인 /subscribe/payments/schedule에 대해 요청을 생성하여 결제를 예약합니다. 빌링키에 대응하는 고객 번호를 customer_uid속성에 지정하고 schedules속성에 주문 및 예약 시각의 정보를 지정합니다. schedules속성은 array타입이므로 한번의 요청에 복수의 주문정보를 입력할 수 있습니다.

schedules의 각 항목에는 merchant_uid, schedule_at, amount속성을 반드시 작성해야 합니다.
  // 결제 예약
  axios({
    url: \`https://api.iamport.kr/subscribe/payments/schedule\`,
    method: "post",
    headers: { "Authorization": access_token }, // 인증 토큰 Authorization header에 추가
    data: {
      customer_uid: "gildong_0001_1234", // 카드(빌링키)와 1:1로 대응하는 값
      schedules: [
        {
          merchant_uid: "order_monthly_0001", // 주문 번호
          schedule_at: 1519862400, // 결제 시도 시각 in Unix Time Stamp. ex. 다음 달 1일
          amount: 8900,
          name: "월간 이용권 정기결제",
          buyer_name: "홍길동",
          buyer_tel: "01012345678",
          buyer_email: "gildong@gmail.com"
        }
      ]
    }
  });
위의 예제 코드에서는 /subscribe/payments/schedule에 대해 POST방식으로 요청을 생성했습니다. 요청 body에는 customer_uid속성에 고객 번호를 지정하고 schedules속성에 한개의 주문 항목을 작성했습니다.

주문 항목에서는 merchant_uid속성에 주문 고유 번호를 지정했고 scheduled_at속성에 결제 시도 시각을 unix timestamp로 지정했습니다. 그리고 amount속성에 결제 요청 금액을 지정하고 고객정보를 지정했습니다.

/subscribe/payments/schedule

/subscribe/payments/schedule에 대한 요청 속성은 아임포트 API 문서에서 자세히 볼 수 있습니다.
2결제 결과 동기화하기
예약한 시간에 결제가 시도되면 아임포트 Webhook이 호출되어 지정한 콜백 url에 imp_uidmerchant_uid를 전달하게 됩니다. 가맹점 서버는 전달받은 imp_uid값으로 아임포트 서버에서 결제 정보를 조회한 후, 결제 상태에 따라 알맞은 로직을 수행합니다.

아임포트 Webhook

아임포트 Webhook을 활용하여 예약한 결제가 시도된 후, 결제 성공여부를 확인하고 결과에 따라 결제 정보를 데이터베이스에 저장하며, 다음 결제를 예약할 수 있습니다. 아임포트 Webhook 문서에서 아임포트 Webhook의 개념과 콜백 url을 설정하는 방법을 자세히 살펴볼 수 있습니다.
먼저, 아임포트 webhook이 호출될 때 전송되는 POST요청을 처리할 endpoint를 생성합니다.
  // "/iamport-callback/schedule"에 대한 POST 요청을 처리
  app.post("/iamport-callback/schedule", async (req, res) => {
    try {
      const { imp_uid, merchant_uid } = req.body;
      ...
    } catch (e) {
      res.status(400).send(e);
    }
  });
/iamport-webhook/iamport-callback에 대한 POST요청을 처리하는 endpoint를 생성했습니다. HTTP request의 body에 담긴 imp_uidmerchant_uid를 추출했습니다.

그 다음, imp_uid를 통해 결제 정보를 조회합니다. 결제가 성공적으로 완료 되었으면, 해당 결제 정보를 데이터베이스에 저장합니다.
  // "/iamport-callback/schedule"에 대한 POST 요청을 처리
  app.post("/iamport-callback/schedule", async (req, res) => {
    try {
      const { imp_uid, merchant_uid } = req.body;
      // 액세스 토큰(access token) 발급 받기
      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: "imp_apikey", // REST API키
          imp_secret: "ekKoeW8RyKuT0zgaZsUtXXTLQ4AhPFW3ZGseDA6bkA5lamv9OqDMnxyeB9wqOsuO9W3Mx9YSJ4dTqJ3f" // REST API Secret
        }
      });
      const { access_token } = getToken.data.response; // 인증 토큰
      // imp_uid로 아임포트 서버에서 결제 정보 조회
      const getPaymentData = await axios({
        url: \`https://api.iamport.kr/payments/\${imp_uid}\`, // imp_uid 전달
        method: "get", // GET method
        headers: { "Authorization": access_token } // 인증 토큰 Authorization header에 추가
      });
      const paymentData = getPaymentData.data.response; // 조회한 결제 정보
      const { status } = paymentData;
      if (status === "paid) { // 결제 완료
        // DB에 결제 정보 저장
        await Orders.findByIdAndUpdate(merchant_uid, { $set: paymentData }); // Mongoose
        ...
      } else {
        // 재결제 시도
      }
    } catch (e) {
      res.status(400).send(e);
    }
  });
위의 코드에서, 인증을 위해 아임포트 계정에 발급되는 REST API키REST API Secret으로 액세스 토큰을 발급받았습니다. 액세스 토큰 발급은 https:\//api.iamport.kr/users/getToken에 대해 "Content-Type""application/json", 그리고 body에 imp_key: REST API키, imp_secret: REST API Secret을 포함하여 POST방식으로 요청을 생성했습니다.

해당 요청에 대한 응답이 오면, 응답 데이터에 담겨있는 액세스 토큰인 access_token을 저장합니다. 그 다음 https:\//api.iamport.kr/payments/{imp_uid}imp_uid를 작성하고 "Authorization"에 발급받은 액세스 토큰인 access_token을 지정하고 GET방식으로 요청을 생성하여 결제정보를 조회했습니다.

그 다음, 조회한 결제 정보의 결제 상태(status)를 통해 결제 완료 여부를 파악하고, 결제가 완료 되었으면 결제 데이터를 가맹점의 데이터베이스에 동기화합니다.
STEP4반복적인 결제 구현하기
/subscribe/payments/schedule로 원하는 시점에 결제를 시도하도록 예약할 수 있기 때문에, 아임포트 webhook을 활용하여 반복적인 결제를 구현할 수 있습니다. 예약한 결제가 시도될 때마다 webhook이 호출되어 가맹점 서버가 콜백 url을 통해 결제 정보를 수신하고, 결제가 성공했음을 확인하면 다음 결제를 예약하는 방식으로 반복적인 결제를 구현할 수 있습니다.

3단계에 이어, 조회한 결제가 완료되었음을 확인한 후, 새로운 결제를 예약합니다.
  // "/iamport-callback/schedule"에 대한 POST 요청을 처리
  app.post("/iamport-callback/schedule", async (req, res) => {
    try {
      const { imp_uid, merchant_uid } = req.body;
      // 액세스 토큰(access token) 발급 받기
      /* ...중략 ... */
      // imp_uid로 아임포트 서버에서 결제 정보 조회
      /* ...중략 ... */
      const paymentData = getPaymentData.data.response; // 조회한 결제 정보
      const { status } = paymentData;
      if (status === "paid) { // 결제 완료
        // DB에 결제 정보 저장
        await Orders.findByIdAndUpdate(merchant_uid, { $set: paymentData }); // Mongoose
        ...
        // 새로운 결제 예약
        axios({
          url: \`https://api.iamport.kr/subscribe/payments/schedule\`,
          method: "post",
          headers: { "Authorization": access_token }, // 인증 토큰 Authorization header에 추가
          data: {
            customer_uid: "gildong_0001_1234", // 카드(빌링키)와 1:1로 대응하는 값
            schedules: [
              {
                merchant_uid: "order_monthly_0001", // 주문 번호
                schedule_at: 1519516800, // 결제 시도 시각 in Unix Time Stamp. ex. 다음 달 1일
                amount: 8900,
                name: "월간 이용권 정기결제",
                ...
              }
            ]
          }
        });
      } else {
        // 재결제 시도
      }
    } catch (e) {
      res.status(400).send(e);
    }
  });
위의 코드 예제에서, 결제가 완료됨(status === "paid")을 확인하고 데이터베이스에 결제 내역을 저장한 뒤, scheduled_at속성에 다음에 결제를 시도할 시각을 unix timestamp로 지정했습니다.