개요

빌링키 방식으로 자동결제를 연동할 수 있도록 구현한 API입니다.
토스 결제서버는 가맹점의 빌링키 생성요청에 따라 구매자가 인증할 수 있는 유니크한 '결제 인증 URL'을 생성하고,
가맹점을 통해 구매자는 토스 앱을 통해 인증을 진행할 수 있습니다.

  • 사용자의 유니크한 빌링키가 생성되며, 가맹점은 이 빌링키를 관리하고 필요 시 결제 승인 요청을 할 수 있습니다.
  • 토스가 제공하는 자동결제는 '토스머니'와 '카드' 결제수단을 제공합니다. 해당 문서는 자동결제 각 API의 기능을 설명합니다.
  • 테스트 계정 및 별도의 SDK 파일을 제공하지 않기에, '토스' 앱 설치 후 최신 버전 사용을 권장합니다.
  • 결제 도메인은 운영환경으로 제공되며, 결제에서 사용하는 상점 apiKey 속성에 따라 실제 출금 여부를 판단합니다.
  • 테스트 키(sk_test_xxx...)는 실제 출금되지 않으니 충분히 테스트할 수 있습니다.
  • 양사 간 계약이 완료된 후 전용 상점정보를 전달하며, 그 전까지는 가이드에 기재된 테스트 apiKey로 진행할 수 있습니다.

각 API의 응답 필드 및 에러코드는 사전 예고 없이 추가될 수 있으니 추가되더라도 오류가 발생하지 않도록 주의가 필요합니다.

자동결제 flow

자동결제 flow

빌링키 생성 요청

토스 자동결제를 등록하기 위해서는 사용자를 식별할 수 있는 고유한 빌링키를 생성해야 합니다.
API 요청의 응답으로 성공 여부와 함께 토스 앱 인증 URL을 전달합니다.
빌링키 생성 요청 API 사양은 다음과 같습니다.

endpoint

(POST)
https://pay.toss.im/api/v1/billing-key

parameters

apiKey string 필수 Max Length: 30
결제 가맹점의 apiKey
결제 보안상 유의가 필요하며 웹 브라우저에 노출되지 않도록 가맹점의 관리가 필요합니다.
테스트용 apiKey: sk_test_w5iNQvNqa5lNQe03nGx (상점 개선이 있을 때만 발송 예정)
userId string 필수 Max Length: 50
가맹점 사용자 식별 값
가맹점에 저장된 회원 아이디를 활용할 수 있습니다.
추후 결제 승인 정보와 매칭하기 위하여 필요하며 유니크한 값을 사용하길 권장합니다. (결제 주문번호의 개념)
최대 50자로 지정하며 숫자, 영문자도 가능하되 특수문자는 _-:.^@= 만 허용합니다.
displayId string Max Length: 50
다중 빌링키 식별 값
빌링키의 경우 기본적으로 하나의 가맹점 - 하나의 토스 유저 - 하나의 빌링키만 사용 가능합니다. 만약 동일한 결제수단을 여러 번 등록하고 싶다면, displayId를 사용하여 여러 개의 빌링키를 생성할 수 있습니다.
해당 값은 userId와 함께 발급된 빌링키를 특정할 수 있는 값이므로, 유니크한 값을 사용하길 권장합니다.
최대 50자로 지정하며 숫자, 영문자도 가능하되 특수문자는 _-:.^@= 만 허용합니다.
만약 동일한 결제수단을 여러 번 등록하길 원한다면, displayId를 보내면서 userId를 다르게 보내야 합니다. 토스에서는 가맹점의 서로 다른 유저에 대한 빌링키 등록으로 인식하여 동일한 결제수단을 여러 번 등록할 수 있게 됩니다. (userId를 동일한 값으로 보내는 경우 동일한 결제수단의 등록은 제한됩니다.)
productDesc string 필수 Max Length: 255
자동결제 상품명
토스 결제창에 표기될 가맹점의 자동결제 상품명
resultCallback String 필수 Max Length: 500
가맹점 설정 콜백 URL
사용자가 토스 앱을 통해 인증을 완료한 후, 이 URL에 인증 결과 데이터를 전달합니다.
콜백 서버는 보안상의 이유로 HTTPS를 권장하며, 80, 443 이외의 포트 사용은 불가합니다.
웹훅 요청에 대한 자세한 설명은 빌링키 처리결과 callback 설명 참고
retAppScheme string Max Length: 1500
인증완료 후 연결할 가맹점의 앱 스킴
토스 결제창 기본적으로 양방향 인증방식을 제공하지만 PC 결제에서는 Web(Web) 이라면 입력하지 않아도 됩니다.
모바일 사용자의 경우 리다이렉트 이후 가맹점 앱 실행을 위해 앱 스킴을 포함하는 것을 권장합니다. 예시) `tossapp://`
returnSuccessUrl string Max Length: 1500
인증성공 후 연결할 가맹점 성공 페이지
retAppScheme 선언되지 않으면 returnSuccessUrl, returnFailureUrl 은 필수로 보내주셔야 합니다.
별도 요청이 완료된 URL로 이동시키며, 빌링키(status), 사용자 식별값(userId), 빌링키(billingKey), 실패 에러코드(errorCode)를 query string 파라미터로 함께 보냅니다.
returnFailureUrl string Max Length: 1500
인증실패 시 연결할 가맹점 실패 페이지
encryptedUserCi string Max Length: 255
가맹점 유저의 CI값
가맹점에서 자동결제를 등록하는 사용자의 실명확인을 통해 생성된 사용자 정보를 전달할 수 있습니다.
가맹점에서 직접 자동결제를 등록하는 경우 사용하지 않습니다. CI는 경우 특성 상 여러 값이 생성되지 않아 일회성으로 사용하지 않을 것을 권장합니다.(RSA 암호화방식 지원)

