Changeset 3216172
- Timestamp:
- 01/03/2025 12:30:32 AM (3 months ago)
- Location:
- nofraud-protection/trunk
- Files:
-
- 1 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
nofraud-protection/trunk/api/class-api.php
r3192579 r3216172 10 10 use WooCommerce\NoFraud\Common\Database; 11 11 use WooCommerce\NoFraud\Payment\Transactions\Transaction_Scheduler; 12 use WooCommerce\NoFraud\Payment\Transactions\Transaction_Manager; 12 13 use WooCommerce\NoFraud\Payment\Transactions\Constants; 13 14 … … 27 28 'callback' => [ get_called_class(), 'transactions_refresh' ], 28 29 )); 30 31 register_rest_route( 'nf', '/transactions/reprocess/run/(?P<startdate>[0-9-]+)/(?P<enddate>[0-9-]+)/', [ 32 'methods' => 'GET', 33 'callback' => [ get_called_class(), 'reprocess_transactions_run' ], 34 'args' => [ 35 'startdate' => [ 36 'required' => true, 37 'validate_callback' => function ($param, $request, $key) { 38 // Validate the MySQL datetime format 39 return (bool) preg_match('/^\d{4}-\d{2}-\d{2}$/', $param); 40 }, 41 'sanitize_callback' => 'sanitize_text_field', 42 'description' => 'MySQL datetime string in the format YYYY-MM-DD', 43 ], 44 'enddate' => [ 45 'required' => true, 46 'validate_callback' => function ($param, $request, $key) { 47 // Validate the MySQL datetime format 48 return (bool) preg_match('/^\d{4}-\d{2}-\d{2}$/', $param); 49 }, 50 'sanitize_callback' => 'sanitize_text_field', 51 'description' => 'MySQL datetime string in the format YYYY-MM-DD', 52 ], 53 ], 54 'permission_callback' => '__return_true', 55 ]); 56 57 register_rest_route( 'nf', '/transactions/reprocess/count/(?P<startdate>[0-9-]+)/(?P<enddate>[0-9-]+)/', [ 58 'methods' => 'GET', 59 'callback' => [ get_called_class(), 'reprocess_transactions_count' ], 60 'args' => [ 61 'startdate' => [ 62 'required' => true, 63 'validate_callback' => function ($param, $request, $key) { 64 // Validate the MySQL datetime format 65 return (bool) preg_match('/^\d{4}-\d{2}-\d{2}$/', $param); 66 }, 67 'sanitize_callback' => 'sanitize_text_field', 68 'description' => 'MySQL datetime string in the format YYYY-MM-DD', 69 ], 70 'enddate' => [ 71 'required' => true, 72 'validate_callback' => function ($param, $request, $key) { 73 // Validate the MySQL datetime format 74 return (bool) preg_match('/^\d{4}-\d{2}-\d{2}$/', $param); 75 }, 76 'sanitize_callback' => 'sanitize_text_field', 77 'description' => 'MySQL datetime string in the format YYYY-MM-DD', 78 ], 79 ], 80 'permission_callback' => '__return_true', 81 ]); 82 83 register_rest_route( 'nf', '/transactions/reprocess/completed/', [ 84 'methods' => 'GET', 85 'callback' => [ get_called_class(), 'reprocess_transactions_count_completed' ], 86 'args' => [ 87 ], 88 'permission_callback' => '__return_true', 89 ]); 29 90 }); 30 91 } 31 92 32 93 add_action('woocommerce_rest_prepare_shop_order_object', [$instance, 'nf_add_data_to_rest_api'], 10, 3); 94 } 95 96 /** 97 * Callback function to handle the reprocessing of transactions. 98 * 99 * @param WP_REST_Request $request The REST request. 100 * @return WP_REST_Response The response. 101 */ 102 public static function reprocess_transactions_run($request) { 103 $startdate = $request->get_param('startdate'); 104 $enddate = $request->get_param('enddate'); 105 106 global $wpdb; 107 108 $startdate = $request->get_param('startdate') . ' 00:00:00'; 109 $enddate = $request->get_param('enddate') . ' 23:59:59'; 110 111 // fetch count of all orders placed in this range that are eligible for reprocessing 112 $nfTransactionsTable = $wpdb->prefix . "nf_transactions"; 113 $wcOrdersTable = $wpdb->prefix . "wc_orders"; 114 $sql = $wpdb->prepare(" 115 SELECT 116 nft.* 117 FROM 118 {$wcOrdersTable} wco 119 INNER JOIN 120 {$nfTransactionsTable} nft 121 ON 122 ( 123 nft.meta_value = 'reprocess' 124 OR 125 nft.meta_value = 'gatewaydisabled' 126 ) 127 AND 128 nft.meta_key = '_nofraud_transaction_review_status' 129 AND 130 nft.order_id = wco.id 131 WHERE 132 wco.date_created_gmt <= %s 133 AND 134 wco.date_created_gmt >= %s 135 AND 136 wco.status NOT IN ('wc-completed', 'wc-cancelled', 'wc-refunded', 'wc-failed') 137 AND 138 wco.type = 'shop_order' 139 ", $enddate, $startdate); 140 141 if ('yes' !== get_option('woocommerce_custom_orders_table_enabled')) { 142 $wcPostsTable = $wpdb->prefix . "posts"; 143 $sql = $wpdb->prepare(" 144 SELECT 145 nft.* 146 FROM 147 {$wcPostsTable} wpt 148 INNER JOIN 149 {$nfTransactionsTable} nft 150 ON 151 ( 152 nft.meta_value = 'reprocess' 153 OR 154 nft.meta_value = 'gatewaydisabled' 155 ) 156 AND 157 nft.meta_key = '_nofraud_transaction_review_status' 158 AND 159 nft.order_id = wpt.id 160 WHERE 161 wpt.post_date_gmt <= %s 162 AND 163 wpt.post_date_gmt >= %s 164 AND 165 wpt.post_status NOT IN ('wc-completed', 'wc-cancelled', 'wc-refunded', 'wc-failed') 166 AND 167 wpt.post_type = 'shop_order' 168 ", $enddate, $startdate); 169 } 170 171 $results = $wpdb->get_results($sql, ARRAY_A); 172 173 $count = 0; 174 if ($results === null) { 175 $response_data = [ 176 'message' => 'Error encountered running reprocessing', 177 'success' => false, 178 'startdate' => $startdate, 179 'enddate' => $enddate, 180 'wpdb_error' => $wpdb->last_error, 181 ]; 182 183 return new \WP_REST_Response($response_data, 200); 184 } 185 186 $transaction_agent = new Transaction_Manager(); 187 $count = 0; 188 if (!empty($results)) { 189 foreach ($results as $nftTransactionObj) { 190 $reprocessCount = Database::get_nf_data($nftTransactionObj['order_id'],Constants::TRANSACTION_STATUS_REPROCESS_COUNT_KEY, false); 191 if (!empty($reprocessCount)) { 192 $reprocessCount = $reprocessCount + 1; 193 } 194 else { 195 $reprocessCount = 1; 196 } 197 198 if ($reprocessCount < 3) { 199 Database::update_nf_data($nftTransactionObj['order_id'],Constants::TRANSACTION_STATUS_KEY, Constants::TRANSACTION_STATUS_REPROCESS); 200 Database::update_nf_data($nftTransactionObj['order_id'],Constants::TRANSACTION_STATUS_REPROCESS_COUNT_KEY, $reprocessCount); 201 $transaction_agent->evaluate_transaction($nftTransactionObj['order_id'], [ 202 'TRANSACTION_REVIEW_REFRESH_LIMIT' => (Transaction_Manager::TRANSACTION_REVIEW_REFRESH_LIMIT*4) 203 ]); 204 Database::update_nf_data($nftTransactionObj['order_id'],Constants::TRANSACTION_STATUS_KEY, Constants::TRANSACTION_STATUS_REPROCESS_COMPLETE); 205 $count++; 206 } 207 } 208 } 209 210 $response_data = [ 211 'message' => 'Reprocessing run finished successfully.', 212 'success' => true, 213 'startdate' => $startdate, 214 'enddate' => $enddate, 215 'count' => $count, 216 ]; 217 218 return new \WP_REST_Response($response_data, 200); 219 } 220 221 /** 222 * Callback function to fetch how many transactions are eligible for reprocessing 223 * 224 * @param WP_REST_Request $request The REST request. 225 * @return WP_REST_Response The response. 226 */ 227 public static function reprocess_transactions_count($request) { 228 global $wpdb; 229 230 $startdate = $request->get_param('startdate') . ' 00:00:00'; 231 $enddate = $request->get_param('enddate') . ' 23:59:59'; 232 233 // fetch count of all orders placed in this range that are eligible for reprocessing 234 $nfTransactionsTable = $wpdb->prefix . "nf_transactions"; 235 $wcOrdersTable = $wpdb->prefix . "wc_orders"; 236 $sql = $wpdb->prepare(" 237 SELECT 238 count(distinct(nft.order_id)) as totalCount 239 FROM 240 {$wcOrdersTable} wco 241 INNER JOIN 242 {$nfTransactionsTable} nft 243 ON 244 ( 245 nft.meta_value = 'reprocess' 246 OR 247 nft.meta_value = 'gatewaydisabled' 248 ) 249 AND 250 nft.meta_key = '_nofraud_transaction_review_status' 251 AND 252 nft.order_id = wco.id 253 WHERE 254 wco.date_created_gmt <= %s 255 AND 256 wco.date_created_gmt >= %s 257 AND 258 wco.status NOT IN ('wc-completed', 'wc-cancelled', 'wc-refunded', 'wc-failed') 259 AND 260 wco.type = 'shop_order' 261 ", $enddate, $startdate); 262 if ('yes' !== get_option('woocommerce_custom_orders_table_enabled')) { 263 $wcPostsTable = $wpdb->prefix . "posts"; 264 $sql = $wpdb->prepare(" 265 SELECT 266 count(distinct(nft.order_id)) as totalCount 267 FROM 268 {$wcPostsTable} wpt 269 INNER JOIN 270 {$nfTransactionsTable} nft 271 ON 272 ( 273 nft.meta_value = 'reprocess' 274 OR 275 nft.meta_value = 'gatewaydisabled' 276 ) 277 AND 278 nft.meta_key = '_nofraud_transaction_review_status' 279 AND 280 nft.order_id = wpt.id 281 WHERE 282 wpt.post_date_gmt <= %s 283 AND 284 wpt.post_date_gmt >= %s 285 AND 286 wpt.post_status NOT IN ('wc-completed', 'wc-cancelled', 'wc-refunded', 'wc-failed') 287 AND 288 wpt.post_type = 'shop_order' 289 ", $enddate, $startdate); 290 } 291 292 $results = $wpdb->get_results($sql, ARRAY_A); 293 294 $count = 0; 295 if ($results === null) { 296 $response_data = [ 297 'message' => 'Reprocess eligible count failed', 298 'success' => false, 299 'startdate' => $startdate, 300 'enddate' => $enddate, 301 'wpdb_error' => $wpdb->last_error, 302 ]; 303 304 return new \WP_REST_Response($response_data, 200); 305 } 306 307 $sampleData = []; 308 if (!empty($results)) { 309 $count = $results[0]['totalCount']; 310 311 $sql = $wpdb->prepare(" 312 SELECT 313 wco.id as order_id, wco.type, wco.date_created_gmt, wco.status, nft.meta_key, nft.meta_value 314 FROM 315 {$wcOrdersTable} wco 316 INNER JOIN 317 {$nfTransactionsTable} nft 318 ON 319 ( 320 nft.meta_value = 'reprocess' 321 OR 322 nft.meta_value = 'gatewaydisabled' 323 ) 324 AND 325 nft.meta_key = '_nofraud_transaction_review_status' 326 AND 327 nft.order_id = wco.id 328 WHERE 329 wco.date_created_gmt <= %s 330 AND 331 wco.date_created_gmt >= %s 332 AND 333 wco.status NOT IN ('wc-completed', 'wc-cancelled', 'wc-refunded', 'wc-failed') 334 AND 335 wco.type = 'shop_order' 336 LIMIT 3 337 ", $enddate, $startdate); 338 if ('yes' !== get_option('woocommerce_custom_orders_table_enabled')) { 339 $wcPostsTable = $wpdb->prefix . "posts"; 340 $sql = $wpdb->prepare(" 341 SELECT 342 wpt.id as order_id, wpt.post_type, wpt.post_date_gmt, wpt.post_status, nft.meta_key, nft.meta_value 343 FROM 344 {$wcPostsTable} wpt 345 INNER JOIN 346 {$nfTransactionsTable} nft 347 ON 348 ( 349 nft.meta_value = 'reprocess' 350 OR 351 nft.meta_value = 'gatewaydisabled' 352 ) 353 AND 354 nft.meta_key = '_nofraud_transaction_review_status' 355 AND 356 nft.order_id = wpt.id 357 WHERE 358 wpt.post_date_gmt <= %s 359 AND 360 wpt.post_date_gmt >= %s 361 AND 362 wpt.post_status NOT IN ('wc-completed', 'wc-cancelled', 'wc-refunded', 'wc-failed') 363 AND 364 wpt.post_type = 'shop_order' 365 LIMIT 3 366 ", $enddate, $startdate); 367 } 368 $sampleData = $wpdb->get_results($sql, ARRAY_A); 369 } 370 371 $response_data = [ 372 'message' => 'Reprocess eligible count succeeded. Note that just because an order is eligible does not mean it will be reprocessed', 373 'success' => true, 374 'startdate' => $startdate, 375 'enddate' => $enddate, 376 'count' => $count, 377 'sample' => $sampleData, 378 ]; 379 380 return new \WP_REST_Response($response_data, 200); 381 } 382 383 /** 384 * Callback function to fetch reprocess completion data 385 * 386 * @param WP_REST_Request $request The REST request. 387 * @return WP_REST_Response The response. 388 */ 389 public static function reprocess_transactions_count_completed($request) { 390 global $wpdb; 391 392 $startdate = $request->get_param('startdate') . ' 00:00:00'; 393 $enddate = $request->get_param('enddate') . ' 23:59:59'; 394 395 // fetch count of all orders placed in this range that are eligible for reprocessing 396 $nfTransactionsTable = $wpdb->prefix . "nf_transactions"; 397 $wcOrdersTable = $wpdb->prefix . "wc_orders"; 398 $sql = $wpdb->prepare(" 399 SELECT 400 nft.meta_value, count(distinct(nft.order_id)) as totalCount 401 FROM 402 {$nfTransactionsTable} nft 403 WHERE 404 ( 405 nft.meta_value = 'reprocess' 406 OR 407 nft.meta_value = 'reprocesscomplete' 408 ) 409 AND 410 nft.meta_key = '_nofraud_transaction_review_status' 411 GROUP BY 412 nft.meta_value 413 ", $enddate, $startdate); 414 $results = $wpdb->get_results($sql, ARRAY_A); 415 416 $count = 0; 417 if ($results === null) { 418 $response_data = [ 419 'message' => 'Reprocess totals count failed', 420 'success' => false, 421 'wpdb_error' => $wpdb->last_error, 422 ]; 423 424 return new \WP_REST_Response($response_data, 200); 425 } 426 $completed_count = 0; 427 $reprocessing_count = 0; 428 if (!empty($results)) { 429 foreach ($results as $resultObj) { 430 if ($resultObj['meta_value'] == 'reprocess') { 431 $reprocessing_count = $resultObj['totalCount']; 432 } 433 if ($resultObj['meta_value'] == 'reprocesscomplete') { 434 $completed_count = $resultObj['totalCount']; 435 } 436 } 437 } 438 439 $response_data = [ 440 'message' => 'Reprocess completed count succeeded.', 441 'success' => true, 442 'completed_count' => $completed_count, 443 'reprocessing_count' => $reprocessing_count, 444 ]; 445 446 return new \WP_REST_Response($response_data, 200); 33 447 } 34 448 … … 366 780 367 781 /** 368 * Add NoFraud metadata to 782 * Add NoFraud metadata to woocommerce_rest_prepare_shop_order_object 369 783 * 370 784 * @since 4.5.0 -
nofraud-protection/trunk/changelog.txt
r3207152 r3216172 1 1 *** NoFraud Protection for WooCommerce Changelog *** 2 3 2025-01-02 - version 4.5.5 4 * Feature - Added REST API setting and API Route for reprocessing unprocessed orders 5 * Feature - Added choice for SkyVerge Authorize.net Autovoid feature to choose between WooCommerce method and legacy method 2 6 3 7 2024-12-10 - version 4.5.4 -
nofraud-protection/trunk/common/class-database.php
r3207152 r3216172 33 33 } 34 34 } 35 36 35 37 36 $tablename = $wpdb->prefix . "nf_transactions"; -
nofraud-protection/trunk/common/class-environment.php
r3207152 r3216172 21 21 * @var string Plugin version. 22 22 */ 23 const PLUGIN_VERSION = '4.5. 4';23 const PLUGIN_VERSION = '4.5.5'; 24 24 25 25 /** -
nofraud-protection/trunk/composer.json
r3207152 r3216172 1 1 { 2 2 "name": "nofraud/nofraud-protection", 3 "version": "4.5. 4",3 "version": "4.5.5", 4 4 "description": "NoFraud fraud detection service plugin for WooCommerce", 5 5 "type": "wordpress-plugin", -
nofraud-protection/trunk/nofraud-protection.php
r3207152 r3216172 4 4 * Plugin URI: https://nofraud.com 5 5 * Description: Eliminate fraudulent orders on your WooCommerce store with NoFraud. If you get a fraud chargeback, NoFraud will pay you back! Visit www.nofraud.com to learn more. 6 * Version: 4.5. 46 * Version: 4.5.5 7 7 * Author: NoFraud 8 8 * Requires PHP: 5.6 -
nofraud-protection/trunk/pages/class-woocommerce-settings.php
r3207152 r3216172 30 30 // Update by NoFraud setting tab. 31 31 add_action('woocommerce_update_options_nofraud', [$instance, 'update_settings_tab'], 10); 32 // Load scripts 33 add_action('admin_enqueue_scripts', [$instance, 'enqueue_nofraud_settings_script']); 34 32 35 } 33 36 … … 39 42 public function admin_init() { 40 43 global $wpdb; 44 45 wp_register_script( 'nofraud-protection-settings-script', plugins_url('../assets/js/settings.js', __FILE__) ); 41 46 42 47 $current_version_in_db = get_option('woocommerce_nofraud_protection_version', false); … … 178 183 } 179 184 $updated_order_statuses['donothing'] = 'Do Nothing'; 185 186 $voidrefund_modes = [ 187 'WOOCOMMERCE' => 'WooCommerce Refund', 188 'GATEWAY' => 'Legacy Direct Gateway', 189 ]; 180 190 181 191 $transaction_types = [ … … 236 246 ], 237 247 [ 248 'title' => __('Void/Refund Mode', 'nofraud-protection'), 249 'type' => 'select', 250 'class' => 'wc-enhanced-select', 251 'desc' => __('WooCommerce Refund will create a refund via WooCommerce methods, Legacy Direct Gateway will only submit an API request to the payment gateway', 'nofraud-protection'), 252 'options' => $voidrefund_modes, 253 'id' => 'woocommerce_nofraud_automatic_voidrefund_mode', 254 'default' => "WOOCOMMERCE", 255 ], 256 [ 238 257 'title' => __('Transaction Status to Initiate Decision Evaluation on', 'nofraud-protection'), 239 258 'type' => 'select', … … 458 477 'default' => 'yes', 459 478 ]; 460 479 480 $settings[] = 481 [ 482 'name' => __('Enable NoFraud REST API', 'nofraud-protection-section-payments'), 483 'type' => 'checkbox', 484 'desc' => __('If checked, NoFraud API endpoints will be enabled. This is disabled by default.', 'nofraud-protection-section-payments'), 485 'id' => 'woocommerce_nofraud_enable_rest_api', 486 'default' => 'no', 487 ]; 488 461 489 $settings[] = 462 490 [ … … 467 495 return apply_filters('woocommerce_nofraud_get_settings', $settings); 468 496 } 497 498 public function enqueue_nofraud_settings_script($hook) { 499 // Only load on WooCommerce settings page 500 if ($hook === 'woocommerce_page_wc-settings') { 501 wp_enqueue_script( 502 'nofraud-protection-settings-script', 503 plugins_url('../assets/js/settings.js', __FILE__), 504 array(), 505 '1.0', 506 true 507 ); 508 } 509 } 469 510 } 470 511 -
nofraud-protection/trunk/payment/methods/class-nofraud-authorize-net-cim-credit-card.php
r3192579 r3216172 179 179 $order_id = $order->get_id(); 180 180 181 $refund_amount = $order->get_remaining_refund_amount(); 182 $calculated_refund_amount = 0; 183 184 $order_items = $order->get_items(); 185 $line_items = array(); 186 187 if (!empty($order_items)) { 188 foreach($order_items as $item_id => $item) { 189 $item_meta = $order->get_item_meta( $item_id ); 190 $tax_data = $item_meta['_line_tax_data']; 191 $refund_tax = 0; 192 if(!empty($tax_data[0]) && is_array($tax_data[0])) { 193 $refund_tax = array_map('wc_format_decimal', $tax_data[0]); 194 } 195 $calculated_refund_amount = wc_format_decimal($calculated_refund_amount) + wc_format_decimal($item_meta['_line_total'][0]); 196 $line_items[$item_id] = [ 197 'qty' => $item_meta['_qty'][0], 198 'refund_total' => wc_format_decimal($item_meta['_line_total'][0]), 199 'refund_tax' => $refund_tax, 200 ]; 201 } 202 } 203 204 $refund = wc_create_refund(array( 205 'amount' => $refund_amount, 206 'reason' => 'NoFraud automatically voided/refunded the charge for this order due to FAIL decision', 207 'order_id' => $order_id, 208 'refund_payment' => true, 209 'restock_items' => true, 210 'line_items' => $line_items, 211 )); 212 if (is_wp_error($refund)) { 213 $order_note = sprintf(__('NoFraud attempted to automatically void/refund the charge for this order but failed due to error: %s', 'nofraud-protection'), $refund->get_error_message()); 214 wc_create_order_note($order_id, $order_note); 215 } else { 216 $order->update_meta_data( 'nofraud_voidrefund_processed', 1 ); 217 218 $order_note = sprintf(__('NoFraud automatically voided/refunded the charge for this order (Transaction ID: %s)', 'nofraud-protection'), $transaction_id); 219 wc_create_order_note($order_id, $order_note); 181 // determine which mode to use to process this voidrefund 182 $woocommerce_nofraud_automatic_voidrefund_mode = get_option('woocommerce_nofraud_automatic_voidrefund_mode', 'WOOCOMMERCE'); 183 184 if ($woocommerce_nofraud_automatic_voidrefund_mode == 'GATEWAY') { 185 // Legacy Payment Gateway Mode 186 //retrieve transaction details by transaction ID 187 $request = new AnetAPI\GetTransactionDetailsRequest(); 188 $request->setMerchantAuthentication($this->merchantAuthentication); 189 $request->setTransId($transaction_id); 190 191 $controller = new AnetController\GetTransactionDetailsController($request); 192 193 $response = null; 194 if('test' === $this->woocommerce_authorize_net_cim_credit_card_settings['environment']) { 195 $response = $controller->executeWithApiResponse( \net\authorize\api\constants\ANetEnvironment::SANDBOX); 196 } 197 else { 198 $response = $controller->executeWithApiResponse( \net\authorize\api\constants\ANetEnvironment::PRODUCTION); 199 } 200 201 $last4 = null; 202 $amountToRefund = '0.00'; 203 $transactionStatus = null; 204 if ((null !== $response) && (self::AUTHORIZENET_RESPONSE_CODES['RESPONSE_OK'] === $response->getMessages()->getResultCode())) 205 { 206 $transactionDetailsObj = $response->getTransaction(); 207 208 $creditCardMaskedTypeObj = $transactionDetailsObj->getPayment()->getCreditCard(); 209 if (!empty($creditCardMaskedTypeObj) && is_object($creditCardMaskedTypeObj) && method_exists($creditCardMaskedTypeObj,'getCardType')) { 210 if(!empty($creditCardMaskedTypeObj->getCardNumber())) { 211 $apiLast4CardNumber = substr($creditCardMaskedTypeObj->getCardNumber(),-4); 212 if(ctype_digit($apiLast4CardNumber) && 4 === strlen($apiLast4CardNumber)) { 213 $last4 = sanitize_text_field($apiLast4CardNumber); 214 } 215 } 216 } 217 218 $amountToRefund = $transactionDetailsObj->getSettleAmount(); 219 $transactionStatus = $transactionDetailsObj->getTransactionStatus(); 220 } 221 else 222 { 223 $errorMessages = $response->getMessages()->getMessage(); 224 error_log('NoFraud error: NoFraud_Authorize_Net_Cim_Credit_Card refund(): ' . print_r($errorMessages, true) ); 225 } 226 227 if (in_array($transactionStatus, ['capturedPendingSettlement','authorizedPendingCapture'])) { 228 $tresponse = $nofraud_payment_method->void($_wc_authorize_net_cim_credit_card_trans_id); 229 if ($tresponse != null && $tresponse->getMessages() != null) { 230 Debug::add_debug_message([ 231 'function' => 'woocommerce_nofraud_automatic_voidrefund:VOID:success', 232 'order_id' => $order_id, 233 '_wc_authorize_net_cim_credit_card_void_auth_code' => $tresponse->getAuthCode(), 234 '_wc_authorize_net_cim_credit_card_void_trans_id' => $tresponse->getTransId(), 235 ]); 236 237 $order->update_meta_data( '_wc_authorize_net_cim_credit_card_void_auth_code', $tresponse->getAuthCode() ); 238 $order->update_meta_data( '_wc_authorize_net_cim_credit_card_void_trans_id', $tresponse->getTransId() ); 239 $order->update_meta_data( 'nofraud_voidrefund_processed', 1 ); 240 241 $order_note = sprintf(__('NoFraud automatically voided the charge for this order (Voided Transaction ID: %s).', 'nofraud-protection'), $_wc_authorize_net_cim_credit_card_trans_id); 242 wc_create_order_note($order_id, $order_note); 243 } 244 else { 245 if ($tresponse->getErrors() != null) { 246 Debug::add_debug_message([ 247 'function' => 'woocommerce_nofraud_automatic_voidrefund:VOID:failed', 248 'order_id' => $order_id, 249 'error_code' => $tresponse->getErrors()[0]->getErrorCode(), 250 'error_msg' => $tresponse->getErrors()[0]->getErrorText(), 251 ]); 252 253 $order_note = sprintf(__('NoFraud attempted to void the charge for this order but the attempt failed with error code (%1$s): %2$s.', 'nofraud-protection'), $tresponse->getErrors()[0]->getErrorCode(), $tresponse->getErrors()[0]->getErrorText()); 254 wc_create_order_note($order_id, $order_note); 255 } 256 } 257 258 if ('settledSuccessfully' === $transactionStatus) { 259 $_wc_authorize_net_cim_credit_card_account_four = $order->get_meta('_wc_authorize_net_cim_credit_card_account_four'); 260 if (!empty($_wc_authorize_net_cim_credit_card_account_four)) { 261 $tresponse = $nofraud_payment_method->refund($order, $_wc_authorize_net_cim_credit_card_trans_id, $last4, $amountToRefund); 262 if ($tresponse != null && $tresponse->getMessages() != null) { 263 Debug::add_debug_message([ 264 'function' => 'woocommerce_nofraud_automatic_voidrefund:REFUND:success', 265 'order_id' => $order_id, 266 '_wc_authorize_net_cim_credit_card_void_auth_code' => $tresponse->getAuthCode(), 267 '_wc_authorize_net_cim_credit_card_void_trans_id' => $tresponse->getTransId(), 268 ]); 269 270 $order->update_meta_data( '_wc_authorize_net_cim_credit_card_refund_auth_code', $tresponse->getAuthCode() ); 271 $order->update_meta_data( '_wc_authorize_net_cim_credit_card_refund_trans_id', $tresponse->getTransId() ); 272 $order->update_meta_data( 'nofraud_voidrefund_processed', 1 ); 273 274 $order_note = sprintf(__('NoFraud automatically refunded the charge for this order (Transaction ID %1$s)', 'nofraud-protection'), $tresponse->getTransId()); 275 wc_create_order_note($order_id, $order_note); 276 } 277 else { 278 if ($tresponse->getErrors() != null) { 279 Debug::add_debug_message([ 280 'function' => 'woocommerce_nofraud_automatic_voidrefund:REFUND:failed', 281 'order_id' => $order_id, 282 'error_code' => $tresponse->getErrors()[0]->getErrorCode(), 283 'error_msg' => $tresponse->getErrors()[0]->getErrorText(), 284 ]); 285 286 $order_note = sprintf(__('NoFraud attempted to refund the charge for this order but the attempt failed with error code (%1$s): %2$s.', 'nofraud-protection'), $tresponse->getErrors()[0]->getErrorCode(), $tresponse->getErrors()[0]->getErrorText()); 287 wc_create_order_note($order_id, $order_note); 288 } 289 } 290 } 291 else { 292 Debug::add_debug_message([ 293 'function' => 'woocommerce_nofraud_automatic_voidrefund:REFUND:failed:missing_last4', 294 'order_id' => $order_id, 295 ]); 296 } 297 } 298 } 299 } 300 else { 301 // WooCommerce Refund Mode 302 $refund_amount = $order->get_remaining_refund_amount(); 303 $calculated_refund_amount = 0; 304 305 $order_items = $order->get_items(); 306 $line_items = array(); 307 308 if (!empty($order_items)) { 309 foreach($order_items as $item_id => $item) { 310 $item_meta = $order->get_item_meta( $item_id ); 311 $tax_data = $item_meta['_line_tax_data']; 312 $refund_tax = 0; 313 if(!empty($tax_data[0]) && is_array($tax_data[0])) { 314 $refund_tax = array_map('wc_format_decimal', $tax_data[0]); 315 } 316 $calculated_refund_amount = wc_format_decimal($calculated_refund_amount) + wc_format_decimal($item_meta['_line_total'][0]); 317 $line_items[$item_id] = [ 318 'qty' => $item_meta['_qty'][0], 319 'refund_total' => wc_format_decimal($item_meta['_line_total'][0]), 320 'refund_tax' => $refund_tax, 321 ]; 322 } 323 } 324 325 $refund = wc_create_refund(array( 326 'amount' => $refund_amount, 327 'reason' => 'NoFraud automatically voided/refunded the charge for this order due to FAIL decision', 328 'order_id' => $order_id, 329 'refund_payment' => true, 330 'restock_items' => true, 331 'line_items' => $line_items, 332 )); 333 if (is_wp_error($refund)) { 334 $order_note = sprintf(__('NoFraud attempted to automatically void/refund the charge for this order but failed due to error: %s', 'nofraud-protection'), $refund->get_error_message()); 335 wc_create_order_note($order_id, $order_note); 336 } else { 337 $order->update_meta_data( 'nofraud_voidrefund_processed', 1 ); 338 339 $order_note = sprintf(__('NoFraud automatically voided/refunded the charge for this order (Transaction ID: %s)', 'nofraud-protection'), $transaction_id); 340 wc_create_order_note($order_id, $order_note); 341 } 220 342 } 221 343 } -
nofraud-protection/trunk/payment/transactions/class-constants.php
r2974562 r3216172 57 57 */ 58 58 const TRANSACTION_STATUS_GATEWAYDISABLED = 'gatewaydisabled'; 59 59 60 /** 61 * "Transaction Reprocess Status" 62 * 63 * @var string Reprocess means the order was triggered for reprocessing 64 */ 65 const TRANSACTION_STATUS_REPROCESS = 'reprocess'; 66 67 /** 68 * "Transaction Reprocess Count" 69 * 70 * @var string Reprocesscount 71 */ 72 const TRANSACTION_STATUS_REPROCESS_COUNT_KEY = 'reprocesscount'; 73 74 /** 75 * "Transaction Reprocess Completed Status" 76 * 77 * @var string Reprocesscomplete means the order completed reprocessing 78 */ 79 const TRANSACTION_STATUS_REPROCESS_COMPLETE = 'reprocesscomplete'; 80 60 81 /** 61 82 * Response from do_action of external plugin -
nofraud-protection/trunk/payment/transactions/class-transaction-manager.php
r3192579 r3216172 313 313 * 314 314 * @param int $order_id Order ID. 315 * @return stdObject NoFraud transaction review. 315 * @param array $options Additional options 316 * @return stdObject NoFraud transaction review. 316 317 * 317 318 * @since 2.0.0 318 319 */ 319 public function evaluate_transaction( $order_id ) {320 public function evaluate_transaction( $order_id, $options = [] ) { 320 321 Debug::add_debug_message([ 321 322 'function' => 'NoFraud:Transaction_Manager:evaluate_transaction', … … 326 327 $original_transaction_review = Database::get_nf_data($order_id, Constants::TRANSACTION_REVIEW_KEY); 327 328 328 $transaction_review = $this->get_transaction_review($order_id );329 $transaction_review = $this->get_transaction_review($order_id, $options); 329 330 if (!empty($transaction_review)) { 330 331 if (isset($transaction_review->id)) { … … 565 566 * Get transaction review. 566 567 * 567 * @param int $order_id Order ID. 568 * @param int $order_id Order ID 569 * @param array $options Additional options 568 570 * @return stdObject|false NoFraud transaction review. 569 571 */ 570 public function get_transaction_review( $order_id ) {572 public function get_transaction_review( $order_id, $options = [] ) { 571 573 Debug::add_debug_message([ 572 574 'function' => 'NoFraud:Transaction_Manager:get_transaction_review()', … … 634 636 635 637 // sanity check don't do a decision if order is older than TRANSACTION_REVIEW_REFRESH_LIMIT 636 if (strtotime($order->get_date_created()) < time() - self::TRANSACTION_REVIEW_REFRESH_LIMIT) { 638 $maxDatetimeRefreshable = time() - self::TRANSACTION_REVIEW_REFRESH_LIMIT; 639 640 // exception: if TRANSACTION_REVIEW_REFRESH_LIMIT is defined in options, overwrite 641 if (!empty($options['TRANSACTION_REVIEW_REFRESH_LIMIT'])) { 642 Debug::add_debug_message([ 643 'function' => 'NoFraud:Transaction_Manager:get_transaction_review():custom_refresh_limit', 644 'order_id' => $order_id, 645 'TRANSACTION_REVIEW_REFRESH_LIMIT' => $options['TRANSACTION_REVIEW_REFRESH_LIMIT'], 646 ]); 647 $maxDatetimeRefreshable = time() - $options['TRANSACTION_REVIEW_REFRESH_LIMIT']; 648 } 649 650 if (strtotime($order->get_date_created()) < $maxDatetimeRefreshable) { 637 651 Debug::add_debug_message([ 638 652 'function' => 'NoFraud:Transaction_Manager:get_transaction_review():order_too_old', … … 646 660 647 661 // Otherwise, create a new transaction review. 648 return $this->create_transaction_review($order_id );662 return $this->create_transaction_review($order_id, $options); 649 663 } 650 664 … … 679 693 * Submit transaction data to NoFraud API to create a transaction review. 680 694 * 681 * @param int $order_id Order ID. 682 * @return stdObject|false NoFraud transaction review. 695 * @param int $order_id Order ID 696 * @param array $options Additional options 697 * @return stdObject|false NoFraud transaction review. 683 698 */ 684 private function create_transaction_review( $order_id ) {699 private function create_transaction_review( $order_id, $options = [] ) { 685 700 Debug::add_debug_message([ 686 701 'function' => 'create_transaction_review', … … 692 707 693 708 // sanity check don't do a decision if order is older than TRANSACTION_REVIEW_REFRESH_LIMIT 694 if (strtotime($order->get_date_created()) < time() - self::TRANSACTION_REVIEW_REFRESH_LIMIT) { 709 $maxDatetimeRefreshable = time() - self::TRANSACTION_REVIEW_REFRESH_LIMIT; 710 711 // exception: if TRANSACTION_REVIEW_REFRESH_LIMIT is defined in options, overwrite 712 if (!empty($options['TRANSACTION_REVIEW_REFRESH_LIMIT'])) { 713 Debug::add_debug_message([ 714 'function' => 'NoFraud:Transaction_Manager:create_transaction_review():custom_refresh_limit', 715 'order_id' => $order_id, 716 'TRANSACTION_REVIEW_REFRESH_LIMIT' => $options['TRANSACTION_REVIEW_REFRESH_LIMIT'], 717 ]); 718 $maxDatetimeRefreshable = time() - $options['TRANSACTION_REVIEW_REFRESH_LIMIT']; 719 } 720 721 if (strtotime($order->get_date_created()) < $maxDatetimeRefreshable) { 695 722 Debug::add_debug_message([ 696 723 'function' => 'create_transaction_review:order_too_old', -
nofraud-protection/trunk/readme.txt
r3207152 r3216172 5 5 Requires PHP: 5.6 6 6 Tested up to: 6.7.1 7 Stable tag: 4.5. 47 Stable tag: 4.5.5 8 8 License: GPL-3.0 9 9 License URI: http://www.gnu.org/licenses/gpl-3.0.txt
Note: See TracChangeset
for help on using the changeset viewer.