PayPal WebHook verification yielding 400 bad request for some users

stromb0li

Well-known member
Affected version
2.3.4
I am seeing 400 responses from the paypalrest provider.

In nginx access logs, I see the 400 response returned (I grabbed one of many lines):
173.0.81.140 - - [30/Dec/2024:01:03:28 +0000] "POST /payment_callback.php?_xfProvider=paypalrest HTTP/1.1" 400 182 "-" "PayPal/AUHR-214.0-58712720"

I see the following in Payment Provider Logs in XenForo:
JSON:
array(9) {
  ["id"] => string(38) "WH-6PW022468P4090935-6L406200PXXXXXXXX"
  ["event_version"] => string(3) "1.0"
  ["create_time"] => string(24) "2024-12-27T17:02:31.992Z"
  ["resource_type"] => string(14) "checkout-order"
  ["resource_version"] => string(3) "2.0"
  ["event_type"] => string(23) "CHECKOUT.ORDER.APPROVED"
  ["summary"] => string(35) "An order has been approved by buyer"
  ["resource"] => array(8) {
    ["create_time"] => string(20) "2024-12-27T17:00:55Z"
    ["purchase_units"] => array(1) {
      [0] => array(6) {
        ["reference_id"] => string(7) "default"
        ["amount"] => array(3) {
          ["currency_code"] => string(3) "USD"
          ["value"] => string(5) "75.00"
          ["breakdown"] => array(0) {
          }
        }
        ["payee"] => array(2) {
          ["email_address"] => string(17) "<redacted>"
          ["merchant_id"] => string(13) "<redacted>"
        }
        ["description"] => string(26) "<redacted>"
        ["custom_id"] => string(32) "<redacted - but is correct request id>"
        ["shipping"] => array(2) {
          ["name"] => array(1) {
            ["full_name"] => string(15) "<redacted name>"
          }
          ["address"] => array(5) {
            ["address_line_1"] => string(15) "<redacted>"
            ["admin_area_2"] => string(7) "<redacted>"
            ["admin_area_1"] => string(2) "<redacted>"
            ["postal_code"] => string(10) "<redacted>"
            ["country_code"] => string(2) "US"
          }
        }
      }
    }
    ["links"] => array(3) {
      [0] => array(3) {
        ["href"] => string(59) "https://api.paypal.com/v2/checkout/orders/5TB66464AXXXXXXXX"
        ["rel"] => string(4) "self"
        ["method"] => string(3) "GET"
      }
      [1] => array(3) {
        ["href"] => string(59) "https://api.paypal.com/v2/checkout/orders/5TB66464AXXXXXXXX"
        ["rel"] => string(6) "update"
        ["method"] => string(5) "PATCH"
      }
      [2] => array(3) {
        ["href"] => string(67) "https://api.paypal.com/v2/checkout/orders/5TB66464AXXXXXXXX/capture"
        ["rel"] => string(7) "capture"
        ["method"] => string(4) "POST"
      }
    }
    ["id"] => string(17) "5TB66464AXXXXXXXX"
    ["payment_source"] => array(1) {
      ["paypal"] => array(5) {
        ["email_address"] => string(22) "<redacted>"
        ["account_id"] => string(13) "<redacted>"
        ["account_status"] => string(10) "VERIFIED"
        ["name"] => array(2) {
          ["given_name"] => string(7) "<redacted>"
          ["surname"] => string(7) "<redacted>"
        }
        ["address"] => array(1) {
          ["country_code"] => string(2) "US"
        }
      }
    }
    ["intent"] => string(7) "CAPTURE"
    ["payer"] => array(4) {
      ["name"] => array(2) {
        ["given_name"] => string(7) "<redacted>"
        ["surname"] => string(7) "<redacted>"
      }
      ["email_address"] => string(22) "<redacted>"
      ["payer_id"] => string(13) "<redacted>"
      ["address"] => array(1) {
        ["country_code"] => string(2) "US"
      }
    }
    ["status"] => string(8) "APPROVED"
  }
  ["links"] => array(2) {
    [0] => array(3) {
      ["href"] => string(94) "https://api.paypal.com/v1/notifications/webhooks-events/WH-6PW022468P4090935-6L406200PXXXXXXXX"
      ["rel"] => string(4) "self"
      ["method"] => string(3) "GET"
    }
    [1] => array(3) {
      ["href"] => string(101) "https://api.paypal.com/v1/notifications/webhooks-events/WH-6PW022468P4090935-6L406200PXXXXXXXX/resend"
      ["rel"] => string(6) "resend"
      ["method"] => string(4) "POST"
    }
  }
}