response

code integer Max Length: 2
응답코드

0 성공
-1 실패 (실패사유는 msg와 errorCode로 제공)
errorCode string Max Length: 40
에러코드
code가 -1일 때만 에러코드와 실패 사유를 전달합니다.
msg string Max Length: 120
에러메시지
상세한 에러 설명
billingKey string Max Length: 50
생성된 자동결제 사용자 빌링키
빌링키는 토스 사용자의 고유한 값으로, 한 상점에서 한 개의 빌링키만 허용합니다.
사용자가 한 상점에서 2개 이상의 상점 계정을 사용하는 경우 혹은 그 외의 경우는 userId로 식별해야 합니다.

checkoutAndroidUri string Max Length: 255
Android 구독 인증 URI
생성된 자동결제를 인증할 앱 URL.
가맹점은 구매자의 디바이스 OS를 구분해서 해당 URL로 보내주면 됩니다.
앱 링크로 전달하는 이유는 토스앱이 미설치된 사용자에게는 설치를 위해 앱 스토어로 이동시키기 위함이며, 생성요청 시점부터 유효시간은 기본이 15분이며 변경이 불가합니다.(유효시간 만료 후 재사용 불가함)

URI 형식은 추후 변경될 수 있으니 변경되더라도 오류가 발생하지 않도록 연동이 필요합니다.
checkoutIosUri string Max Length: 255
iOS 구독 인증 URI
iOS에서 사용되는 구독 인증 URI로, 토스앱이 설치된 사용자가 앱을 통해 인증을 완료할 수 있도록 합니다.
checkoutUri string Max Length: 255
토스 앱 호출 링크
요청에서 retAppScheme 포함 여부에 따라 기능이 다른 링크를 생성합니다.
• retAppScheme 가 포함된 경우 : 가맹점에서 사용자 OS 구분이 어렵다면 혼용 가능한 onelink 를 제공합니다. 가맹점 앱에서 토스 앱을 호출하는 기능입니다.
• retAppScheme 가 포함되지 않은 경우 : pay Server 에서는 Web 결제로 인식하여 PC에서 호출 가능한 payfront 링크를 제공합니다. 토스 일반결제의 checkoutPage 의 기능과 같습니다.

Definition
POST https://pay.toss.im/api/v1/billing-key
Example Request
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://YOUR-SITE.COM/callback",
        "retAppScheme": "testshop://",
        "returnSuccessUrl": "https://YOUR-SITE.COM/success",
        "returnFailureUrl": "https://YOUR-SITE.COM/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://YOUR-SITE.COM/callback");
