File "class-wc-background-swedbank-pay-queue.php"
Full Path: /home/siazco/grocery.siazco.se/wp-content/plugins/swedbank-pay-payments/includes/class-wc-background-swedbank-pay-queue.php
File size: 6.34 KB
MIME-type: text/x-php
Charset: utf-8
<?php
namespace SwedbankPay\Payments\WooCommerce;
use WC_Background_Process;
use WC_Logger;
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( 'WC_Background_Process', false ) ) {
include_once WC_ABSPATH . '/includes/abstracts/class-wc-background-process.php';
}
/**
* Class WC_Background_Swedbank_Queue
*/
class WC_Background_Swedbank_Pay_Queue extends WC_Background_Process {
/**
* @var WC_Logger
*/
private $logger;
/**
* Initiate new background process.
*/
public function __construct() {
$this->logger = wc_get_logger();
// Uses unique prefix per blog so each blog has separate queue.
$this->prefix = 'wp_' . get_current_blog_id();
$this->action = 'wc_swedbank_pay_queue';
// Dispatch queue after shutdown.
add_action( 'shutdown', array( $this, 'dispatch_queue' ), 100 );
parent::__construct();
}
/**
* Schedule fallback event.
*/
protected function schedule_event() {
if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
wp_schedule_event(
time() + MINUTE_IN_SECONDS,
$this->cron_interval_identifier,
$this->cron_hook_identifier
);
}
}
/**
* Get batch.
*
* @return \stdClass Return the first batch from the queue.
*/
protected function get_batch() {
global $wpdb;
$table = $wpdb->options;
$column = 'option_name';
$key_column = 'option_id';
$value_column = 'option_value';
if ( is_multisite() ) {
$table = $wpdb->sitemeta;
$column = 'meta_key';
$key_column = 'meta_id';
$value_column = 'meta_value';
}
$key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
$results = array();
// phpcs:disable
$data = $wpdb->get_results(
$wpdb->prepare(
"SELECT * FROM {$table} WHERE {$column} LIKE %s ORDER BY {$key_column} ASC",
$key ) ); // @codingStandardsIgnoreLine.
// phpcs:enable
// Check the records
$sorting_flow = array();
foreach ( $data as $id => $result ) {
$task = array_filter( (array) maybe_unserialize( $result->$value_column ) );
if ( ! is_array( $task ) ||
empty( $task[0]['webhook_data'] ) ||
null === json_decode( $task[0]['webhook_data'], true )
) {
// Remove invalid record from the database
// phpcs:disable
$wpdb->query( $wpdb->prepare( "DELETE FROM {$table} WHERE {$key_column} = %s", $data[$key_column] ) ); // @codingStandardsIgnoreLine.
// phpcs:enable
continue;
}
// Check the payment method ID
if ( ! in_array( $task[0]['payment_method_id'], WC_Swedbank_Plugin::PAYMENT_METHODS ) ) {
// Try with another queue processor
continue;
}
$batch = new \stdClass();
$batch->key = $result->$column;
$batch->data = $task;
// Create Sorting Flow by Transaction Number
$webhook = json_decode( $task[0]['webhook_data'], true );
$sorting_flow[ $id ] = $webhook['transaction']['number'];
$results[ $id ] = $batch;
}
// Sorting
array_multisort( $sorting_flow, SORT_ASC, SORT_NUMERIC, $results );
unset( $data, $sorting_flow );
$batch = array_shift( $results ); // Get first result
if ( ! $batch ) {
$batch = new \stdClass();
$batch->key = null;
$batch->data = array();
}
return $batch;
}
/**
* Log message.
*
* @param $message
*/
private function log( $message ) {
$this->logger->info( $message, array( 'source' => $this->action ) );
}
/**
* Code to execute for each item in the queue.
*
* @param mixed $item Queue item to iterate over.
*
* @return mixed
*/
protected function task( $item ) {
$this->log( sprintf( 'Start task: %s', var_export( $item, true ) ) );
try {
$data = json_decode( $item['webhook_data'], true );
if ( JSON_ERROR_NONE !== json_last_error() ) {
throw new \Exception( 'Invalid webhook data' );
}
$gateways = WC()->payment_gateways()->payment_gateways();
/** @var \WC_Gateway_Swedbank_Pay_Cc $gateway */
$gateway = isset( $gateways[ $item['payment_method_id'] ] ) ? $gateways[ $item['payment_method_id'] ] : false;
if ( ! $gateway ) {
throw new \Exception(
sprintf(
'Can\'t retrieve payment gateway instance: %s',
$item['payment_method_id']
)
);
}
if ( ! isset( $data['payment'] ) || ! isset( $data['payment']['id'] ) ) {
throw new \Exception( 'Error: Invalid payment value' );
}
if ( ! isset( $data['transaction'] ) || ! isset( $data['transaction']['number'] ) ) {
throw new \Exception( 'Error: Invalid transaction number' );
}
// Get Order by Payment Id
$transaction_id = $data['transaction']['number'];
$payment_id = $data['payment']['id'];
$order_id = $this->get_post_id_by_meta( '_payex_payment_id', $payment_id );
if ( ! $order_id ) {
throw new \Exception( sprintf( 'Error: Failed to get order Id by Payment Id %s', $payment_id ) );
}
// Get Order
$order = wc_get_order( $order_id );
if ( ! $order ) {
throw new \Exception( sprintf( 'Error: Failed to get order by Id %s', $order_id ) );
}
$transactions = (array) $order->get_meta( '_sb_transactions' );
if ( in_array( $transaction_id, $transactions) ) {
$this->log( sprintf( 'Transaction #%s was processed before.', $transaction_id ) );
// Remove from queue
return false;
}
} catch ( \Exception $e ) {
$this->log( sprintf( '[ERROR]: Validation error: %s', $e->getMessage() ) );
// Remove from queue
return false;
}
try {
$gateway->core->fetchTransactionsAndUpdateOrder( $order_id, $data['transaction']['number'] );
} catch ( \Exception $e ) {
$this->log( sprintf( '[ERROR]: %s', $e->getMessage() ) );
// Remove from queue
return false;
}
$this->log( sprintf( 'Transaction #%s has been processed.', $transaction_id ) );
// Remove from queue
return false;
}
/**
* This runs once the job has completed all items on the queue.
*
* @return void
*/
protected function complete() {
parent::complete();
$this->log( 'Completed ' . $this->action . ' queue job.' );
}
/**
* Save and run queue.
*/
public function dispatch_queue() {
if ( ! empty( $this->data ) ) {
$this->save()->dispatch();
}
}
/**
* Get Post Id by Meta
*
* @param $key
* @param $value
*
* @return null|string
*/
private function get_post_id_by_meta( $key, $value ) {
global $wpdb;
return $wpdb->get_var(
$wpdb->prepare(
"SELECT post_id FROM {$wpdb->prefix}postmeta WHERE meta_key = %s AND meta_value = %s;",
$key,
$value
)
);
}
}