Payload on PayPal's website:
JSON:
{
  "id": "WH-6PW022468P4090935-6L406200PXXXXXXXX",
  "create_time": "2024-12-27T17:02:31.992Z",
  "resource_type": "checkout-order",
  "event_type": "CHECKOUT.ORDER.APPROVED",
  "summary": "An order has been approved by buyer",
  "resource": {
    "create_time": "2024-12-27T17:00:55Z",
    "purchase_units": [
      {
        "reference_id": "default",
        "amount": {
          "currency_code": "USD",
          "value": "75.00",
          "breakdown": {}
        },
        "payee": {
          "email_address": "<redacted>",
          "merchant_id": "<redacted>"
        },
        "description": "<redacted>",
        "custom_id": "<redacted - but is correct request id>"
        "shipping": {
          "name": {
            "full_name": "<redacted>"
          },
          "address": {
            "address_line_1": "<redacted>",
            "admin_area_2": "<redacted>",
            "admin_area_1": "<redacted>",
            "postal_code": "<redacted>",
            "country_code": "US"
          }
        }
      }
    ],
    "links": [
      {
        "href": "https://api.paypal.com/v2/checkout/orders/5TB66464AXXXXXXXX",
        "rel": "self",
        "method": "GET"
      },
      {
        "href": "https://api.paypal.com/v2/checkout/orders/5TB66464AXXXXXXXX",
        "rel": "update",
        "method": "PATCH"
      },
      {
        "href": "https://api.paypal.com/v2/checkout/orders/5TB66464AXXXXXXXX/capture",
        "rel": "capture",
        "method": "POST"
      }
    ],
    "id": "<redacted>",
    "payment_source": {
      "paypal": {
        "email_address": "<redacted>",
        "account_id": "<redacted>",
        "account_status": "VERIFIED",
        "name": {
          "given_name": "<redacted>",
          "surname": "<redacted>"
        },
        "address": {
          "country_code": "US"
        }
      }
    },
    "intent": "CAPTURE",
    "payer": {
      "name": {
        "given_name": "<redacted>",
        "surname": "<redacted>"
      },
      "email_address": "<redacted>",
      "payer_id": "<redacted>",
      "address": {
        "country_code": "US"
      }
    },
    "status": "APPROVED"
  },
  "status": "PENDING",
  "transmissions": [
    {
      "webhook_url": "https://<redacted>/payment_callback.php?_xfProvider=paypalrest",
      "http_status": 400,
      "reason_phrase": "HTTP/1.1 200 Connection established",
      "response_headers": {
        "X-Frame-Options": "SAMEORIGIN",
        "Server": "nginx/1.14.2",
        "Connection": "keep-alive",
        "Content-Length": "182",
        "Date": "Mon, 30 Dec 2024 01:19:30 GMT",
        "Content-Type": "text/plain; charset=utf-8"
      },
      "transmission_id": "aa034d92-c649-11ef-983e-a7b65d593cda",
      "status": "PENDING",
      "timestamp": "2024-12-30T01:01:55Z"
    }
  ],
  "links": [
    {
      "href": "https://api.paypal.com/v1/notifications/webhooks-events/WH-6PW022468P4090935-6L406200PXXXXXXXX",
      "rel": "self",
      "method": "GET",
      "encType": "application/json"
    },
    {
      "href": "https://api.paypal.com/v1/notifications/webhooks-events/WH-6PW022468P4090935-6L406200PXXXXXXXX/resend",
      "rel": "resend",
      "method": "POST",
      "encType": "application/json"
    }
  ],
  "event_version": "1.0",
  "resource_version": "2.0"
}

