src/VindiWoocommerce.php
<?php
namespace VindiPaymentGateways;
use WC_Subscriptions_Product;
require_once plugin_dir_path(__FILE__) . '/utils/AbstractInstance.php';
/**
* @SuppressWarnings(PHPMD)
*/
class WcVindiPayment extends AbstractInstance
{
/**
* @var string
*/
const TEMPLATE_DIR = '/templates/';
/**
* @var string
*/
const WC_API_CALLBACK = 'vindi_webhook';
/**
* Instance of this class.
*
* @var object
*/
static $instance = null;
/**
* @var VindiPaymentGateway\VindiLanguages
*/
private $languages;
/**
* @var VindiPaymentGateway\VindiSettings
*/
private $settings;
/**
* @var VindiPaymentGateway\VindiControllers
*/
private $controllers;
/**
* @var VindiPaymentGateway\VindiWebhooks
*/
private $webhooks;
/**
* @var VindiPaymentGateway\FrontendFilesLoader
*/
private $frontend_files_loader;
/**
* @var VindiPaymentGateway\VindiSubscriptionStatusHandler
*/
private $subscription_status_handler;
/**
* @var VindiPaymentGateway\ProductsMetabox
*/
private $product_metabox;
/**
* @var VindiPaymentGateway\VindiProductStatus
*/
private $vindi_status_notifier;
/**
* @var VindiPaymentGateway\InterestPriceHandler
*/
private $interest_price_handler;
/**
* @var VindiWCSRenewalDisable
*/
private $wcs_renewal_disable;
public function __construct()
{
// Checks if Woocommerce is installed and activated
$this->init();
$this->languages = new VindiLanguages();
$this->settings = new VindiSettings();
$this->controllers = new VindiControllers($this->settings);
$this->webhooks = new VindiWebhooks($this->settings);
$this->frontend_files_loader = new FrontendFilesLoader();
$this->subscription_status_handler = new VindiSubscriptionStatusHandler($this->settings);
$this->vindi_status_notifier = new VindiProductStatus($this->settings);
$this->interest_price_handler = new InterestPriceHandler();
$this->product_metabox = new ProductsMetabox();
$this->wcs_renewal_disable = new VindiWCSRenewalDisable();
/**
* Add Gateway to Woocommerce
*/
add_filter('woocommerce_payment_gateways', array(&$this, 'add_gateway'));
/**
* Register webhook handler
*/
add_action('woocommerce_api_' . self::WC_API_CALLBACK, array(
$this->webhooks, 'handle'
));
add_filter('woocommerce_add_to_cart_validation', [$this, 'limit_same_subscriptions'], 10, 3);
add_filter('woocommerce_update_cart_validation', [$this, 'limit_duplicate_subscriptions_cart_update'], 10, 4);
add_filter('woocommerce_add_to_cart_validation', [$this, 'disallow_subscription_single_product_cart'], 10, 4);
add_filter('woocommerce_cart_needs_payment', [$this, 'filter_woocommerce_cart_needs_payment'], 10, 2);
add_action('wp_ajax_renew_pix_charge', [$this, 'renew_pix_charge']);
add_action('wp_ajax_nopriv_renew_pix_charge', [$this, 'renew_pix_charge']);
do_action('woocommerce_set_cart_cookies', true);
}
/**
* Init the plugin after plugins_loaded so environment variables are set.
*
* @since 1.0.0
* @version 1.0.0
*/
public function init()
{
// Helpers and Languages
require_once plugin_dir_path(__FILE__) . '/services/Api.php';
require_once plugin_dir_path(__FILE__) . '/services/Logger.php';
require_once plugin_dir_path(__FILE__) . '/i18n/Languages.php';
require_once plugin_dir_path(__FILE__) . '/services/VindiHelpers.php';
require_once plugin_dir_path(__FILE__) . '/services/Webhooks.php';
require_once plugin_dir_path(__FILE__) . '/services/WebhooksHelpers.php';
// Loading Abstract Method and Utils
require_once plugin_dir_path(__FILE__) . '/utils/PaymentGateway.php';
require_once plugin_dir_path(__FILE__) . '/utils/Conversions.php';
require_once plugin_dir_path(__FILE__) . '/utils/RedirectCheckout.php';
require_once plugin_dir_path(__FILE__) . '/utils/PostMeta.php';
require_once plugin_dir_path(__FILE__) . '/includes/admin/CouponsMetaBox.php';
require_once plugin_dir_path(__FILE__) . '/includes/admin/ProductsMetabox.php';
require_once plugin_dir_path(__FILE__) . '/includes/admin/Settings.php';
require_once plugin_dir_path(__FILE__) . '/includes/gateways/CreditPayment.php';
require_once plugin_dir_path(__FILE__) . '/includes/gateways/BankSlipPayment.php';
require_once plugin_dir_path(__FILE__) . '/includes/gateways/PixPayment.php';
require_once plugin_dir_path(__FILE__) . '/includes/gateways/BolepixPayment.php';
require_once plugin_dir_path(__FILE__) . '/utils/SubscriptionStatusHandler.php';
require_once plugin_dir_path(__FILE__) . '/utils/InterestPriceHandler.php';
require_once plugin_dir_path(__FILE__) . '/includes/admin/ProductStatus.php';
// Routes import
require_once plugin_dir_path(__FILE__) . '/routes/RoutesApi.php';
// Controllers
require_once plugin_dir_path(__FILE__) . '/controllers/index.php';
require_once plugin_dir_path(__FILE__) . '/utils/PaymentProcessor.php';
require_once plugin_dir_path(__FILE__) . '/utils/WCSRenewalDisable.php';
}
public static function getPath()
{
return plugin_dir_path(__FILE__);
}
public static function get_instance()
{
require_once plugin_dir_path(__FILE__) . '/utils/FrontendFilesLoader.php';
new FrontendFilesLoader();
if (VindiDependencies::check()) {
// If the single instance hasn't been set, set it now.
if (null == self::$instance) {
self::$instance = new self;
}
return self::$instance;
}
}
/**
* Add the gateway to WooCommerce.
* @param array $methods WooCommerce payment methods.
* @return array Payment methods with Vindi.
*/
public function add_gateway($methods)
{
$methods[] = new VindiCreditGateway($this->settings, $this->controllers);
$methods[] = new VindiBankSlipGateway($this->settings, $this->controllers);
$methods[] = new VindiPixGateway($this->settings, $this->controllers);
$methods[] = new VindiBolepixGateway($this->settings, $this->controllers);
return $methods;
}
/**
* Sobrescreve o método que remove os métodos de pagamento para assinaturas com trial
* @return bool
*/
public function filter_woocommerce_cart_needs_payment($needs_payment, $cart)
{
if (floatval($cart->total) == 0 || $this->cart_has_trial($cart)) {
return true;
}
return $needs_payment;
}
private function cart_has_trial($cart)
{
$items = $cart->get_cart();
foreach ($items as $item) {
if (class_exists('WC_Subscriptions_Product')
&& WC_Subscriptions_Product::get_trial_length($item['product_id']) > 0
) {
return true;
}
}
return false;
}
public function renew_pix_charge()
{
$order_id = filter_input(INPUT_POST, 'order_id', FILTER_SANITIZE_NUMBER_INT);
$charge_id = filter_input(INPUT_POST, 'charge_id', FILTER_SANITIZE_NUMBER_INT);
$subscription_id = filter_input(INPUT_POST, 'subscription_id', FILTER_SANITIZE_NUMBER_INT);
$order = wc_get_order($order_id);
$vindi_order = $order->get_meta('vindi_order', true);
if ($charge_id && $subscription_id) {
$routes = new VindiRoutes($this->settings);
$charge = $routes->renewCharge($charge_id);
if (isset($charge['status']) && isset($charge['last_transaction']['gateway_response_fields'])) {
$last_transaction = $charge['last_transaction']['gateway_response_fields'];
$subscription = $vindi_order[$subscription_id];
$bill = [
'id' => $subscription['bill']['id'],
'status' => $subscription['bill']['status'],
'charge_id' => $charge['id'],
'pix_expiration' => $last_transaction['max_days_to_keep_waiting_payment'],
'pix_code' => $last_transaction['qrcode_original_path'],
'pix_qr' => $last_transaction['qrcode_path'],
];
$vindi_order[$subscription_id]['bill'] = $bill;
$order->update_meta_data('vindi_order', $vindi_order);
$order->save();
}
}
}
public function limit_same_subscriptions($passed, $product_id, $quantity)
{
$product = wc_get_product($product_id);
if ($product->is_virtual()) {
return $passed;
}
if (WC_Subscriptions_Product::is_subscription($product_id)) {
$subscription_count = $this->get_subscription_count($product_id);
if ($subscription_count + $quantity > 1) {
wc_add_notice('Você só pode ter até 1 assinatura do mesmo produto no seu carrinho.', 'error');
return false;
}
}
return $passed;
}
public function get_subscription_count($product_id)
{
$cart = WC()->cart->get_cart();
$subscription_count = 0;
foreach ($cart as $cart_item) {
if ($cart_item['data']->get_id() === $product_id) {
$subscription_count += $cart_item['quantity'];
}
}
return $subscription_count;
}
public function limit_duplicate_subscriptions_cart_update($passed, $cart_item_key, $values, $quantity)
{
$product_id = $values['product_id'];
$product = wc_get_product($product_id);
if ($this->is_virtual_product($product)) {
return $passed;
}
if ($this->subscription_exceeds_limit($product_id, $quantity)) {
return false;
}
return $passed;
}
public function is_virtual_product($product)
{
return $product->is_virtual();
}
public function subscription_exceeds_limit($product_id, $quantity)
{
if (WC_Subscriptions_Product::is_subscription($product_id)) {
$subscription_count = $this->count_subscriptions_in_cart($product_id);
if ($subscription_count >= 1 && $quantity > 1) {
$message ='Você só pode ter até 1 assinatura do mesmo produto no seu carrinho.';
wc_add_notice(__($message, 'vindi-payment-gateway'), 'error');
return true;
}
}
return false;
}
public function count_subscriptions_in_cart($product_id)
{
$subscription_count = 0;
foreach (WC()->cart->get_cart() as $cart_item) {
if ($cart_item['data']->get_id() === $product_id) {
$subscription_count++;
}
}
return $subscription_count;
}
public function disallow_subscription_single_product_cart($passed, $product_id, $quantity)
{
$product = wc_get_product($product_id);
if ($product->is_virtual()) {
return $passed;
}
if ($this->is_cart_mixed_with_subscription($product_id)) {
wc_add_notice(__('Olá! Finalize a compra da assinatura adicionada
ao carrinho antes de adicionar outra assinatura ou produto.', 'vindi-payment-gateway'), 'error');
return false;
}
return $passed;
}
public function is_cart_mixed_with_subscription($product_id)
{
$cart = WC()->cart->get_cart();
if (empty($cart)) {
return false;
}
$is_subscription = false;
$new_product_subscription = WC_Subscriptions_Product::is_subscription($product_id);
foreach ($cart as $cart_item) {
if (WC_Subscriptions_Product::is_subscription($cart_item['data']->get_id())) {
$is_subscription = true;
break;
}
}
return $is_subscription !== $new_product_subscription;
}
}
add_action('plugins_loaded', array(WcVindiPayment::class, 'get_instance'));