決済処理中の受注ロールバックの多重実行
- Dominant language
- PHP
- Stars
- 92
- Forks
- 97
- Avg merge
- 4d 2h
- Merged PRs (30d)
- 9
Description
`SC_Helper_Purchase::checkDbAllPendingOrder()`にて排他ロックを行なっていないため、一つの受注に複数回のロールバックが発生し、本来の在庫より多く戻ってしまう。
アクセス数が多いほど発生確率が高くなる。
関連: #369
対応例 (MySQL環境にて動作確認済み):
``` patch
/**
* 決済処理中スタータスの全受注検索
*/
public function checkDbAllPendingOrder()
{
$term = PENDING_ORDER_CANCEL_TIME;
if (!SC_Utils_Ex::isBlank($term) && preg_match("/^[0-9]+$/", $term)) {
$target_time = strtotime('-' . $term . ' sec');
$objQuery =& SC_Query_Ex::getSingletonInstance();
$arrVal = array(date('Y/m/d H:i:s', $target_time), ORDER_PENDING);
+ $arrOrderIds = $objQuery->getCol('order_id', 'dtb_order', 'create_date <= ? and status = ? and del_flg = 0', $arrVal);
+ if (empty($arrOrderIds)) {
+ return;
+ }
$objQuery->begin();
- $arrOrders = $objQuery->select('order_id', 'dtb_order', 'create_date <= ? and status = ? and del_flg = 0', $arrVal);
+ $placeholders = SC_Utils_Ex::repeatStrWithSeparator('?', count($arrOrderIds));
+ $statement = $objQuery->prepare("SELECT order_id, status FROM dtb_order WHERE order_id IN ($placeholders) FOR UPDATE");
+ $result = $objQuery->execute($statement, $arrOrderIds);
+ if (PEAR::isError($result)) {
+ $objQuery->rollback();
+ return;
+ }
+ $arrOrders = $result->fetchAll();
if (!SC_Utils_Ex::isBlank($arrOrders)) {
foreach ($arrOrders as $arrOrder) {
+ if ($arrOrder['status'] != ORDER_PENDING) {
+ continue;
+ }
$order_id = $arrOrder['order_id'];
SC_Helper_Purchase_Ex::cancelOrder($order_id, ORDER_CANCEL, true);
GC_Utils_Ex::gfPrintLog('order cancel.(time expire) order_id=' . $order_id);
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.