Moving a payment integration from sandbox to production is the most anxiety inducing stage of gateway development. Everything worked in testing. The requests went through, the callbacks arrived, the order statuses updated. But sandbox environments and production environments are different systems, and the differences matter. This guide covers the practical steps of transitioning a mobile payments API integration from sandbox testing into live WooCommerce transactions, including what should change, what should stay the same, field mapping verification, timeout adjustments, retry behavior, logging practices, and the specific checks that catch problems before they affect real customers and real money. This is the follow on guide to building a custom WooCommerce payment gateway plugin and pairs with the sandbox testing guide.
How a Sandbox Differs from Production
Sandbox environments are designed to let you test the integration workflow without processing real money. They accept test credentials, return simulated responses, and generally behave like the production system with some important exceptions.
Response timing is usually faster in sandbox because there is no real payment processing happening. In production, the provider actually contacts a bank, a mobile money operator, or a card network, and that processing adds latency that does not exist in sandbox. If your timeout settings were tuned for sandbox response times, they may be too aggressive for production.
Error handling in sandbox is often incomplete. Sandbox environments may return generic success responses for scenarios that would fail in production. Some sandboxes do not enforce field validation as strictly as production. I have worked with providers where the sandbox accepted a request with a missing required field that production rejected immediately. The sandbox gave false confidence that the request format was correct.
Callback behavior differs too. Sandbox callbacks may arrive faster, may not retry on failure, or may not send certain status types that production sends. If your callback handler was only tested against the sandbox callback patterns, it may not handle the full range of production callback scenarios.
What Should Be Mocked and What Should Not
During development and testing, some parts of the integration can be safely mocked and others should always use the real sandbox. The request building logic, payload formatting, and signature generation should be tested against the real sandbox because these need to match exactly what the provider expects. The order management, status update, and notification logic can be tested with mocked responses because they depend on your code, not the provider's.
What should not be mocked is the end to end flow. At least some of your testing should send real requests to the sandbox and receive real sandbox responses. This validates not just your code but the actual network communication, the SSL handshake, the header formatting, and the provider's current response format. Mocking everything means you are testing your assumptions about the provider's API rather than the actual API.
Request and Response Field Mapping
Field mapping between your WooCommerce order data and the provider's API is where subtle bugs hide. The provider expects an amount in cents but WooCommerce stores the total with decimal places. The provider uses a specific date format that does not match what PHP outputs by default. The provider expects the customer phone number in international format with country code but WooCommerce stores it in whatever format the customer entered.
Document every field mapping explicitly. For each provider API field, note: the WooCommerce source field, any transformation required, the expected format, and what happens when the source data is missing or invalid. This mapping document becomes your reference when debugging production issues later.
// Field mapping example
$payload = array(
// Provider expects amount in cents (integer)
'amount' => intval( $order->get_total() * 100 ),
// Provider expects ISO 4217 currency code
'currency' => $order->get_currency(),
// Provider expects phone in format: 256XXXXXXXXX
'phone' => preg_replace( '/[^0-9]/', '',
$order->get_billing_phone() ),
// Provider expects unique merchant reference, max 20 chars
'reference' => substr(
$order->get_order_number() . '-' . time(), 0, 20
),
); Pay particular attention to character encoding. If your WooCommerce store supports customer names with non ASCII characters, make sure the provider's API handles them correctly. Some providers require URL encoding of string fields. Others expect UTF-8 but reject specific characters. Test with realistic data that includes accented characters, spaces, and special characters.
Timeout and Retry Behavior
Production API latency is almost always higher than sandbox latency. For mobile money providers in East Africa, I have seen production response times ranging from 2 seconds for the initial payment request to 45 seconds for the payment processing confirmation. If your gateway code times out at 15 seconds because that was plenty for sandbox, you will get false timeout failures in production.
Set your initial request timeout to at least 30 seconds for the payment initiation request. For callback endpoints, there is no timeout to set because the provider initiates the request, but be aware that the provider's retry behavior is based on your response time. If your callback processing takes too long, the provider may time out waiting for your response and retry, leading to duplicate processing.
Retry logic on the outgoing request side is a judgment call. If the initial payment request times out, should your code retry? Generally no, because a timeout does not mean the payment was not initiated. The provider may have received and started processing the request before the timeout occurred. Retrying could initiate a duplicate payment. Instead of retrying, log the timeout, mark the order with a pending status, and let the callback handle the final status update. If no callback arrives within a reasonable window, flag the order for manual review.
Logging Without Leaking Sensitive Data
Logging is critical for production payment integrations. When something goes wrong, your logs are the primary diagnostic tool. But payment processing involves sensitive data that should not be stored in plain text in log files: credit card numbers, API secrets, customer personal information, and authentication tokens.
The principle is: log enough to diagnose, not enough to compromise. Log transaction IDs, order numbers, request timestamps, response status codes, and error messages. Do not log full request bodies that contain API keys or customer payment details. If you need to log part of a request body for debugging, mask the sensitive fields first.
function log_gateway_event( $order_id, $event, $details = '' ) {
$timestamp = current_time( 'mysql' );
$log_entry = sprintf(
'[%s] Order #%s - %s %s',
$timestamp,
$order_id,
$event,
$details
);
error_log( $log_entry );
// Also store in order notes for operator visibility
$order = wc_get_order( $order_id );
if ( $order ) {
$order->add_order_note( $event . ' ' . $details );
}
} Rollout Checks
Before enabling the gateway on a production store, run through this checklist. Each item addresses a specific failure mode that has caused real problems on real stores.
- Verify that the production API endpoint URL is correctly configured and different from the sandbox URL.
- Verify that production API credentials are loaded, not sandbox credentials.
- Verify that the callback URL is accessible from outside your network and returns the correct response.
- Test the callback URL manually using a tool like cURL to confirm it receives and processes a test payload.
- Verify that SSL certificates are valid and not expired on your domain.
- Confirm that the currency and amount formatting matches production requirements.
- Check that timeout values are appropriate for production API latency.
- Verify that logging is active and writing to a location you can access.
- Confirm that the WooCommerce order statuses used by your gateway match the store's workflow expectations.
- Test on a mobile device to verify checkout behavior is correct outside desktop.
If the provider supports a production test mode, where real API infrastructure is used but transactions are flagged as test, use that for initial production validation. Process a few test transactions and verify the entire flow: checkout, redirect, payment processing, callback delivery, and order status update. Only after those succeed should you enable the gateway for real customer transactions.
Consider enabling the new gateway alongside an existing payment method rather than as a replacement. This lets customers choose and gives you real comparison data on error rates and processing behavior without putting all payment capability at risk if something goes wrong with the new integration.
For the complete gateway implementation guide, see building a custom WooCommerce payment gateway plugin. For sandbox testing patterns, see the sandbox testing guide. For callback and webhook endpoint architecture, see receiving data via REST API from webhooks.