This guide covers the implementation of the four required routes for a VTEX payment connector: authorize, cancel, settle, and refund. You’ll learn about request/response formats, response helpers, and asynchronous payment flows.
Overview of payment routes
Every payment connector must implement four core methods:
authorize Validates and authorizes a payment transaction
cancel Cancels an authorized payment before settlement
settle Captures/settles an authorized payment
refund Refunds a settled payment
Authorization route
The authorization route is the most complex route, handling payment validation and supporting multiple payment flows.
Basic authorization implementation
Import required types and helpers
import {
AuthorizationRequest ,
AuthorizationResponse ,
Authorizations ,
PaymentProvider ,
} from '@vtex/payment-provider'
Implement the authorize method
export default class TestSuiteApprover extends PaymentProvider {
public async authorize (
authorization : AuthorizationRequest
) : Promise < AuthorizationResponse > {
// Validate the payment request
// Communicate with your payment gateway
// Return an appropriate response
return Authorizations . approve ( authorization , {
authorizationId: 'unique-auth-id' ,
nsu: 'unique-nsu' ,
tid: 'transaction-id' ,
})
}
}
Authorization response types
The @vtex/payment-provider package provides helper methods for different authorization responses:
Approve
Deny
Pending
Redirect
Bank invoice
import { Authorizations } from '@vtex/payment-provider'
// Approve the authorization immediately
Authorizations . approve ( request , {
authorizationId: 'unique-auth-id' ,
nsu: 'network-sequence-number' ,
tid: 'transaction-id' ,
})
Handling different payment methods
Use type guards to handle different payment method types:
import {
isCardAuthorization ,
isBankInvoiceAuthorization ,
isTokenizedCard ,
} from '@vtex/payment-provider'
export default class TestSuiteApprover extends PaymentProvider {
public async authorize (
authorization : AuthorizationRequest
) : Promise < AuthorizationResponse > {
// Handle bank invoice payments
if ( isBankInvoiceAuthorization ( authorization )) {
return this . handleBankInvoice ( authorization )
}
// Handle card payments
if ( isCardAuthorization ( authorization )) {
const { card } = authorization
if ( isTokenizedCard ( card )) {
// Handle tokenized card
return this . handleTokenizedCard ( authorization , card )
} else {
// Handle regular card
return this . handleRegularCard ( authorization , card )
}
}
// Default handling
return Authorizations . deny ( authorization , { tid: 'unknown-method' })
}
}
Asynchronous authorization flow
For payments that require async processing, use the callback mechanism:
import { VBase } from '@vtex/api'
export default class TestSuiteApprover extends PaymentProvider {
private async saveAndRetry (
req : AuthorizationRequest ,
resp : AuthorizationResponse
) {
// Persist the response
await this . context . clients . vbase . saveJSON (
'authorizations' ,
resp . paymentId ,
resp
)
// Send callback to VTEX
this . callback ( req , resp )
}
public async authorize (
authorization : AuthorizationRequest
) : Promise < AuthorizationResponse > {
// Return pending response immediately
const pendingResponse = Authorizations . pending ( authorization , {
delayToCancel: 1000 ,
tid: 'pending-transaction' ,
})
// Process asynchronously and callback later
this . processPaymentAsync ( authorization ). then ( finalResponse => {
this . saveAndRetry ( authorization , finalResponse )
})
return pendingResponse
}
}
Ensure the outbound-access policy is configured in your manifest.json to enable callbacks to VTEX.
Cancellation route
The cancellation route handles canceling authorized but not yet settled payments.
Basic cancellation implementation
import {
CancellationRequest ,
CancellationResponse ,
Cancellations ,
} from '@vtex/payment-provider'
export default class TestSuiteApprover extends PaymentProvider {
public async cancel (
cancellation : CancellationRequest
) : Promise < CancellationResponse > {
// Communicate with your payment gateway to cancel the transaction
// Return appropriate response
return Cancellations . approve ( cancellation , {
cancellationId: 'unique-cancellation-id' ,
})
}
}
Cancellation response helpers
import { Cancellations } from '@vtex/payment-provider'
Cancellations . approve ( request , {
cancellationId: 'unique-cancellation-id' ,
})
Settlement route
The settlement route captures/settles an authorized payment.
Basic settlement implementation
import {
SettlementRequest ,
SettlementResponse ,
Settlements ,
} from '@vtex/payment-provider'
export default class TestSuiteApprover extends PaymentProvider {
public async settle (
settlement : SettlementRequest
) : Promise < SettlementResponse > {
// Communicate with your payment gateway to settle the transaction
// Return appropriate response
return Settlements . approve ( settlement , {
settleId: 'unique-settlement-id' ,
})
}
}
Settlement response helpers
import { Settlements } from '@vtex/payment-provider'
Settlements . approve ( request , {
settleId: 'unique-settlement-id' ,
})
Refund route
The refund route handles refunding a settled payment.
Basic refund implementation
import {
RefundRequest ,
RefundResponse ,
Refunds ,
} from '@vtex/payment-provider'
export default class TestSuiteApprover extends PaymentProvider {
public async refund ( refund : RefundRequest ) : Promise < RefundResponse > {
// Communicate with your payment gateway to refund the transaction
// Return appropriate response
return Refunds . approve ( refund , {
refundId: 'unique-refund-id' ,
})
}
}
Refund response helpers
import { Refunds } from '@vtex/payment-provider'
Refunds . approve ( request , {
refundId: 'unique-refund-id' ,
})
Complete example
Here’s a complete example from the TestSuiteApprover connector:
import {
AuthorizationRequest ,
AuthorizationResponse ,
CancellationRequest ,
CancellationResponse ,
Cancellations ,
PaymentProvider ,
RefundRequest ,
RefundResponse ,
Refunds ,
SettlementRequest ,
SettlementResponse ,
Settlements ,
} from '@vtex/payment-provider'
import { VBase } from '@vtex/api'
import { randomString } from './utils'
import { executeAuthorization } from './flow'
const authorizationsBucket = 'authorizations'
const persistAuthorizationResponse = async (
vbase : VBase ,
resp : AuthorizationResponse
) => vbase . saveJSON ( authorizationsBucket , resp . paymentId , resp )
const getPersistedAuthorizationResponse = async (
vbase : VBase ,
req : AuthorizationRequest
) =>
vbase . getJSON < AuthorizationResponse | undefined >(
authorizationsBucket ,
req . paymentId ,
true
)
export default class TestSuiteApprover extends PaymentProvider {
private async saveAndRetry (
req : AuthorizationRequest ,
resp : AuthorizationResponse
) {
await persistAuthorizationResponse ( this . context . clients . vbase , resp )
this . callback ( req , resp )
}
public async authorize (
authorization : AuthorizationRequest
) : Promise < AuthorizationResponse > {
if ( this . isTestSuite ) {
const persistedResponse = await getPersistedAuthorizationResponse (
this . context . clients . vbase ,
authorization
)
if ( persistedResponse !== undefined && persistedResponse !== null ) {
return persistedResponse
}
return executeAuthorization ( authorization , response =>
this . saveAndRetry ( authorization , response )
)
}
throw new Error ( 'Not implemented' )
}
public async cancel (
cancellation : CancellationRequest
) : Promise < CancellationResponse > {
if ( this . isTestSuite ) {
return Cancellations . approve ( cancellation , {
cancellationId: randomString (),
})
}
throw new Error ( 'Not implemented' )
}
public async refund ( refund : RefundRequest ) : Promise < RefundResponse > {
if ( this . isTestSuite ) {
return Refunds . deny ( refund )
}
throw new Error ( 'Not implemented' )
}
public async settle (
settlement : SettlementRequest
) : Promise < SettlementResponse > {
if ( this . isTestSuite ) {
return Settlements . deny ( settlement )
}
throw new Error ( 'Not implemented' )
}
public inbound : undefined
}
Always implement proper error handling and validation in production code. The example above uses simplified logic for demonstration purposes.
Next steps
Configuration Configure your connector with manifest and service settings
Payment methods Configure supported payment methods