jsonBody.put("retAppScheme", "testshop://");
jsonBody.put("returnSuccessUrl", "https://YOUR-SITE.COM/success");
jsonBody.put("returnFailureUrl", "https://YOUR-SITE.COM/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://YOUR-SITE.COM/callback";
$arrayBody["retAppScheme"] = "testshop://";
$arrayBody["returnSuccessUrl"] = "https://YOUR-SITE.COM/success";
$arrayBody["returnFailureUrl"] = "https://YOUR-SITE.COM/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;Dim data, httpRequest, postResponse

data = "apiKey=sk_test_w5lNQylNqa5lNQe013Nq"
data = data & "&productDesc=토스 자동결제 상품"
data = data & "&userId=TOSS-TEST-1"
data = data & "&resultCallback=https://YOUR-SITE.COM/callback"
data = data & "&retAppScheme=testshop://"
data = data & "&returnSuccessUrl=https://YOUR-SITE.COM/success"
data = data & "&returnFailureUrl=https://YOUR-SITE.COM/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 postResponseimport urllib, urllib2

url = "https://pay.toss.im/api/v1/billing-key"
params = {
    "apiKey": "sk_test_w5lNQylNqa5lNQe013Nq",
    "productDesc": "토스 자동결제 상품",
    "userId": "TOSS-TEST-1",
    "resultCallback": "https://YOUR-SITE.COM/callback",
    "retAppScheme": "testshop://",
    "returnSuccessUrl": "https://YOUR-SITE.COM/success",
    "returnFailureUrl": "https://YOUR-SITE.COM/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://YOUR-SITE.COM/callback",
    "retAppScheme" => "testshop://",
    "returnSuccessUrl" => "https://YOUR-SITE.COM/success",
    "returnFailureUrl" => "https://YOUR-SITE.COM/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)
Example Response
{ 
    "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"
}
            

빌링키 처리결과 callback

사용자가 토스 앱을 통해 빌링 등록을 '성공적'으로 완료한 경우 토스 Server는 가맹점이 설정한 resultCallback URL을 통해 결과를 전달합니다. (실패한 경우는 전달하지 않습니다.)

  • 토스 쪽에서 삭제가 발생되는 경우 토스 pay Server에서 삭제(REMOVED) callback을 보낼 수 있음을 참고해야 합니다.
  • callback에 대한 응답의 HTTP status code가 200인 경우에만 '정상' 수신으로 간주하며, 그 외의 응답 코드는 미수신으로 실패한 것으로 인식하여 3분 간격으로 최대 4번 접근을 시도합니다.
  • 빌링키 생성결과 callback의 Payload는 다음과 같습니다.
* 사전 예고 없이 field 가 추가될 수 있습니다. 추가되더라도 오류가 발생하지 않도록 연동 부탁드립니다.

response

action string Max Length: 20
요청 처리에 따른 빌링키 상태
• ACTIVATED : 빌링키 활성화 완료
빌링키 생성요청에 따라, 토스 -> 가맹점으로 '정상처리'를 알리는 콜백

• REMOVED : 빌링키 삭제 완료
토스 -> 가맹점으로 빌링키 삭제를 요청할 수 있다. 그 때, '삭제완료' 상태를 알리는 콜백
processedTs string Max Length: 20
상태 처리시간
action 에 따라 각 상태의 처리시간을 전달합니다.
userId string Max Length: 50
가맹점이 생성한 사용자 식별 값
가맹점의 요청 값 그대로를 전달합니다.
displayId string Max Length: 50
가맹점이 생성한 표시 가능한 빌링키 식별 값
가맹점의 요청 값 그대로를 전달합니다.
billingKey string Max Length: 50
활성화/삭제 자동결제 사용자 빌링키
payMethod string Max Length: 10
사용자가 토스에서 인증한 결제수단
선택한 결제수단에 따라 토스머니(TOSS_MONEY) 또는 카드(CARD)를 전달합니다.
cardMethodType string Max Length: 10
승인된 카드의 타입을 구분
선택한 결제수단에 따라 신용카드(CREDIT) 또는 체크카드(CHECK) 또는 선불카드(PREPAYMENT)를 전달합니다.
cardUserType string Max Length: 20
카드 사용자 구분
• PERSONAL : 본인 카드
• PERSONAL_FAMILY : 가족 카드
• CORP_PERSONAL : 법인정 결제계좌 임직원
• CORP_PRIVATE : 법인 공용
• CORP_COMPANY : 법인정 결제계좌 회사(하나카드만)
cardCompanyNo integer Max Length: 2
사용자가 선택한 카드의 카드코드
사용자가 선택한 결제수단(payMethod)이 '카드'인 경우 토스가 정의한 카드코드를 전달합니다.
cardCompanyName string Max Length: 2
사용자가 선택한 카드의 카드사명
사용자가 선택한 결제수단(payMethod)이 '카드'인 경우 카드사명을 함께 전달합니다.
cardNumber string Max Length: 20
사용자가 선택한 카드의 번호
카드번호 16자리 중 중간자리는 마스킹
cardNum4Print string Max Length: 4
사용자가 선택한 카드의 끝 4자리
사용자가 선택한 결제수단(payMethod)이 '카드'인 경우 카드번호를 포함하여 전달합니다.
cardBinNumber string Max Length: 8
카드사에서 준 카드 빈번호
마스킹 되어 있을 수 있으며, 100% 신뢰는 불가
accountBankCode string Max Length: 3
사용자가 선택한 계좌의 은행코드
사용자가 선택한 결제수단(payMethod)이 '토스머니'인 경우 토스가 정의한 은행코드를 전달합니다.
accountBankName string Max Length: 20
사용자가 선택한 계좌의 은행명
은행코드 리스트
accountNumber string Max Length: 30
사용자가 선택한 계좌번호
계좌번호는 일부 마스킹을 포함할 수 있습니다.
Definition
POST https://YOUR-SITE.COM/callback (결제 생성 시 가맹점에서 설정한 callback URL)
Content-Type application/json;charset=UTF-8
Example Request
{
  "action": "ACTIVATED",
  "processedTs" : "2020-04-01 12:34:11",
  "userId": "TOSS-TEST-1",
  //"displayId": "TEST_SERVICE_1",
  "billingKey": "example-billingKey",
  "payMethod" : "TOSS_MONEY",
  "accountBankCode" : "88",
  "accountBankName" : "신한은행",
  "accountNumber" : "110******676"
}                            
                        

자동결제(bill) 승인 요청

빌링키 생성결과 callback 에서 전달받은 빌링키로 가맹점은 승인요청을 할 수 있습니다.
유효시간이나 최대횟수를 제한하지 않으니 승인요청 API 를 활용해서 결제를 진행할 수 있습니다.
자동결제 승인요청 API spec 은 다음과 같습니다.
승인 응답은 가맹점에 예고없이 추가될 수 있으니 오류가 발생하지 않도록 연동 부탁드립니다.

endpoint

(POST)
https://pay.toss.im/api/v1/billing-key/bill

parameters

apiKey string 필수 Max Length: 30
결제 가맹점의 apiKey
빌링키 생성요청 시 사용된 apiKey 와 동일해야 합니다.
그렇지 않으면 오류가 발생합니다.
billingKey string 필수 Max Length: 50
자동결제 사용자 빌링키
승인할 사용자의 빌링키
orderNo string 필수 Max Length: 50
결제 주문번호
가맹점의 상품 주문번호
• 최대 50자로 지정하며 숫자, 영문자도 가능하되 특수문자는 _-:.^@= 만 허용합니다.
• 가맹점의 주문번호는 매회 유니크한 값으로 생성하길 권장드립니다. (테스트와 라이브 환경에서 중복되지 않아야 합니다.)
productDesc string 필수 Max Length: 255
상품 설명
결제할 상품 설명
amount Integer필수 Max Length: 7
총 결제 요청 금액
가맹점의 상품 주문번호
• 토스에서 금액과 관련된 모든 필드는 Number 형태로 선언합니다.
• 필수 체크는 총금액(amount) 과 비과세 금액(amountTaxFree) 만 체크합니다. 판매 상품이 과세 상품이라면 amount 와 amountTaxFree 만 포함하면 되고, 이후 계산은 토스 서버에서 자동으로 계산됩니다.
amountTaxFree Integer필수 Max Length: 7
요청 금액 중 비과세 금액
판매하는 상품이 과세 품목이라면 해당 값을 0으로 선언합니다. 그 외의 과세 계산은 토스 서버에서 자동처리 합니다.
• 토스에서 금액과 관련된 모든 필드는 Number 형태로 선언합니다. 필수 체크는 총금액과 비과세 금액만 체크합니다.
amountTaxable Integer Max Length: 7
요청 금액 중 과세 금액
amountVat Integer Max Length: 7
요청 금액 중 부가세
amountServiceFee Integer Max Length: 7
요청 금액 중 봉사료
spreadOut Integer Max Length: 8
카드 할부개월
사용자가 선택한 카드 할부개월 (5만원 미만은 기본 일시불 결제)
• 0(일시불) ~ 12개월 까지 숫자형태로 선언합니다.
cashReceipt Boolean Max Length: 5
현금영수증 발급여부
토스 현금영수증 자동발행 기능을 사용한다면 매회 결제 시 true 값을, 미 사용하는 경우(가맹점 자체 발행) false 로 선언하면 됩니다.
반드시 true 또는 false 값을 전달해주셔야 하고 null과 같은 비정상 값을 전달할 경우 해당 필드는 명시적으로 false로 처리됩니다.
cashReceiptTradeOption string Max Length: 9
현금영수증 발급타입
문화비 관련 상품의 경우, 발급타입 설정이 필요합니다.
• CULTURE : 문화비
• GENERAL : 일반(default)
• PUBLIC_TP : 교통비
sendFailPush Boolean Max Length: 5
결제실패 푸시알람 사용여부
빌링키 결제가 실패할 경우, 사용자에게 결제 실패 알람을 발송합니다.(기본값은 true)
• 같은 빌링키로 다회 요청을 하더라도, 결제 실패 알람은 1시간 최대 1회 발송 가능합니다.
• 고객에게 빌링 결제시 잔액부족 알람 발송을 희망하지 않을경우, 해당 파라미터 값을 false 로 선언합니다.

response

code integer Max Length: 2
성공여부

0 성공
-1 실패 (실패사유는 msg와 errorCode로 제공)
mode string Max Length: 4
결제환경

LIVE 실거래용
TEST 테스트용
orderNo string Max Length: 50
결제 주문번호
가맹점의 상품 주문번호
errorCode string Max Length: 40
에러코드
code 가 -1 일때만 에러코드와 실패 사유를 전달합니다.
(errorCode 리스트는 추후 재 정의하며, 사전 예고없이 추가될 수 있으니 유의가 필요합니다.)
msg string Max Length: 120
에러메시지
'잔액부족' 등의 결제실패의 경우, 가맹점은 사용자에게 재결제 시도를 요청해야 합니다. 토스에서는 별도의 노티를 하지 않습니다.
approvalTime string Max Length: 20
결제건의 승인 처리 시간
결제건이 실제 승인된 시간을 리턴합니다. (yyyy-MM-dd HH:mm:ss 형식)
amount Integer Max Length: 7
승인금액
금액과 관련된 모든 파라미터는 Number 형태로 보내주셔야 에러가 발생하지 않습니다.
payMethod string Max Length: 10
승인된 결제수단

TOSS_MONEY 토스머니/계좌
CARD 카드
payToken string Max Length: 30
승인된 결제토큰
정상 승인처리 되었을 때, 토스 서버에서 매회 유니크한 결제 토큰 값을 전달합니다.
가맹점에서는 이 값을 반드시 저장해야 하며, 거래 환불요청 시 중요한 키 값이 될 수 있으니 관리가 필요합니다.
transactionId string Max Length: 36
거래 트랜잭션 코드
결제의 거래구분을 위하여 토스 서버에서는 매회 유니크한 값을 생성해서 리턴합니다.
매출전표를 호출하거나 환불 진행 시 구분 값으로 활용할 수 있습니다.
discountedAmount integer Max Length: 7
토스부담 할인 금액
승인에서 할인이 적용된 금액을 전달하며 할인적용이 없을 경우 0으로 전달합니다.
할인 금액에는 토스 앱에서 자동 적용되는 즉시할인과 토스 포인트 사용금액이 포함됩니다.
paidAmount integer Max Length: 7
지불수단 승인금액
총 금액에서 할인금액 등을 제외한 순수한 지불수단 승인금액을 의미합니다.
현금영수증 발행 또는 별도로 활용하는 경우 이 값을 참조할 수 있습니다.strong>
cardUserType string Max Length: 20
카드 사용자 구분

PERSONAL 본인 카드
PERSONAL_FAMILY 가족 카드
CORP_PERSONAL 법인지정 결제계좌 임직원
CORP_PRIVATE 법인 공용
CORP_COMPANY 법인지정 결제계좌 회사(하나카드만)
cardCompanyName string Max Length: 2
승인된 카드사명
카드 결제의 경우만 전달되며, 승인된 카드사 명과 카드코드를 확인할 수 있습니다.
cardCompanyCode integer Max Length: 2
카드사 코드
토스에서 정의한 카드사 코드는 다음과 같으며,
미지원 카드사는 현재 준비중입니다. (매입 카드사 기준입니다.)


cardCompanyName cardCompanyCode
신한 1
현대 2
삼성 3
국민 4
롯데 5
하나 6
우리 7
농협 8
씨티 (현재 미지원) 9
비씨(BC) 10
cardAuthorizationNo string Max Length: 8
구매자가 확인할 수 있는 카드사 승인번호 8자리
테스트 거래의 경우 00000000 으로 전달되며, 정상적인 카드사 승인번호는 라이브 키 결제에서 확인하실 수 있습니다.
cardNumber string Max Length: 20
마스킹된 카드번호
카드번호 16자리 중 중간자리는 마스킹됩니다.
cardNum4Print string Max Length: 4
사용자가 선택한 카드의 끝 4자리
사용자가 선택한 결제수단(payMethod) 이 '카드' 인 경우 카드번호 끝 4자리를 전달(카드사에 따라 마스킹이 포함되어 있을 수 있습니다.)
cardBinNumber string Max Length: 8
카드 BIN 번호
카드사에서 준 카드 빈번호(마스킹 되어 있을 수 있습니다.)
100% 신뢰는 불가

cardMethodType string Max Length: 10
카드 타입
승인된 카드의 타입을 구분
CREDIT 신용카드
CHECK 체크카드
PREPAYMENT 선불카드
salesCheckLinkUrl string Max Length: 120
신용카드 매출전표 호출URL
승인된 카드 결제건의 매출전표를 확인할 수 있는 URL
spreadOut integer Max Length: 2
카드 할부개월
승인요청에서 구매자가 선택한 할부개월이 리턴됩니다.(5만원 미만 금액 및 일시불 결제의 경우 0으로 리턴됩니다.)
noInterest boolean Max Length: 5
카드 무이자 적용 여부

true 무이자
false 일반
accountBankCode string Max Length: 3
은행 코드
사용자가 선택한 결제수단(payMethod) 이 '토스머니' 인 경우 토스가 정의한 은행 코드를 전달합니다.
accountBankName string Max Length: 20
accountNumber string Max Length: 30
계좌번호
계좌번호는 일부 마스킹을 포함하고 있습니다.
Definition
POST https://pay.toss.im/api/v1/billing-key/bill
Example Request
curl https://pay.toss.im/api/v1/billing-key/bill \
    -H "Content-Type: application/json" \
    -d '{
    "apiKey": "sk_test_w5lNQylNqa5lNQe013Nq",
    "billingKey": "example-billingKey",
    "orderNo": "TEST_billing_1",
    "productDesc": "테스트샵 빌링 상품",
    "amount" : 10000,
    "amountTaxFree" : 0,
    "spreadOut" : 7,
    "cashReceipt" : true,
    "sendFailPush" : true
        }'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/bill");
	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("billingKey", "example-billingKey");
jsonBody.put("orderNo", "TEST_billing_1");
jsonBody.put("productDesc", "테스트샵 빌링 상품");
jsonBody.put("amount", "10000");
jsonBody.put("amountTaxFree", "0");
jsonBody.put("spreadOut", "7");
jsonBody.put("cashReceipt", "true");
jsonBody.put("sendFailPush", "true");
	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["billingKey"] = "example-billingKey";
$arrayBody["orderNo"] = "TEST_billing_1";
$arrayBody["productDesc"] = "테스트샵 빌링 상품";
$arrayBody["amount"] = "10000";
$arrayBody["amountTaxFree"] = "0";
$arrayBody["spreadOut"] = "7";
$arrayBody["cashReceipt"] = "true";
$arrayBody["sendFailPush"] = "true";
$jsonBody = json_encode($arrayBody);

$ch = curl_init('https://pay.toss.im/api/v1/billing-key/bill');
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;Dim data, httpRequest, postResponse

data = "apiKey=sk_test_w5lNQylNqa5lNQe013Nq"
data = data & "&billingKey=example-billingKey"
data = data & "&orderNo=TEST_billing_1"
data = data & "&productDesc=테스트샵 빌링 상품"
data = data & "&amount=10000"
data = data & "&amountTaxFree=0"
data = data & "&spreadOut=7"
data = data & "&cashReceipt=true"
data = data & "&sendFailPush=true"

Set httpRequest = Server.CreateObject("MSXML2.ServerXMLHTTP")
httpRequest.Open "POST", "https://pay.toss.im/api/v1/billing-key/bill", False
httpRequest.SetRequestHeader "Content-Type", "application/json"
httpRequest.Send data

postResponse = httpRequest.ResponseText

Response.Write postResponseimport urllib, urllib2

url = "https://pay.toss.im/api/v1/billing-key/bill"
params = {
    "apiKey": "sk_test_w5lNQylNqa5lNQe013Nq",
    "billingKey": "example-billingKey",
    "orderNo": "TEST_billing_1",
    "productDesc": "테스트샵 빌링 상품",
    "amount" : 10000,
    "amountTaxFree" : 0,
    "spreadOut" : 7,
    "cashReceipt" : true,
    "sendFailPush" : true
}

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/bill")

params = {
    "apiKey" => "sk_test_w5lNQylNqa5lNQe013Nq",
    "billingKey" => "example-billingKey",
    "orderNo" => "TEST_billing_1",
    "productDesc" => "테스트샵 빌링 상품",
    "amount" => "10000",
    "amountTaxFree" => "0",
    "spreadOut" => "7",
    "cashReceipt" => "true",
    "sendFailPush" => "true"
}

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)
Example Response
{
    "code": 0,
    "mode": "TEST",
    "approvalTime": "2020-04-06 11:28:09",
    "amount": "150000",
    "payMethod": "CARD", //"TOSS_MONEY"
    "payToken": "example-payToken",
    "orderNo": "TEST_billing_1",
    "transactionId": "3243c76e-e9cf-4669-881b-33a3b82ddf49",
    "discountedAmount" : 0,
    "paidAmount" : "15000",
 
    //payMethod 가 CARD 일때
   "cardCompanyName": "롯데",
   "cardCompanyCode": 5,
   "cardAuthorizationNo": "00000000",
   "salesCheckLinkUrl": "https://alpha-pay.toss.im/payfront/web/external/sales-check?payToken=0PxriKdAz8Nsj7j5ZVO94b&transactionId=5a8cf658-b60d-4ae3-a959-279c66fc6743",
   "spreadOut": 0,
   "noInterest": false,
   "cardUserType": "PERSONAL",
   "cardMethodType": "CREDIT",
   "cardNumber": "534292******790*"
   "cardNum4Print": "410*",
   "cardBinNumber": "531764
 
    //payMethod 가 TOSS_MONEY 일때
    //"accountBankCode" : "88",
    //"accountBankName" : "신한은행",
    //"accountNumber" : "110******676"
}
            

