[Admin] Create New Order: changing Shipping Method destroys client-side initialized payment forms and entered card data
@lbajsarowicz is already working on this.
Since Jul 17, 2026.
- Dominant language
- PHP
- Stars
- 12.2k
- Forks
- 9.4k
- PR merge metrics
- No merged PRs in 30d
Description
### Summary
In Admin Panel → Sales → Create New Order, changing the Shipping Method (and several other actions: address edits, "shipping same as billing" toggle) reloads the `billing_method` area:
```js
setShippingMethod: function (method) {
var data = {};
data['order[shipping_method]'] = method;
this.loadArea([
'shipping_method',
'totals',
'billing_method'
], true, data);
},
```
(`app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js`)
`loadAreaResponseHandler()` replaces the section's DOM wholesale via `$(this.getAreaId(id)).update(response[id])` — even when the returned content is equivalent to what is already rendered.
For payment methods bundled with Open Source (`checkmo`, `banktransfer`, `purchaseorder`) this is invisible: their state is persisted on the quote, and the re-rendered form comes back pre-selected and pre-filled (the template's inline script also re-applies `order.setPaymentMethod(...)`).
For the entire class of payment integrations whose form is initialized client-side (hosted fields / iframe / tokenized card elements — Stripe, Braintree hosted fields, and similar), the DOM replacement is destructive in a way no re-initialization can repair: card data typed by the admin exists **only inside the gateway's iframe** (by PCI design, it is never round-tripped through the quote). The gateway JS re-mounts after the replacement — but as a fresh, empty form. Result: every Shipping Method change wipes the card inputs the admin just filled in, and any client-side token/nonce state is invalidated, which can subsequently fail order placement.
### Preconditions
- Magento 2.4-develop (also reproducible on 2.4.x releases)
- At least two active shipping methods
- Any payment method whose admin order form is rendered/initialized by client-side JS (e.g. a hosted-fields card gateway)
### Steps to reproduce
1. Admin Panel → Sales → Orders → Create New Order
2. Select a customer and add a product
3. In *Payment Method*, select the JS-initialized method; the gateway form (card fields) renders
4. Enter card data (do not submit)
5. In *Shipping Method*, click "Get available shipping methods and rates" and select a method (or change the already selected one)
### Expected result
Shipping method and totals refresh. The payment form — whose set of available methods did not change — keeps its DOM, its initialized client-side state, and the data entered by the admin.
### Actual result
The *Payment Method* section DOM is unconditionally replaced. The gateway form is destroyed and re-mounted empty; entered card data is lost. The admin must re-enter payment data after every shipping change.
Technical detail: the `POST .../sales/order_create/loadBlock/block/shipping_method,totals,billing_method` response contains a `billing_method` fragment equivalent to the currently rendered one (same available methods, same selection persisted on the quote) — the destructive replacement gains nothing in this case.
### Proposed solution
In `loadAreaResponseHandler()`, skip replacing the `billing_method` area when a payment method is currently selected and the set of available payment methods in the incoming fragment is identical to the one already rendered. When availability genuinely changes (minimum-order-amount rules, country/shipping-based payment restrictions), the area is re-rendered exactly as today.
I will submit a PR with this change.
### Origin
The `billing_method` entry in `setShippingMethod`'s reload list was introduced by MAGETWO-94437 "Improve order creation flow" (`1c16d68d9ff`, 2018). Bundled offline methods mask the data loss because their state survives server-side, which is likely why this has not been reported against core.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.