토스페이 연동가이드
API 레퍼런스자동 결제 API

자동결제(bill) 승인 요청

빌링키 생성결과 callback에서 전달받은 빌링키로 가맹점은 승인 요청을 할 수 있습니다. 유효시간이나 최대 횟수를 제한하지 않으니 승인요청 API를 활용해서 결제를 진행할 수 있습니다.

자동결제 승인요청 API 사양은 다음과 같습니다.

각 API 응답 필드와 에러코드는 사전 공지 없이 추가되거나 변경될 수도 있으니, 추가된 항목으로 인해 오류가 발생하지 않도록 처리에 유의해 주시기 바랍니다.

엔드포인트

POSThttps://pay.toss.im/api/v1/billing-key/bill

요청 파라미터

apiKeystring필수

결제 가맹점의 API Key. 빌링키 생성요청 시 사용된 API Key와 동일해야 합니다. 그렇지 않으면 오류가 발생합니다.

최대 길이: 30
billingKeystring필수

자동결제 사용자 빌링키. 승인할 사용자의 빌링키

최대 길이: 50
orderNostring필수

결제 주문번호. 가맹점의 상품 주문번호. 최대 50자로 지정하며 숫자, 영문자도 가능하되 특수문자는 _ - : . ^ @ = 만 허용합니다. 가맹점의 주문번호는 매회 유니크한 값으로 생성하길 권장드립니다. (테스트와 라이브 환경에서 중복되지 않아야 합니다.)

최대 길이: 50
productDescstring필수

상품 설명. 결제할 상품 설명

최대 길이: 255
amountinteger필수

총 결제 요청 금액. 토스에서 금액과 관련된 모든 필드는 Number 형태만 허용합니다. 카드 결제를 지원하는 가맹점: 최대 10억 원까지 결제 가능. 카드 결제를 지원하지 않는 가맹점: 최대 200만 원까지만 결제 가능 (200만 원을 초과하는 경우 결제 생성 단계에서 에러가 발생할 수 있습니다). 일부 고액·현금성 상품은 카드사·은행의 1회 한도가 더 낮을 수 있으며, 이 경우 결제가 실패할 수 있습니다.

최대 길이: 10
amountTaxFreeinteger필수

요청 금액 중 비과세 금액. 판매하는 상품이 과세 품목이라면 해당 값을 0으로 선언합니다. 그 외의 과세 계산은 토스 서버에서 자동 처리합니다. 토스에서 금액과 관련된 모든 필드는 Number 형태로 선언합니다. 필수 체크는 총금액과 비과세 금액만 체크합니다.

최대 길이: 10
amountTaxableinteger

요청 금액 중 과세 금액

최대 길이: 10
amountVatinteger

요청 금액 중 부가세

최대 길이: 10
amountServiceFeeinteger

요청 금액 중 봉사료

최대 길이: 10
spreadOutinteger

카드 할부개월. 사용자가 선택한 카드 할부개월 (5만원 미만은 기본 일시불 결제). 0(일시불) ~ 12개월까지 숫자 형태로 선언합니다.

최대 길이: 8
cashReceiptboolean

현금영수증 발급여부. 토스 현금영수증 자동발행 기능을 사용한다면 매회 결제 시 true 값을, 미 사용하는 경우(false)로 선언하면 됩니다. 반드시 true 또는 false 값을 전달해주셔야 하고 null과 같은 비정상 값을 전달할 경우 해당 필드는 명시적으로 false로 처리됩니다.

최대 길이: 5
cashReceiptTradeOptionstring

현금영수증 발급타입. 문화비 관련 상품의 경우, 발급타입 설정이 필요합니다. CULTURE: 문화비, GENERAL: 일반(default), PUBLIC_TP: 교통비

최대 길이: 9
가능한 값:
CULTUREGENERALPUBLIC_TP
sendFailPushboolean

결제실패 푸시알람 사용여부. 빌링키 결제가 실패할 경우, 사용자에게 결제 실패 알람을 발송합니다.(기본값은 true). 같은 빌링키로 다회 요청을 하더라도, 결제 실패 알람은 1시간 최대 1회 발송 가능합니다. 고객에게 빌링 결제 시 잔액부족 알람 발송을 희망하지 않을 경우, 해당 파라미터 값을 false로 선언합니다.

최대 길이: 5

응답 파라미터

codeinteger

성공여부. 0: 성공, -1: 실패 (실패사유는 msg와 errorCode로 제공)

최대 길이: 2
가능한 값:
0-1
modestring

결제환경. LIVE: 실거래용, TEST: 테스트용

최대 길이: 4
가능한 값:
LIVETEST
orderNostring

결제 주문번호. 가맹점의 상품 주문번호

최대 길이: 50
errorCodestring

에러코드. code가 -1일 때만 에러코드와 실패 사유를 전달합니다. (errorCode는 사전 예고 없이 추가될 수 있으니 유의가 필요합니다.)

최대 길이: 40
msgstring

에러메시지. 한 가지 에러코드에 상황별로 다른 에러 메시지를 전달합니다. 여러 상황이 발생할 수 있으니 되도록이면 전달되는 에러 메시지 그대로를 처리해주세요. '잔액부족' 등의 결제 실패의 경우, 가맹점은 사용자에게 재결제 시도를 요청해야 합니다. 토스에서는 별도의 노티를 하지 않습니다.

최대 길이: 120
approvalTimestring

결제건의 승인 처리 시간. 결제건이 실제 승인된 시간을 리턴합니다. (yyyy-MM-dd HH:mm:ss 형식)

최대 길이: 20
amountinteger