자동결제 환불 요청

https://tossdev.github.io/api.html#refunds
토스 결제 환불요청은 표준 개발 가이드에 기재된 Spec 과 동일하게 사용할 수 있습니다. 위 링크를 참조 부탁드립니다. (전체/부분환불 모두 가능)

결제 상태조회

https://tossdev.github.io/api.html#status
승인된 결제의 상태확인은 표준 개발가이드 링크를 참고하시면 되고, 생성된 빌링키 상태확인은 아래 빌링키 상태조회 부분을 참고 부탁드립니다.

빌링키 상태 조회

가맹점은 생성된 빌링키를 관리하고 회원 관리의 목적으로 빌링키의 상태를 조회할 수 있습니다. 사용자가 토스앱에서 결제수단을 변경한 경우 결제수단(payMethod) 정보가 업데이트 될 수 있습니다.
빌링키 조회 API spec 은 다음과 같습니다.
상태조회 응답은 가맹점 예고없이 추가될 수 있으니 오류가 발생하지 않도록 연동이 필요합니다.

endpoint

(POST)
https://pay.toss.im/api/v1/billing-key/status

parameters

apiKey string 필수 Max Length: 30
결제 가맹점의 apiKey
가맹점에 발급된 apiKey
빌링키 생성요청 시 사용된 apiKey 와 동일해야 합니다. 그렇지 않으면 오류가 발생합니다.
userId string 필수 Max Length: 50
가맹점 사용자 식별 값
가맹점이 생성한 사용자 식별 값
빌링키 생성 요청 에서 가맹점이 토스로 전달한 값
displayId string Max Length: 50
가맹점이 생성한 표시 가능한 빌링키 식별 값
가맹점이 생성한 표시 가능한 빌링키 식별 값, 존재 한다면 필수
빌링키 생성 요청 에서 가맹점이 토스로 전달한 값

