Skip to content

Class Name: StripeAdapter

Last Updated: 2025-10-22 Source Code: StripeAdapter.cls

API Name: StripeAdapter Type: API/Integration Test Coverage: Not specified Author: Ecaterina Popa Created: 06/26/2024

Business Purpose

This class implements the Stripe payment gateway integration for Salesforce Commerce Cloud, enabling AANP to process credit card payments through Stripe. It handles payment tokenization, authorization, and capture operations, converting between Salesforce Commerce payment objects and Stripe API calls while maintaining PCI compliance.

Class Overview

Scope and Sharing

  • Sharing Model: Not specified (global class)
  • Access Modifier: global
  • Interfaces Implemented: commercepayments.PaymentGatewayAdapter

Key Responsibilities

  • Process payment authorization requests through Stripe
  • Tokenize credit card information for secure storage
  • Capture previously authorized payments
  • Handle payment gateway responses and error conditions
  • Convert between Salesforce currency formats and Stripe's currency units
  • Manage Stripe customer and card token creation

Public Methods

processRequest

global commercepayments.GatewayResponse processRequest(commercepayments.paymentGatewayContext gatewayContext)

Purpose: Main entry point for all payment gateway operations. Routes requests to appropriate handler methods based on request type.

Parameters: - gatewayContext (commercepayments.paymentGatewayContext): Context containing payment request type and details

Returns: - commercepayments.GatewayResponse: Response object specific to the request type (AuthorizationResponse, CaptureResponse, or TokenizationResponse)

Throws: - StripeValidationException: Caught internally and converted to GatewayErrorResponse

Usage Example:

// Called automatically by Salesforce Commerce payment processing
commercepayments.GatewayResponse response = adapter.processRequest(gatewayContext);

Business Logic: - Routes Authorize requests to createAuthResponse() - Routes Capture requests to createCaptureResponse() - Routes Tokenize requests to createTokenizeResponse() - Wraps validation exceptions in gateway error responses


createTokenizeResponse

public commercepayments.GatewayResponse createTokenizeResponse(commercepayments.PaymentMethodTokenizationRequest tokenizeRequest)

Purpose: Creates a Stripe token for a credit card and associates it with a Stripe customer, enabling future charges without storing card details in Salesforce.

Parameters: - tokenizeRequest (commercepayments.PaymentMethodTokenizationRequest): Contains card details, billing address, and account information

Returns: - commercepayments.PaymentMethodTokenizationResponse: Contains gateway token and customer ID on success - commercepayments.GatewayErrorResponse: Error response if tokenization fails

Business Logic: - Creates Stripe card token with card details and billing address - Retrieves Account name for Stripe customer record - Creates Stripe customer and associates card token - Stores customer ID in GatewayTokenDetails - Stores card token ID in GatewayToken - Handles card_error types with specific decline codes - Only processes in non-test context (returns error in tests)


createAuthResponse

public commercepayments.GatewayResponse createAuthResponse(commercepayments.AuthorizationRequest authRequest)

Purpose: Authorizes a payment amount on a previously tokenized card without immediately capturing funds. Holds the amount for later capture.

Parameters: - authRequest (commercepayments.AuthorizationRequest): Contains payment method ID, amount, and currency

Returns: - commercepayments.AuthorizationResponse: Contains authorization code and amount on success - commercepayments.GatewayErrorResponse: Error response if authorization fails

Business Logic: - Queries CardPaymentMethod for GatewayToken and GatewayTokenDetails - Handles zero-dollar authorizations without API call - Converts amount to Stripe currency units (cents for USD) - Creates Stripe charge with capture=false - Stores charge ID as GatewayAuthCode for later capture - Maps Stripe decline codes to Salesforce result codes


createCaptureResponse

public commercepayments.GatewayResponse createCaptureResponse(commercepayments.CaptureRequest captureRequest)

Purpose: Captures funds from a previously authorized payment, completing the transaction and transferring money from customer to merchant.

Parameters: - captureRequest (commercepayments.CaptureRequest): Contains payment authorization ID and amount to capture

Returns: - commercepayments.CaptureResponse: Contains captured amount and transaction details - commercepayments.GatewayErrorResponse: Error response if capture fails

Business Logic: - Queries PaymentAuthorization for GatewayAuthCode (Stripe charge ID) - Converts amount to Stripe currency units - Calls Stripe charge capture endpoint - Returns balance transaction ID and receipt URL - Converts captured amount back to decimal format


Private/Helper Methods

doPost

Purpose: Executes HTTP POST requests to Stripe API with proper authentication Called By: All payment operation methods (tokenize, authorize, capture) Details: Uses Named Credentials for authentication, formats request body as URL-encoded

urlEncodedParams

Purpose: Converts parameter map to URL-encoded request body Called By: doPost method Details: Builds query string format, does not encode values to allow credential replacement

urlEncode

Purpose: URL-encodes string values Called By: urlEncodedParams, tokenization methods Details: Uses UTF-8 encoding

toStripeCurrencyUnits

Purpose: Converts decimal amount to Stripe's integer currency units (e.g., dollars to cents) Called By: Authorization and capture methods Details: Currently only supports USD, multiplies by 100 and rounds

toCodeInfo

Purpose: Converts SalesforceResultCode enum to SalesforceResultCodeInfo object Called By: All response creation methods Details: Wrapper for creating result code info objects


Dependencies

Apex Classes

  • commercepayments.PaymentGatewayAdapter: Interface implementation
  • commercepayments.PaymentsHttp: Salesforce HTTP class for payment callouts
  • QueryUtils: Dynamic SOQL query builder