Example of a successful payment using the same paypalrest provider (from XF Payment provider logs):
JSON:
array(9) {
  ["id"] => string(38) "WH-58T59035HE061184K-37302437KXXXXXXXX"
  ["event_version"] => string(3) "1.0"
  ["create_time"] => string(24) "2024-12-29T22:10:47.791Z"
  ["resource_type"] => string(14) "checkout-order"
  ["resource_version"] => string(3) "2.0"
  ["event_type"] => string(23) "CHECKOUT.ORDER.APPROVED"
  ["summary"] => string(35) "An order has been approved by buyer"
  ["resource"] => array(8) {
    ["create_time"] => string(20) "2024-12-29T22:10:19Z"
    ["purchase_units"] => array(1) {
      [0] => array(6) {
        ["reference_id"] => string(7) "default"
        ["amount"] => array(3) {
          ["currency_code"] => string(3) "USD"
          ["value"] => string(5) "75.00"
          ["breakdown"] => array(0) {
          }
        }
        ["payee"] => array(2) {
          ["email_address"] => string(17) "<redacted>"
          ["merchant_id"] => string(13) "<redacted>"
        }
        ["description"] => string(26) "<redacted>"
        ["custom_id"] => string(32) "<redacted - correct request id>"
        ["shipping"] => array(2) {
          ["name"] => array(1) {
            ["full_name"] => string(24) "<redacted>"
          }
          ["address"] => array(5) {
            ["address_line_1"] => string(14) "<redacted>"
            ["admin_area_2"] => string(5) "<redacted>"
            ["admin_area_1"] => string(2) "<redacted>"
            ["postal_code"] => string(10) "<redacted>"
            ["country_code"] => string(2) "US"
          }
        }
      }
    }
    ["links"] => array(3) {
      [0] => array(3) {
        ["href"] => string(59) "https://api.paypal.com/v2/checkout/orders/9A902511UXXXXXXXX"
        ["rel"] => string(4) "self"
        ["method"] => string(3) "GET"
      }
      [1] => array(3) {
        ["href"] => string(59) "https://api.paypal.com/v2/checkout/orders/9A902511UXXXXXXXX"
        ["rel"] => string(6) "update"
        ["method"] => string(5) "PATCH"
      }
      [2] => array(3) {
        ["href"] => string(67) "https://api.paypal.com/v2/checkout/orders/9A902511UXXXXXXXX/capture"
        ["rel"] => string(7) "capture"
        ["method"] => string(4) "POST"
      }
    }
    ["id"] => string(17) "9A902511UXXXXXXXX"
    ["payment_source"] => array(1) {
      ["paypal"] => array(5) {
        ["email_address"] => string(17) "<redacted>"
        ["account_id"] => string(13) "<redacted>"
        ["account_status"] => string(8) "VERIFIED"
        ["name"] => array(2) {
          ["given_name"] => string(8) "<redacted>"
          ["surname"] => string(5) "<redacted>"
        }
        ["address"] => array(1) {
          ["country_code"] => string(2) "US"
        }
      }
    }
    ["intent"] => string(7) "CAPTURE"
    ["payer"] => array(4) {
      ["name"] => array(2) {
        ["given_name"] => string(8) "<redacted>"
        ["surname"] => string(5) "<redacted>"
      }
      ["email_address"] => string(17) "<redacted>"
      ["payer_id"] => string(13) "<redacted>"
      ["address"] => array(1) {
        ["country_code"] => string(2) "US"
      }
    }
    ["status"] => string(8) "APPROVED"
  }
  ["links"] => array(2) {
    [0] => array(3) {
      ["href"] => string(94) "https://api.paypal.com/v1/notifications/webhooks-events/WH-58T59035HE061184K-37302437KXXXXXXXX"
      ["rel"] => string(4) "self"
      ["method"] => string(3) "GET"
    }
    [1] => array(3) {
      ["href"] => string(101) "https://api.paypal.com/v1/notifications/webhooks-events/WH-58T59035HE061184K-37302437KXXXXXXXX/resend"
      ["rel"] => string(6) "resend"
      ["method"] => string(4) "POST"
    }
  }
}

Action on the failed events says the following:
Error: Webhook received from PayPal could not be verified as being valid. Try toggling "Enable webhook verification" off and on again in the payment profile if the issue persists.

Toggling Enable webhook verification doesn't resolve the issue.

The issue is sporadic, where payment is accepted for some users, but the majority not.
 
Last edited:
I still receive the error: "Error: Webhook received from PayPal could not be verified as being valid. Try toggling "Enable webhook verification" off and on again in the payment profile if the issue persists." Toggling the webhook verification checkbox doesn't yield a different result post 2.3.5 upgrade.
 
So this issue is still affecting you; you've reverted back from the REST based provider to the legacy provider?
 
Last edited:
After hours of fighting with this today, I think I finally have PayPal Rest provider working.

To fix, I had to delete every API Credential / REST API apps in PayPal linked to our business (irrespective if they were being referenced/used by any provider in XenForo or not). Once everything was deleted, I created the PayPal REST provider in XenForo. After creation, I noticed the Webhook entry (under Live Webhooks when looking at the app/credential) was still not created, so I unchecked Webhook verification and saved. Then checked Webhook verification and validated the Webhook entry in the PayPal portal again (i.e. https://yourdomain.com/payment_callback.php?_xfProvider=paypalrest).

At this point, we are starting to see success on payments.

Hope this helps someone else!

Note: Unchecking the Webhook verification box and checking it again, did NOT work for me. Neither did recreating the application in PayPal. It wasn't until we completely deleted all applications and solely defined XenForo that it worked.
 
Last edited:
Back
Top Bottom