response

code integer Max Length: 2
성공여부

0 성공
-1 실패 (실패 사유는 msg와 errorCode로 제공)
errorCode string Max Length: 40
에러코드
code가 -1일 때만 에러코드와 실패 사유를 전달합니다.
(errorCode는 사전 예고없이 추가될 수 있으니 유의가 필요합니다.)
msg string Max Length: 120
에러 메시지
한 가지 에러코드에 상황별로 다른 에러 메시지를 전달합니다.
여러 상황이 발생할 수 있으니 되도록이면 전달되는 에러 메시지 그대로를 처리해주세요.
status string Max Length: 30
빌링키 상태 값

ACTIVE 빌링키 활성화 (사용자의 인증이 완료되어 사용할 수 있는 상태)
CREATE 미인증
AUTH 인증
REMOVE 삭제
FAIL 실패
CANCEL 취소
userId Max Length: 50
가맹점 사용자 식별 값
displayId Max Length: 50
가맹점이 생성한 표시 가능한 빌링키 식별 값
billingKey string Max Length: 50
생성된 자동결제 사용자 빌링키
payMethod string Max Length: 10
사용자가 토스앱에서 인증한 결제수단
토스 앱에서 선택한 결제수단에 따라 토스머니(TOSS_MONEY) 또는 카드(CARD)를 전달합니다.
cardCompanyNo integer Max Length: 2
사용자가 선택한 카드의 카드코드
결제수단이 카드인 경우에만 포함
cardCompanyName string Max Length: 2
사용자가 선택한 카드의 카드사명
사용자가 선택한 결제수단(payMethod)이 '카드'인 경우 카드사명을 함께 전달합니다.
cardNumber string Max Length: 20
마스킹된 카드번호
cardNum4Print string Max Length: 4
사용자가 선택한 카드의 끝 4자리
cardBinNumber string Max Length: 8
카드사에서 준 카드 빈번호(마스킹 되어 있을 수도 있음)
cardUserType string Max Length: 20
카드 사용자 구분

