포트원(PortOne, 구 import) 사용하여 결제 API 연동하기
포트원 API를 사용하여 결제 기능을 구현하기 위해 먼저 포트원에 가입을 진행한다.
결제에 필요한 정보
포트원 API를 호출하기 위해서 몇 가지 필요한 정보가 있다.
1. 고객사 식별코드
가입하면 자동으로 부여받는다.
왼쪽 메뉴의 상점 ・ 계정 관리 > 상단의 내 식별코드 ・ API Keys 에서 확인할 수 있다.
2. 상점 아이디
채널을 추가해야 한다.
연동모드를 테스트로 하고, 결제 대행사 및 결제 모듈을 선택한다. 여기서는 KG이니시스, 일반/정기결제 V1 을 선택하였다. 이 때, 하단의 PG Provider를 복사해둔다.
나중에 코드에서 PG Provider 와 상점 아이디를 붙여서 body 에 세팅해줘야한다.
글을 내려보면 두 값을 붙인 값을 환경변수에 세팅해줬는데, 환경변수를 따로 만들어서 코드에서 붙이는 작업을 하는 것이 더 좋겠다.
PG Provider는 결제 대행사마다 다르다.
PG상점 아이디(MID)는 선택할 수 있는데, 테스트 연동이라면 INIBillTst 와 INIPayTest 를 선택할 수 있다. 여기서는 그냥 INIPayTest 를 선택한다.
과세구분 (부가세 신고 참고 자료용)은 어차피 테스트이기 때문에 미설정으로 하고 저장 버튼 클릭
채널 생성 확인
프로젝트에 세팅하기
1. 아래와 같이 index.html에 import.js 모듈을 로드할 수 있도록 세팅하자.
<body>
<div id='root'></div>
<script src='https://cdn.iamport.kr/v1/iamport.js'></script>
<script type='module' src='./src/main.tsx'></script>
</body>
2. main.tsx 에서 가맹점 식별코드 세팅
function main() {
// PortOne initialization
Reflect.get(window, 'IMP').init(process.env.PORTONE_IMP);
// ...
}
환경 변수는 아래와 같은 형태로 설정
# 고객사 식별코드
PORTONE_IMP=imp999999
# PG사 코드 + 상점 아이디
PORTONE_PG_CODE=html5_inicis.INIpayTest
3. PaymentService 를 만들고 portone 문서를 참고하여 결제 API 요청 코드를 만들 수 있다
@singleton()
export default class PaymentService {
private instance = Reflect.get(window, 'IMP');
async requestPayment({
merchantId,
product,
buyer,
}: {
merchantId: string;
product: Product;
buyer?: Buyer;
}): Promise<{
merchantId: string;
transactionId: string;
}> {
return new Promise((resolve, reject) => {
this.instance.request_pay(
{
pg: PG_CODE,
pay_method: 'card',
merchant_uid: merchantId,
name: product.name,
amount: product.price,
buyer_email: buyer?.email,
buyer_name: buyer?.name,
buyer_tel: buyer?.phoneNumber,
buyer_addr: buyer?.address,
buyer_postcode: buyer?.postalCode,
},
(response: PaymentResponse) => {
if (response.success) {
resolve({
merchantId: response.merchant_uid,
transactionId: response.imp_uid ?? '',
});
} else {
reject(Error(response.error_msg));
}
},
);
});
}
}
export const paymentService = container.resolve(PaymentService);
눈여겨 봐야 할 부분은 request_pay의 객체로 들어가는 부분이다.
merchant_uid: portone 에 전달해야 할 유니크한 값이고, 사용하는 쪽에서 만들어줘야 한다. 유니크한 키를 생성한 후에 DB에 저장하는 것이 좋다.
pay_method: 기본적으로 card 로 진행. 카카오페이 간편결제 기능도 card 로 가능하다.
PortOne에서는 프론트에서 결제 요청을 보낸 뒤 금액 위변조 체크를 권장하고 있다.
이것은 백엔드에서 수행하는 것이 좋다.
이 때 merchant_uid 값을 사용하여 결제 테이블에서 금액을 가져와서 비교할 수 있고, 해당 값으로 portone 에서 검색도 가능하다.
결제 요청을 하기 전에 결제 정보를 DB에 저장해도 되고, 요청이 성공한 후에 DB에 저장해도 된다. 필요에 따라서 달라질 수 있다.
결제 API가 REST API로 제공해준다면, 훨씬 더 쉬울 수 있는데, 일단 V1에서는 존재하지 않는다.