LogoLogo
  • 포트원 서비스 업데이트 안내
    • 관리자콘솔 릴리즈노트
      • 2023-05-08 업데이트
      • 2023-04-24 업데이트
    • API/SDK 릴리즈노트
      • 2023-05-08 업데이트
      • 2023-04-24 업데이트
  • 🧩포트원 결제 연동 Docs
    • 🚗GET STARTED
  • 🛫결제 연동 준비하기
    • 🖥️1. 포트원 회원가입 하기
    • 🧷2. PG정보 설정하기
      • 🏢Payment Gateway
        • ⌨️NHN KCP 설정
        • ⌨️KG 이니시스 설정
        • ⌨️NICE페이먼츠 설정
        • ⌨️토스페이먼츠 설정
        • ⌨️KSNET 설정
        • ⌨️KICC 설정
        • ⌨️페이먼트월 설정
        • ⌨️다우 설정
        • ⌨️다날 설정
        • ⌨️JTNET 설정
        • ⌨️핵토파이낸셜 설정
          • 🚩내통장 결제
        • ⌨️KG모빌리언스 설정
        • ⌨️스마트로 설정
        • ⌨️페이팔 설정
        • ⌨️페이팔 SPB 일반결제 설정
        • ⌨️엑심베이 설정
        • ⌨️블루월넛 설정
      • ⛺간편 결제사
        • ⌨️네이버페이(결제형) 설정
        • ⌨️카카오페이 설정
        • ⌨️페이코 설정
        • ⌨️알리페이 설정
        • ⌨️토스간편결제 설정
    • ✔️3. 연동정보 확인하기
  • 결제창 연동하기
    • 🖥️인증결제 연동하기
      • 📒인증결제 정의
      • 🌠1. 포트원 라이브러리 추가
      • 💡2. 객체 초기화 하기
      • 🪧3. 결제 요청하기
      • 🎁4. 결제결과 처리하기
        • 🪟iframe 결제창 결과처리
        • 🖼️redirect 결제창 결과처리
      • 🔦5. 결제정보 검증하기
        • ⬅️결제정보 사전 검증하기
        • ➡️결제정보 사후 검증하기
      • 🛬6. 결제완료 처리하기
    • ⏰비 인증결제 연동하기
      • 🏍️빌링키 결제 요청하기
        • 🖱️REST API 이용하기
        • 🛡️PG결제창 이용하기
      • 💳카드정보를 이용한 키인결제
      • 🪧빌링키를 이용한 정기결제
    • 💸결제취소(환불) 연동하기
      • 💷가상계좌 환불하기
  • 결제결과 연동하기
    • ⚒️웹훅(Webhook) 연동하기
    • ✔️가상결제 입금통보 설정
  • 기타 서비스 연동하기
    • 📱휴대폰 본인인증 연동하기
      • 📔1. 본인인증 준비하기
      • 🥏2. 본인인증창 호출하기
      • 🚚3. 인증 완료정보 전달하기
      • 🤹4. 인증정보 조회 및 활용하기
    • 🚚통합인증 연동하기
      • 📒통합인증 준비하기
      • 🥏통합인증 요청하기
      • 🚚인증 완료정보 전달하기
      • 🤹인증정보 조회 및 활용하기
    • 💳신용카드 본인인증 연동
      • 📒1. 본인인증 준비하기
      • 🥏2. 본인인증 요청하기
      • 🚚3. 인증 완료정보 전달하기
      • 🤹4. 인증정보 조회 및 활용하기
    • 💻결제 URL 생성하기
    • 🛩️버짓핸들러 연동하기
    • 📟네이티브 모바일 SDK
  • TIP
    • 🌽결제금액 면세 적용방법
    • ✅오픈 전 체크사항
    • 🔏Confirm Process
    • 🎼포트원 결제 FLOW
    • 🎈Agency & Tier 란?
    • 📦PG사별 빌링키 획득 규칙
    • 🏦PG사별 은행코드표
    • 🧾PG사 코드표
    • 🚚택배사 코드표
    • 🪧리디렉션이란?
    • 📰PG사 오류코드
  • 관리자 콘솔 사용하기
    • 🎡관리자 콘솔 가이드
      • 전자결제 신청
      • 내 식별코드, API Keys
      • 관리자 및 하위 상점 계정 관리
      • 결제 연동 하기
      • 결제 내역
    • 💻복수 PG설정 및 사용하기
  • API
    • 📋포트원 API 소개
    • 🖇️REST API Access Token
    • 💳결제관련 API
      • ⌨️결제취소 API
      • ⌨️결제내역 단건조회 API
      • ⌨️결제내역 복수조회 API
      • ⌨️결제상태기준 복수조회 API
      • ⌨️결제 복수조회(주문All) API
      • ⌨️결제 복수조회(주문UQ) API
      • ⌨️빌링키 결제 복수조회 API
      • ⌨️결제금액 사전등록 API
      • ⌨️결제금액 단건 수정 API
      • ⌨️결제금액 단건조회
      • ⌨️결제 상세내역 조회 API
    • 📝빌링키 관리 API
      • ⌨️빌링키 발급 API
      • ⌨️빌링키 삭제 API
      • ⌨️빌링키 정보 단건조회 API
      • ⌨️빌링키 정보 복수조회 API
      • ⌨️빌링키 결제예약 조회 API
    • 🧭정기결제 관련 API
      • ⌨️결제 예약 API
      • ⌨️결제 예약취소 API
      • ⌨️결제예약 복수조회 API
      • ⌨️결제예약 단건조회 API
      • ⌨️결제예약 복수조회(빌키) API
    • 🪂비 인증 결제관련 API
      • ⌨️비 인증 결제(빌링키) API
      • ⌨️비 인증 결제(일회성) API
    • 🌏해외PG 관련 API
      • ⌨️페이먼트월 배송등록 API
    • 👮본인인증 관련 API
      • ⌨️본인인증 결과조회 API
      • ⌨️본인인증 정보삭제 API
      • ⌨️본인인증 요청 API
      • ⌨️본인인증 완료 API
    • 🎫간편결제 서비스 API
      • 🧽카카오페이
        • ⌨️주문내역 조회 API
      • 🛩️KCP Quick Pay
        • ⌨️구매자 정보 단건 삭제 API
      • 🧰페이코
        • ⌨️주문상태 단건 수정 API
      • 📗네이버페이 결제형
        • ⌨️에스크로 주문확정 API
        • ⌨️포인트 적립 API
        • ⌨️현금영수증 발급 가용액 조회 API
    • 🏦에스크로 관련 API
      • ⌨️배송정보 단건조회 API
      • ⌨️배송정보 단건등록 API
      • ⌨️배송정보 단건수정 API
    • 💵현금영수증 API
      • ⌨️포트원 발급분 취소 API
      • ⌨️발급내역 단건 조회 API
      • ⌨️현금영수증 단건발급 API
      • ⌨️외부 발급분 취소 API
      • ⌨️외부 발급내역 단건 조회 API
      • ⌨️현금영수증 발급(외부) API
    • 🏛️가상계좌 관련 API
      • ⌨️가상계좌 발급 API
      • ⌨️가상계좌 발급취소 API
      • ⌨️가상계좌 발급정보 수정 API
      • ⌨️예금주 조회 API
    • 🍶기타 API
      • 🎽베네피아 포인트
        • ⌨️포인트 단건조회 API
        • ⌨️포인트 결제 요청
      • 🏪편의점 결제
        • ⌨️수납번호 발급 API
        • ⌨️수납취소 API
      • 🗃️기관코드 조회
        • ⌨️카드사코드 전체조회 API
        • ⌨️카드사명 단건조회 API
        • ⌨️은행코드 전체조회 API
        • ⌨️은행명 단건조회 API
      • 🛖PG 정보
        • ⌨️PG MID 복수조회 API
  • SDK
    • 🔖JavaScript SDK
      • 💿결제요청 파라미터
      • 📀결제응답 파라미터
      • 💿본인인증 요청 파라미터
      • 📀본인인증 결과 파라미터
    • 📚JavaScript SDK (구버전)
      • ✏️SDK Release Note
  • FAQ
    • ⁉️자주 묻는 질문
  • 🔑PG사별 결제 연동 가이드
    • 🏢Payment Gateway
      • ⌨️NHN KCP
      • ⌨️KG 이니시스
      • ⌨️토스페이먼츠 (구 모듈)
      • ⌨️토스페이먼츠
        • 📍연동 유의사항
      • ⌨️(주)케이에스넷
        • 🚩연동 주의사항
      • ⌨️NICE페이먼츠
      • ⌨️KICC
      • ⌨️다우 (키움페이/페이조아)
        • 📍페이조아 유의사항
      • ⌨️KG모빌리언스
      • ⌨️페이먼트월
      • ⌨️다날
      • ⌨️핵토파이낸셜
        • 🏦내통장 결제
      • ⌨️JTNET
      • ⌨️스마트로
      • ⌨️페이팔
      • ⌨️페이팔 SPB 일반결제
        • 😲연동 유의사항
      • ⌨️엑심베이
      • ⌨️블루월넛
    • ⛺간편 결제사
      • ⌨️네이버페이(결제형)
      • ⌨️카카오페이
      • ⌨️페이코
      • ⌨️알리페이
      • ⌨️토스 간편결제
  • 워드프레스 플러그인 사용하기
    • 워드프레스 플러그인
      • 우커머스 플러그인
        • 일반결제 연동하기
        • 정기결제 연동하기
        • 가상계좌 입금통보 URL 설정하기
      • Easy Digital Downloads 플러그인
      • 결제버튼생성 플러그인
  • V2 연동하기 (beta)
    • ⚠️V2 연동 시작하기
    • 🖥️인증결제 연동하기
      • 1. 포트원 SDK 설치
      • 2. 결제 요청하기
      • 3. 결제검증 API 구현하기 (서버)
      • 4. 결제완료 처리하기 (클라이언트)
        • iframe 방식의 결과처리
        • redirect 방식의 결과처리
    • ⏰비인증결제 연동하기
      • 빌링키 결제
        • 1. 빌링키 발급하기
          • PG 결제창 이용하기
            • 1. 빌링키 결제 API 구현하기 (서버)
            • 2. 결제창을 통해 빌링키 발급하기
          • 포트원 API 이용하기
        • 2. 정기(예약)/반복결제 구현하기 (서버)
      • 키인(수기) 결제
    • 💸웹훅 연동하기
    • 🚀JavaScript SDK
      • 결제요청 파라미터
      • 결제응답 파라미터
      • 빌링키 발급 요청 파라미터
      • 빌링키 발급 응답 파라미터
    • 🏢PG사별 연동 가이드
      • ⌨️카카오페이
    • 🛬온보딩 연동 가이드 - 별도 계약 필요
  • API (V2 beta)
    • ⚠️V2 API 시작하기
    • 채널 관련 API
    • 인증 관련 API
    • 결제 관련 API
    • 현금영수증 관련 API
    • 정기결제 관련 API
    • 빌링키 관련 API
    • 가맹점 관리 API - 별도 계약 필요
    • 온보딩 API - 별도 계약 필요
  • 영문 연동가이드