PERSONAL 본인 카드
PERSONAL_FAMILY 가족 카드
CORP_PERSONAL 법인지정 결제계좌 임직원
CORP_PRIVATE 법인 공용
CORP_COMPANY 법인지정 결제계좌 회사(하나카드만)
cardMethodType string Max Length: 10
카드 타입
승인된 카드의 타입을 구분
CREDIT 신용카드
CHECK 체크카드
PREPAYMENT 선불카드
accountBankCode string Max Length: 3
사용자가 선택한 계좌의 은행코드
결제수단이 토스머니인 경우에만 포함
accountBankName string Max Length: 20
사용자가 선택한 계좌의 은행명
은행코드 리스트
accountNumber string Max Length: 30
마스킹된 계좌번호
Definition
POST https://pay.toss.im/api/v1/billing-key/status
Example Request
curl https://pay.toss.im/api/v1/billing-key/status \
    -H "Content-Type: application/json" \
    -d '{
        "apiKey": "sk_test_w5lNQylNqa5lNQe013Nq",
         //"displayId": "TEST_SERVICE_1",
        "userId": "TOSS-TEST-1"
        }'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/status");
	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("displayId", "TEST_SERVICE_1");
jsonBody.put("userId", "TOSS-TEST-1");

	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["displayId"] = "TEST_SERVICE_1";
