If you’re curious, my record_credit_card_decline function basically just creates a row in a table for that IP address and is defined as follows:
// Function to record card failures to a simple database by IP address.
function record_credit_card_decline($order_id = NULL)
{
$ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
if (!empty($ip_address))
{
// Insert a row into CREDIT_CARD_ATTEMPTS_TABLE
global $wpdb;
$insert = $wpdb->get_results( $wpdb->prepare("INSERT INTO " . $wpdb->prefix . CREDIT_CARD_ATTEMPTS_TABLE . " SET ip_address = '%s', order_id = '%s'", $ip_address, $order_id), OBJECT );
}
// Send a php error as well (in case there was no IP address)
error_log("Recording credit card decline for order '$order_id' against IP '$ip_address'.");
}
If you copy this, be careful with $_SERVER['HTTP_X_FORWARDED_FOR']
. That’s the $_SERVER variable I have to use because I’m behind a load balancer and would otherwise get the load balancer’s address.
This is the function I use to check how many failures there have been for that IP in the past 24 hours:
// Function to return how many credit card attempts there have been from the same IP address today.
function credit_card_attempt_count()
{
$ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
if (!empty($ip_address))
{
// Query the CREDIT_CARD_ATTEMPTS_TABLE table, defined as
// CREATE TABLE CREDIT_CARD_ATTEMPTS_TABLE (
// id int(11) NOT NULL,
// ip_address varchar(15) COLLATE utf8mb4_0900_ai_ci NOT NULL,
// time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
// order_id int(11) DEFAULT NULL
// ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
global $wpdb;
$yesterday = date('Y-m-d H:i:s', time() - (60*60*24));
$select_query = $wpdb->prepare('SELECT * FROM ' . $wpdb->prefix . CREDIT_CARD_ATTEMPTS_TABLE . ' WHERE ip_address = "%s" AND time > "%s"', $ip_address, $yesterday);
$select_results = $wpdb->get_results( $select_query, OBJECT );
$attempts = count($select_results);
return $attempts;
}
else
{
return 999;
}
}
Finally, the best place I’ve found to actually check those failure and block payments is here, by removing the eWay plugins form being available (and then customising the error message caused by no available gateways):
// Plugin-agnostic method of removing the payment plugins.
add_filter('woocommerce_available_payment_gateways', 'filter_woocommerce_available_payment_gateways', 10, 1);
function filter_woocommerce_available_payment_gateways($gateways)
{
if ( credit_card_attempt_count() >= CREDIT_CARD_MAXIMUM_ATTEMPTS )
{
unset($gateways['eway']);
unset($gateways['eway_payments']);
}
return $gateways;
}
// Customise the resulting error message.
add_filter( 'woocommerce_no_available_payment_methods_message', function(){
return 'Sorry, there have been too many declined credit card attempts. Please contact us if you require assistance or wish to make alternate arrangements.';
});
(If you copy any of this, be careful, as this forum didn’t like the backquotes in my SQL statements. I’ve tried to clean ’em up but check your work!)
-
This reply was modified 2 years ago by jaydisc.
-
This reply was modified 2 years ago by jaydisc.
-
This reply was modified 2 years ago by jaydisc.
-
This reply was modified 2 years ago by jaydisc.