Salesforce Objects

  • CardPaymentMethod: Stores tokenized card information (GatewayToken, GatewayTokenDetails)
  • PaymentAuthorization: Stores authorization details (GatewayAuthCode)
  • Account: Retrieves account name for Stripe customer creation
  • Payment: Links to PaymentAuthorization (commented out in refund logic)

Custom Settings/Metadata

  • Named Credential configured for Stripe API authentication

External Services

  • Stripe API v1:
  • POST /v1/tokens - Card tokenization
  • POST /v1/customers - Customer creation
  • POST /v1/charges - Payment authorization
  • POST /v1/charges/{id}/capture - Payment capture
  • POST /v1/refunds - Refund processing (commented out)

Design Patterns

  • Adapter Pattern: Implements Salesforce's PaymentGatewayAdapter interface to integrate Stripe
  • Strategy Pattern: Different response creation strategies based on request type
  • Factory Pattern: Creates different response types based on operation

Governor Limits Considerations

SOQL Queries: 1-2 queries per payment operation (CardPaymentMethod, PaymentAuthorization, Account lookups) DML Operations: None (payment records managed by Salesforce Commerce framework) CPU Time: Low - mostly HTTP callouts and JSON parsing Heap Size: Low - small JSON payloads

Bulkification: Not applicable - payment gateway adapter processes one payment at a time Async Processing: Synchronous only - required by payment gateway interface

Error Handling

Strategy: - try-catch at processRequest level - HTTP status code validation - Stripe error type mapping to Salesforce result codes - Custom StripeValidationException for validation errors

Logging: - No explicit logging - Errors returned as GatewayErrorResponse objects - Debug statements in test contexts

User Notifications: - Gateway error responses include error messages from Stripe - Decline codes mapped to user-friendly descriptions

Security Considerations

Sharing Rules: Not applicable (global class, no sharing keyword) Field-Level Security: Bypassed - uses SOQL without WITH SECURITY_ENFORCED CRUD Permissions: Bypassed - direct SOQL queries Input Validation: - Currency code validation (throws exception for unsupported currencies) - Test context validation to prevent real API calls - HTTP status code validation

PCI Compliance: - Card numbers never stored in Salesforce - Tokenization occurs immediately - Uses Salesforce's secure payment framework

Test Class

Test Class: StripeAdapterTest.cls Coverage: Not specified Test Scenarios Covered: - Successful tokenization - Successful authorization - Successful capture - Card error handling - Unknown error code handling - Zero-dollar authorization

Mock Classes: - StripeHttpCalloutMock.MockSuccess: Simulates successful Stripe responses - StripeHttpCalloutMock.MockErrorKnownCode: Simulates card decline errors - StripeHttpCalloutMock.MockErrorUnknownCode: Simulates unknown errors

Changes & History

  • 2024-06-26: Initial implementation by Ecaterina Popa
  • Refund functionality: Commented out - refunds processed outside Stripe context

Pre-Go-Live Concerns

CRITICAL - Fix Before Go-Live

  • HARDCODED CURRENCY: Only supports USD, will throw exception for other currencies
  • TEST CONTEXT BYPASS: Returns generic error in test context instead of proper mock handling
  • FLS/CRUD BYPASS: No security checks on SOQL queries (CardPaymentMethod, PaymentAuthorization, Account)
  • SOQL IN LOOPS: Not currently an issue but tokenization queries Account inside token creation flow
  • INCOMPLETE ERROR HANDLING: Many TODO comments for error mapping
  • MAGIC NUMBERS: Hardcoded status codes (200, 400, 500) without constants

HIGH - Address Soon After Go-Live

  • COMMENTED CODE: Large refund method commented out - remove or implement properly
  • INCOMPLETE CURRENCY CONVERSION: toStripeCurrencyUnits throws exception for non-USD
  • NO LOGGING: No error logging or audit trail for payment operations
  • HARDCODED CURRENCY IN CAPTURE: Always uses 'usd' regardless of original authorization currency
  • NO RETRY LOGIC: Single HTTP call without retry for transient failures
  • QueryUtils USAGE: Dynamic SOQL builder may have performance overhead vs static SOQL

MEDIUM - Future Enhancement

  • Support multiple currencies with proper conversion logic
  • Implement comprehensive error code mapping between Stripe and Salesforce
  • Add detailed logging for payment operations (PCI-compliant)
  • Remove commented refund code or implement fully
  • Add idempotency keys for Stripe API calls to prevent duplicate charges
  • Implement partial capture support
  • Add support for Stripe Connect (multi-merchant)

LOW - Monitor

  • Monitor HTTP callout timeout performance
  • Track Stripe API version compatibility
  • Monitor Named Credential authentication failures
  • Review Stripe decline code list for updates

Maintenance Notes

Complexity: High Recommended Review Schedule: Quarterly Key Maintainer Notes: - This is a critical payment processing class - all changes require thorough testing in sandbox with real Stripe test mode - Stripe API versions may introduce breaking changes - monitor Stripe changelog - Named Credential must be properly configured in each environment - Test.isRunningTest() checks prevent real API calls during deployment - DO NOT log card details or full API responses (PCI compliance) - Refund logic is intentionally disabled - refunds processed through alternative method - Zero-dollar authorization bypass (line 187-193) is intentional for free orders - Currency conversion assumes 2 decimal places - verify for all supported currencies before enabling - Any changes to token storage format (GatewayToken/GatewayTokenDetails) will impact existing payment methods - Stripe charge IDs (ch_xxx) must be stored as GatewayAuthCode for capture to work