shop.balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

squareup.php (21702B)


      1 <?php
      2 
      3 class ModelExtensionPaymentSquareup extends Model {
      4     const RECURRING_ACTIVE = 1;
      5     const RECURRING_INACTIVE = 2;
      6     const RECURRING_CANCELLED = 3;
      7     const RECURRING_SUSPENDED = 4;
      8     const RECURRING_EXPIRED = 5;
      9     const RECURRING_PENDING = 6;
     10     
     11     const TRANSACTION_DATE_ADDED = 0;
     12     const TRANSACTION_PAYMENT = 1;
     13     const TRANSACTION_OUTSTANDING_PAYMENT = 2;
     14     const TRANSACTION_SKIPPED = 3;
     15     const TRANSACTION_FAILED = 4;
     16     const TRANSACTION_CANCELLED = 5;
     17     const TRANSACTION_SUSPENDED = 6;
     18     const TRANSACTION_SUSPENDED_FAILED = 7;
     19     const TRANSACTION_OUTSTANDING_FAILED = 8;
     20     const TRANSACTION_EXPIRED = 9;
     21 
     22     public function getMethod($address, $total) {
     23         $geo_zone_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "zone_to_geo_zone WHERE geo_zone_id = '" . (int)$this->config->get('payment_squareup_geo_zone_id') . "' AND country_id = '" . (int)$address['country_id'] . "' AND (zone_id = '" . (int)$address['zone_id'] . "' OR zone_id = '0')");
     24 
     25         $squareup_display_name = $this->config->get('payment_squareup_display_name');
     26 
     27         $this->load->language('extension/payment/squareup');
     28 
     29         if (!empty($squareup_display_name[$this->config->get('config_language_id')])) {
     30             $title = $squareup_display_name[$this->config->get('config_language_id')];
     31         } else {
     32             $title = $this->language->get('text_default_squareup_name');
     33         }
     34 
     35         $status = true;
     36 
     37         $minimum_total = (float)$this->config->get('payment_squareup_total');
     38 
     39         $squareup_geo_zone_id = $this->config->get('payment_squareup_geo_zone_id');
     40 
     41         if ($minimum_total > 0 && $minimum_total > $total) {
     42             $status = false;
     43         } else if (empty($squareup_geo_zone_id)) {
     44             $status = true;
     45         } else if ($geo_zone_query->num_rows == 0) {
     46             $status = false;
     47         }
     48 
     49         $method_data = array();
     50 
     51         if ($status) {
     52             $method_data = array(
     53                 'code'      => 'squareup',
     54                 'title'     => $title,
     55                 'terms'     => '',
     56                 'sort_order' => (int)$this->config->get('payment_squareup_sort_order')
     57             );
     58         }
     59 
     60         return $method_data;
     61     }
     62 
     63     public function addTransaction($transaction, $merchant_id, $address, $order_id, $user_agent, $ip) {
     64         $amount = $this->squareup->standardDenomination($transaction['tenders'][0]['amount_money']['amount'], $transaction['tenders'][0]['amount_money']['currency']);
     65 
     66         $this->db->query("INSERT INTO `" . DB_PREFIX . "squareup_transaction` SET transaction_id='" . $this->db->escape($transaction['id']) . "', merchant_id='" . $this->db->escape($merchant_id) . "', location_id='" . $this->db->escape($transaction['location_id']) . "', order_id='" . (int)$order_id . "', transaction_type='" . $this->db->escape($transaction['tenders'][0]['card_details']['status']) . "', transaction_amount='" . (float)$amount . "', transaction_currency='" . $this->db->escape($transaction['tenders'][0]['amount_money']['currency']) . "', billing_address_city='" . $this->db->escape($address['locality']) . "', billing_address_country='" . $this->db->escape($address['country']) . "', billing_address_postcode='" . $this->db->escape($address['postal_code']) . "', billing_address_province='" . $this->db->escape($address['sublocality']) . "', billing_address_street_1='" . $this->db->escape($address['address_line_1']) . "', billing_address_street_2='" . $this->db->escape($address['address_line_2']) . "', device_browser='" . $this->db->escape($user_agent) . "', device_ip='" . $this->db->escape($ip) . "', created_at='" . $this->db->escape($transaction['created_at']) . "', is_refunded='" . (int)(!empty($transaction['refunds'])) . "', refunded_at='" . $this->db->escape(!empty($transaction['refunds']) ? $transaction['refunds'][0]['created_at'] : '') . "', tenders='" . $this->db->escape(json_encode($transaction['tenders'])) . "', refunds='" . $this->db->escape(json_encode(!empty($transaction['refunds']) ? $transaction['refunds'] : array())) . "'");
     67     }
     68 
     69     public function tokenExpiredEmail() {
     70         if (!$this->mailResendPeriodExpired('token_expired')) {
     71             return;
     72         }
     73 
     74         $mail = new Mail();
     75 
     76         $mail->protocol = $this->config->get('config_mail_protocol');
     77         $mail->parameter = $this->config->get('config_mail_parameter');
     78 
     79         $mail->smtp_hostname = $this->config->get('config_mail_smtp_hostname');
     80         $mail->smtp_username = $this->config->get('config_mail_smtp_username');
     81         $mail->smtp_password = html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8');
     82         $mail->smtp_port = $this->config->get('config_mail_smtp_port');
     83         $mail->smtp_timeout = $this->config->get('config_mail_smtp_timeout');
     84 
     85         $subject = $this->language->get('text_token_expired_subject');
     86         $message = $this->language->get('text_token_expired_message');
     87 
     88         $mail->setTo($this->config->get('config_email'));
     89         $mail->setFrom($this->config->get('config_email'));
     90         $mail->setSender($this->config->get('config_name'));
     91         $mail->setSubject(html_entity_decode($subject, ENT_QUOTES, 'UTF-8'));
     92         $mail->setText(strip_tags($message));
     93         $mail->setHtml($message);
     94 
     95         $mail->send();
     96     }
     97 
     98     public function tokenRevokedEmail() {
     99         if (!$this->mailResendPeriodExpired('token_revoked')) {
    100             return;
    101         }
    102 
    103         $mail = new Mail();
    104 
    105         $mail->protocol = $this->config->get('config_mail_protocol');
    106         $mail->parameter = $this->config->get('config_mail_parameter');
    107 
    108         $mail->smtp_hostname = $this->config->get('config_mail_smtp_hostname');
    109         $mail->smtp_username = $this->config->get('config_mail_smtp_username');
    110         $mail->smtp_password = html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8');
    111         $mail->smtp_port = $this->config->get('config_mail_smtp_port');
    112         $mail->smtp_timeout = $this->config->get('config_mail_smtp_timeout');
    113 
    114         $subject = $this->language->get('text_token_revoked_subject');
    115         $message = $this->language->get('text_token_revoked_message');
    116 
    117         $mail->setTo($this->config->get('config_email'));
    118         $mail->setFrom($this->config->get('config_email'));
    119         $mail->setSender($this->config->get('config_name'));
    120         $mail->setSubject(html_entity_decode($subject, ENT_QUOTES, 'UTF-8'));
    121         $mail->setText(strip_tags($message));
    122         $mail->setHtml($message);
    123         
    124         $mail->send();
    125     }
    126 
    127     public function cronEmail($result) {
    128         $mail = new Mail();
    129         
    130         $mail->protocol = $this->config->get('config_mail_protocol');
    131         $mail->parameter = $this->config->get('config_mail_parameter');
    132 
    133         $mail->smtp_hostname = $this->config->get('config_mail_smtp_hostname');
    134         $mail->smtp_username = $this->config->get('config_mail_smtp_username');
    135         $mail->smtp_password = html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8');
    136         $mail->smtp_port = $this->config->get('config_mail_smtp_port');
    137         $mail->smtp_timeout = $this->config->get('config_mail_smtp_timeout');
    138 
    139         $br = '<br />';
    140 
    141         $subject = $this->language->get('text_cron_subject');
    142 
    143         $message = $this->language->get('text_cron_message') . $br . $br;
    144 
    145         $message .= '<strong>' . $this->language->get('text_cron_summary_token_heading') . '</strong>' . $br;
    146 
    147         if ($result['token_update_error']) {
    148             $message .= $result['token_update_error'] . $br . $br;
    149         } else {
    150             $message .= $this->language->get('text_cron_summary_token_updated') . $br . $br;
    151         }
    152 
    153         if (!empty($result['transaction_error'])) {
    154             $message .= '<strong>' . $this->language->get('text_cron_summary_error_heading') . '</strong>' . $br;
    155 
    156             $message .= implode($br, $result['transaction_error']) . $br . $br;
    157         }
    158 
    159         if (!empty($result['transaction_fail'])) {
    160             $message .= '<strong>' . $this->language->get('text_cron_summary_fail_heading') . '</strong>' . $br;
    161 
    162             foreach ($result['transaction_fail'] as $order_recurring_id => $amount) {
    163                 $message .= sprintf($this->language->get('text_cron_fail_charge'), $order_recurring_id, $amount) . $br;
    164             }
    165         }
    166 
    167         if (!empty($result['transaction_success'])) {
    168             $message .= '<strong>' . $this->language->get('text_cron_summary_success_heading') . '</strong>' . $br;
    169 
    170             foreach ($result['transaction_success'] as $order_recurring_id => $amount) {
    171                 $message .= sprintf($this->language->get('text_cron_success_charge'), $order_recurring_id, $amount) . $br;
    172             }
    173         }
    174 
    175         $mail->setTo($this->config->get('payment_squareup_cron_email'));
    176         $mail->setFrom($this->config->get('config_email'));
    177         $mail->setSender($this->config->get('config_name'));
    178         $mail->setSubject(html_entity_decode($subject, ENT_QUOTES, 'UTF-8'));
    179         $mail->setText(strip_tags($message));
    180         $mail->setHtml($message);
    181         $mail->send();
    182     }
    183 
    184     public function recurringPayments() {
    185         return (bool)$this->config->get('payment_squareup_recurring_status');
    186     }
    187 
    188     public function createRecurring($recurring, $order_id, $description, $reference) {
    189         $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring` SET `order_id` = '" . (int)$order_id . "', `date_added` = NOW(), `status` = '" . self::RECURRING_ACTIVE . "', `product_id` = '" . (int)$recurring['product_id'] . "', `product_name` = '" . $this->db->escape($recurring['name']) . "', `product_quantity` = '" . $this->db->escape($recurring['quantity']) . "', `recurring_id` = '" . (int)$recurring['recurring']['recurring_id'] . "', `recurring_name` = '" . $this->db->escape($recurring['recurring']['name']) . "', `recurring_description` = '" . $this->db->escape($description) . "', `recurring_frequency` = '" . $this->db->escape($recurring['recurring']['frequency']) . "', `recurring_cycle` = '" . (int)$recurring['recurring']['cycle'] . "', `recurring_duration` = '" . (int)$recurring['recurring']['duration'] . "', `recurring_price` = '" . (float)$recurring['recurring']['price'] . "', `trial` = '" . (int)$recurring['recurring']['trial'] . "', `trial_frequency` = '" . $this->db->escape($recurring['recurring']['trial_frequency']) . "', `trial_cycle` = '" . (int)$recurring['recurring']['trial_cycle'] . "', `trial_duration` = '" . (int)$recurring['recurring']['trial_duration'] . "', `trial_price` = '" . (float)$recurring['recurring']['trial_price'] . "', `reference` = '" . $this->db->escape($reference) . "'");
    190 
    191         return $this->db->getLastId();
    192     }
    193 
    194     public function validateCRON() {
    195         if (!$this->config->get('payment_squareup_status') || !$this->config->get('payment_squareup_recurring_status')) {
    196             return false;
    197         }
    198 
    199         if (isset($this->request->get['cron_token']) && $this->request->get['cron_token'] == $this->config->get('payment_squareup_cron_token')) {
    200             return true;
    201         }
    202 
    203         if (defined('SQUAREUP_ROUTE')) {
    204             return true;
    205         }
    206 
    207         return false;
    208     }
    209 
    210     public function updateToken() {
    211         try {
    212             $response = $this->squareup->refreshToken();
    213 
    214             if (!isset($response['access_token']) || !isset($response['token_type']) || !isset($response['expires_at']) || !isset($response['merchant_id']) || $response['merchant_id'] != $this->config->get('payment_squareup_merchant_id')) {
    215                 return $this->language->get('error_squareup_cron_token');
    216             } else {
    217                 $this->editTokenSetting(array(
    218                     'payment_squareup_access_token' => $response['access_token'],
    219                     'payment_squareup_access_token_expires' => $response['expires_at']
    220                 ));
    221             }
    222         } catch (\Squareup\Exception $e) {
    223             return $e->getMessage();
    224         }
    225 
    226         return '';
    227     }
    228 
    229     public function nextRecurringPayments() {
    230         $payments = array();
    231 
    232         $this->load->library('squareup');
    233 
    234         $recurring_sql = "SELECT * FROM `" . DB_PREFIX . "order_recurring` `or` INNER JOIN `" . DB_PREFIX . "squareup_transaction` st ON (st.transaction_id = `or`.reference) WHERE `or`.status='" . self::RECURRING_ACTIVE . "'";
    235 
    236         $this->load->model('checkout/order');
    237 
    238         foreach ($this->db->query($recurring_sql)->rows as $recurring) {
    239             if (!$this->paymentIsDue($recurring['order_recurring_id'])) {
    240                 continue;
    241             }
    242 
    243             $order_info = $this->model_checkout_order->getOrder($recurring['order_id']);
    244 
    245             $billing_address = array(
    246                 'first_name' => $order_info['payment_firstname'],
    247                 'last_name' => $order_info['payment_lastname'],
    248                 'address_line_1' => $recurring['billing_address_street_1'],
    249                 'address_line_2' => $recurring['billing_address_street_2'],
    250                 'locality' => $recurring['billing_address_city'],
    251                 'sublocality' => $recurring['billing_address_province'],
    252                 'postal_code' => $recurring['billing_address_postcode'],
    253                 'country' => $recurring['billing_address_country'],
    254                 'organization' => $recurring['billing_address_company']
    255             );
    256 
    257             $transaction_tenders = @json_decode($recurring['tenders'], true);
    258 
    259             $price = (float)($recurring['trial'] ? $recurring['trial_price'] : $recurring['recurring_price']);
    260 
    261             $transaction = array(
    262                 'idempotency_key' => uniqid(),
    263                 'amount_money' => array(
    264                     'amount' => $this->squareup->lowestDenomination($price * $recurring['product_quantity'], $recurring['transaction_currency']),
    265                     'currency' => $recurring['transaction_currency']
    266                 ),
    267                 'billing_address' => $billing_address,
    268                 'buyer_email_address' => $order_info['email'],
    269                 'delay_capture' => false,
    270                 'customer_id' => $transaction_tenders[0]['customer_id'],
    271                 'customer_card_id' => $transaction_tenders[0]['card_details']['card']['id'],
    272                 'integration_id' => Squareup::SQUARE_INTEGRATION_ID
    273             );
    274 
    275             $payments[] = array(
    276                 'is_free' => $price == 0,
    277                 'order_id' => $recurring['order_id'],
    278                 'order_recurring_id' => $recurring['order_recurring_id'],
    279                 'billing_address' => $billing_address,
    280                 'transaction' => $transaction
    281             );
    282         }
    283 
    284         return $payments;
    285     }
    286 
    287     public function addRecurringTransaction($order_recurring_id, $reference, $amount, $status) {
    288         if ($status) {
    289             $type = self::TRANSACTION_PAYMENT;
    290         } else {
    291             $type = self::TRANSACTION_FAILED;
    292         }
    293 
    294         $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET order_recurring_id='" . (int)$order_recurring_id . "', reference='" . $this->db->escape($reference) . "', type='" . (int)$type . "', amount='" . (float)$amount . "', date_added=NOW()");
    295     }
    296 
    297     public function updateRecurringExpired($order_recurring_id) {
    298         $recurring_info = $this->getRecurring($order_recurring_id);
    299 
    300         if ($recurring_info['trial']) {
    301             // If we are in trial, we need to check if the trial will end at some point
    302             $expirable = (bool)$recurring_info['trial_duration'];
    303         } else {
    304             // If we are not in trial, we need to check if the recurring will end at some point
    305             $expirable = (bool)$recurring_info['recurring_duration'];
    306         }
    307 
    308         // If recurring payment can expire (trial_duration > 0 AND recurring_duration > 0)
    309         if ($expirable) {
    310             $number_of_successful_payments = $this->getTotalSuccessfulPayments($order_recurring_id);
    311 
    312             $total_duration = (int)$recurring_info['trial_duration'] + (int)$recurring_info['recurring_duration'];
    313             
    314             // If successful payments exceed total_duration
    315             if ($number_of_successful_payments >= $total_duration) {
    316                 $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET status='" . self::RECURRING_EXPIRED . "' WHERE order_recurring_id='" . (int)$order_recurring_id . "'");
    317 
    318                 return true;
    319             }
    320         }
    321 
    322         return false;
    323     }
    324 
    325     public function updateRecurringTrial($order_recurring_id) {
    326         $recurring_info = $this->getRecurring($order_recurring_id);
    327 
    328         // If recurring payment is in trial and can expire (trial_duration > 0)
    329         if ($recurring_info['trial'] && $recurring_info['trial_duration']) {
    330             $number_of_successful_payments = $this->getTotalSuccessfulPayments($order_recurring_id);
    331 
    332             // If successful payments exceed trial_duration
    333             if ($number_of_successful_payments >= $recurring_info['trial_duration']) {
    334                 $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET trial='0' WHERE order_recurring_id='" . (int)$order_recurring_id . "'");
    335 
    336                 return true;
    337             }
    338         }
    339 
    340         return false;
    341     }
    342 
    343     public function suspendRecurringProfile($order_recurring_id) {
    344         $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET status='" . self::RECURRING_SUSPENDED . "' WHERE order_recurring_id='" . (int)$order_recurring_id . "'");
    345 
    346         return true;
    347     }
    348 
    349     private function getLastSuccessfulRecurringPaymentDate($order_recurring_id) {
    350         return $this->db->query("SELECT date_added FROM `" . DB_PREFIX . "order_recurring_transaction` WHERE order_recurring_id='" . (int)$order_recurring_id . "' AND type='" . self::TRANSACTION_PAYMENT . "' ORDER BY date_added DESC LIMIT 0,1")->row['date_added'];
    351     }
    352 
    353     private function getRecurring($order_recurring_id) {
    354         $recurring_sql = "SELECT * FROM `" . DB_PREFIX . "order_recurring` WHERE order_recurring_id='" . (int)$order_recurring_id . "'";
    355 
    356         return $this->db->query($recurring_sql)->row;
    357     }
    358 
    359     private function getTotalSuccessfulPayments($order_recurring_id) {
    360         return $this->db->query("SELECT COUNT(*) as total FROM `" . DB_PREFIX . "order_recurring_transaction` WHERE order_recurring_id='" . (int)$order_recurring_id . "' AND type='" . self::TRANSACTION_PAYMENT . "'")->row['total'];
    361     }
    362 
    363     private function paymentIsDue($order_recurring_id) {
    364         // We know the recurring profile is active.
    365         $recurring_info = $this->getRecurring($order_recurring_id);
    366 
    367         if ($recurring_info['trial']) {
    368             $frequency = $recurring_info['trial_frequency'];
    369             $cycle = (int)$recurring_info['trial_cycle'];
    370         } else {
    371             $frequency = $recurring_info['recurring_frequency'];
    372             $cycle = (int)$recurring_info['recurring_cycle'];
    373         }
    374         // Find date of last payment
    375         if (!$this->getTotalSuccessfulPayments($order_recurring_id)) {
    376             $previous_time = strtotime($recurring_info['date_added']);
    377         } else {
    378             $previous_time = strtotime($this->getLastSuccessfulRecurringPaymentDate($order_recurring_id));
    379         }
    380 
    381         switch ($frequency) {
    382             case 'day' : $time_interval = 24 * 3600; break;
    383             case 'week' : $time_interval = 7 * 24 * 3600; break;
    384             case 'semi_month' : $time_interval = 15 * 24 * 3600; break;
    385             case 'month' : $time_interval = 30 * 24 * 3600; break;
    386             case 'year' : $time_interval = 365 * 24 * 3600; break;
    387         }
    388 
    389         $due_date = date('Y-m-d', $previous_time + ($time_interval * $cycle));
    390 
    391         $this_date = date('Y-m-d');
    392 
    393         return $this_date >= $due_date;
    394     }
    395 
    396     private function editTokenSetting($settings) {
    397         foreach ($settings as $key => $value) {
    398             $this->db->query("DELETE FROM `" . DB_PREFIX . "setting` WHERE `code`='payment_squareup' AND `key`='" . $key . "'");
    399 
    400             $this->db->query("INSERT INTO `" . DB_PREFIX . "setting` SET `code`='payment_squareup', `key`='" . $key . "', `value`='" . $this->db->escape($value) . "', serialized=0, store_id=0");
    401         }
    402     }
    403 
    404     private function mailResendPeriodExpired($key) {
    405         $result = (int)$this->cache->get('squareup.' . $key);
    406 
    407         if (!$result) {
    408             // No result, therefore this is the first e-mail and the re-send period should be regarded as expired.
    409             $this->cache->set('squareup.' . $key, time());
    410         } else {
    411             // There is an entry in the cache. We will calculate the time difference (delta)
    412             $delta = time() - $result;
    413 
    414             if ($delta >= 15 * 60) {
    415                 // More than 15 minutes have passed, therefore the re-send period has expired.
    416                 $this->cache->set('squareup.' . $key, time());
    417             } else {
    418                 // Less than 15 minutes have passed before the last e-mail, therefore the re-send period has not expired.
    419                 return false;
    420             }
    421         }
    422 
    423         // In all other cases, the re-send period has expired.
    424         return true;
    425     }
    426 }