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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions