webpay-api

📁 xoverlap/webpay-skill 📅 1 day ago
3
总安装量
3
周安装量
#57991
全站排名
安装命令
npx skills add https://github.com/xoverlap/webpay-skill --skill webpay-api

Agent 安装分布

opencode 3
gemini-cli 3
antigravity 3
claude-code 3
github-copilot 3
codex 3

Skill 文档

Webpay Plus – REST API Integration Skill

This skill provides everything needed to integrate the Transbank Webpay Plus payment gateway using its REST API (HTTP). It covers the complete purchase cycle: creating transactions, confirming payments, checking status, refunding/reversing, and deferred capture.

This skill covers Webpay Plus only (single-store). It does NOT cover Webpay Plus Mall (multi-store) or Oneclick.

Table of Contents

  1. Environments and Credentials
  2. Payment Flow Overview
  3. API Endpoints
  4. Reference Tables
  5. Error Codes
  6. Going to Production

Environments and Credentials

The Webpay REST API is secured via TLSv1.2 and authenticated using two HTTP headers on every request:

Header Description
Tbk-Api-Key-Id Commerce code (codigo de comercio)
Tbk-Api-Key-Secret Secret key (llave secreta)

All requests must also include Content-Type: application/json.

Environments

Environment Base URL
Integration (testing) https://webpay3gint.transbank.cl
Production https://webpay3g.transbank.cl

Integration Test Credentials

Use these credentials freely for testing in the integration environment:

Tbk-Api-Key-Id: 597055555532
Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C

Test Cards for Integration

For testing in the integration environment, use the test cards documented at https://www.transbankdevelopers.cl/documentacion/como_empezar#ambientes

Common test data for a successful transaction:

  • Card number: 4051 8856 0044 6623
  • Expiration date: Any future date
  • CVV: 123
  • RUT: 11.111.111-1
  • Password: 123

To simulate a rejected transaction, use RUT 11.111.111-1 with password 123 but reject the payment in the Webpay form.

Commerce Codes for Integration

Product Commerce Code
Webpay Plus 597055555532
Webpay Plus (Deferred Capture) 597055555540

Payment Flow Overview

The Webpay Plus payment cycle follows this sequence:

1. MERCHANT SERVER                    2. WEBPAY (Transbank)
   |                                     |
   |-- POST /transactions -------------->|  (Create transaction)
   |<-- { token, url } ------------------|
   |                                     |
   |-- Redirect user to url + token ---->|  (User pays on Webpay form)
   |                                     |
   |<-- Redirect to return_url ----------|  (Webpay sends token_ws via POST)
   |                                     |
   |-- PUT /transactions/{token} ------->|  (Confirm / Commit transaction)
   |<-- { transaction result } ----------|
   |                                     |
   |-- Show result to user              |

Step-by-step:

  1. Create transaction: Your server calls POST /rswebpaytransaction/api/webpay/v1.2/transactions with the order details. You receive a token and a url.

  2. Redirect to Webpay: Redirect the user’s browser to the returned url, passing the token via a form POST field called token_ws:

    <form method="POST" action="{url}">
      <input type="hidden" name="token_ws" value="{token}">
      <input type="submit" value="Pagar">
    </form>
    
  3. User pays: The user enters their card details on Transbank’s secure form and authorizes the payment.

  4. Webpay redirects back: After authorization (or rejection/abort), Webpay redirects the user back to your return_url via POST, sending:

    • token_ws: The transaction token (if the user completed the flow)
    • TBK_TOKEN + TBK_ORDEN_COMPRA + TBK_ID_SESION: Only if the user aborted the payment
  5. Confirm transaction: Your server calls PUT /rswebpaytransaction/api/webpay/v1.2/transactions/{token} to confirm and get the result.

  6. Show result: Display the payment result to the user.

Handling Aborted Payments

If the user clicks “Anular” (cancel) on the Webpay form, the redirect to return_url will include TBK_TOKEN, TBK_ORDEN_COMPRA, and TBK_ID_SESION instead of token_ws. In this case, the transaction was NOT completed. Do not call commit; inform the user that payment was cancelled.

Timeout Behavior

If the user does not complete the payment within the allowed time, two requests arrive at return_url:

  1. First with TBK_TOKEN, TBK_ORDEN_COMPRA, TBK_ID_SESION (and empty token_ws)
  2. A second request with just TBK_TOKEN (a POST from the user’s browser)

Both indicate the transaction was abandoned. Do not confirm the transaction.


API Endpoints

All endpoint paths are relative to the base URL for the chosen environment.

Base path: /rswebpaytransaction/api/webpay/v1.2

1. Create Transaction

Initialize a Webpay Plus payment. Returns a token and URL for the payment form.

Endpoint: POST /rswebpaytransaction/api/webpay/v1.2/transactions

Request Headers:

Tbk-Api-Key-Id: 597055555532
Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C
Content-Type: application/json

Request Body:

{
  "buy_order": "ordenCompra12345678",
  "session_id": "sesion1234557545",
  "amount": 10000,
  "return_url": "http://www.comercio.cl/webpay/retorno"
}

Request Parameters:

Parameter Type Description
buy_order String Unique order ID for this transaction. Max length: 26. Allowed chars: letters, numbers, and |_=&%.,~:/?[+!@()>-
session_id String Session identifier, for internal use by the merchant. Returned at the end of the transaction. Max length: 61
amount Decimal Transaction amount. Integer for CLP, max 2 decimals for USD. Max length: 17
return_url String URL where Webpay redirects after authorization. Max length: 256

Response (200 OK):

{
  "token": "e9d555262db0f989e49d724b4db0b0af367cc415cde41f500a776550fc5fddd3",
  "url": "https://webpay3gint.transbank.cl/webpayserver/initTransaction"
}

Response Fields:

Field Type Description
token String Transaction token. Length: 64
url String Webpay payment form URL. Max length: 255

2. Confirm Transaction (Commit)

After the user completes payment on Webpay and is redirected to return_url, confirm the transaction. This is mandatory to finalize the payment.

Endpoint: PUT /rswebpaytransaction/api/webpay/v1.2/transactions/{token}

Request Headers:

Tbk-Api-Key-Id: 597055555532
Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C
Content-Type: application/json

URL Parameters:

Parameter Type Description
token String Transaction token (in the URL path, not body). Length: 64

No request body is needed.

Response (200 OK):

{
  "vci": "TSY",
  "amount": 10000,
  "status": "AUTHORIZED",
  "buy_order": "ordenCompra12345678",
  "session_id": "sesion1234557545",
  "card_detail": {
    "card_number": "6623"
  },
  "accounting_date": "0522",
  "transaction_date": "2019-05-22T16:41:21.063Z",
  "authorization_code": "1213",
  "payment_type_code": "VN",
  "response_code": 0,
  "installments_number": 0
}

Response Fields:

Field Type Description
vci String Cardholder authentication result. See VCI Codes
amount Decimal Transaction amount. Max length: 17
status String Transaction status. See Transaction Statuses
buy_order String Order ID sent in create. Max length: 26
session_id String Session ID sent in create. Max length: 61
card_detail Object Card details object
card_detail.card_number String Last 4 digits of the card. Max length: 19
accounting_date String Authorization date. Length: 4, format: MMDD
transaction_date String Authorization date/time. ISO 8601 format
authorization_code String Authorization code. Max length: 6
payment_type_code String Payment type. See Payment Type Codes
response_code Number Authorization response code. 0 = approved
installments_amount Number Installment amount. Max length: 17
installments_number Number Number of installments. Max length: 2
balance Number Remaining balance for a nullified detail. Max length: 17

Validating a Successful Transaction

After calling commit, verify the transaction was successful by checking:

  1. response_code equals 0
  2. status equals "AUTHORIZED"

If response_code is not 0, the transaction was rejected.


3. Get Transaction Status

Query the state of a transaction at any time. Useful for error recovery or verifying a transaction’s current state.

Endpoint: GET /rswebpaytransaction/api/webpay/v1.2/transactions/{token}

Request Headers:

Tbk-Api-Key-Id: 597055555532
Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C
Content-Type: application/json

URL Parameters:

Parameter Type Description
token String Transaction token (in URL, not body). Length: 64

Response: Same structure as Commit response (see above).


4. Refund / Reverse Transaction

Refund all or part of a completed transaction. If called within the same day as the original transaction, it may result in a reversal (REVERSED). If called on a different day, it becomes a nullification (NULLIFIED).

Endpoint: POST /rswebpaytransaction/api/webpay/v1.2/transactions/{token}/refunds

Request Headers:

Tbk-Api-Key-Id: 597055555532
Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C
Content-Type: application/json

URL Parameters:

Parameter Type Description
token String Transaction token (in URL, not body). Length: 64

Request Body:

{
  "amount": 1000
}

Request Parameters:

Parameter Type Description
amount Decimal Amount to refund/reverse. Integer for CLP, max 2 decimals for USD. Max length: 17

Response (200 OK) – Nullification:

{
  "type": "NULLIFIED",
  "authorization_code": "123456",
  "authorization_date": "2019-03-20T20:18:20Z",
  "nullified_amount": 1000.00,
  "balance": 0.00,
  "response_code": 0
}

Response (200 OK) – Reversal:

{
  "type": "REVERSED"
}

Response Fields:

Field Type Description
type String Refund type: REVERSED or NULLIFIED. Max length: 10
authorization_code String (NULLIFIED only) Authorization code. Max length: 6
authorization_date String (NULLIFIED only) Authorization date/time
balance Decimal (NULLIFIED only) Updated balance. Max length: 17
nullified_amount Decimal (NULLIFIED only) Amount nullified. Max length: 17
response_code Number (NULLIFIED only) Result code. 0 = success. Max: 2

Refund Error Codes:

Code Description
304 Null input field validation
245 Commerce code does not exist
22 Commerce is not active
316 Commerce does not match certificate
308 Operation not allowed
274 Transaction not found
16 Transaction does not allow nullification
292 Transaction is not authorized
284 Nullification period exceeded
310 Transaction already nullified
311 Amount exceeds available balance to nullify
312 Generic nullification error
315 Authorizer error
53 Transaction does not allow partial nullification with installments

5. Capture Transaction (Deferred)

For merchants configured with deferred capture, this endpoint captures a previously authorized transaction. Requires a specific commerce code for deferred capture.

Integration commerce code for deferred capture: 597055555540

Endpoint: PUT /rswebpaytransaction/api/webpay/v1.2/transactions/{token}/capture

Request Headers:

Tbk-Api-Key-Id: 597055555540
Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C
Content-Type: application/json

URL Parameters:

Parameter Type Description
token String Transaction token (in URL, not body). Length: 64

Request Body:

{
  "buy_order": "415034240",
  "authorization_code": "12345",
  "capture_amount": 1000
}

Request Parameters:

Parameter Type Description
buy_order String Order ID of the transaction to capture. Max length: 26
authorization_code String Authorization code from the original transaction. Max length: 6
capture_amount Decimal Amount to capture. Max length: 17

Response (200 OK):

{
  "token": "e074d38c628122c63e5c0986368ece22974d6fee1440617d85873b7b4efa48a3",
  "authorization_code": "123456",
  "authorization_date": "2019-03-20T20:18:20Z",
  "captured_amount": 1000,
  "response_code": 0
}

Response Fields:

Field Type Description
token String Transaction token. Max length: 64
authorization_code String Deferred capture authorization code. Max length: 6
authorization_date String Authorization date/time
captured_amount Decimal Captured amount. Max length: 6
response_code Number Result code. 0 = success. Max: 2

Capture Error Codes:

Code Description
304 Null input field validation
245 Commerce code does not exist
22 Commerce is not active
316 Commerce does not match certificate
308 Operation not allowed
274 Transaction not found
16 Transaction is not deferred capture
292 Transaction is not authorized
284 Capture period exceeded
310 Transaction previously reversed
309 Transaction previously captured
311 Capture amount exceeds authorized amount
315 Authorizer error

Reference Tables

Transaction Statuses

Status Description
INITIALIZED Transaction has been created, waiting for user to complete payment
AUTHORIZED Transaction was authorized successfully
REVERSED Transaction was reversed (same-day refund)
FAILED Transaction was rejected or failed
NULLIFIED Transaction was nullified (refund after accounting date)
PARTIALLY_NULLIFIED Transaction was partially nullified
CAPTURED Transaction was captured (deferred capture)

Payment Type Codes

Code Description
VD Debit Sale (Venta Debito)
VN Normal Sale – Credit (Venta Normal)
VC Installment Sale (Venta en Cuotas)
SI 3 interest-free installments (3 Cuotas sin Interes)
S2 2 interest-free installments (2 Cuotas sin Interes)
NC N interest-free installments (N Cuotas sin Interes)
VP Prepaid Sale (Venta Prepago)

VCI Codes

The vci field indicates cardholder authentication results. This is supplementary information to response_code. Merchants should NOT validate this field as new codes are constantly added.

Domestic transactions:

Code Description
TSY Authentication successful
TSN Authentication rejected
NP Non-participating, no authentication
U3 Connection failure, authentication rejected
INV Invalid data
A Attempted
CNP1 Commerce does not participate
EOP Operational error
BNA BIN not enrolled
ENA Issuer not enrolled

Foreign sale codes:

Code Description
TSYS Successful frictionless authentication
TSAS Attempt, card not enrolled / issuer unavailable
TSNS Failed, not authenticated, denied
TSRS Authentication rejected, frictionless
TSUS Authentication failed due to technical issue
TSCF Challenge authentication (not accepted by commerce)
TSYF Successful challenge authentication
TSNF Not authenticated, denied with challenge
TSUF Challenge authentication failed due to technical issue
NPC Commerce does not participate
NPB BIN does not participate
NPCB Commerce and BIN do not participate
SPCB Commerce and BIN participate, authorization incomplete

Error Codes

HTTP Status Codes

HTTP Code Description
200 Operation executed successfully
204 DELETE operation executed successfully
400 Invalid JSON message (malformed or unexpected field)
401 Unauthorized. Invalid API Key and/or API Secret
404 Transaction not found
405 Method not allowed
406 Cannot process response in requested format
415 Message type not allowed
422 Request cannot be processed (data validation or business logic)
500 Unexpected error

All errors return a JSON body:

{
  "error_message": "token is required"
}

Going to Production

To move from integration to production:

  1. Complete the certification process with Transbank
  2. Obtain your production commerce code and API secret
  3. Change the base URL from https://webpay3gint.transbank.cl to https://webpay3g.transbank.cl
  4. Replace the integration credentials with your production credentials

More details at https://www.transbankdevelopers.cl/documentacion/como_empezar#puesta-en-produccion


Implementation Examples

Node.js / Express Backend Example

const express = require('express');
const axios = require('axios');

const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Configuration
const WEBPAY_BASE_URL = 'https://webpay3gint.transbank.cl'; // Use production URL for prod
const API_KEY_ID = '597055555532';
const API_KEY_SECRET = '579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C';

const headers = {
  'Tbk-Api-Key-Id': API_KEY_ID,
  'Tbk-Api-Key-Secret': API_KEY_SECRET,
  'Content-Type': 'application/json'
};

// Step 1: Create transaction
app.post('/api/webpay/create', async (req, res) => {
  try {
    const { buy_order, session_id, amount, return_url } = req.body;

    const response = await axios.post(
      `${WEBPAY_BASE_URL}/rswebpaytransaction/api/webpay/v1.2/transactions`,
      { buy_order, session_id, amount, return_url },
      { headers }
    );

    // Return token and url to frontend
    res.json(response.data);
  } catch (error) {
    res.status(error.response?.status || 500).json({
      error: error.response?.data || 'Error creating transaction'
    });
  }
});

// Step 2: Confirm transaction (return_url handler)
app.post('/api/webpay/confirm', async (req, res) => {
  try {
    const token_ws = req.body.token_ws;

    // Check if payment was aborted
    if (!token_ws || req.body.TBK_TOKEN) {
      return res.redirect('/payment-cancelled');
    }

    const response = await axios.put(
      `${WEBPAY_BASE_URL}/rswebpaytransaction/api/webpay/v1.2/transactions/${token_ws}`,
      null,
      { headers }
    );

    const result = response.data;

    // Validate successful transaction
    if (result.response_code === 0 && result.status === 'AUTHORIZED') {
      // Payment successful - update your database
      res.redirect(`/payment-success?order=${result.buy_order}`);
    } else {
      // Payment rejected
      res.redirect(`/payment-rejected?order=${result.buy_order}`);
    }
  } catch (error) {
    res.redirect('/payment-error');
  }
});

// Check transaction status
app.get('/api/webpay/status/:token', async (req, res) => {
  try {
    const response = await axios.get(
      `${WEBPAY_BASE_URL}/rswebpaytransaction/api/webpay/v1.2/transactions/${req.params.token}`,
      { headers }
    );
    res.json(response.data);
  } catch (error) {
    res.status(error.response?.status || 500).json({
      error: error.response?.data || 'Error checking status'
    });
  }
});

// Refund transaction
app.post('/api/webpay/refund', async (req, res) => {
  try {
    const { token, amount } = req.body;

    const response = await axios.post(
      `${WEBPAY_BASE_URL}/rswebpaytransaction/api/webpay/v1.2/transactions/${token}/refunds`,
      { amount },
      { headers }
    );
    res.json(response.data);
  } catch (error) {
    res.status(error.response?.status || 500).json({
      error: error.response?.data || 'Error refunding transaction'
    });
  }
});

Frontend Redirect Example

<!-- After receiving token and url from your backend -->
<form id="webpay-form" method="POST" action="">
  <input type="hidden" name="token_ws" id="token_ws">
  <button type="submit">Pagar con Webpay</button>
</form>

<script>
async function initiatePayment(orderData) {
  const response = await fetch('/api/webpay/create', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      buy_order: orderData.orderId,
      session_id: orderData.sessionId,
      amount: orderData.amount,
      return_url: window.location.origin + '/api/webpay/confirm'
    })
  });

  const { token, url } = await response.json();

  // Redirect to Webpay payment form
  const form = document.getElementById('webpay-form');
  form.action = url;
  document.getElementById('token_ws').value = token;
  form.submit();
}
</script>

cURL Examples

Create transaction:

curl -X POST "https://webpay3gint.transbank.cl/rswebpaytransaction/api/webpay/v1.2/transactions" \
  -H "Tbk-Api-Key-Id: 597055555532" \
  -H "Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C" \
  -H "Content-Type: application/json" \
  -d '{
    "buy_order": "order123",
    "session_id": "session456",
    "amount": 10000,
    "return_url": "http://localhost:3000/webpay/confirm"
  }'

Confirm transaction:

curl -X PUT "https://webpay3gint.transbank.cl/rswebpaytransaction/api/webpay/v1.2/transactions/{token}" \
  -H "Tbk-Api-Key-Id: 597055555532" \
  -H "Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C" \
  -H "Content-Type: application/json"

Get transaction status:

curl -X GET "https://webpay3gint.transbank.cl/rswebpaytransaction/api/webpay/v1.2/transactions/{token}" \
  -H "Tbk-Api-Key-Id: 597055555532" \
  -H "Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C" \
  -H "Content-Type: application/json"

Refund:

curl -X POST "https://webpay3gint.transbank.cl/rswebpaytransaction/api/webpay/v1.2/transactions/{token}/refunds" \
  -H "Tbk-Api-Key-Id: 597055555532" \
  -H "Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C" \
  -H "Content-Type: application/json" \
  -d '{"amount": 5000}'

Capture (deferred):

curl -X PUT "https://webpay3gint.transbank.cl/rswebpaytransaction/api/webpay/v1.2/transactions/{token}/capture" \
  -H "Tbk-Api-Key-Id: 597055555540" \
  -H "Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C" \
  -H "Content-Type: application/json" \
  -d '{
    "buy_order": "order123",
    "authorization_code": "123456",
    "capture_amount": 10000
  }'

Important Implementation Notes

  1. The buy_order must be unique for each transaction. It cannot be reused.

  2. Always confirm (commit) the transaction after receiving the redirect. If you don’t call commit, the transaction remains in INITIALIZED state and the payment will not be processed.

  3. Commit has a time limit: You must confirm the transaction within a few seconds after the user is redirected back. If too much time passes, the transaction may expire.

  4. Handle all redirect scenarios at your return_url:

    • token_ws present: Normal flow, proceed to commit
    • TBK_TOKEN present (no token_ws): User aborted
    • Both present with empty token_ws: Timeout
  5. Refund vs Reversal: The API automatically determines whether to reverse (same day, before accounting cutoff) or nullify (after accounting cutoff). You always call the same endpoint.

  6. Partial refunds are supported: You can refund any amount up to the original transaction amount. Multiple partial refunds are allowed until the balance reaches zero.

  7. Deferred capture requires a special commerce code and configuration with Transbank. Not all merchants have this feature enabled.

  8. The vci field should NOT be used for business logic validation. Use response_code instead. The vci field is informational only and new values are added without documentation updates.

  9. The response_code is the definitive indicator of whether a transaction was approved (0) or rejected (non-zero).