Skip to main content

Overview

The PaymentProviderService class is responsible for registering your payment provider connector with the VTEX IO runtime. It handles HTTP routing, request validation, and connects your PaymentProvider implementation to the VTEX Payment Gateway.

Class signature

class PaymentProviderService {
  constructor(options: PaymentProviderServiceOptions)
}

interface PaymentProviderServiceOptions {
  connector: typeof PaymentProvider
  timeout?: number
}

Constructor

Creates a new payment provider service instance and registers it with the VTEX IO runtime.

Parameters

options
PaymentProviderServiceOptions
required
Configuration object for the service
options.connector
typeof PaymentProvider
required
The connector class that extends PaymentProvider. This is the class constructor, not an instance.
options.timeout
number
default:10000
Optional timeout in milliseconds for payment operations. Defaults to 10 seconds.

Usage

Basic setup

The service is typically instantiated in your node/index.ts file:
node/index.ts
import { PaymentProviderService } from '@vtex/payment-provider'
import TestSuiteApprover from './connector'

export default new PaymentProviderService({
  connector: TestSuiteApprover,
})
Pass the class itself (constructor), not an instance. The service will instantiate your connector for each request.

With custom timeout

For payment providers that require longer processing times:
node/index.ts
import { PaymentProviderService } from '@vtex/payment-provider'
import SlowPaymentProvider from './connector'

export default new PaymentProviderService({
  connector: SlowPaymentProvider,
  timeout: 30000, // 30 seconds
})
VTEX recommends keeping timeouts under 15 seconds to prevent gateway timeouts. For longer operations, use asynchronous flows with callbacks.

How it works

The PaymentProviderService automatically:
  1. Registers HTTP routes for the Payment Provider Protocol:
    • POST /payments - Authorization requests
    • POST /cancellations - Cancellation requests
    • POST /settlements - Settlement requests
    • POST /refunds - Refund requests
    • POST /inbound - Webhook notifications (if defined)
  2. Validates requests according to the Payment Provider Protocol specification
  3. Instantiates your connector for each request with the proper context
  4. Handles errors and formats responses according to VTEX standards
  5. Manages timeouts and ensures responses are sent within the configured limit

Request flow

Complete example

node/index.ts
import { PaymentProviderService } from '@vtex/payment-provider'
import TestSuiteApprover from './connector'

export default new PaymentProviderService({
  connector: TestSuiteApprover,
})

Error handling

The service automatically handles common error scenarios:

Timeout errors

// If your connector takes too long
public async authorize(
  authorization: AuthorizationRequest
): Promise<AuthorizationResponse> {
  // This operation takes 20 seconds but timeout is 10 seconds
  await longRunningOperation()
  
  // Service will return timeout error to VTEX Gateway
}
Solution: Use asynchronous flows for long-running operations:
public async authorize(
  authorization: AuthorizationRequest
): Promise<AuthorizationResponse> {
  // Start async operation
  this.startAsyncOperation(authorization)
  
  // Return pending immediately
  return Authorizations.pending(authorization, {
    delayToCancel: 300000,
    tid: 'transaction-id',
  })
}

private async startAsyncOperation(auth: AuthorizationRequest) {
  // Process in background
  const result = await longRunningOperation()
  
  // Send result via callback
  this.callback(auth, Authorizations.approve(auth, result))
}

Validation errors

// Invalid response format will be caught
public async authorize(
  authorization: AuthorizationRequest
): Promise<AuthorizationResponse> {
  // Don't return plain objects - use helper methods
  return {
    status: 'approved', // ❌ Wrong
    paymentId: authorization.paymentId,
  }
  
  // Use helper methods instead
  return Authorizations.approve(authorization, { // ✅ Correct
    authorizationId: 'auth-id',
  })
}

Runtime errors

public async authorize(
  authorization: AuthorizationRequest
): Promise<AuthorizationResponse> {
  try {
    const result = await this.paymentGateway.process(authorization)
    return Authorizations.approve(authorization, result)
  } catch (error) {
    // Log error for debugging
    console.error('Payment processing failed:', error)
    
    // Return denial to VTEX
    return Authorizations.deny(authorization, {
      tid: 'error',
    })
  }
}

Environment context

Your connector receives a context object with VTEX IO runtime information:
export default class MyConnector extends PaymentProvider {
  public async authorize(
    authorization: AuthorizationRequest
  ): Promise<AuthorizationResponse> {
    // Access VTEX context
    const { account, workspace } = this.context.vtex
    
    // Access pre-configured clients
    const vbase = this.context.clients.vbase
    
    // Use VBase for persistence
    await vbase.saveJSON('bucket', 'key', { data: 'value' })
    
    // ...
  }
}

Testing

The service integrates with VTEX’s test suite. Use the isTestSuite property to enable test-specific behavior:
node/connector.ts
export default class TestSuiteApprover extends PaymentProvider {
  public async authorize(
    authorization: AuthorizationRequest
  ): Promise<AuthorizationResponse> {
    if (this.isTestSuite) {
      // Test suite specific logic
      return executeAuthorization(authorization, response =>
        this.callback(authorization, response)
      )
    }

    // Production logic
    throw new Error('Not implemented')
  }
}
The test suite validates that your connector implements the Payment Provider Protocol correctly. Passing the test suite is required before your connector can be used in production.

See also

PaymentProvider

Learn about the abstract class your connector extends

Configuration

Configure your payment provider settings

Testing

Test your connector with the VTEX test suite

Deployment

Publish your connector to production

Build docs developers (and LLMs) love