포트원 결제고유번호(imp_uid), 가맹점 주문번호(merchant_uid)를 프론트엔드로부터 수신
STEP 01 결제결과 서버 수신
결제정보를 받은 가맹점 endpoint URL 에 대한 POST 요청을 수신하는 예제
app.use(bodyParser.json());// "{서버의 결제 정보를 받는 가맹점 endpoint}" POST 요청 수신부app.post("/payments/complete",async (req, res) => {try {// req의 body에서 imp_uid, merchant_uid 추출const { imp_uid,merchant_uid } =req.body; } catch (e) {res.status(400).send(e); }});
STEP 02 결제내역 단건 조회
수신받은 포트원 결제고유번호(imp_uid)로 결제단건조회API 를 호출하여 결제정보 획득 예제
app.use(bodyParser.json());app.post("/payments/complete",async (req, res) => {try {// req의 body에서 imp_uid, merchant_uid 추출const { imp_uid,merchant_uid } =req.body; ...// 액세스 토큰(access token) 발급 받기constgetToken=awaitaxios({ url:"https://api.iamport.kr/users/getToken", method:"post",// POST method headers: { "Content-Type":"application/json" }, data: { imp_key:"imp_apikey",// REST API 키 imp_secret: "ekKoeW8RyKuT0zgaZsUtXXTLQ4AhPFW3ZGseDA6bkA5lamv9OqDMnxyeB9wqOsuO9W3Mx9YSJ4dTqJ3f" // REST API Secret
} });const { access_token } =getToken.data; // 인증 토큰...// imp_uid로 포트원 서버에서 결제 정보 조회constgetPaymentData=awaitaxios({// imp_uid 전달 url:`https://api.iamport.kr/payments/${imp_uid}`,// GET method method:"get",// 인증 토큰 Authorization header에 추가 headers: { "Authorization": access_token } });constpaymentData=getPaymentData.data; // 조회한 결제 정보... } catch (e) {res.status(400).send(e); }});
STEP 03 결제정보 검증
결제된 실 금액과 요청 금액을 비교하여 결제금액 위변조여부 검증 및 DB저장 예시
app.use(bodyParser.json());app.post("/payments/complete",async (req, res) => {try {// req의 body에서 imp_uid, merchant_uid 추출const { imp_uid,merchant_uid } =req.body; // 액세스 토큰(access token) 발급 받기// 코드 생략// imp_uid로 포트원 서버에서 결제 정보 조회// 코드 생략constpaymentData=getPaymentData.data; // 조회한 결제 정보// ...// DB에서 결제되어야 하는 금액 조회constorder=awaitOrders.findById(paymentData.merchant_uid);constamountToBePaid=order.amount; // 결제 되어야 하는 금액// ...// 결제 검증하기const { amount,status } = paymentData;// 결제금액 일치. 결제 된 금액 === 결제 되어야 하는 금액if (amount === amountToBePaid) { awaitOrders.findByIdAndUpdate(merchant_uid, { $set: paymentData }); // DB에 결제 정보 저장// ...switch (status) {case"ready": // 가상계좌 발급// DB에 가상계좌 발급 정보 저장const { vbank_num,vbank_date,vbank_name } = paymentData;awaitUsers.findByIdAndUpdate("/* 고객 id */", { $set: { vbank_num, vbank_date, vbank_name }});// 가상계좌 발급 안내 문자메시지 발송SMS.send({ text:`가상계좌 발급이 성공되었습니다. 계좌 정보 ${vbank_num}${vbank_date}${vbank_name}`});res.send({ status:"vbankIssued", message:"가상계좌 발급 성공" });break;case"paid": // 결제 완료res.send({ status:"success", message:"일반 결제 성공" });break; } } else { // 결제금액 불일치. 위/변조 된 결제throw { status:"forgery", message:"위조된 결제시도" }; } } catch (e) {res.status(400).send(e); }});
처음 요청한 금액은 merchant_uid 로 데이터베이스에서 조회하고 실제 결제금액은 imp_uid로 포트원 서버에서 조회하여 두 값을 비교합니다. 검증이 성공하면 결제 정보를 데이터베이스에 저장한 뒤 결제 상태(status)에 따라 알맞은 응답을 반환하고 실패 시 에러 메세지를 출력합니다.
결제결과 DB 처리는 웹훅(Webhook)을 연동하여 수신되는 데이터를 기준으로 처리하셔야 결제결과 누락없이 안정적인 결과처리를 완료하실 수 있습니다.