Skip to content

複数商品種別環境で決済画面から戻った際にカートが空になる不具合 #1246

@nanasess

Description

@nanasess

環境

  • EC-CUBE バージョン: 2.13.0 以降
  • 影響範囲: 複数商品種別を使用している環境
  • 決済モジュールの決済画面で、注文確認画面から戻る際に SC_Helper_Purchase::checkDbMyPendignOrder() に処理を任せている場合
  • PENDING_ORDER_CANCEL_FLAG=false の環境

問題の概要

複数の商品種別がカートに入っている状態で決済画面(クレジットカード入力画面等)から「戻る」ボタンをクリックした際に、購入対象の商品種別のカートが空になってしまう不具合が発生します。

再現手順

  1. 2種類の商品種別(例:おなべとおなべレシピ)をカートに追加
  2. 購入フローを進めて決済画面(クレジットカード入力画面)に到達
  3. 決済画面で「戻る」ボタンをクリック
  4. 購入確認画面に戻る

期待される結果

  • 購入対象の商品種別のカートは復元される
  • 購入対象外の商品種別のカートは保持される

実際の結果

  • 購入対象の商品種別のカートが空になってしまう

根本原因

data/class/helper/SC_Helper_Purchase.phpcheckDbMyPendignOrder メソッドにおいて:

  1. 注文完了時completeOrdercleanupSession で特定の商品種別のカートのみ削除
  2. 戻る処理時getKeys() で全ての商品種別をチェック

この非対称な処理により、購入対象外の商品種別のカートが残存している場合、rollbackOrder ではなく cancelOrder が実行されてしまいます。

該当コード

// 1550行目
$cartKeys = $objCartSess->getKeys(); // 全商品種別をチェック

// 1555行目
if (SC_Utils_Ex::isBlank($cartKeys) && $target_time < $create_time) {
    SC_Helper_Purchase_Ex::rollbackOrder($order_id, ORDER_CANCEL, true);
} else {
    SC_Helper_Purchase_Ex::cancelOrder($order_id, ORDER_CANCEL, true); // こちらが実行される
}

if (SC_Utils_Ex::isBlank($cartKeys) && $target_time < $create_time) {
SC_Helper_Purchase_Ex::rollbackOrder($order_id, ORDER_CANCEL, true);
GC_Utils_Ex::gfPrintLog('order rollback.(my pending) order_id='.$order_id);
} else {
SC_Helper_Purchase_Ex::cancelOrder($order_id, ORDER_CANCEL, true);
if ($target_time > $create_time) {
GC_Utils_Ex::gfPrintLog('order cancel.(my pending and time expire) order_id='.$order_id);
} else {
GC_Utils_Ex::gfPrintLog('order cancel.(my pending and set cart) order_id='.$order_id);
}
}

修正提案

注文詳細(dtb_order_detaildtb_products_class)から購入対象の商品種別を取得し、その商品種別のカートのみをチェック対象とする:

// 注文詳細から商品種別を取得
$arrOrderDetails = static::getOrderDetail($order_id);
$orderProductTypes = array_unique(array_column($arrOrderDetails, 'product_type_id'));

// 購入対象の商品種別のカートのみチェック
$purchaseCartEmpty = true;
foreach ($orderProductTypes as $productTypeId) {
    if ($objCartSess->getTotalQuantity($productTypeId) > 0) {
        $purchaseCartEmpty = false;
        break;
    }
}

if ($purchaseCartEmpty && $target_time < $create_time) {
    SC_Helper_Purchase_Ex::rollbackOrder($order_id, ORDER_CANCEL, true);
} else {
    SC_Helper_Purchase_Ex::cancelOrder($order_id, ORDER_CANCEL, true);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions