온라인 결제 연동은 어렵고 복잡하다는 인식이 있어요. 하지만 토스페이먼츠와 함께라면 PG 심사부터 연동까지 간편하게 완료할 수 있어요. 오늘은 토스페이먼츠 PG 계약을 신청하는 방법과 결제를 연동하는 방법을 간략히 알아볼게요.
일단 PG를 가입하기 전에 기본적으로 아래 4가지 사항을 충족해야 돼요. 사이트가 아래 조건을 모두 충족하는지 확인하세요. 더 자세한 내용은 전자결제 심사, 한 번에 통과하는 방법에서 확인하세요.
1~3번은 직접 확인하고 구현하고, 4번은 토스페이먼츠와 함께 해요.
먼저 결제 연동 및 심사를 위해 토스페이먼츠 홈페이지에서 회원가입하세요. 이메일 주소, 이름, 휴대폰 번호만 있으면 바로 가입할 수 있어요.
회원가입하고 메일 인증을 완료하면 아래 그림의 왼쪽 화면이 보이는데요. 개발 테스트 배너를 눌러서 개발자용 테스트 상점의 개발 정보를 확인하세요. API 키 메뉴에서 보이는 결제위젯 연동 키로 시작할게요.
클라이언트 연동만 완료해도 PG 계약 및 카드사 심사는 통과할 수 있어요. 사이트에서 결제창(카드사 인증창)이 열리는 것만 심사하기 때문이에요.
✅ 클라이언트 연동 과정
클라이언트 연동 과정을 간략히 알아볼게요. 결제위젯 SDK를 초기화하면 결제위젯 인스턴스가 생성돼요. 이 인스턴스로 SDK의 결제 UI 렌더링 메서드, 이용약관 UI 렌더링 메서드 등 다양한 메서드를 호출할 수 있어요.
결제창을 띄우고 결제를 요청하는 메서드는 requestPayment()
이고, 이 메서드의 파라미터로 다양한 설정을 바꿀 수 있어요. 예를 들어 successUrl
, failUrl
는 필수 파라미터인데요. 결제창에서 카드사 인증에 성공 또는 실패했을 때 구매자가 이동하는 페이지에요. 또 선택 파라미터로 면세 금액, 문화비 지출 여부 등 다양한 요소를 제어할 수 있으니 SDK 문서를 읽어보고 필요한 파라미터를 넘기세요.
클라이언트 연동 과정에 대한 더 자세한 설명은 토스페이먼츠 공식 결제 연동 가이드에서 확인하세요.
✅ 결제 요청 샘플 코드
주문서가 있는 페이지에 아래 코드를 넣어보세요. widgetClientKey
를 토스페이먼츠 회원가입해서 받은 결제위젯 연동 키 > 클라이언트 키로 바꾸세요. 그럼 페이지에 결제 및 이용약관 UI가 보일 거예요. React, Next.js, Vue 샘플이 필요하다면 토스페이먼츠 GitHub을 확인하세요.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<script src="https://js.tosspayments.com/v1/payment-widget"></script>
</head>
<body>
<!-- 결제 UI, 이용약관 UI 영역 -->
<div id="payment-method"></div>
<div id="agreement"></div>
<!-- 결제하기 버튼 -->
<button id="payment-button">결제하기</button>
<script>
const coupon = document.getElementById("coupon-box");
const button = document.getElementById("payment-button");
// 1. SDK 초기화
const widgetClientKey = "{WIDGET_CLIENT_KEY}";
const customerKey = "_oXp1imMWLpbSNQ2g3bqB";
const paymentWidget = PaymentWidget(widgetClientKey, customerKey); // 회원 결제
// 2. 결제 UI 렌더링
const paymentMethodWidget = paymentWidget.renderPaymentMethods(
"#payment-method",
{ value: 50000 },
{ variantKey: "DEFAULT" }
);
// 3. 이용약관 UI 렌더링
paymentWidget.renderAgreement(
"#agreement",
{ variantKey: "AGREEMENT" }
)
// 4. 버튼에 결제 요청 이벤트 걸기
button.addEventListener("click", function () {
paymentWidget.requestPayment({
orderId: "1W_pCfO4rzG9szJEcThKe",
orderName: "토스 티셔츠 외 2건",
successUrl: window.location.origin + "/success",
failUrl: window.location.origin + "/fail",
customerEmail: "customer123@gmail.com",
customerName: "김토스",
customerMobilePhone: "01012341234",
});
});
</script>
</body>
</html>
✅ successUrl 샘플 코드
결제 요청(카드 인증)에 성공해도 아직 결제는 완료되지 않았어요. 인증에 성공하면 구매자는 successUrl
로 이동해요. successUrl
에는 결제 승인에 필요한 값들이 쿼리 파라미터가 붙어요. 결제 승인 API는 보안상 서버에서 호출해야 돼요.
아래 코드는 successUrl
페이지에서 쿼리 파라미터로 넘어온 결제 데이터로 결제 승인 엔드포인트 /confirm
을 호출해요. 서버 쪽의 코드는 밑에서 알아볼게요.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8" />
</head>
<body>
<h2>결제 성공</h2>
<script>
// 쿼리 파라미터 값이 결제 요청할 때 보낸 데이터와 동일한지 반드시 확인하세요.
// 클라이언트에서 결제 금액을 조작하는 행위를 방지할 수 있습니다.
const urlParams = new URLSearchParams(window.location.search);
const paymentKey = urlParams.get("paymentKey");
const orderId = urlParams.get("orderId");
const amount = urlParams.get("amount");
async function confirm() {
const requestData = {
paymentKey: paymentKey,
orderId: orderId,
amount: amount,
};
const response = await fetch("/confirm", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(requestData),
});
const json = await response.json();
if (!response.ok) {
// 결제 실패 비즈니스 로직을 구현하세요.
console.log(json);
window.location.href = `/fail?message=${json.message}&code=${json.code}`;
}
// 결제 성공 비즈니스 로직을 구현하세요.
console.log(json);
}
</script>
</body>
</html>
PG 계약 및 카드사 심사에는 서버 연동이 필요 없지만 실제로 구매자에게 결제를 받을 때 꼭 필요하죠. 서버는 API를 호출하고 결제 데이터를 저장하는 역할을 해줘요.
✅ 결제 데이터 저장하기
토스페이먼츠 결제 승인 API는 Payment 객체를 응답으로 반환해요. 서버에서 Payment 객체를 처리할 수 있는 데이터 객체를 만드세요. 그리고 paymentKey
, amount
, orderId
필드는 필수로 데이터베이스에 저장하세요. 결제 조회, 취소 등 결제 운영에 사용되는 값이에요. 다른 필드의 값은 필요에 따라 저장하세요.
Payment 객체와 각종 결제 API를 더 자세히 알아보고 싶다면 토스페이먼츠 코어 API 문서를 확인하세요.
✅ 결제 승인 샘플 코드
아래는 Java 코드는 /confirm
엔드포인트에서 토스페이먼츠 결제 승인 API를 호출하는 코드에요. 코드의 widgetSecretKey
에 결제위젯 연동 키 > 시크릿 키를 넣으세요. 더 자세한 설명과 다양한 언어의 코드 샘플은 토스페이먼츠 공식 결제 연동 가이드에서 확인하세요.
package com.example.demo.controller;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
@Controller
public class WidgetController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@RequestMapping(value = "/confirm")
public ResponseEntity<JSONObject> confirmPayment(@RequestBody String jsonBody) throws Exception {
JSONParser parser = new JSONParser();
String orderId;
String amount;
String paymentKey;
try {
// 클라이언트에서 받은 JSON 요청 바디입니다.
JSONObject requestData = (JSONObject) parser.parse(jsonBody);
paymentKey = (String) requestData.get("paymentKey");
orderId = (String) requestData.get("orderId");
amount = (String) requestData.get("amount");
} catch (ParseException e) {
throw new RuntimeException(e);
};
JSONObject obj = new JSONObject();
obj.put("orderId", orderId);
obj.put("amount", amount);
obj.put("paymentKey", paymentKey);
// 토스페이먼츠 API는 시크릿 키를 Basic 인증의 사용자 ID로 사용하고, 비밀번호는 사용하지 않습니다.
// 비밀번호가 없다는 것을 알리기 위해 시크릿 키 뒤에 콜론을 추가합니다.
String widgetSecretKey = "{WIDGET_SECRET_KEY}";
Base64.Encoder encoder = Base64.getEncoder();
byte[] encodedBytes = encoder.encode((widgetSecretKey + ":").getBytes("UTF-8"));
String authorizations = "Basic " + new String(encodedBytes, 0, encodedBytes.length);
// 결제를 승인하면 결제수단에서 금액이 차감돼요.
URL url = new URL("https://api.tosspayments.com/v1/payments/confirm");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Authorization", authorizations);
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestMethod("POST");
connection.setDoOutput(true);
OutputStream outputStream = connection.getOutputStream();
outputStream.write(obj.toString().getBytes("UTF-8"));
int code = connection.getResponseCode();
boolean isSuccess = code == 200 ? true : false;
InputStream responseStream = isSuccess ? connection.getInputStream() : connection.getErrorStream();
// 결제 성공 및 실패 비즈니스 로직을 구현하세요.
Reader reader = new InputStreamReader(responseStream, StandardCharsets.UTF_8);
JSONObject jsonObject = (JSONObject) parser.parse(reader);
responseStream.close();
return ResponseEntity.status(code).body(jsonObject);
}
}
PG 계약 심사를 위한 준비가 끝났다면 토스페이먼츠 계약을 신청하세요.
토스페이먼츠 홈페이지에서 로그인해서 ‘결제 서비스 신청하기’ 배너를 누르세요. 사업자등록번호, 홈페이지 주소 등 내 회사 정보를 입력하는 페이지가 차례대로 나와요. 필요한 회사 정보를 모두 입력하면 신청서 접수 완료입니다. 1~3일 내에 연락처로 심사 결과를 알려드려요.
계약 과정에서 어려움이나 문의가 있다면 토스페이먼츠 고객센터(1544-7772, support@tosspayments.com)로 연락해주세요.
결제 연동에 도움이 필요하다면 토스페이먼츠 개발자센터의 다양한 가이드와 콘텐츠를 확인하세요.
Write 박수연 Graphic 이은호, 이나눔
토스페이먼츠 Twitter를 팔로우하시면 더욱 빠르게 블로그 업데이트 소식을 만나보실 수 있어요.