bindConfig($config);
// phpcs:ignore PSR2.ControlStructures.ControlStructureSpacing.SpacingAfterOpenBrace
if (!empty($services = $config['services'] ?? null)) {
$this->registerServices($services);
}
}
/**
* @param float $totalAmount
* @param int $numberOfInstalments
*
* @return array
*/
public static function calculateInstalmentPlan(float $totalAmount, int $numberOfInstalments = 3): array
{
$totalAmount = $totalAmount * 100;
$modAmount = $totalAmount % $numberOfInstalments;
$downPayment = round(floatval((($totalAmount - $modAmount) / $numberOfInstalments / 100) + ($modAmount / 100)), 2);
$instalment = ($totalAmount - $modAmount) / $numberOfInstalments / 100;
return [
static::DOWN_PAYMENT => $downPayment,
static::INSTALMENT => $instalment,
];
}
/**
* Register service providers set in config
*
* @param $services
*/
protected function registerServices($services)
{
foreach ($services as $serviceClassname => $serviceConfig) {
$this->singleton(
$serviceClassname,
function ($container) use ($serviceClassname, $serviceConfig) {
$serviceInstance = new $serviceClassname();
if (method_exists($serviceInstance, 'bindConfig')) {
$serviceInstance->bindConfig($serviceConfig);
}
if (in_array(ServiceTrait::class, class_uses($serviceInstance))) {
$serviceInstance->setContainer($container);
$serviceInstance->init();
}
return $serviceInstance;
}
);
}
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* @param string $alias
*
* @return mixed
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function getService($alias)
{
return $this->make($alias);
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* Get the `view` service
*
* @return ViewService
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public static function getServiceView()
{
return static::getInstance()->getService(ViewService::class);
}
/**
* @param $config
*
* @throws Exception
*/
public static function initInstanceWithConfig($config)
{
if (is_null(static::$instance)) {
static::setInstance(new static($config));
}
// phpcs:ignore PSR2.ControlStructures.ControlStructureSpacing.SpacingAfterOpenBrace
if (!static::getInstance() instanceof static) {
throw new Exception('No plugin initialized.');
}
}
/**
* Initialize all needed things for this plugin: hooks, assignments...
*/
public function initPlugin(): void
{
add_action('init', [$this, 'checkWooCommerceExistence']);
if (!class_exists('WooCommerce')) {
return;
}
// Load text domain
add_action('init', [$this, 'tamaraLoadTextDomain']);
// Register new Tamara custom statuses
add_action('init', [$this, 'registerTamaraCustomOrderStatuses']);
// For Admin
add_action('admin_enqueue_scripts', [$this, 'enqueueAdminSettingScripts']);
// Handle refund when a refund is created
add_action('woocommerce_create_refund', [$this, 'tamaraRefundPayment'], 10, 2);
// Add Tamara custom statuses to wc order status list
add_filter('wc_order_statuses', [$this, 'addTamaraCustomOrderStatuses']);
// Add note on Refund
add_action('woocommerce_order_item_add_action_buttons', [$this, 'addRefundNote']);
add_filter('woocommerce_rest_prepare_shop_order_object', [$this, 'updateTamaraCheckoutDataToOrder'], 10, 3);
add_action('init', [$this, 'addCustomRewriteRules']);
add_action('init', [$this, 'addTamaraAuthoriseFailedMessage'], 1000);
add_action('parse_request', [$this, 'handleTamaraApi'], 1000);
add_action('wp_enqueue_scripts', [$this, 'enqueueScripts']);
// add_filter('woocommerce_checkout_fields', [$this, 'adjustBillingPhoneDescription']);
add_filter('woocommerce_payment_gateways', [$this, 'registerTamaraPaymentGateway']);
add_filter('woocommerce_available_payment_gateways', [$this, 'adjustTamaraPaymentTypesOnCheckout'], 9998, 1);
add_action('woocommerce_update_options_checkout_'.static::TAMARA_GATEWAY_ID, [$this, 'onSaveSettings'], 10, 1);
add_action($this->getTamaraPopupWidgetPosition(), [$this, 'showTamaraProductPopupWidget']);
add_action($this->getTamaraCartPopupWidgetPosition(), [$this, 'showTamaraCartProductPopupWidget']);
add_action('wp_ajax_tamara_perform_cron', [$this, 'performCron']);
add_action('wp_ajax_tamara-authorise', [$this, 'tamaraAuthoriseHandler']);
add_action('wp_ajax_nopriv_tamara-authorise', [$this, 'tamaraAuthoriseHandler']);
add_action('wp_head', [$this, 'tamaraCheckoutParams']);
add_action('woocommerce_checkout_update_order_review', [$this, 'getUpdatedPhoneNumberOnCheckout']);
if ($this->isCronjobEnabled() && rand(0,20) === 1) {
add_action('admin_footer', [$this, 'addCronJobTriggerScript']);
}
add_shortcode('tamara_show_popup', [$this, 'tamaraProductPopupWidget']);
add_shortcode('tamara_show_cart_popup', [$this, 'tamaraCartPopupWidget']);
add_shortcode('tamara_authorise_order', [$this, 'doAuthoriseOrderAction']);
// For Rest Api
add_filter('rest_pre_dispatch', [$this, 'populateRestApiRequest'], 1, 3);
// Update Settings Url in admin for Pay By Instalments
add_action('admin_head', [$this, 'updatePayByInstalmentSettingUrl']);
add_filter('woocommerce_billing_fields', [$this, 'forceRequireBillingPhone'], 1001, 2);
add_action('wp_ajax_tamara-get-instalment-plan', [$this, 'getInstalmentPlanAccordingToProductVariation']);
add_action('wp_ajax_nopriv_tamara-get-instalment-plan', [$this, 'getInstalmentPlanAccordingToProductVariation']);
add_action('wp_ajax_update-tamara-checkout-params', [$this, 'updateTamaraCheckoutParams']);
add_action('wp_ajax_nopriv_update-tamara-checkout-params', [$this, 'updateTamaraCheckoutParams']);
add_action('get_header', [$this, 'overrideWcClearCart'], 8);
add_action('wp_loaded', [$this, 'cancelOrder'], 21);
// Add Tamara Note on Order Received page
add_filter('woocommerce_thankyou_order_received_text', [$this, 'tamaraOrderReceivedText'], 10, 2);
}
/**
* Populate Rest Api Request
*
* @param mixed $result
* @param \WP_REST_Server $restApiServer
* @param \WP_REST_Request $restApiRequest
*
* @return mixed
*/
public function populateRestApiRequest($result, $restApiServer, $restApiRequest)
{
$this->setRestApiRequest($restApiRequest);
return $result;
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* Add Tamara Note after successful payment
*
* @param string $str
* @param \Automattic\WooCommerce\Admin\Overrides\Order $order
*
* @return string
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function tamaraOrderReceivedText($str, $order)
{
if (empty($order)) {
return $str;
}
$payment_method = $order->get_payment_method();
if (!empty($payment_method) && $this->isTamaraGateway($payment_method)) {
return $str.$this->getServiceView()->render('views/woocommerce/checkout/tamara-order-received-button',
[
'textDomain' => $this->textDomain,
]);
}
return $str;
}
/**
* Handle Tamara log message
*
* @param string $message
*
*/
public function logMessage($message)
{
if ($this->isCustomLogMessageEnabled()) {
if (is_array($message)) {
$message = json_encode($message);
}
$fileHandle = fopen($this->logMessageFilePath(), "a");
fwrite($fileHandle, "[".gmdate('Y-m-d h:i:s')."] ".$message."\n");
fclose($fileHandle);
}
}
/**
* Update order status and add order note wrapper
*
* @param WC_Order $wcOrder
* @param string $orderNote
* @param string $newOrderStatus
* @param string $updateOrderStatusNote
*
*/
public function updateOrderStatusAndAddOrderNote($wcOrder, $orderNote, $newOrderStatus, $updateOrderStatusNote)
{
if ($wcOrder) {
$this->logMessage(sprintf("Tamara - Prepare to Update Order Status - Order ID: %s, Order Note: %s, new order status: %s, order status note: %s", $wcOrder->get_id(), $orderNote, $newOrderStatus, $updateOrderStatusNote));
try {
$wcOrder->add_order_note($orderNote);
$wcOrder->update_status($newOrderStatus, $updateOrderStatusNote, true);
} catch (Exception $exception) {
$this->logMessage(sprintf("Tamara - Failed to Update Order Status - Order ID: %s, Order Note: %s, new order status: %s, order status note: %s. Error Message: %s", $wcOrder->get_id(), $orderNote, $newOrderStatus, $updateOrderStatusNote, $exception->getMessage()));
}
}
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* Get WC Tamara Gateway Pay By Later class
*
* @return WCTamaraGateway
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function getWCTamaraGatewayService()
{
return $this->getService(WCTamaraGateway::class);
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* Get WC Tamara Gateway Pay Now class
*
* @return WCTamaraGatewayPayNow
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function getWCTamaraGatewayPayNowService()
{
return $this->getService(WCTamaraGatewayPayNow::class);
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* Get WC Tamara Gateway Pay By Instalments class
*
* @return WCTamaraGateway
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function getWCTamaraGatewayPayByInstalmentsService()
{
return $this->getService(WCTamaraGatewayPayByInstalments::class);
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* Get WC Tamara Gateway Pay In X class
*
* @param $instalment
*
* @return WCTamaraGateway
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function getWCTamaraGatewayPayInXService($instalment)
{
$instalmentService = 'Tamara\Wp\Plugin\Services\WCTamaraGatewayPayIn'.$instalment;
return $this->getService($instalmentService);
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* Get WC Tamara Gateway Single Checkout class
*
* @return WCTamaraGateway
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function getWCTamaraGatewayCheckoutService()
{
return $this->getService(WCTamaraGatewayCheckout::class);
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* Get WC Tamara Gateway Pay Next Month class
*
* @return WCTamaraGateway
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function getWCTamaraGatewayPayNextMonthService()
{
return $this->getService(WCTamaraGatewayPayNextMonth::class);
}
/**
* Get Tamara Popup Widget postion
*/
public function getTamaraPopupWidgetPosition()
{
return $this->getWCTamaraGatewayOptions()['popup_widget_position'] ?? 'woocommerce_before_add_to_cart_form';
}
/**
* Get Tamara Cart Popup Widget postion
*/
public function getTamaraCartPopupWidgetPosition()
{
return $this->getWCTamaraGatewayOptions()['cart_popup_widget_position'] ?? 'woocommerce_proceed_to_checkout';
}
/**
* Check if Payment type Pay By Later is enabled in admin settings
*/
public function isPayByLaterEnabled()
{
return 'yes' === ($this->getWCTamaraGatewayOptions()['pay_by_later_enabled'] ?? 'no');
}
/**
* Check if Payment type Pay Now is enabled in admin settings
*/
public function isPayNowEnabled()
{
return 'yes' === ($this->getWCTamaraGatewayOptions()['pay_now_enabled'] ?? 'no');
}
/**
* Check if Payment type Pay By Instalments is enabled in admin settings
*/
public function isPayByInstalmentsEnabled()
{
return 'yes' === ($this->getWCTamaraGatewayOptions()['pay_by_instalments_enabled'] ?? 'no');
}
/**
* Check if a specific Pay In X payment type is enabled in admin settings
*
* @param $instalment
* @param $countryCode
*
* @return bool
*/
public function isPayInXEnabled($instalment, $countryCode)
{
return 'yes' === ($this->getWCTamaraGatewayOptions()['pay_in_'.$instalment.'_'.$countryCode] ?? 'no');
}
/**
* Check if Tamara Gateway is enabled in admin settings
*/
public function isTamaraGatewayEnabled()
{
return 'yes' === ($this->getWCTamaraGatewayOptions()['enabled'] ?? 'no');
}
/**
* Check if Tamara custom log message is enabled in admin settings
*/
public function isCustomLogMessageEnabled()
{
return 'yes' === ($this->getWCTamaraGatewayOptions()['custom_log_message_enabled'] ?? 'no');
}
/**
* Check if Tamara force billing phone option is enabled in admin settings
*/
public function isForceBillingPhoneEnabled()
{
return 'yes' === ($this->getWCTamaraGatewayOptions()['force_billing_phone'] ?? 'no');
}
/**
* Check if Cronjob is enabled in admin settings
*/
public function isCronjobEnabled()
{
return 'yes' === ($this->getWCTamaraGatewayOptions()['crobjob_enabled'] ?? 'no');
}
/**
* Check if Tamara Pay Later popup widget is enabled in admin settings
*/
public function isPayLaterPDPEnabled()
{
return 'yes' === ($this->getWCTamaraGatewayOptions()['pay_later_popup_widget_enabled'] ?? 'no');
}
/**
* Check if Always Show Popup Widget is enabled in admin settings
*/
public function isAlwaysShowWidgetPopupEnabled()
{
return 'yes' === ($this->getWCTamaraGatewayOptions()['always_show_popup_widget_enabled'] ?? 'no');
}
/**
* Check if Showing Popup Widget is disabled in admin settings
*/
public function isWidgetPopupDisabled()
{
return 'yes' === ($this->getWCTamaraGatewayOptions()['popup_widget_disabled'] ?? 'no');
}
/**
* Check if Showing Popup Widget in Cart page is disabled in admin settings
*/
public function isCartWidgetPopupDisabled()
{
return 'yes' === ($this->getWCTamaraGatewayOptions()['cart_popup_widget_disabled'] ?? 'no');
}
/**
* Check if Credit Precheck is enabled in admin settings
*/
public function isCreditPrecheckEnabled()
{
return 'yes' === ($this->getWCTamaraGatewayOptions()['credit_precheck_enabled'] ?? 'no');
}
/**
* Get WC Tamara Gateway options
*/
public function getWCTamaraGatewayOptions()
{
return get_option($this->getWCTamaraGatewayOptionKey(), null);
}
/**
* Get WC Tamara Gateway options
*/
public function getWCTamaraGatewayOptionKey()
{
return 'woocommerce_'.static::TAMARA_GATEWAY_ID.'_settings';
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* Get on save settings method from WC Tamara Gateway
*
* @param $settings
*
* @return void
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function onSaveSettings($settings)
{
return $this->getWCTamaraGatewayService()->onSaveSettings($settings);
}
/**
* Tamara Log File Path
*/
public function logMessageFilePath()
{
return (defined('UPLOADS') ? UPLOADS : (WP_CONTENT_DIR.'/uploads/').static::MESSAGE_LOG_FILE_NAME);
}
/**
* Tamara Log File Url
*/
public function logMessageFileUrl()
{
return wp_upload_dir()['baseurl'].'/'.static::MESSAGE_LOG_FILE_NAME;
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* Force pending capture payments within 180 days to be captured
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function forceCaptureTamaraOrder()
{
$tamaraCapturePaymentStatus = $this->getWCTamaraGatewayService()->tamaraStatus['payment_capture'] ?? 'wc-completed';
$customerOrders = [
'fields' => 'ids',
'post_type' => 'shop_order',
'post_status' => $tamaraCapturePaymentStatus,
'date_query' => [
'before' => date('Y-m-d', strtotime('-14 days')),
'after' => date('Y-m-d', strtotime('-180 days')),
'inclusive' => true,
],
'meta_query' => [
'relation' => 'AND',
[
'key' => '_tamara_order_id',
'compare' => 'EXISTS',
],
[
'key' => '_tamara_capture_id',
'compare' => 'NOT EXISTS',
],
[
'key' => '_tamara_force_capture_checked',
'compare' => 'NOT EXISTS',
],
],
];
$customerOrdersQuery = new \WP_Query($customerOrders);
$wcOrderIds = $customerOrdersQuery->posts;
foreach ($wcOrderIds as $wcOrderId) {
update_post_meta($wcOrderId, '_tamara_force_capture_checked', 1);
if (static::TAMARA_FULLY_CAPTURED_STATUS === TamaraCheckout::getInstance()->getTamaraOrderStatus($wcOrderId)) {
$wcOrder = wc_get_order($wcOrderId);
$wcOrder->add_order_note(__('Tamara - The payment has been captured successfully.', $this->textDomain));
$tamaraCaptureId = $this->getWCTamaraGatewayService()->getTamaraCaptureId($wcOrderId);
update_post_meta($wcOrderId, '_tamara_capture_id', $tamaraCaptureId);
return true;
} else {
$this->getWCTamaraGatewayService()->captureWcOrder($wcOrderId);
}
}
}
/**
* Force pending authorise payments within 180 days to be authorised
*
*/
public function forceAuthoriseTamaraOrder()
{
$toAuthoriseStatus = 'wc-pending';
$customerOrders = [
'fields' => 'ids',
'post_type' => 'shop_order',
'post_status' => $toAuthoriseStatus,
'date_query' => [
'before' => date('Y-m-d', strtotime('-3 hours')),
'after' => date('Y-m-d', strtotime('-180 days')),
'inclusive' => true,
],
'meta_query' => [
'relation' => 'AND',
[
'key' => 'tamara_checkout_session_id',
'compare' => 'EXISTS',
],
[
'key' => '_tamara_order_id',
'compare' => 'NOT EXISTS',
],
[
'key' => '_tamara_force_authorise_checked',
'compare' => 'NOT EXISTS',
],
],
];
$customerOrdersQuery = new \WP_Query($customerOrders);
$wcOrderIds = $customerOrdersQuery->posts;
foreach ($wcOrderIds as $wcOrderId) {
update_post_meta($wcOrderId, '_tamara_force_authorise_checked', 1);
if (!$this->isOrderAuthorised($wcOrderId)) {
$this->authoriseOrder($wcOrderId);
}
}
}
/**
* Add Tamara Refund Note
*
* @param WC_Order $order
*/
public function addRefundNote($order)
{
if ($this->isTamaraGateway($order->get_payment_method())) {
echo '
'.__('This order is paid via Tamara Pay Later.', $this->textDomain);
echo '
'.''.__('You need to refund the full shipping amount.',
$this->textDomain).'';
}
}
/**
* Register Tamara new statuses
*/
public function registerTamaraCustomOrderStatuses()
{
register_post_status('wc-tamara-p-canceled', [
'label' => _x('Tamara Payment Cancelled', 'Order status', $this->textDomain),
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('Tamara Payment Cancelled (%s)',
'Tamara Payment Cancelled (%s)', $this->textDomain),
]);
register_post_status('wc-tamara-p-failed', [
'label' => _x('Tamara Payment Failed', 'Order status', $this->textDomain),
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('Tamara Payment Failed (%s)',
'Tamara Payment Failed (%s)', $this->textDomain),
]);
register_post_status('wc-tamara-c-failed', [
'label' => _x('Tamara Capture Failed', 'Order status', $this->textDomain),
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('Tamara Capture Failed (%s)',
'Tamara Capture Failed (%s)', $this->textDomain),
]);
register_post_status('wc-tamara-a-done', [
'label' => _x('Tamara Authorise Success', 'Order status', $this->textDomain),
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('Tamara Authorise Success (%s)',
'Tamara Authorise Success (%s)', $this->textDomain),
]);
register_post_status('wc-tamara-a-failed', [
'label' => _x('Tamara Authorise Failed', 'Order status', $this->textDomain),
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('Tamara Authorise Failed (%s)',
'Tamara Authorise Failed (%s)', $this->textDomain),
]);
register_post_status('wc-tamara-o-canceled', [
'label' => _x('Tamara Order Cancelled', 'Order status', $this->textDomain),
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('Tamara Order Cancelled (%s)',
'Tamara Order Cancelled (%s)', $this->textDomain),
]);
register_post_status('wc-tamara-p-capture', [
'label' => _x('Tamara Payment Capture', 'Order status', $this->textDomain),
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('Tamara Payment Capture (%s)',
'Tamara Payment Capture (%s)', $this->textDomain),
]);
}
/**
* Add Tamara Statuses to the list of WC Order statuses
*
* @param array $order_statuses
*
* @return array $order_statuses
*/
public function addTamaraCustomOrderStatuses($order_statuses)
{
$order_statuses['wc-tamara-p-canceled'] = _x('Tamara Payment Cancelled', 'Order status',
$this->textDomain);
$order_statuses['wc-tamara-p-failed'] = _x('Tamara Payment Failed', 'Order status',
$this->textDomain);
$order_statuses['wc-tamara-c-failed'] = _x('Tamara Capture Failed', 'Order status',
$this->textDomain);
$order_statuses['wc-tamara-a-done'] = _x('Tamara Authorise Done', 'Order status',
$this->textDomain);
$order_statuses['wc-tamara-a-failed'] = _x('Tamara Authorise Failed', 'Order status',
$this->textDomain);
$order_statuses['wc-tamara-o-canceled'] = _x('Tamara Order Cancelled', 'Order status',
$this->textDomain);
$order_statuses['wc-tamara-p-capture'] = _x('Tamara Payment Capture', 'Order status',
$this->textDomain);
return $order_statuses;
}
/**
* Localize the plugin
*/
public function tamaraLoadTextDomain()
{
$locale = determine_locale();
$mofile = $locale.'.mo';
load_textdomain($this->textDomain, $this->basePath.'/languages/'.$this->textDomain.'-'.$mofile);
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* Handle process for Tamara endpoint slug returned
*
* @param WP $wp
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function handleTamaraApi($wp)
{
$pagename = $wp->query_vars['pagename'] ?? null;
$tamaraPageSlugs = [
WCTamaraGateway::IPN_SLUG,
WCTamaraGateway::WEBHOOK_SLUG,
WCTamaraGateway::PAYMENT_SUCCESS_SLUG,
WCTamaraGateway::PAYMENT_CANCEL_SLUG,
WCTamaraGateway::PAYMENT_FAIL_SLUG,
];
if (in_array($pagename, $tamaraPageSlugs)) {
$this->logMessage(sprintf('Pagename: %s', $pagename));
}
if (WCTamaraGateway::IPN_SLUG === $pagename) {
/** @var TamaraNotificationService $tamara_notification_service */
$tamara_notification_service = $this->getService(TamaraNotificationService::class);
$tamara_notification_service->handleIpnRequest();
exit;
} // Handle webhook
elseif (WCTamaraGateway::WEBHOOK_SLUG === $pagename) {
/** @var TamaraNotificationService $tamara_notification_service */
$tamara_notification_service = $this->getService(TamaraNotificationService::class);
$tamara_notification_service->handleWebhook();
exit;
} elseif (WCTamaraGateway::PAYMENT_CANCEL_SLUG === $pagename) {
$this->handleTamaraCancelUrl();
do_action('after_tamara_cancel');
exit;
} elseif (WCTamaraGateway::PAYMENT_FAIL_SLUG === $pagename) {
$this->handleTamaraFailureUrl();
do_action('after_tamara_failure');
exit;
}
}
/**
* Detect if an order is authorised or not
*
* @param $wcOrderId
*
* @return bool
*/
public function isOrderAuthorised($wcOrderId)
{
return !!get_post_meta($wcOrderId, 'tamara_authorized', true);
}
/**
* Prevent an order is cancelled from FE if its payment has been authorised from Tamara
*
* @param WC_Order $wcOrder
* @param int $wcOrderId
*
*/
protected function preventOrderCancelAction($wcOrder, $wcOrderId)
{
$orderNote = 'This order can not be cancelled because the payment was authorised from Tamara. Order ID: '.$wcOrderId;
$wcOrder->add_order_note($orderNote);
$this->logMessage($orderNote);
wp_redirect(wc_get_cart_url());
}
/**
* Add needed params for Tamara checkout success url
*/
public function tamaraCheckoutParams()
{
$storeCurrency = get_woocommerce_currency();
$publicKey = $this->getWCTamaraGatewayService()->getPublicKey() ?? '';
$siteLocale = substr(get_locale(), 0, 2) ?? "en";
$countryCode = $this->getWCTamaraGatewayService()->getCurrentCountryCode();
?>
getWCTamaraGatewayService()->isLiveMode()) { ?>
getTamaraOrderByWcOrderId($wcOrderId);
if ($tamaraOrder && 'approved' === $tamaraOrder->getStatus()) {
return true;
}
return false;
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* Get Tamara order id by WC order Id
*
* @param int $wcOrderId
*
* @return string
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
protected function getTamaraOrderId($wcOrderId)
{
$tamaraOrder = $this->getTamaraOrderByWcOrderId($wcOrderId);
if ($tamaraOrder) {
return $tamaraOrder->getOrderId();
}
return null;
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* Get Tamara order by WC order Id
*
* @param int $wcOrderId
*
* @return null|Dependencies\Tamara\Response\Order\GetOrderByReferenceIdResponse
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function getTamaraOrderByWcOrderId($wcOrderId)
{
$tamaraClient = $this->getWCTamaraGatewayService()->tamaraClient;
try {
$tamaraOrderResponse = $tamaraClient->getOrderByReferenceId(new GetOrderByReferenceIdRequest($wcOrderId));
$this->logMessage(sprintf("Tamara Get Order by Reference ID Response: %s", print_r($tamaraOrderResponse, true)));
if ($tamaraOrderResponse->isSuccess()) {
return $tamaraOrderResponse;
}
} catch (Exception $tamaraOrderResponseException) {
$this->logMessage(
sprintf(
"Tamara Get Order by Reference ID Failed Response.\nError message: ' %s'.\nTrace: %s",
$tamaraOrderResponseException->getMessage(),
$tamaraOrderResponseException->getTraceAsString()
)
);
}
return null;
}
/**
* If the order is not authorised from Tamara, do it on the Tamara Success Url returned
*/
public function tamaraAuthoriseHandler()
{
$wcOrderId = filter_input(INPUT_POST, 'wcOrderId', FILTER_SANITIZE_NUMBER_INT);
$authoriseSuccessResponse = [
'message' => 'authorise_success',
];
if ($this->isOrderAuthorised($wcOrderId) || $this->authoriseOrder($wcOrderId)) {
wp_send_json($authoriseSuccessResponse);
}
wp_send_json(
[
'message' => 'authorise_failed',
]
);
}
/**
* Do authorise order with order id from payload returning from Tamara
*/
public function doAuthoriseOrderAction()
{
$wcOrderId = filter_input(INPUT_GET, 'wcOrderId', FILTER_SANITIZE_NUMBER_INT);
$wcOrderId || $wcOrderId = filter_input(INPUT_POST, 'wcOrderId', FILTER_SANITIZE_NUMBER_INT);
$this->authoriseOrder($wcOrderId);
}
/**
* @param $wcOrderId
*
* @return bool true if an authorise action is made successfully, false if failed
* or already authorised
*/
public function authoriseOrder($wcOrderId)
{
$wcOrder = wc_get_order($wcOrderId);
try {
if (!$this->isOrderAuthorised($wcOrderId) && $wcOrder && ($this->isOrderTamaraApproved($wcOrderId))) {
$tamaraOrderId = $this->getTamaraOrderId($wcOrderId);
/** @var TamaraNotificationService $tamaraNotificationService */
$tamaraNotificationService = $this->getService(TamaraNotificationService::class);
$tamaraNotificationService->authoriseOrder($wcOrderId, $tamaraOrderId);
if ($this->isOrderAuthorised($wcOrderId)) {
return true;
}
}
} catch (Exception $exception) {
}
return false;
}
/**
* Add Tamara Authorise Failed Message on cart page
*/
public function addTamaraAuthoriseFailedMessage()
{
$tamaraAuthoriseParam = filter_input(INPUT_GET, 'tamara_authorise');
if ('failed' === $tamaraAuthoriseParam && !static::isRestRequest()) {
if (function_exists('wc_add_notice')) {
wc_add_notice(__('We are unable to authorise your payment from Tamara. Please contact us if you need assistance.', $this->textDomain), 'error');
}
}
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* Do needed things on Tamara Cancel Url returned
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function handleTamaraCancelUrl()
{
$orderId = filter_input(INPUT_GET, 'wcOrderId', FILTER_SANITIZE_NUMBER_INT);
$wcOrder = wc_get_order($orderId);
if ($this->isOrderAuthorised($orderId)) {
$this->preventOrderCancelAction($wcOrder, $orderId);
} elseif (!empty($orderId)) {
$newOrderStatus = $this->getWCTamaraGatewayService()->tamaraStatus['payment_cancelled'];
$orderNote = 'The payment for this order has been cancelled from Tamara.';
$this->updateOrderStatusAndAddOrderNote($wcOrder, $orderNote, $newOrderStatus, '');
$cancelUrlFromTamara = add_query_arg(
[
'tamara_custom_status' => 'tamara-p-canceled',
'redirect_from' => 'tamara',
'cancel_order' => 'true',
'order' => $wcOrder->get_order_key(),
'order_id' => $orderId,
'_wpnonce' => wp_create_nonce('woocommerce-cancel_order'),
],
$wcOrder->get_cancel_order_url_raw()
);
wp_redirect($cancelUrlFromTamara);
}
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* Do needed things on Tamara Failure Url returned
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function handleTamaraFailureUrl()
{
$orderId = filter_input(INPUT_GET, 'wcOrderId', FILTER_SANITIZE_NUMBER_INT);
$wcOrder = wc_get_order($orderId);
if ($this->isOrderAuthorised($orderId)) {
$this->preventOrderCancelAction($wcOrder, $orderId);
} elseif (!empty($orderId)) {
$newOrderStatus = $this->getWCTamaraGatewayService()->tamaraStatus['payment_failed'];
$orderNote = 'The payment for this order has been declined from Tamara.';
$this->updateOrderStatusAndAddOrderNote($wcOrder, $orderNote, $newOrderStatus, '');
$failureUrlFromTamara = add_query_arg(
[
'tamara_custom_status' => 'tamara-p-failed',
'redirect_from' => 'tamara',
'cancel_order' => 'true',
'order' => $wcOrder->get_order_key(),
'order_id' => $orderId,
'_wpnonce' => wp_create_nonce('woocommerce-cancel_order'),
],
$wcOrder->get_cancel_order_url_raw()
);
wp_redirect($failureUrlFromTamara);
}
}
/**
* Do some needed things when activate plugin
*/
public function activatePlugin()
{
if (!class_exists('WooCommerce')) {
die(sprintf(__('Plugin `%s` needs Woocommerce to be activated', $this->textDomain),
'Tamara Checkout'));
}
}
/**
* @noinspection PhpUnusedDeclarationInspection
*/
public function deactivatePlugin()
{
// The problem with calling flush_rewrite_rules() is that the rules instantly get regenerated, while your plugin's hooks are still active.
delete_option('rewrite_rules');
}
/**
* Add rewrite rule for Tamara IPN and Webhook response page
*/
public function addCustomRewriteRules()
{
add_rewrite_rule(WCTamaraGateway::IPN_SLUG.'/?$', 'index.php?pagename='.WCTamaraGateway::IPN_SLUG, 'top');
add_rewrite_rule(WCTamaraGateway::WEBHOOK_SLUG.'/?$', 'index.php?pagename='.WCTamaraGateway::WEBHOOK_SLUG, 'top');
add_rewrite_rule(WCTamaraGateway::PAYMENT_SUCCESS_SLUG.'/?$', 'index.php?pagename='.WCTamaraGateway::PAYMENT_SUCCESS_SLUG, 'top');
add_rewrite_rule(WCTamaraGateway::PAYMENT_CANCEL_SLUG.'/?$', 'index.php?pagename='.WCTamaraGateway::PAYMENT_CANCEL_SLUG, 'top');
add_rewrite_rule(WCTamaraGateway::PAYMENT_FAIL_SLUG.'/?$', 'index.php?pagename='.WCTamaraGateway::PAYMENT_FAIL_SLUG, 'top');
}
/**
* Run this method under the "init" action
*/
public function checkWooCommerceExistence()
{
if (class_exists('WooCommerce')) {
// Add "Settings" link when the plugin is active
add_filter('plugin_action_links_tamara-checkout/tamara-checkout.php', [$this, 'addSettingsLinks']);
} else {
require_once(ABSPATH.'wp-admin/includes/plugin.php');
// Throw a notice if WooCommerce is NOT active
deactivate_plugins(plugin_basename($this->pluginFilename));
add_action('admin_notices', [$this, 'noticeNonWooCommerce']);
}
}
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/**
* Add more links to plugin settings
*
* @param $pluginLinks
*
* @return array
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function addSettingsLinks($pluginLinks)
{
$pluginLinks[] = ''.esc_html__('Settings',
$this->textDomain).'';
return $pluginLinks;
}
/**
* Throw a notice if WooCommerce is NOT active
*/
public function noticeNonWooCommerce()
{
$class = 'notice notice-warning';
$message = sprintf(__('Plugin `%s` deactivated because WooCommerce is not active. Please activate WooCommerce first.',
$this->textDomain), 'Tamara Checkout');
printf('
%2$s