Powered by GitBook
On this page
  • STEP 01. 취소 요청하기
  • STEP 02. 결제정보 조회하기
  • STEP 03. 아임포트 서버에 취소 요청하기
  • STEP 04. 환불 결과 저장하기
  • STEP 04. 환불 응답 처리하기

Was this helpful?

  1. 결제창 연동하기

결제취소(환불) 연동하기

포트원 결제취소 API를 이용한 결제취소 방법을 안내합니다.

Previous빌링키를 이용한 정기결제Next가상계좌 환불하기

Last updated 2 years ago

Was this helpful?

Deprecated

이 문서는 더 이상 관리되지 않습니다.

를 이용해주세요.

STEP 01. 취소 요청하기

필요한 취소 정보를 서버로 전달하여 취소 요청을 진행합니다. 가상계좌 환불의 경우 환불수령 계좌 정보를 추가 파라미터로 전달해야 합니다. 다음은 환불요청을 하기 위해 서버로 해당 정보를 전달하는 예제입니다.

client-side
<button onclick="cancelPay()">환불하기</button>
<script
  src="https://code.jquery.com/jquery-3.3.1.min.js"
  integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
  crossorigin="anonymous"></script>
<script>
  function cancelPay() {
    jQuery.ajax({
      // 예: http://www.myservice.com/payments/cancel
      "url": "{환불정보를 수신할 가맹점 서비스 URL}", 
      "type": "POST",
      "contentType": "application/json",
      "data": JSON.stringify({
        "merchant_uid": "{결제건의 주문번호}", // 예: ORD20180131-0000011
        "cancel_request_amount": 2000, // 환불금액
        "reason": "테스트 결제 환불" // 환불사유
        // [가상계좌 환불시 필수입력] 환불 수령계좌 예금주
        "refund_holder": "홍길동", 
        // [가상계좌 환불시 필수입력] 환불 수령계좌 은행코드(예: KG이니시스의 경우 신한은행은 88번)
        "refund_bank": "88" 
        // [가상계좌 환불시 필수입력] 환불 수령계좌 번호
        "refund_account": "56211105948400" 
      }),
      "dataType": "json"
    });
  }
