빌링키 생성 요청
토스 자동결제를 등록하기 위해서는 사용자를 식별할 수 있는 고유한 빌링키를 생성해야 합니다. API 요청의 응답으로 성공 여부와 함께 토스 앱 인증 URL을 전달합니다.
각 API 응답 필드와 에러코드는 사전 공지 없이 추가되거나 변경될 수도 있으니, 추가된 항목으로 인해 오류가 발생하지 않도록 처리에 유의해 주시기 바랍니다.
엔드포인트
https://pay.toss.im/api/v1/billing-key요청 파라미터
apiKeystring필수결제 가맹점의 API Key. 결제 보안상 유의가 필요하며 웹 브라우저에 노출되지 않도록 가맹점의 관리가 필요합니다.
30userIdstring필수가맹점 사용자 식별 값. 가맹점에 저장된 회원 아이디를 활용할 수 있습니다. 추후 결제 승인 정보와 매칭하기 위하여 필요하며 유니크한 값을 사용하길 권장합니다. 최대 50자로 지정하며 숫자, 영문자도 가능하되 특수문자는 _ - : . ^ @ = 만 허용합니다.
50displayIdstring다중 빌링키 식별 값. 빌링키의 경우 기본적으로 하나의 가맹점 - 하나의 토스 유저 - 하나의 빌링키만 사용 가능합니다. 만약 동일한 결제수단을 여러 번 등록하고 싶다면, displayId를 사용하여 여러 개의 빌링키를 생성할 수 있습니다. 해당 값은 userId와 함께 발급된 빌링키를 특정할 수 있는 값이므로, 유니크한 값을 사용하길 권장합니다. 최대 50자로 지정하며 숫자, 영문자도 가능하되 특수문자는 _ - : . ^ @ = 만 허용합니다.
50productDescstring필수자동결제 상품명. 토스 결제창에 표기될 가맹점의 자동결제 상품명
255resultCallbackstring필수가맹점 설정 콜백 URL. 사용자가 토스 앱을 통해 인증을 완료한 후, 이 URL에 인증 결과 데이터를 전달합니다. 콜백 서버는 보안상의 이유로 HTTPS를 권장하며, 80, 443 이외의 포트 사용은 불가합니다. '인증완료' 외에도 빌링키 처리 결과 등 다양한 상황에서 Callback이 전달됩니다.
500retAppSchemestring인증완료 후 연결할 가맹점의 앱 스킴. 토스 결제창은 기본적으로 양방향 인증 방식을 제공하며, PC 결제(Web)는 별도 설정 없이 사용할 수 있습니다. App to App 결제 환경에서는 토스페이 완료 후 가맹점 앱으로 리디렉션하기 위해 앱 스킴 설정이 필요합니다. (예: tossapp://)
1500returnSuccessUrlstring인증성공 후 연결할 가맹점 성공 페이지. retAppScheme이 선언되지 않으면 returnSuccessUrl, returnFailureUrl은 필수로 보내주셔야 합니다. 별도 요청이 완료된 URL로 이동시키며, 빌링키(status), 사용자 식별값(userId), 빌링키(billingKey), 실패 에러코드(errorCode)를 query string 파라미터로 함께 보냅니다.
1500returnFailureUrlstring인증실패 시 연결할 가맹점 실패 페이지
1500encryptedUserCistring가맹점 유저의 CI값. 가맹점에서 자동결제를 등록하는 사용자의 실명확인을 통해 생성된 사용자 정보를 전달할 수 있습니다. 가맹점에서 직접 자동결제를 등록하는 경우 사용하지 않습니다. CI는 특성 상 여러 값이 생성되지 않아 일회성으로 사용하지 않을 것을 권장합니다. (RSA 암호화방식 지원)
255응답 파라미터
codeinteger응답코드. 0: 성공, -1: 실패 (실패사유는 msg와 errorCode로 제공)
0-1errorCodestring에러코드. code가 -1일 때만 에러코드와 실패 사유를 전달합니다.
40msgstring에러메시지. 상세한 에러 설명
120billingKeystring생성된 자동결제 사용자 빌링키. 빌링키는 토스 사용자의 고유한 값으로, 한 상점에서 한 개의 빌링키만 허용합니다. 사용자가 한 상점에서 2개 이상의 상점 계정을 사용하는 경우 혹은 그 외의 경우는 userId로 식별해야 합니다.
50checkoutAndroidUristringAndroid 구독 인증 URI. 생성된 자동결제를 인증할 앱 URL. 가맹점은 구매자의 디바이스 OS를 구분해서 해당 URL로 보내주면 됩니다. 앱 링크로 전달하는 이유는 토스앱이 미설치된 사용자에게는 설치를 위해 앱 스토어로 이동시키기 위함이며, 생성요청 시점부터 유효시간은 기본이 15분입니다.
255checkoutIosUristringiOS 구독 인증 URI. iOS에서 사용되는 구독 인증 URI로, 토스앱이 설치된 사용자가 앱을 통해 인증을 완료할 수 있도록 합니다.
255checkoutUristring토스 앱 호출 링크. 요청에서 retAppScheme 포함 여부에 따라 기능이 다른 링크를 생성합니다. retAppScheme가 포함된 경우 가맹점에서 사용자 OS 구분이 어렵다면 혼용 가능한 onelink를 제공합니다. retAppScheme가 포함되지 않은 경우 Web 결제로 인식하여 PC에서 호출 가능한 payfront 링크를 제공합니다.
255예제
요청 예제
curl https://pay.toss.im/api/v1/billing-key \
-H "Content-Type: application/json" \
-d '{
"apiKey": "sk_test_w5lNQylNqa5lNQe013Nq",
"productDesc": "토스 자동결제 상품",
"userId": "TOSS-TEST-1",
"resultCallback": "https://pay.toss.im/payfront/demo/callback",
"retAppScheme": "testshop://",
"returnSuccessUrl": "https://pay.toss.im/payfront/demo/success",
"returnFailureUrl": "https://pay.toss.im/payfront/demo/fail"
}'import java.nio.charset.StandardCharsets;
URL url = null;
URLConnection connection = null;
StringBuilder responseBody = new StringBuilder();
try {
url = new URL("https://pay.toss.im/api/v1/billing-key");
connection = url.openConnection();
connection.addRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
connection.setDoInput(true);
org.json.simple.JSONObject jsonBody = new JSONObject();
jsonBody.put("apiKey", "sk_test_w5lNQylNqa5lNQe013Nq");
jsonBody.put("productDesc", "토스 자동결제 상품");
jsonBody.put("userId", "TOSS-TEST-1");
jsonBody.put("resultCallback", "https://pay.toss.im/payfront/demo/callback");
jsonBody.put("retAppScheme", "testshop://");
jsonBody.put("returnSuccessUrl", "https://pay.toss.im/payfront/demo/success");
jsonBody.put("returnFailureUrl", "https://pay.toss.im/payfront/demo/fail");
BufferedOutputStream bos = new BufferedOutputStream(connection.getOutputStream());
bos.write(jsonBody.toJSONString().getBytes(StandardCharsets.UTF_8));
bos.flush();
bos.close();
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
String line = null;
while ((line = br.readLine()) != null) {
responseBody.append(line);
}
br.close();
} catch (Exception e) {
responseBody.append(e);
}
System.out.println(responseBody.toString());$arrayBody = array();
$arrayBody["apiKey"] = "sk_test_w5lNQylNqa5lNQe013Nq";
$arrayBody["productDesc"] = "토스 자동결제 상품";
$arrayBody["userId"] = "TOSS-TEST-1";
$arrayBody["resultCallback"] = "https://pay.toss.im/payfront/demo/callback";
$arrayBody["retAppScheme"] = "testshop://";
$arrayBody["returnSuccessUrl"] = "https://pay.toss.im/payfront/demo/success";
$arrayBody["returnFailureUrl"] = "https://pay.toss.im/payfront/demo/fail";
$jsonBody = json_encode($arrayBody);
$ch = curl_init('https://pay.toss.im/api/v1/billing-key');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonBody);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($jsonBody))
);
$result = curl_exec($ch);
curl_close($ch);
echo "Response: ".$result;import urllib, urllib2
url = "https://pay.toss.im/api/v1/billing-key"
params = {
"apiKey": "sk_test_w5lNQylNqa5lNQe013Nq",
"productDesc": "토스 자동결제 상품",
"userId": "TOSS-TEST-1",
"resultCallback": "https://pay.toss.im/payfront/demo/callback",
"retAppScheme": "testshop://",
"returnSuccessUrl": "https://pay.toss.im/payfront/demo/success",
"returnFailureUrl": "https://pay.toss.im/payfront/demo/fail"
}
response = urllib.urlopen(url, urllib.urlencode(params))
print(response.read())require 'net/http'
require 'json'
uri = URI.parse("https://pay.toss.im/api/v1/billing-key")
params = {
"apiKey" => "sk_test_w5lNQylNqa5lNQe013Nq",
"productDesc" => "토스 자동결제 상품",
"userId" => "TOSS-TEST-1",
"resultCallback" => "https://pay.toss.im/payfront/demo/callback",
"retAppScheme" => "testshop://",
"returnSuccessUrl" => "https://pay.toss.im/payfront/demo/success",
"returnFailureUrl" => "https://pay.toss.im/payfront/demo/fail"
}
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri.path)
request.set_form_data(params)
response = http.request(request)
p JSON.parse(response.body)Dim data, httpRequest, postResponse
data = "apiKey=sk_test_w5lNQylNqa5lNQe013Nq"
data = data & "&productDesc=토스 자동결제 상품"
data = data & "&userId=TOSS-TEST-1"
data = data & "&resultCallback=https://pay.toss.im/payfront/demo/callback"
data = data & "&retAppScheme=testshop://"
data = data & "&returnSuccessUrl=https://pay.toss.im/payfront/demo/success"
data = data & "&returnFailureUrl=https://pay.toss.im/payfront/demo/fail"
Set httpRequest = Server.CreateObject("MSXML2.ServerXMLHTTP")
httpRequest.Open "POST", "https://pay.toss.im/api/v1/billing-key", False
httpRequest.SetRequestHeader "Content-Type", "application/json"
httpRequest.Send data
postResponse = httpRequest.ResponseText
Response.Write postResponse응답 예제
{
"code": 0,
"billingKey": "example-billingKey",
"checkoutAndroidUri": "intent://pay/BillingKey?billingKey=example-billingKey#Intent;scheme=supertoss;package=viva.republica.toss;end",
"checkoutIosUri": "https://ul.toss.im?scheme=supertoss%3A%2F%2Fpay/BillingKey%3FbillingKey%3Dexample-billingKey",
"checkoutUri": "https://toss.onelink.me/3563614660?pid=referral&af_dp=supertoss%3A%2F%2Fpay%2FbillingKey%3FbillingKey%3Dexample-billingKey%26_minVerAos%3D4.64.0%26_minVerIos%3D4.51.0"
}