Fatal error at checkout when tokenization nonce is missing
-
Plugin version: 1.7.7
WooCommerce: 11.0.1
WordPress: 7.1
PHP: 8.3.33
Host: SiteGround
Checkout: classic shortcode (not blocks)This is closely related to two earlier reports that were both closed without a fix:
- “Argument 2 passed to API/GatewayAPI.php on line 405 in” (Feb 2024)
- “PHP crash is back, Argument #2 ($nonce) must be of type string, null given” (closed Jan 2024)
Both of those originated from
add_payment_method()— a customer saving a card in My Account. Mine is fromprocess_payment()during a live checkout, which is a different entry point with a worse outcome: the customer sees WordPress’s critical error screen instead of a payment failure message, and the sale is lost.What happened
A customer attempted to place a $799 order. Three attempts in 67 seconds, all three producing an uncaught TypeError and a white screen. The customer abandoned checkout and contacted us by email. The order was left in a failed state with no gateway response recorded against it.
PHP Warning: Undefined property: stdClass::$nonce in .../godaddy-payments/src/API/GatewayAPI.php on line 410 PHP Fatal error: Uncaught TypeError: GoDaddy\WooCommerce\Poynt\API\Cards\TokenizeRequest::__construct(): Argument #2 ($nonce) must be of type string, null given, called in .../godaddy-payments/src/API/GatewayAPI.php on line 410 and defined in .../godaddy-payments/src/API/Cards/TokenizeRequest.php:31 Stack trace: #0 .../godaddy-payments/src/API/GatewayAPI.php(410): TokenizeRequest->__construct('4abdefa4-99e2-4...', NULL) #1 .../godaddy-payments/src/Gateways/CreditCardGateway.php(1196): GatewayAPI->tokenize_payment_method(Object(Order)) #2 .../skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php(860): CreditCardGateway->do_credit_card_transaction(Object(Order)) #3 .../class-sv-wc-payment-gateway-direct.php(388): SV_WC_Payment_Gateway_Direct->do_transaction(Object(Order)) #4 .../woocommerce/includes/class-wc-checkout.php(1157): SV_WC_Payment_Gateway_Direct->process_payment(12345)Diagnosis
The warning immediately preceding the fatal is the actual cause.
$order->paymentis a dynamic stdClass the plugin populates from the submitted checkout form, and->nonceholds the token generated client-side by the Poynt Collect SDK. In this session the browser never populated that field, so the property was undefined, resolved tonull, and was passed straight into a constructor typedstring.GatewayAPI.php line 410 in 1.7.7:
$request = new TokenizeRequest($this->getBusinessId(), $order->payment->nonce);The root cause is browser-side and I can’t reproduce it — same as both previous reporters, which I believe is why those threads stalled. Likely candidates are an extension or network filter blocking the SDK, or a browser the SDK doesn’t fully support. That part may well be unfixable from the plugin’s side.
But the failure mode is fixable, and that’s the more important half.
There is no guard between an empty nonce and the constructor. A condition the plugin cannot control produces an uncaught fatal in the middle of
process_payment(), which means:- The customer sees a WordPress critical error page, not a payment error
- The order is left with no gateway note explaining anything
- Nothing is written to the WooCommerce gateway log
- The customer has no indication that retrying might help, and no cart or form state is preserved
A missing nonce is functionally a failed tokenization. It should be handled like any other payment failure.
Suggested patch
In
GatewayAPI::tokenize_payment_method(), immediately before line 410:$nonce = $order->payment->nonce ?? null; if (!is_string($nonce) || $nonce === '') { throw new SV_WC_Payment_Gateway_Exception( 'Payment nonce missing from checkout request; card was not tokenized in the browser.' ); } $request = new TokenizeRequest($this->getBusinessId(), $nonce);(With the appropriate
usestatement for the version-namespaced framework exception class.)The framework already catches
SV_WC_Payment_Gateway_Exceptioninsideprocess_payment()and converts it into a standard declined-payment flow: order marked failed with a note, customer-facing notice, checkout page preserved with the customer’s details intact. So this guard converts a site-crash into an ordinary retryable failure with no other changes required.A complementary improvement would be checking for the nonce in the gateway’s
validate_fields(), so the customer is stopped before order creation rather than after — but the guard above is the minimum needed to stop the fatal.One environmental note that may or may not be relevant
The SkyVerge framework actually executing on my install is
v5_15_12, loaded out ofwoocommerce-customer-order-csv-export/vendor/rather than the copy bundled with this plugin. I understand that’s the framework’s normal highest-version-wins behavior, but flagging it in case the version drift matters.Context on frequency
This is rare, not systemic. Over the same 21-day window the store took 41 orders, 30 completed normally, and the other failures were ordinary AVS mismatches and issuer declines with clean gateway responses recorded in the order notes. So this isn’t a misconfiguration on my end — it’s one edge case that happens to fail catastrophically instead of gracefully.
Given this is now the third independent report of the same null across two different code paths since 2022, I’d ask that the guard be added even if the browser-side cause can’t be tracked down. Merchants shouldn’t lose sales to a white screen when a declined-card message would do.
Happy to provide anything further. Gateway debug logging is now enabled on my install, so if it recurs I’ll have the Poynt-side request/response to add.
You must be logged in to reply to this topic.