</script>
client-side
class CancelPay extends React.Component {
  cancelPay = () => {
    axios({
      url: "{환불요청을 받을 서비스 URL}", // 예: http://www.myservice.com/payments/cancel
      method: "POST",
      headers: {
        "Content-Type": "application/json,
      },
      data: { 
        merchant_uid: "{결제건의 주문번호}", // 주문번호
        cancel_request_amount: 2000, // 환불금액
        reason: "테스트 결제 환불" // 환불사유
        refund_holder: "홍길동", // [가상계좌 환불시 필수입력] 환불 수령계좌 예금주
        refund_bank: "88" // [가상계좌 환불시 필수입력] 환불 수령계좌 은행코드(예: KG이니시스의 경우 신한은행은 88번)
        refund_account: "56211105948400" // [가상계좌 환불시 필수입력] 환불 수령계좌 번호
      }
    });
  }
  ...
  render() {
    return <button onClick={this.cancelPay}>환불하기</button>;
  }
}

STEP 02. 결제정보 조회하기

아래와 같이 결제정보를 저장하는 **Payments**라는 테이블을 생성했다고 가정합니다.

server-side
/* ... model/payments.js ... */
  var mongoose = require('mongoose');
  var Schema = mongoose.Schema;
  ...
  var PaymentsSchema = new Schema({
    imp_uid: String, // 포트원 `unique key`(환불 요청시 `unique key`로 사용)
    merchant_uid: String, // 주문번호(결제정보 조회시 사용)
    amount: { type: Number, default: 0 }, // 결제 금액(환불 가능 금액 계산시 사용)
    // 환불 된 총 금액(환불 가능 금액 계산시 사용)
    cancel_amount: { type: Number, default: 0 }, 
    ...
  });
  ...
  module.exports = mongoose.model('Payments', PaymentsSchema);