승인금액. 금액과 관련된 모든 파라미터는 Number 형태로 보내주셔야 에러가 발생하지 않습니다.

최대 길이: 10
payMethodstring

승인된 결제수단. TOSS_MONEY: 토스머니/계좌, CARD: 카드

최대 길이: 10
가능한 값:
TOSS_MONEYCARD
payTokenstring

승인된 결제토큰. 정상 승인처리 되었을 때, 토스 서버에서 매회 유니크한 결제 토큰 값을 전달합니다. 가맹점에서는 이 값을 반드시 저장해야 하며, 거래 환불요청 시 중요한 키 값이 될 수 있으니 관리가 필요합니다.

최대 길이: 30
transactionIdstring

거래 트랜잭션 코드. 결제의 거래 구분을 위하여 토스 서버에서는 매회 유니크한 값을 생성해서 리턴합니다. 매출전표를 호출하거나 환불 진행 시 구분 값으로 활용할 수 있습니다.

최대 길이: 36
discountedAmountinteger

토스 부담 할인 금액. 승인에서 할인이 적용된 금액을 전달하며 할인 적용이 없을 경우 0으로 전달합니다. 할인 금액에는 토스 앱에서 자동 적용되는 즉시할인과 토스 포인트 사용금액이 포함됩니다.

최대 길이: 10
paidAmountinteger

지불수단 승인금액. 총 금액에서 할인금액 등을 제외한 순수한 지불수단 승인금액을 의미합니다. 현금영수증 발행 또는 별도로 활용하는 경우 이 값을 참조할 수 있습니다.

최대 길이: 10
cardUserTypestring

카드 사용자 구분. PERSONAL: 본인 카드, PERSONAL_FAMILY: 가족 카드, CORP_PERSONAL: 법인지정 결제계좌 임직원, CORP_PRIVATE: 법인 공용, CORP_COMPANY: 법인지정 결제계좌 회사(하나카드만)

최대 길이: 20
가능한 값:
PERSONALPERSONAL_FAMILYCORP_PERSONALCORP_PRIVATECORP_COMPANY
cardMethodTypestring

카드 타입. 승인된 카드의 타입을 구분. CREDIT: 신용카드, CHECK: 체크카드, PREPAYMENT: 선불카드

최대 길이: 10
가능한 값:
CREDITCHECKPREPAYMENT
cardCompanyNamestring

승인된 카드사명. 카드 결제의 경우만 전달되며, 승인된 카드사 명과 카드코드를 확인할 수 있습니다.

최대 길이: 2
cardCompanyCodeinteger

카드사 코드. 자세한 내용은 카드 코드를 참조해주세요.

최대 길이: 2
cardAuthorizationNostring

카드사 승인번호. 구매자가 확인할 수 있는 카드사 승인번호 8자리. 테스트 거래의 경우 00000000으로 전달되며, 정상적인 카드사 승인번호는 라이브 키 결제에서 확인하실 수 있습니다.

최대 길이: 8
cardNumberstring

마스킹된 카드번호. 카드번호 16자리 중 중간자리는 마스킹됩니다.

최대 길이: 20
cardNum4Printstring

사용자가 선택한 카드의 끝 4자리. 카드사에 따라 마스킹이 포함되어 있을 수 있습니다.

최대 길이: 4
cardBinNumberstring

카드 BIN 번호. 카드사에서 준 카드 BIN 번호(마스킹 되어 있을 수 있습니다.). 100% 신뢰는 불가합니다.

최대 길이: 8
salesCheckLinkUrlstring

신용카드 매출전표 호출 URL. 승인된 카드 결제건의 매출전표를 확인할 수 있는 URL

최대 길이: 120
spreadOutinteger

카드 할부개월. 승인요청에서 구매자가 선택한 할부개월이 리턴됩니다. 5만원 미만 금액 및 일시불 결제의 경우 0으로 리턴됩니다.

최대 길이: 2
noInterestboolean

카드 무이자 적용 여부. true: 무이자, false: 일반

최대 길이: 5
accountBankCodestring

사용자가 선택한 계좌의 은행코드. 사용자가 선택한 결제수단(payMethod)이 '토스머니'인 경우 토스가 정의한 은행 코드를 전달합니다.

최대 길이: 3
accountBankNamestring

사용자가 선택한 계좌의 은행명. 은행코드 리스트를 참조해주세요.

최대 길이: 20
accountNumberstring

계좌번호. 계좌번호는 일부 마스킹을 포함하고 있습니다.

최대 길이: 30

예제

요청 예제

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;
import java.net.URL;
import java.net.URLConnection;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;

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 org.json.simple.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());
<?php
$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;
?>
import requests

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

response = requests.post(url, json=data)
print(response.text)
require 'net/http'
require 'uri'
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['Content-Type'] = 'application/json'
request.body = params.to_json
response = http.request(request)

puts response.body
Dim data, httpRequest, postResponse

data = "{""apiKey"":""sk_test_w5lNQylNqa5lNQe013Nq"",""billingKey"":""example-billingKey"",""orderNo"":""TEST_billing_1"",""productDesc"":""테스트샵 빌링 상품"",""amount"":10000,""amountTaxFree"":0,""spreadOut"":7,""cashReceipt"":true,""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 postResponse

응답 예제

{
  "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": "150000",

  // payMethod 가 CARD 일때
  "cardCompanyName": "롯데",
  "cardCompanyCode": 5,
  "cardAuthorizationNo": "00000000",
  "salesCheckLinkUrl": "https://alpha-pay.toss.im/payfront/web/external/sales-check?payToken=example-payToken&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"
}