magento / magento/magento2

[Admin] Create New Order: changing Shipping Method destroys client-side initialized payment forms and entered card data

Open
#41,006 3 comments 0 reactions 1 assignee View on GitHub

@lbajsarowicz is already working on this.

Since Jul 17, 2026.

Issue: ready for confirmation Reported on 2.4.x
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.