클라이언트에서 받은 주문번호(merchant_uid)를 사용해서 해당 주문의 결제정보를 Payments 테이블에서 조회합니다.

server-side
/* ... 중략 ... */
  var Payments = require('./models/payments');
  app.post('/payments/cancel', async (req, res, next) => {
    try {
      /* 액세스 토큰(access token) 발급 */
      /* ... 중략 ... */
      /* 결제정보 조회 */
      const { body } = req;
      const { merchant_uid } = body; // 클라이언트로부터 전달받은 주문번호
      Payments.find({ merchant_uid }, async function(err, payment) { 
        if (err) {
          return res.json(err);
        }
        const paymentData = payment[0]; // 조회된 결제정보
        /* 포트원 REST API로 결제환불 요청 */
        ...
      });
    } catch (error) {
      res.status(400).send(error);
    }
  });

STEP 03. 아임포트 서버에 취소 요청하기

휴대폰 소액결제 환불 시 유의사항

  • 결제가 이루어진 월과 환불을 요청하는 월이 다를 경우, 전액환불도 불가능합니다. 예를 들어, 1월 31일 결제건은 2월 1일에 환불할 수 없습니다.

아래는 환불요청 시 유의해야 하는 파라미터들입니다.

환불 unique key

환불 대상 거래를 특정하기 위해서 imp_uid 또는 merchant_uid를 환불 unique key로 설정합니다. imp_uid의 값이 우선순위를 갖게되며 유효하지 않는 imp_uid값을 입력하면 merchant_uid값과 무관하게 환불요청이 실패합니다.

환불 금액(amount)

미입력시 전액이 환불됩니다.

환불 가능 금액(checksum)

환불이 가능한 금액을 입력합니다. 예를 들어, 10**,**000원짜리 제품의 checksum은 10,000입니다. 만약 10,000원짜리 제품이 과거 1,000원 부분환불 되었다면, 이후 환불시 checksum은 9,000입니다.입력된 checksum을 사용해서 서버와 포트원 서버간에 환불 가능 금액이 일치하는지 확인합니다. 만약 일치하지 않으면 환불 요청은 실패하며 미 입력시 검증은 실행되지 않습니다.

checksum을 입력해야 하는 이유

checksum은 필수입력은 아니지만 서버와 포트원 서버간에 환불 가능 금액을 검증하기 위해서 입력을 권장합니다.

예를 들어, 10**,**000원짜리 제품에 대한 1,000원 부분환불 요청이 포트원 서버에서 완료하였으나 가맹점이 서버 혹은 DB오류로 이를 반영하지 못했다면? 포트원 서버의 checksum은 9,000이 되고, 가맹점 서버의 checksum은 그대로 10,000이 됩니다.

이후 남은 금액을 환불하려고 할때 checksum(10,000)을 입력하면, 해당 값이 포트원 서버의 checksum(9,000)과 일치하지 않으므로 요청은 실패합니다.

아래는 환불 요청을 하는 예제입니다.