$arrayBody["userId"] = "TOSS-TEST-1";
$jsonBody = json_encode($arrayBody);

$ch = curl_init('https://pay.toss.im/api/v1/billing-key/status');
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;Dim data, httpRequest, postResponse

data = "apiKey=sk_test_w5lNQylNqa5lNQe013Nq"
//data = data & "&displayId=TEST_SERVICE_1"
data = data & "&userId=TOSS-TEST-1"

Set httpRequest = Server.CreateObject("MSXML2.ServerXMLHTTP")
httpRequest.Open "POST", "https://pay.toss.im/api/v1/billing-key/status", False
httpRequest.SetRequestHeader "Content-Type", "application/json"
httpRequest.Send data

postResponse = httpRequest.ResponseText

Response.Write postResponseimport urllib, urllib2

url = "https://pay.toss.im/api/v1/billing-key/status"
params = {
    "apiKey": "sk_test_w5lNQylNqa5lNQe013Nq",
//    "displayId": "TEST_SERVICE_1",
    "userId": "TOSS-TEST-1",
}

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/status")

params = {
    "apiKey" => "sk_test_w5lNQylNqa5lNQe013Nq",
 //   "displayId" => "TEST_SERVICE_1",
    "userId" => "TOSS-TEST-1",
}

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)
Example Response
// payMethod 가 CARD 일때
{
    "code": 0,
    "userId": "TEST=2023-07-03T14:29:00.201Z",
    "displayId": "테스트777",
    "billingKey": "8JZBi0gmKZlfxaV4Zm4762",
    "status": "ACTIVE",
    "payMethod": "CARD",
    "cardMethodType": "CREDIT",
    "cardUserType": "PERSONAL",
    "cardCompanyNo": 7,
    "cardCompanyName": "우리",
    "cardNum4Print": "410*",
    "cardNumber": "531764******410*",
    "cardBinNumber": "531764"
}

