Skip to content
This repository has been archived by the owner on Nov 13, 2024. It is now read-only.

Commit

Permalink
Clean up more lint issues; edit .gitignore
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisfromthelc committed Oct 30, 2024
1 parent 0164400 commit 4c46e03
Show file tree
Hide file tree
Showing 3 changed files with 342 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ GitHub.sublime-settings

### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
Expand Down
190 changes: 190 additions & 0 deletions src/inc/abuse-decisions-actions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
<?php

namespace WPCOMSpecialProjects\SiftDecisions\Abuse_Decision_Actions;

/**
* Unblock a user from making purchases if Sift indicates that they are no longer a fraud risk.
*
* @param integer $user_id The ID of the user to unblock from making purchases.
*
* @return void
*/
function unblock_user_from_purchases( $user_id ) {
delete_user_meta( $user_id, 'is_blocked_from_purchases' );
}

/**
* Void and refund all orders for a user.
*
* @param integer $user_id The ID of the user to void and refund orders for.
*
* @return void
*/
function void_and_refund_user_orders( $user_id ) {
$orders = wc_get_orders(
array(
'customer' => $user_id,
'status' => array( 'completed', 'processing' ),
)
);

foreach ( $orders as $order ) {
sift_fraud_void_refund_order( $order->get_id() );
}
}

/**
* Cancel all subscriptions for a user.
*
* @param integer $user_id The ID of the user to cancel subscriptions for.
*
* @return void
*/
function cancel_and_remove_user_subscriptions( $user_id ) {
$subscriptions = wcs_get_users_subscriptions( $user_id );

foreach ( $subscriptions as $subscription ) {
if ( 'active' === $subscription->get_status() || 'pending-cancel' === $subscription->get_status() ) {
$subscription->update_status( 'cancelled', __( 'Cancelled by system due to account block. SGDC Error OYBPXRQ', 'sift-decisions' ) );
wp_delete_post( $subscription->get_id(), true );
}
}
}

/**
* Remove licenses and product keys associated with a user.
*
* @param integer $user_id The ID of the user to remove licenses and product keys for.
*
* @return void
*/
function remove_user_licenses_and_product_keys( $user_id ) {
delete_user_meta( $user_id, 'user_licenses' );
delete_user_meta( $user_id, 'user_product_keys' );

$args = array(
'post_type' => array( 'license', 'product_key' ),
'meta_key' => 'user_id',
'meta_value' => $user_id,
'post_status' => 'any',
);

$posts = get_posts( $args );
foreach ( $posts as $post ) {
wp_delete_post( $post->ID, true );
}
}

/**
* Display the SGDC error to the user.
*
* @param string $message Override the default message to display to the user.
*
* @return void
*/
function display_sgdc_error( $message = '' ) {
$default_message = __( 'Your account has been blocked from making purchases. SGDC Error OYBPXRQ', 'sift-decisions' );
$message = $message ? $message : $default_message;
wc_add_notice( $message, 'error' );
}

/**
* Force user logout when they are blocked from making purchases.
*
* @param integer $user_id The ID of the user to log out.
*
* @return void
*/
function force_user_logout( $user_id ) {
if ( class_exists( 'WP_Session_Tokens' ) ) {
$user_sessions = WP_Session_Tokens::get_instance( $user_id );
$user_sessions->destroy_all();
}

if ( get_current_user_id() === $user_id ) {
wp_logout();
}
}

/**
* To void/cancel/refund an order...
*
* Loosely based on https://www.ibenic.com/how-to-create-woocommerce-refunds-programmatically/ -- but needs review.
*
* @param mixed $order_id Post object or post ID of the order.
*
* @return \WC_Order_Refund|\WP_Error
*/
function sift_fraud_void_refund_order( $order_id ) {
$order = wc_get_order( $order_id );

if ( ! is_a( $order, 'WC_Order' ) ) {
return new \WP_Error(
'wc-order',
__( 'Provided ID is not a WC Order', 'sift-decisions' )
);
}

if ( 'refunded' === $order->get_status() ) {
return new \WP_Error(
'wc-order',
__( 'Order has been already refunded', 'sift-decisions' )
);
}

$order_items = $order->get_items( array( 'line_item', 'fee', 'shipping' ) );

$refund_amount = 0;
$line_items = array();

if ( ! $order_items ) {
return new \WP_Error(
'wc-order',
__( 'This order has no items', 'sift-decisions' )
);
}

foreach ( $order_items as $item_id => $item ) {
$line_total = $order->get_line_total( $item, false, false );
$qty = $item->get_quantity();
$tax_data = wc_get_order_item_meta( $item_id, '_line_tax_data' );

$refund_tax = array();

// Check if it's shipping costs. If so, get shipping taxes.
if ( $item instanceof \WC_Order_Item_Shipping ) {
$tax_data = wc_get_order_item_meta( $item_id, 'taxes' );
}

// If taxdata is set, format as decimal.
if ( ! empty( $tax_data['total'] ) ) {
$refund_tax = array_filter( array_map( 'wc_format_decimal', $tax_data['total'] ) );
}

// Calculate line total, including tax.
$line_total_inc_tax = wc_format_decimal( $line_total ) + ( is_numeric( reset( $refund_tax ) ) ? wc_format_decimal( reset( $refund_tax ) ) : 0 );

// Add the total for this line to the grand total.
$refund_amount += round( $line_total_inc_tax, 2 );

// Fill item per line.
$line_items[ $item_id ] = array(
'qty' => $qty,
'refund_total' => wc_format_decimal( $line_total ),
'refund_tax' => array_map( 'wc_round_tax_total', $refund_tax ),
);
}

$refund = wc_create_refund(
array(
'amount' => $refund_amount,
'reason' => 'Sift Fraud Detection - Voiding Order',
'order_id' => $order->ID,
'line_items' => $line_items,
'refund_payment' => true,
'restock_items' => true,
)
);

return $refund;
}
151 changes: 151 additions & 0 deletions src/inc/abuse-decisions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php

