File "class-wc-swedbank-pay-instant-capture.php"
Full Path: /home/siazco/grocery.siazco.se/wp-content/plugins/swedbank-pay-checkout/includes/class-wc-swedbank-pay-instant-capture.php
File size: 12.71 KB
MIME-type: text/x-php
Charset: utf-8
<?php
namespace SwedbankPay\Checkout\WooCommerce;
defined( 'ABSPATH' ) || exit;
use SwedbankPay\Core\Log\LogLevel;
use SwedbankPay\Core\OrderItemInterface;
class WC_Swedbank_Pay_Instant_Capture {
/** Payment IDs */
const PAYMENT_METHODS = array(
'payex_checkout',
);
/**
* CAPTURE Type options
*/
const CAPTURE_VIRTUAL = 'online_virtual';
const CAPTURE_PHYSICAL = 'physical';
const CAPTURE_RECURRING = 'recurring';
const CAPTURE_FEE = 'fee';
/**
* @var \WC_Gateway_Swedbank_Pay_Cc
*/
private $gateway;
/**
* Constructor.
*/
public function __construct() {
add_action( 'woocommerce_order_status_on-hold', array( $this, 'maybe_capture_instantly' ), 50, 1 );
}
/**
* Maybe capture instantly.
*
* @param $order_id
*
* @throws \SwedbankPay\Core\Exception
*/
public function maybe_capture_instantly( $order_id ) {
$order = wc_get_order( $order_id );
$payment_method = $order->get_payment_method();
if ( ! in_array( $payment_method, WC_Swedbank_Plugin::PAYMENT_METHODS, true ) ) {
return;
}
$payment_order_id = $order->get_meta( '_payex_paymentorder_id' );
if ( empty( $payment_order_id ) ) {
return;
}
$this->gateway = $this->get_payment_method( $order );
$payment_id = $this->gateway->core->getPaymentIdByPaymentOrder( $payment_order_id );
if ( empty( $payment_id ) ) {
return;
}
// Fetch transactions list
$transactions = $this->gateway->core->fetchTransactionsList( $payment_id );
$this->gateway->core->saveTransactions( $order->get_id(), $transactions );
// Check if have captured transactions
$hasCaptured = false;
foreach ( $transactions as $transaction ) {
if ( \SwedbankPay\Core\Api\TransactionInterface::TYPE_CAPTURE === $transaction->getType() &&
$transaction->isCompleted()
) {
$hasCaptured = true;
break;
}
}
// Capture if possible
if ( ! $hasCaptured ) {
try {
$this->instant_capture( $order );
} catch ( \Exception $e ) {
$this->gateway->adapter->log(
LogLevel::INFO,
sprintf( '%s: Warning: %s', __METHOD__, $e->getMessage() )
);
}
}
}
/**
* Capture order using "Instant Capture".
*
* @param \WC_Order $order
*
* @throws \Exception
*/
private function instant_capture( $order ) {
$items = $this->get_instant_capture_items( $order );
$this->gateway->adapter->log( LogLevel::INFO, __METHOD__, [ $items ] );
if ( count( $items ) > 0 ) {
try {
if ( 'payex_checkout' === $order->get_payment_method() ) {
// Capture Checkout
$this->gateway->core->captureCheckout( $order->get_id(), $items );
} elseif ( 'payex_psp_invoice' === $order->get_payment_method() ) {
// Capture Invoice
$this->gateway->core->captureInvoice( $order->get_id(), $items );
} else {
// Capture Payments
$amount = array_sum( array_column( $items, OrderItemInterface::FIELD_AMOUNT ) ) / 100;
$vat_amount = array_sum( array_column( $items, OrderItemInterface::FIELD_VAT_AMOUNT ) ) / 100;
$this->gateway->core->capture( $order->get_id(), $amount, $vat_amount );
}
} catch ( \SwedbankPay\Core\Exception $e ) {
throw new \Exception( $e->getMessage() );
}
}
}
/**
* Get Payment Method Instance.
*
* @param \WC_Order $order
*
* @return \WC_Gateway_Swedbank_Pay_Checkout|\WP_Error
*/
private function get_payment_method( $order ) {
$payment_method = $order->get_payment_method();
// Get Payment Gateway
$gateways = WC()->payment_gateways()->payment_gateways();
/** @var \WC_Gateway_Swedbank_Pay_Cc $gateway */
if ( isset( $gateways[ $payment_method ] ) ) {
return $gateways[ $payment_method ];
}
return new \WP_Error( 'not_found', 'Payment method is not found.' );
}
/**
* Get items which should be captured instantly.
*
* @param \WC_Order $order
* @return array
*/
private function get_instant_capture_items( $order ) {
if ( ! is_array( $this->gateway->instant_capture ) || count( $this->gateway->instant_capture ) === 0 ) {
return array();
}
$items = array();
foreach ( $order->get_items() as $order_item ) {
/** @var \WC_Order_Item_Product $order_item */
/** @var \WC_Product $product */
$product = $order_item->get_product();
$price = $order->get_line_subtotal( $order_item, false, false );
$price_with_tax = $order->get_line_subtotal( $order_item, true, false );
$tax = $price_with_tax - $price;
$tax_percent = ( $tax > 0 ) ? round( 100 / ( $price / $tax ) ) : 0;
$qty = $order_item->get_quantity();
$image = wp_get_attachment_image_src( $order_item->get_product()->get_image_id(), 'full' );
if ( $image ) {
$image = array_shift( $image );
} else {
$image = wc_placeholder_img_src( 'full' );
}
if (null === parse_url( $image, PHP_URL_SCHEME ) &&
mb_substr( $image, 0, mb_strlen(WP_CONTENT_URL), 'UTF-8' ) === WP_CONTENT_URL
) {
$image = wp_guess_url() . $image;
}
// Get Product Class
$product_class = $product->get_meta( '_sb_product_class' );
if ( empty( $product_class ) ) {
$product_class = 'ProductGroup1';
}
// Get Product Sku
$product_reference = trim(
str_replace(
array( ' ', '.', ',' ),
'-',
$order_item->get_product()->get_sku()
)
);
if ( empty( $product_reference ) ) {
$product_reference = wp_generate_password( 12, false );
}
$product_name = trim( $order_item->get_name() );
if ( in_array(self::CAPTURE_PHYSICAL, $this->gateway->instant_capture, true ) &&
( ! self::wcs_is_subscription_product( $product ) &&
$product->needs_shipping() &&
! $product->is_downloadable() )
) {
$items[] = array(
// The field Reference must match the regular expression '[\\w-]*'
OrderItemInterface::FIELD_REFERENCE => $product_reference,
OrderItemInterface::FIELD_NAME => !empty($product_name) ? $product_name : '-',
OrderItemInterface::FIELD_TYPE => OrderItemInterface::TYPE_PRODUCT,
OrderItemInterface::FIELD_CLASS => $product_class,
OrderItemInterface::FIELD_ITEM_URL => $order_item->get_product()->get_permalink(),
OrderItemInterface::FIELD_IMAGE_URL => $image,
OrderItemInterface::FIELD_DESCRIPTION => $order_item->get_name(),
OrderItemInterface::FIELD_QTY => $qty,
OrderItemInterface::FIELD_QTY_UNIT => 'pcs',
OrderItemInterface::FIELD_UNITPRICE => round( $price_with_tax / $qty * 100 ),
OrderItemInterface::FIELD_VAT_PERCENT => round( $tax_percent * 100 ),
OrderItemInterface::FIELD_AMOUNT => round( $price_with_tax * 100 ),
OrderItemInterface::FIELD_VAT_AMOUNT => round( $tax * 100 ),
);
continue;
} elseif ( in_array(self::CAPTURE_VIRTUAL, $this->gateway->instant_capture, true ) &&
( ! self::wcs_is_subscription_product( $product ) &&
( $product->is_virtual() || $product->is_downloadable() ) )
) {
$items[] = array(
// The field Reference must match the regular expression '[\\w-]*'
OrderItemInterface::FIELD_REFERENCE => $product_reference,
OrderItemInterface::FIELD_NAME => !empty($product_name) ? $product_name : '-',
OrderItemInterface::FIELD_TYPE => OrderItemInterface::TYPE_PRODUCT,
OrderItemInterface::FIELD_CLASS => $product_class,
OrderItemInterface::FIELD_ITEM_URL => $order_item->get_product()->get_permalink(),
OrderItemInterface::FIELD_IMAGE_URL => $image,
OrderItemInterface::FIELD_DESCRIPTION => $order_item->get_name(),
OrderItemInterface::FIELD_QTY => $qty,
OrderItemInterface::FIELD_QTY_UNIT => 'pcs',
OrderItemInterface::FIELD_UNITPRICE => round( $price_with_tax / $qty * 100 ),
OrderItemInterface::FIELD_VAT_PERCENT => round( $tax_percent * 100 ),
OrderItemInterface::FIELD_AMOUNT => round( $price_with_tax * 100 ),
OrderItemInterface::FIELD_VAT_AMOUNT => round( $tax * 100 ),
);
continue;
} elseif ( in_array( self::CAPTURE_RECURRING, $this->gateway->instant_capture, true ) &&
self::wcs_is_subscription_product( $product )
) {
$items[] = array(
// The field Reference must match the regular expression '[\\w-]*'
OrderItemInterface::FIELD_REFERENCE => $product_reference,
OrderItemInterface::FIELD_NAME => !empty($product_name) ? $product_name : '-',
OrderItemInterface::FIELD_TYPE => OrderItemInterface::TYPE_PRODUCT,
OrderItemInterface::FIELD_CLASS => $product_class,
OrderItemInterface::FIELD_ITEM_URL => $order_item->get_product()->get_permalink(),
OrderItemInterface::FIELD_IMAGE_URL => $image,
OrderItemInterface::FIELD_DESCRIPTION => $order_item->get_name(),
OrderItemInterface::FIELD_QTY => $qty,
OrderItemInterface::FIELD_QTY_UNIT => 'pcs',
OrderItemInterface::FIELD_UNITPRICE => round( $price_with_tax / $qty * 100 ),
OrderItemInterface::FIELD_VAT_PERCENT => round( $tax_percent * 100 ),
OrderItemInterface::FIELD_AMOUNT => round( $price_with_tax * 100 ),
OrderItemInterface::FIELD_VAT_AMOUNT => round( $tax * 100 ),
);
continue;
}
}
// Add Shipping Total
if ( in_array(self::CAPTURE_PHYSICAL, $this->gateway->instant_capture ) ) {
if ( (float) $order->get_shipping_total() > 0 ) {
$shipping = (float) $order->get_shipping_total();
$tax = (float) $order->get_shipping_tax();
$shipping_with_tax = $shipping + $tax;
$tax_percent = ($tax > 0) ? round(100 / ($shipping / $tax)) : 0;
$shipping_method = trim( $order->get_shipping_method() );
$items[] = array(
OrderItemInterface::FIELD_REFERENCE => 'shipping',
OrderItemInterface::FIELD_NAME => !empty($shipping_method) ? $shipping_method : __(
'Shipping',
'woocommerce'
),
OrderItemInterface::FIELD_TYPE => OrderItemInterface::TYPE_SHIPPING,
OrderItemInterface::FIELD_CLASS => 'ProductGroup1',
OrderItemInterface::FIELD_QTY => 1,
OrderItemInterface::FIELD_QTY_UNIT => 'pcs',
OrderItemInterface::FIELD_UNITPRICE => round( $shipping_with_tax * 100 ),
OrderItemInterface::FIELD_VAT_PERCENT => round( $tax_percent * 100 ),
OrderItemInterface::FIELD_AMOUNT => round( $shipping_with_tax * 100 ),
OrderItemInterface::FIELD_VAT_AMOUNT => round( $tax * 100 ),
);
}
}
// Add fees
if ( in_array(self::CAPTURE_FEE, $this->gateway->instant_capture ) ) {
foreach ( $order->get_fees() as $order_fee ) {
/** @var \WC_Order_Item_Fee $order_fee */
$fee = (float) $order_fee->get_total();
$tax = (float) $order_fee->get_total_tax();
$fee_with_tax = $fee + $tax;
$tax_percent = ($tax > 0) ? round(100 / ($fee / $tax)) : 0;
$items[] = array(
OrderItemInterface::FIELD_REFERENCE => 'fee',
OrderItemInterface::FIELD_NAME => $order_fee->get_name(),
OrderItemInterface::FIELD_TYPE => OrderItemInterface::TYPE_OTHER,
OrderItemInterface::FIELD_CLASS => 'ProductGroup1',
OrderItemInterface::FIELD_QTY => 1,
OrderItemInterface::FIELD_QTY_UNIT => 'pcs',
OrderItemInterface::FIELD_UNITPRICE => round( $fee_with_tax * 100 ),
OrderItemInterface::FIELD_VAT_PERCENT => round( $tax_percent * 100 ),
OrderItemInterface::FIELD_AMOUNT => round( $fee_with_tax * 100 ),
OrderItemInterface::FIELD_VAT_AMOUNT => round( $tax * 100 ),
);
}
}
// Add discounts
if ( $order->get_total_discount( false ) > 0 ) {
$discount = abs( $order->get_total_discount( true ) );
$discount_with_tax = abs( $order->get_total_discount( false ) );
$tax = $discount_with_tax - $discount;
$tax_percent = ( $tax > 0 ) ? round( 100 / ( $discount / $tax ) ) : 0;
$items[] = array(
OrderItemInterface::FIELD_REFERENCE => 'discount',
OrderItemInterface::FIELD_NAME => __('Discount', 'swedbank-pay-woocommerce-payments'),
OrderItemInterface::FIELD_TYPE => OrderItemInterface::TYPE_DISCOUNT,
OrderItemInterface::FIELD_CLASS => 'ProductGroup1',
OrderItemInterface::FIELD_QTY => 1,
OrderItemInterface::FIELD_QTY_UNIT => 'pcs',
OrderItemInterface::FIELD_UNITPRICE => round(-100 * $discount_with_tax),
OrderItemInterface::FIELD_VAT_PERCENT => round(100 * $tax_percent),
OrderItemInterface::FIELD_AMOUNT => round(-100 * $discount_with_tax),
OrderItemInterface::FIELD_VAT_AMOUNT => round(-100 * $tax),
);
}
return $items;
}
/**
* Checks if there's Subscription Product.
*
* @param \WC_Product $product
*
* @return bool
*/
private static function wcs_is_subscription_product( $product ) {
return class_exists( '\\WC_Subscriptions_Product', false ) &&
\WC_Subscriptions_Product::is_subscription( $product );
}
}
new WC_Swedbank_Pay_Instant_Capture();