// payMethod 가 TOSS_MONEY(계좌) 일때
{
    "code": 0,
    "userId": "TEST=2023-07-03T14:29:00.201Z",
    "displayId": "테스트777",
    "billingKey": "8JZBi0gmKZlfxaV4Zm4762",
    "status": "ACTIVE",
    "payMethod": "TOSS_MONEY",
    "accountBankName": "신한은행",
    "accountBankCode": "088",
    "accountNumber": "110******676" // 토스머니일 경우 "accountNumber":"토스머니"
}

            

빌링키 삭제

가맹점은 주체적으로 생성된 빌링키를 삭제할 수 있습니다.
빌링키 삭제 API spec 은 다음과 같습니다.

endpoint

(POST)
https://pay.toss.im/api/v1/billing-key/remove

parameters

apiKey string 필수 Max Length: 30
결제 가맹점의 apiKey
가맹점에 발급된 apiKey
빌링키 생성요청 시 사용된 apiKey 와 동일해야 합니다. 그렇지 않으면 오류가 발생합니다.
billingKey string 필수 Max Length: 50
자동결제 사용자 빌링키
토스가 생성한 자동결제 사용자 빌링키
Definition
POST https://pay.toss.im/api/v1/billing-key/remove
Example Request
curl https://pay.toss.im/api/v1/billing-key/remove \
    -H "Content-Type: application/json" \
    -d '{
        "apiKey": "sk_test_w5lNQylNqa5lNQe013Nq",
        "billingKey": "example-billingKey"
        }'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/remove");
	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("billingKey", "example-billingKey");

	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["billingKey"] = "example-billingKey";
$jsonBody = json_encode($arrayBody);

$ch = curl_init('https://pay.toss.im/api/v1/billing-key/remove');
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;Dim data, httpRequest, postResponse

data = "apiKey=sk_test_w5lNQylNqa5lNQe013Nq"
data = data & "&billingKey=example-billingKey"

Set httpRequest = Server.CreateObject("MSXML2.ServerXMLHTTP")
httpRequest.Open "POST", "https://pay.toss.im/api/v1/billing-key/remove", False
httpRequest.SetRequestHeader "Content-Type", "application/json"
httpRequest.Send data

postResponse = httpRequest.ResponseText

Response.Write postResponseimport urllib, urllib2

url = "https://pay.toss.im/api/v1/billing-key/remove"
params = {
    "apiKey": "sk_test_w5lNQylNqa5lNQe013Nq",
    "billingKey": "example-billingKey",
}

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/remove")

params = {
    "apiKey" => "sk_test_w5lNQylNqa5lNQe013Nq",
    "billingKey" => "example-billingKey",
}

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)
Example Response

{
    "code": 0
}

            

결제 에러코드

https://tossdev.github.io/qna.html#faq-7
토스에서 전달받은 응답 중 code -1 (실패)인 경우에 전달되는 값으로 기본적인 토스 결제 에러코드와 유사하지만, 자동결제에서 발생할 수 있는 에러코드를 정의합니다.
지속적으로 업데이트 및 추가될 수 있으며, 중복되는 에러코드가 있어서 다른 토스결제 에러코드들도 참고가 필요합니다.