namespace WPCOMSpecialProjects\SiftDecisions\Abuse_Decisions;

use function WPCOMSpecialProjects\SiftDecisions\Abuse_Decision_Actions\{
unblock_user_from_purchases,
void_and_refund_user_orders,
cancel_and_remove_user_subscriptions,
remove_user_licenses_and_product_keys,
display_sgdc_error,
force_user_logout
};

/**
* Process the Sift decision received.
*
* @param mixed $return_value The return value.
* @param string $decision_id The ID of the Sift decision.
* @param integer $entity_id The ID of the entity the decision is for.
*
* @return mixed
*/
function process_sift_decision_received( $return_value, $decision_id, $entity_id ) {

switch ( $decision_id ) {
case 'trust_list_payment_abuse':
handle_trust_list_payment_abuse( $entity_id );
break;

case 'looks_good_payment_abuse':
handle_looks_good_payment_abuse( $entity_id );
break;

case 'not_likely_fraud_payment_abuse':
handle_not_likely_fraud_payment_abuse( $entity_id );
break;

case 'likely_fraud_refundno_renew_payment_abuse':
handle_likely_fraud_refundno_renew_payment_abuse( $entity_id );
break;

case 'likely_fraud_keep_purchases_payment_abuse':
handle_likely_fraud_keep_purchases_payment_abuse( $entity_id );
break;

case 'fraud_payment_abuse':
handle_fraud_payment_abuse( $entity_id );
break;

case 'block_wo_review_payment_abuse':
handle_block_wo_review_payment_abuse( $entity_id );
break;

case 'looks_ok_payment_abuse':
case 'looks_suspicious_payment_abuse':
case 'order_looks_ok_payment_abuse':
case 'order_looks_suspicious_payment_abuse':
// Not Currently Implemented.
break;
}

return $return_value;
}
add_filter( 'sift_decision_received', __NAMESPACE__ . '\process_sift_decision_received', 10, 5 );

/**
* Handle the 'trust_list_payment_abuse' decision.
*
* @param integer $user_id The ID of the user.
*
* @return void
*/
function handle_trust_list_payment_abuse( $user_id ) {
unblock_user_from_purchases( $user_id );
}

/**
* Handle the 'looks_good_payment_abuse' decision.
*
* @param integer $user_id The ID of the user.
*
* @return void
*/
function handle_looks_good_payment_abuse( $user_id ) {
unblock_user_from_purchases( $user_id );
}

/**
* Handle the 'not_likely_fraud_payment_abuse' decision.
*
* @param integer $user_id The ID of the user.
*
* @return void
*/
function handle_not_likely_fraud_payment_abuse( $user_id ) {
unblock_user_from_purchases( $user_id );
}

/**
* Handle the 'likely_fraud_refundno_renew_payment_abuse' decision.
*
* @param integer $user_id The ID of the user.
*
* @return void
*/
function handle_likely_fraud_refundno_renew_payment_abuse( $user_id ) {
update_user_meta( $user_id, 'is_blocked_from_purchases', true );
void_and_refund_user_orders( $user_id );
cancel_and_remove_user_subscriptions( $user_id );
remove_user_licenses_and_product_keys( $user_id );
display_sgdc_error( 'You are blocked from making purchases due to a recent fraud review. SGDC Error OYBPXRQ' );
}

/**
* Handle the 'likely_fraud_keep_purchases_payment_abuse' decision.
*
* @param integer $user_id The ID of the user.
*
* @return void
*/
function handle_likely_fraud_keep_purchases_payment_abuse( $user_id ) {
update_user_meta( $user_id, 'is_blocked_from_purchases', true );
display_sgdc_error( 'You are blocked from making purchases due to a recent fraud review. SGDC Error OYBPXRQ' );
}

/**
* Handle the 'fraud_payment_abuse' decision.
*
* @param integer $user_id The ID of the user.
*
* @return void
*/
function handle_fraud_payment_abuse( $user_id ) {
update_user_meta( $user_id, 'is_blocked_from_purchases', true );
void_and_refund_user_orders( $user_id );
cancel_and_remove_user_subscriptions( $user_id );
remove_user_licenses_and_product_keys( $user_id );
display_sgdc_error( 'You are blocked from making purchases due to fraudulent activity. SGDC Error OYBPXRQ' );
force_user_logout( $user_id );
}

/**
* Handle the 'block_wo_review_payment_abuse' decision.
*
* @param integer $user_id The ID of the user.
*
* @return void
*/
function handle_block_wo_review_payment_abuse( $user_id ) {
update_user_meta( $user_id, 'is_blocked_from_purchases', true );
}

0 comments on commit 4c46e03

Please sign in to comment.