• Resolved Daniel Chase

    (@riseofweb)


    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:

    Both of those originated from add_payment_method() — a customer saving a card in My Account. Mine is from process_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->payment is a dynamic stdClass the plugin populates from the submitted checkout form, and ->nonce holds 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 to null, and was passed straight into a constructor typed string.

    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 use statement for the version-namespaced framework exception class.)

    The framework already catches SV_WC_Payment_Gateway_Exception inside process_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 of woocommerce-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.

Viewing 3 replies - 1 through 3 (of 3 total)
  • Plugin Support markopec

    (@markopec)

    Hey there,

    Marko here, thanks for contacting SkyVerge about our GoDaddy Payments plugin! We’re happy to help out. 🙂

    Thank you for such a thorough report — genuinely, this is one of the clearest write-ups we’ve seen, and the stack trace, patch suggestion, and order-volume context all make it much easier for us to act on quickly. We’re sorry this cost you a $799 sale and a frustrating few minutes for your customer at checkout. That’s exactly the kind of failure we don’t want merchants to hit.

    To confirm we’re on the same page: this is happening during process_payment() at live checkout (not the saved-card flow from the earlier threads you linked), when the Poynt Collect SDK doesn’t populate the payment nonce client-side. Right now that missing nonce isn’t caught before it hits TokenizeRequest, so instead of a normal declined-payment message, the customer hits a white screen and the order is left with no note and nothing in the gateway log. You’ve diagnosed that correctly.

    On the browser-side root cause — why the SDK doesn’t set the nonce for that particular session — we don’t have a reproduction case either, and neither did the two earlier reports. We’re not going to pretend we can chase that down right now without something to reproduce it against. But we agree with you that this shouldn’t matter: a missing nonce should be treated as a failed tokenization, not a fatal error. That’s the part we can and will fix, and your suggested guard (checking the nonce is a non-empty string before it reaches the constructor, throwing SV_WC_Payment_Gateway_Exception instead) is exactly the right shape of fix, since the framework’s process_payment() already catches that exception and routes it into the normal failed-order flow with a note and customer-facing message. We’ve opened this internally and will track it against the two prior reports.

    One small correction on your framework version note: it’s not quite “highest version wins.” When multiple plugins bundle the framework, whichever loads first wins if the versions are identical — so in that scenario the version number itself isn’t deciding anything. We looked into it and don’t think the framework instance running on your site (v5_15_12 via the CSV Export plugin) is a contributing factor to this bug, so no action needed there on your end.

    If it happens again with debug logging on, we’d love to see the Poynt-side request/response you mentioned — that could end up being the thread that finally cracks the browser-side mystery, even though it’s not what we’re fixing right now.

    We’ve added this to our issue tracker for the developers to get this patched up. While we don’t have an estimated time for resolution right now, please know that our team is now aware of the issue and will work to incorporate a fix into the plugin as soon as they can.

    Thanks again for taking the time to dig into this as deeply as you did — reports like this make the plugin better for everyone.

    All the best,

    Thread Starter Daniel Chase

    (@riseofweb)

    Hi Marko,

    Thanks for the quick and thoughtful reply — much appreciated.

    Good to hear the guard is the right shape and that it’s tracked internally alongside the earlier reports. Glad to hear the CSV Export instance isn’t a factor here.

    Debug logging is enabled on my install now, so if this fires again I’ll grab the Poynt request/response and post it here.

    Thanks

    Plugin Support markopec

    (@markopec)

    Hey Daniel @riseofweb ,

    Thanks so much for your prompt reply here, and for your kind words about our team’s efforts to assist you.

    I’m really glad to hear that debug logging is enabled on your end, and that if the error pops up again you’ll share the logs with us. That’s very reassuring.

    I’m going to mark this request as solved now, since we’ve already created a bug report with our plugin engineers. In the meantime, please keep an eye out for the next plugin updates—they should include the fix for this error.

    Have a great day ahead!

    Best regards,

Viewing 3 replies - 1 through 3 (of 3 total)

You must be logged in to reply to this topic.