Node.js
/* ... 중략 ... */
  app.post('/payments/cancel', async (req, res, next) => {
    try {
      /* 액세스 토큰(access token) 발급 */
      /* ... 중략 ... */
      /* 결제정보 조회 */
      const { body } = req;
      // 클라이언트로부터 전달받은 주문번호, 환불사유, 환불금액
      const { merchant_uid, reason, cancel_request_amount } = body; 
      Payments.find({ merchant_uid }, async function(err, payment) { 
        /* ... 중략 ... */
        const paymentData = payment[0]; // 조회된 결제정보
        // 조회한 결제정보로부터 imp_uid, amount(결제금액), cancel_amount(환불된 총 금액) 추출
        const { imp_uid, amount, cancel_amount } = paymentData;
        // 환불 가능 금액(= 결제금액 - 환불 된 총 금액) 계산 
        const cancelableAmount = amount - cancel_amount; 
        if (cancelableAmount <= 0) { // 이미 전액 환불된 경우
          return res.status(400).json({ message: "이미 전액환불된 주문입니다." });
        }
        ...
        /* 포트원 REST API로 결제환불 요청 */
        const getCancelData = await axios({
          url: "https://api.iamport.kr/payments/cancel",
          method: "post",
          headers: {
            "Content-Type": "application/json",
            "Authorization": access_token // 포트원 서버로부터 발급받은 엑세스 토큰
          },
          data: {
            reason, // 가맹점 클라이언트로부터 받은 환불사유
            imp_uid, // imp_uid를 환불 `unique key`로 입력
            amount: cancel_request_amount, // 가맹점 클라이언트로부터 받은 환불금액
            checksum: cancelableAmount // [권장] 환불 가능 금액 입력
          }
        });
        const { response } = getCancelData.data; // 환불 결과
        /* 환불 결과 동기화 */
        ...
      });
    } catch (error) {
      res.status(400).send(error);
    }
  })

STEP 04. 환불 결과 저장하기

결제 취소가 완료되면 그 결과를 데이터베이스에 다음과 같이 저장합니다.

Node.js
/* ... 중략 ... */
  app.post('/payments/cancel', async (req, res, next) => {
    try {
      /* 액세스 토큰(access token) 발급 */
      /* ... 중략 ... */
      /* 결제정보 조회 */
      Payments.find({ merchant_uid }, async function(err, payment) { 
        /* ... 중략 ... */
        /* 포트원 REST API로 결제환불 요청 */
        /* ... 중략 ... */
        const { response } = getCancelData.data; // 환불 결과
        /* 환불 결과 동기화 */
        const { merchant_uid } = response; // 환불 결과에서 주문정보 추출
        Payments.findOneAndUpdate({ merchant_uid }, response, { new: true }, function(err, payment) { // 주문정보가 일치하는 결제정보를 추출해 동기화
          if (err) {
            return res.json(err);
          }
          res.json(payment); // 가맹점 클라이언트로 환불 결과 반환
        });
      });
    } catch (error) {
      res.status(400).send(error);
    }
  });

취소 시 유의할 점

STEP 04. 환불 응답 처리하기

취소요청에 대한 응답을 클라이언트에게 처리하는 로직을 아래와 같이 작성합니다.

client-side
<button onclick="cancelPay()">환불하기</button>
<script
  src="https://code.jquery.com/jquery-3.3.1.min.js"
  integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
  crossorigin="anonymous"></script><!-- jQuery CDN --->
<script>
  function cancelPay() {
    jQuery.ajax({
      /* ... 중략 ... */
    }).done(function(result) { // 환불 성공시 로직 
      alert("환불 성공");
    }).fail(function(error) { // 환불 실패시 로직
      alert("환불 실패");
    });
  }
</script>
client-side
class CancelPay extends React.Component {
  cancelPay = () => {
    axios({
      /* ... 중략 ... */
    }).then(response => { // 환불 성공시 로직 
      alert("환불 성공");
    }).catch(error => { // 환불 실패시 로직 
      alert("환불 실패");
    });
  }
  ...
  render() {
    return <button onClick={this.cancelPay}>환불하기</button>;
  }
}

취소 요청을 하기 위해서 먼저 을 발급받습니다. 발급받은 액세스 토큰(access token)을 이용하여 를 호출하여 결제 취소를 요청합니다.

REST API 요청에 대한 응답 코드가 200이라도 응답 body의 code가 0이 아니면 환불에 실패했다는 의미입니다. 실패 사유는 body의 message를 통해 확인하셔야 합니다.

💸
PortOne 개발자센터
REST API access token
아임포트 취소 API
(POST https://api.iamport.kr/payments/cancel)
환불버튼 예제