Magento one page checkout stuck on billing or payment: how to find the cause
On the default Magento 2 checkout the shipping step can work perfectly while the payment step does not: the billing address will not save, the Place Order button does nothing, or a spinner never stops. The cause is almost always one failing request or one JavaScript error, and the browser shows which.

What happens on the payment step
Leaving the shipping step sends `shipping-information` to the REST API, which saves the address and the method and returns the totals and the available payment methods. On the payment step the billing address is either copied from shipping (“My billing and shipping address are the same”) or saved from its own form. Place Order sends `payment-information`, which saves the billing address and the payment and creates the order.
For a guest the calls go to `/rest/<store>/V1/guest-carts/<id>/…`, for a logged-in customer to `/rest/<store>/V1/carts/mine/…`.
Find the failing request
Open the developer tools, Network tab, filter on `payment-information`, and press Place Order. A 400 response carries a message in JSON, often a missing required field. A 401 or 403 points to a lost session or a firewall rule on the REST API. A 500 points to an exception, logged in `var/log/exception.log` and `var/log/system.log`. No request at all means JavaScript stopped earlier: check the Console.
The usual causes
Address validation: a field made required in configuration (telephone, region, company, VAT number) that the billing form does not show, or a region list that does not match the country, so validation fails without a visible message. Custom address attributes from an extension that are not sent with the billing address.
JavaScript: a broken RequireJS dependency or a mixin from an extension, often after enabling JS bundling or minification, or after a theme or extension upgrade without a static content deploy. Payment: a method that renders but fails to initialise its own script, such as a card form iframe blocked by a Content Security Policy rule.
Server: an observer on order placement that throws, a stock reservation or salable quantity problem, or a third-party tax, fraud or address-check call that times out. See also Magento salable quantity and one step checkout extensions.
Test both paths
Check with the billing-same-as-shipping box ticked and unticked, as a guest and as a logged-in customer with a saved address. These are different code paths and one can break alone. The free Magento checkout test walks the checkout in a real browser, Luma or Hyvä, and shows the step where it stops.
Common questions
Why does the Magento Place Order button do nothing?
Usually a JavaScript error stops the click handler, or the payment-information request fails validation. The browser Console and Network tab show which.
Why is the Magento billing address not saving?
A required field the form does not show, a region that does not match the country, or a custom address attribute that is not sent. The 400 response from payment-information names the field.
Does this apply to Hyvä Checkout?
Hyvä Checkout uses its own components and server requests instead of the Luma Knockout scripts, but the server-side causes (validation, observers, stock, payment modules) are the same.