| @@ -6,8 +6,12 @@ | ||
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | add_action( 'usces_construct', 'usces_action_acting_construct', 10 ); |
| 9 | 9 | add_action( 'usces_after_cart_instant', 'usces_action_acting_transaction', 10 ); |
| 10 | +// A3 (Layer 3 / uscesid removal): restore the shopper's cart/entry for settlement notifications | |
| 11 | +// from the transaction-keyed DB store, uscesid-independently. Must run after usces_session_start() | |
| 12 | +// (constructor end) and before usces_main()'s `new usces_cart()`, hence the usces_main hook. | |
| 13 | +add_action( 'usces_main', 'usces_restore_acting_session_from_store', 1 ); | |
| 10 | 14 | |
| 11 | 15 | /** |
| 12 | 16 | * Settlement Result Notification Processing. |
| 13 | 17 | * usces_construct |
| @@ -19,10 +23,10 @@ | ||
| 19 | 23 | $rand = wp_unslash( $_POST['X-S_TORIHIKI_NO'] ); |
| 20 | 24 | $datas = array(); |
| 21 | 25 | /* 決済成功の時のみセッション復帰 */ |
| 22 | 26 | if ( 0 == $_POST['X-ERRLEVEL'] ) { |
| 23 | - $datas = usces_get_order_acting_data( $rand ); | |
| 24 | - $_GET['uscesid'] = $datas['sesid']; | |
| 27 | + $datas = usces_get_order_acting_data( $rand ); | |
| 28 | + // A3: uscesid ブリッジは廃止。セッション復元は usces_restore_acting_session_from_store()(usces_main)で DBストアから実施. | |
| 25 | 29 | if ( empty( $datas['sesid'] ) ) { |
| 26 | 30 | /* sesidが無い場合はファイルログのみ */ |
| 27 | 31 | usces_log( 'remise construct : error1', 'acting_transaction.log' ); |
| 28 | 32 | } else { |
| @@ -33,11 +37,11 @@ | ||
| 33 | 37 | |
| 34 | 38 | /* digitalcheck_conv */ |
| 35 | 39 | } elseif ( isset( $_POST['SID'] ) && isset( $_POST['FUKA'] ) && isset( $_POST['CVS'] ) ) { |
| 36 | 40 | |
| 37 | - $sid = wp_unslash( $_POST['SID'] ); | |
| 38 | - $datas = usces_get_order_acting_data( $sid ); | |
| 39 | - $_GET['uscesid'] = $datas['sesid']; | |
| 41 | + $sid = wp_unslash( $_POST['SID'] ); | |
| 42 | + $datas = usces_get_order_acting_data( $sid ); | |
| 43 | + // A3: uscesid ブリッジは廃止。セッション復元は usces_restore_acting_session_from_store()(usces_main)で DBストアから実施. | |
| 40 | 44 | if ( empty( $datas['sesid'] ) ) { |
| 41 | 45 | $log = array( |
| 42 | 46 | 'acting' => 'digitalcheck', |
| 43 | 47 | 'key' => $sid, |
| @@ -52,11 +56,11 @@ | ||
| 52 | 56 | |
| 53 | 57 | /* AnotherLane */ |
| 54 | 58 | } elseif ( isset( $_REQUEST['SiteId'] ) && isset( $_REQUEST['rand'] ) ) { |
| 55 | 59 | |
| 56 | - $rand = wp_unslash( $_REQUEST['rand'] ); | |
| 57 | - $datas = usces_get_order_acting_data( $rand ); | |
| 58 | - $_GET['uscesid'] = $datas['sesid']; | |
| 60 | + $rand = wp_unslash( $_REQUEST['rand'] ); | |
| 61 | + $datas = usces_get_order_acting_data( $rand ); | |
| 62 | + // A3: uscesid ブリッジは廃止。セッション復元は usces_restore_acting_session_from_store()(usces_main)で DBストアから実施. | |
| 59 | 63 | if ( empty( $datas['sesid'] ) ) { |
| 60 | 64 | $log = array( |
| 61 | 65 | 'acting' => 'anotherlane', |
| 62 | 66 | 'key' => $rand, |
| @@ -71,11 +75,13 @@ | ||
| 71 | 75 | |
| 72 | 76 | /* Veritrans */ |
| 73 | 77 | } elseif ( isset( $_POST['orderId'] ) && isset( $_POST['merchantEncryptionKey'] ) ) { |
| 74 | 78 | |
| 75 | - $orderid = wp_unslash( $_POST['orderId'] ); | |
| 76 | - $datas = usces_get_order_acting_data( $orderid ); | |
| 77 | - $_GET['uscesid'] = $datas['sesid']; | |
| 79 | + $orderid = wp_unslash( $_POST['orderId'] ); | |
| 80 | + $datas = usces_get_order_acting_data( $orderid ); | |
| 81 | + // A3: uscesid ブリッジは廃止($_GET['uscesid'] を読む処理は撤廃済みのため代入は無意味だった)。 | |
| 82 | + // ベリトランス Air-Web は選択可能な決済から除外済み(settlement.class.php)のため、DBストアからの | |
| 83 | + // セッション復元(usces_restore_acting_session_from_store)の対象外とする. | |
| 78 | 84 | if ( empty( $datas['sesid'] ) ) { |
| 79 | 85 | $log = array( |
| 80 | 86 | 'acting' => 'veritrans', |
| 81 | 87 | 'key' => $orderid, |
| @@ -90,8 +96,83 @@ | ||
| 90 | 96 | } |
| 91 | 97 | } |
| 92 | 98 | |
| 93 | 99 | /** |
| 100 | + * 決済通知(サーバー間・ブラウザ Cookie 無し)で、確定時に保存したカート/エントリを DBストア | |
| 101 | + * (usces_access)から $_SESSION へ復元する。uscesid セッション橋渡しの置き換え(Layer 3 / A3)。 | |
| 102 | + * | |
| 103 | + * usces_session_start()(コンストラクタ末尾)より後・usces_main() の `new usces_cart()` より前に | |
| 104 | + * 実行する必要があるため usces_main フックに登録する(construct では直後の @session_start() に | |
| 105 | + * 上書きされてしまうため)。復元後、usces_cart 生成 → usces_after_cart_instant | |
| 106 | + * (usces_action_acting_transaction)が $usces->cart->get_cart() を参照して処理する。 | |
| 107 | + * | |
| 108 | + * 対象はサーバー間通知でセッション復元が要る remise / digitalcheck_conv / AnotherLane。 | |
| 109 | + * | |
| 110 | + * usces_main | |
| 111 | + */ | |
| 112 | +function usces_restore_acting_session_from_store() { | |
| 113 | + $rand = ''; | |
| 114 | + if ( isset( $_POST['X-TRANID'] ) && ! isset( $_POST['OPT'] ) && isset( $_POST['X-S_TORIHIKI_NO'] ) ) { | |
| 115 | + /* remise: 決済成功時(X-ERRLEVEL == 0)のみ復元 */ | |
| 116 | + if ( isset( $_POST['X-ERRLEVEL'] ) && 0 == $_POST['X-ERRLEVEL'] ) { | |
| 117 | + $rand = wp_unslash( $_POST['X-S_TORIHIKI_NO'] ); | |
| 118 | + } | |
| 119 | + } elseif ( isset( $_POST['SID'] ) && isset( $_POST['FUKA'] ) && isset( $_POST['CVS'] ) ) { | |
| 120 | + /* digitalcheck_conv */ | |
| 121 | + $rand = wp_unslash( $_POST['SID'] ); | |
| 122 | + } elseif ( isset( $_REQUEST['SiteId'] ) && isset( $_REQUEST['rand'] ) ) { | |
| 123 | + /* AnotherLane: 通知は $_REQUEST(GET/POST 両様)。旧 usces_action_acting_construct の | |
| 124 | + * $_GET['uscesid']=$datas['sesid'] ブリッジの置き換え。KickType サーバー通知で order_processing() | |
| 125 | + * がカートを読む前にここで DBストアから復元する。 */ | |
| 126 | + $rand = wp_unslash( $_REQUEST['rand'] ); | |
| 127 | + } | |
| 128 | + | |
| 129 | + if ( '' === $rand ) { | |
| 130 | + return; | |
| 131 | + } | |
| 132 | + | |
| 133 | + $datas = usces_get_order_acting_data( $rand ); | |
| 134 | + if ( empty( $datas ) || empty( $datas['order_data'] ) ) { | |
| 135 | + return; | |
| 136 | + } | |
| 137 | + | |
| 138 | + $order_data = wel_safe_maybe_unserialize( $datas['order_data'] ); | |
| 139 | + if ( ! is_array( $order_data ) ) { | |
| 140 | + return; | |
| 141 | + } | |
| 142 | + | |
| 143 | + if ( isset( $order_data['cart'] ) && is_array( $order_data['cart'] ) ) { | |
| 144 | + /* | |
| 145 | + * DBストア(usces_access)の cart は save_order_acting_data() が保存した | |
| 146 | + * $usces->cart->get_cart() の「出力形式」= [ i => array( serial, post_id, sku, options, | |
| 147 | + * price, unit_price, quantity, advance ) ](インデックス配列)。 | |
| 148 | + * 一方 $_SESSION['usces_cart'] の「内部形式」は | |
| 149 | + * [ '<serial>' => array( 'price', 'unit_price', 'quant', 'advance' ) ](serial をキーにしたマップ)で、 | |
| 150 | + * usces_cart::get_cart()/key_unserialize() はこの内部形式を前提に読む | |
| 151 | + * (キー=serial/数量キーは 'quant')。そのまま代入すると整数キー 0 が serial として | |
| 152 | + * unserialize され false → array_keys(false) で致命的エラーになるため、内部形式へ変換して復元する。 | |
| 153 | + */ | |
| 154 | + $session_cart = array(); | |
| 155 | + foreach ( $order_data['cart'] as $item ) { | |
| 156 | + if ( ! is_array( $item ) || ! isset( $item['serial'] ) ) { | |
| 157 | + continue; | |
| 158 | + } | |
| 159 | + $session_cart[ $item['serial'] ] = array( | |
| 160 | + 'price' => isset( $item['price'] ) ? $item['price'] : 0, | |
| 161 | + 'unit_price' => isset( $item['unit_price'] ) ? $item['unit_price'] : 0, | |
| 162 | + 'quant' => isset( $item['quantity'] ) ? $item['quantity'] : 0, | |
| 163 | + 'advance' => isset( $item['advance'] ) ? $item['advance'] : '', | |
| 164 | + ); | |
| 165 | + } | |
| 166 | + $_SESSION['usces_cart'] = $session_cart; | |
| 167 | + } | |
| 168 | + if ( isset( $order_data['entry'] ) ) { | |
| 169 | + $_SESSION['usces_entry'] = $order_data['entry']; | |
| 170 | + } | |
| 171 | + usces_log( 'acting session restored from DB store (uscesid-independent) : ' . $rand, 'acting_transaction.log' ); | |
| 172 | +} | |
| 173 | + | |
| 174 | +/** | |
| 94 | 175 | * 決済結果通知の送信元IPが許可リストに含まれるか判定する。 |
| 95 | 176 | * |
| 96 | 177 | * @param string $remote_addr Source IP address of the notification. |
| 97 | 178 | * @param array|string $allowed Allowed IP addresses / CIDR ranges. |
| @@ -496,9 +577,9 @@ | ||
| 496 | 577 | usces_log( 'PayPal IPN transaction : ' . wp_unslash( $_REQUEST['txn_id'] ), 'acting_transaction.log' ); |
| 497 | 578 | } |
| 498 | 579 | die( 'PayPal' ); |
| 499 | 580 | |
| 500 | - /* telecom edy */ | |
| 581 | + /* telecom edy 提供対象外のため無効化. CVE-2026-19887(PHP Object Injection)対応. | |
| 501 | 582 | } elseif ( isset( $_REQUEST['clientip'] ) && isset( $_REQUEST['sendid'] ) && ( isset( $_REQUEST['acting'] ) && 'telecom_edy' == $_REQUEST['acting'] ) ) { |
| 502 | 583 | $data = array(); |
| 503 | 584 | foreach ( $_REQUEST as $key => $value ) { |
| 504 | 585 | $data[ $key ] = $value; |
| @@ -513,9 +594,9 @@ | ||
| 513 | 594 | if ( 'yes' === wp_unslash( $_REQUEST['rel'] ) && isset( $_REQUEST['option'] ) ) { |
| 514 | 595 | $table_meta_name = $wpdb->prefix . 'usces_order_meta'; |
| 515 | 596 | $mquery = $wpdb->prepare( "SELECT order_id, meta_value FROM $table_meta_name WHERE meta_key = %s", wp_unslash( $_REQUEST['option'] ) ); |
| 516 | 597 | $mvalue = $wpdb->get_row( $mquery, ARRAY_A ); |
| 517 | - $value = unserialize( $mvalue['meta_value'] ); | |
| 598 | + $value = wel_safe_maybe_unserialize( $mvalue['meta_value'] ); | |
| 518 | 599 | $_SESSION['usces_cart'] = $value['usces_cart']; |
| 519 | 600 | $_SESSION['usces_entry'] = $value['usces_entry']; |
| 520 | 601 | $_SESSION['usces_member'] = $value['usces_member']; |
| 521 | 602 | $res = $usces->order_processing(); |
| @@ -543,11 +624,17 @@ | ||
| 543 | 624 | usces_save_order_acting_error( $log ); |
| 544 | 625 | usces_log( 'telecom edy - Error 2 : ' . print_r( $data, true ), 'acting_transaction.log' ); |
| 545 | 626 | } |
| 546 | 627 | die( 'SuccessOK' ); |
| 628 | + */ | |
| 547 | 629 | |
| 548 | 630 | /* telecom credit */ |
| 549 | 631 | } elseif ( isset( $_REQUEST['clientip'] ) && isset( $_REQUEST['sendid'] ) && isset( $_REQUEST['rel'] ) ) { |
| 632 | + $acting_clientip = ( isset( $usces->options['acting_settings']['telecom']['clientip'] ) ) ? (string) $usces->options['acting_settings']['telecom']['clientip'] : ''; | |
| 633 | + if ( '' === $acting_clientip || (string) wp_unslash( $_REQUEST['clientip'] ) !== $acting_clientip ) { | |
| 634 | + /* 設定済みクライアントIPと一致しない通知は正規のものではないため記録せず終了 */ | |
| 635 | + die( 'SuccessOK' ); | |
| 636 | + } | |
| 550 | 637 | $data = array(); |
| 551 | 638 | foreach ( $_REQUEST as $key => $value ) { |
| 552 | 639 | $data[ $key ] = $value; |
| 553 | 640 | } |