PageRenderTime 43ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/catalog/model/payment/pp_express.php

https://gitlab.com/reclamare/mao
PHP | 358 lines | 264 code | 82 blank | 12 comment | 32 complexity | 040ca89587236ef1d7dabd7a073cee4f MD5 | raw file
  1. <?php
  2. class ModelPaymentPPExpress extends Model {
  3. public function cleanReturn($data) {
  4. $data = explode('&', $data);
  5. $arr = array();
  6. foreach ($data as $k=>$v) {
  7. $tmp = explode('=', $v);
  8. $arr[$tmp[0]] = urldecode($tmp[1]);
  9. }
  10. return $arr;
  11. }
  12. public function call($data) {
  13. if ($this->config->get('pp_express_test') == 1) {
  14. $api_endpoint = 'https://api-3t.sandbox.paypal.com/nvp';
  15. $user = $this->config->get('pp_express_sandbox_username');
  16. $password = $this->config->get('pp_express_sandbox_password');
  17. $signature = $this->config->get('pp_express_sandbox_signature');
  18. } else {
  19. $api_endpoint = 'https://api-3t.paypal.com/nvp';
  20. $user = $this->config->get('pp_express_username');
  21. $password = $this->config->get('pp_express_password');
  22. $signature = $this->config->get('pp_express_signature');
  23. }
  24. $settings = array(
  25. 'USER' => $user,
  26. 'PWD' => $password,
  27. 'SIGNATURE' => $signature,
  28. 'VERSION' => '109.0',
  29. 'BUTTONSOURCE' => 'OpenCart_2.0_EC',
  30. );
  31. $this->log($data, 'Call data');
  32. $defaults = array(
  33. CURLOPT_POST => 1,
  34. CURLOPT_HEADER => 0,
  35. CURLOPT_URL => $api_endpoint,
  36. CURLOPT_USERAGENT => "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1",
  37. CURLOPT_FRESH_CONNECT => 1,
  38. CURLOPT_RETURNTRANSFER => 1,
  39. CURLOPT_FORBID_REUSE => 1,
  40. CURLOPT_TIMEOUT => 0,
  41. CURLOPT_SSL_VERIFYPEER => 0,
  42. CURLOPT_SSL_VERIFYHOST => 0,
  43. CURLOPT_POSTFIELDS => http_build_query(array_merge($data, $settings), '', "&")
  44. );
  45. $ch = curl_init();
  46. curl_setopt_array($ch, $defaults);
  47. if (!$result = curl_exec($ch)) {
  48. $this->log(array('error' => curl_error($ch), 'errno' => curl_errno($ch)), 'cURL failed');
  49. }
  50. $this->log($result, 'Result');
  51. curl_close($ch);
  52. return $this->cleanReturn($result);
  53. }
  54. public function createToken($len = 32) {
  55. $base = 'ABCDEFGHKLMNOPQRSTWXYZabcdefghjkmnpqrstwxyz123456789';
  56. $max = strlen($base)-1;
  57. $activate_code = '';
  58. mt_srand((float)microtime()*1000000);
  59. while (strlen($activate_code)<$len+1) {
  60. $activate_code .= $base{mt_rand(0, $max)};
  61. }
  62. return $activate_code;
  63. }
  64. public function log($data, $title = null) {
  65. if ($this->config->get('pp_express_debug')) {
  66. $this->log->write('PayPal Express debug (' . $title . '): ' . json_encode($data));
  67. }
  68. }
  69. public function getMethod($address, $total) {
  70. $this->load->language('payment/pp_express');
  71. $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "zone_to_geo_zone` WHERE `geo_zone_id` = '" . (int)$this->config->get('pp_express_geo_zone_id') . "' AND `country_id` = '" . (int)$address['country_id'] . "' AND (`zone_id` = '" . (int)$address['zone_id'] . "' OR `zone_id` = '0')");
  72. if ($this->config->get('pp_express_total') > $total) {
  73. $status = false;
  74. } elseif (!$this->config->get('pp_express_geo_zone_id')) {
  75. $status = true;
  76. } elseif ($query->num_rows) {
  77. $status = true;
  78. } else {
  79. $status = false;
  80. }
  81. $method_data = array();
  82. if ($status) {
  83. $method_data = array(
  84. 'code' => 'pp_express',
  85. 'title' => $this->language->get('text_title'),
  86. 'terms' => '',
  87. 'sort_order' => $this->config->get('pp_express_sort_order')
  88. );
  89. }
  90. return $method_data;
  91. }
  92. public function addOrder($order_data) {
  93. /**
  94. * 1 to 1 relationship with order table (extends order info)
  95. */
  96. $this->db->query("INSERT INTO `" . DB_PREFIX . "paypal_order` SET
  97. `order_id` = '" . (int)$order_data['order_id'] . "',
  98. `date_added` = NOW(),
  99. `date_modified` = NOW(),
  100. `capture_status` = '" . $this->db->escape($order_data['capture_status']) . "',
  101. `currency_code` = '" . $this->db->escape($order_data['currency_code']) . "',
  102. `total` = '" . (float)$order_data['total'] . "',
  103. `authorization_id` = '" . $this->db->escape($order_data['authorization_id']) . "'");
  104. return $this->db->getLastId();
  105. }
  106. public function addTransaction($transaction_data) {
  107. /**
  108. * 1 to many relationship with paypal order table, many transactions per 1 order
  109. */
  110. $this->db->query("INSERT INTO `" . DB_PREFIX . "paypal_order_transaction` SET
  111. `paypal_order_id` = '" . (int)$transaction_data['paypal_order_id'] . "',
  112. `transaction_id` = '" . $this->db->escape($transaction_data['transaction_id']) . "',
  113. `parent_transaction_id` = '" . $this->db->escape($transaction_data['parent_transaction_id']) . "',
  114. `date_added` = NOW(),
  115. `note` = '" . $this->db->escape($transaction_data['note']) . "',
  116. `msgsubid` = '" . $this->db->escape($transaction_data['msgsubid']) . "',
  117. `receipt_id` = '" . $this->db->escape($transaction_data['receipt_id']) . "',
  118. `payment_type` = '" . $this->db->escape($transaction_data['payment_type']) . "',
  119. `payment_status` = '" . $this->db->escape($transaction_data['payment_status']) . "',
  120. `pending_reason` = '" . $this->db->escape($transaction_data['pending_reason']) . "',
  121. `transaction_entity` = '" . $this->db->escape($transaction_data['transaction_entity']) . "',
  122. `amount` = '" . (float)$transaction_data['amount'] . "',
  123. `debug_data` = '" . $this->db->escape($transaction_data['debug_data']) . "'");
  124. }
  125. public function paymentRequestInfo() {
  126. $data['PAYMENTREQUEST_0_SHIPPINGAMT'] = '';
  127. $data['PAYMENTREQUEST_0_CURRENCYCODE'] = $this->currency->getCode();
  128. $data['PAYMENTREQUEST_0_PAYMENTACTION'] = $this->config->get('pp_express_method');
  129. $i = 0;
  130. $item_total = 0;
  131. foreach ($this->cart->getProducts() as $item) {
  132. $data['L_PAYMENTREQUEST_0_DESC' . $i] = '';
  133. $option_count = 0;
  134. foreach ($item['option'] as $option) {
  135. if ($option['type'] != 'file') {
  136. $value = $option['value'];
  137. } else {
  138. $filename = $this->encryption->decrypt($option['value']);
  139. $value = utf8_substr($filename, 0, utf8_strrpos($filename, '.'));
  140. }
  141. $data['L_PAYMENTREQUEST_0_DESC' . $i] .= ($option_count > 0 ? ', ' : '') . $option['name'] . ':' . (utf8_strlen($value) > 20 ? utf8_substr($value, 0, 20) . '..' : $value);
  142. $option_count++;
  143. }
  144. $data['L_PAYMENTREQUEST_0_DESC' . $i] = substr($data['L_PAYMENTREQUEST_0_DESC' . $i], 0, 126);
  145. $item_price = $this->currency->format($item['price'], false, false, false);
  146. $data['L_PAYMENTREQUEST_0_NAME' . $i] = $item['name'];
  147. $data['L_PAYMENTREQUEST_0_NUMBER' . $i] = $item['model'];
  148. $data['L_PAYMENTREQUEST_0_AMT' . $i] = $item_price;
  149. $item_total += number_format($item_price * $item['quantity'], 2, '.', '');
  150. $data['L_PAYMENTREQUEST_0_QTY' . $i] = $item['quantity'];
  151. $data['L_PAYMENTREQUEST_0_ITEMURL' . $i] = $this->url->link('product/product', 'product_id=' . $item['product_id']);
  152. if ($this->config->get('config_cart_weight')) {
  153. $weight = $this->weight->convert($item['weight'], $item['weight_class_id'], $this->config->get('config_weight_class_id'));
  154. $data['L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE' . $i] = number_format($weight / $item['quantity'], 2, '.', '');
  155. $data['L_PAYMENTREQUEST_0_ITEMWEIGHTUNIT' . $i] = $this->weight->getUnit($this->config->get('config_weight_class_id'));
  156. }
  157. if ($item['length'] > 0 || $item['width'] > 0 || $item['height'] > 0) {
  158. $unit = $this->length->getUnit($item['length_class_id']);
  159. $data['L_PAYMENTREQUEST_0_ITEMLENGTHVALUE' . $i] = $item['length'];
  160. $data['L_PAYMENTREQUEST_0_ITEMLENGTHUNIT' . $i] = $unit;
  161. $data['L_PAYMENTREQUEST_0_ITEMWIDTHVALUE' . $i] = $item['width'];
  162. $data['L_PAYMENTREQUEST_0_ITEMWIDTHUNIT' . $i] = $unit;
  163. $data['L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE' . $i] = $item['height'];
  164. $data['L_PAYMENTREQUEST_0_ITEMHEIGHTUNIT' . $i] = $unit;
  165. }
  166. $i++;
  167. }
  168. if (!empty($this->session->data['vouchers'])) {
  169. foreach ($this->session->data['vouchers'] as $voucher) {
  170. $item_total += $this->currency->format($voucher['amount'], false, false, false);
  171. $data['L_PAYMENTREQUEST_0_DESC' . $i] = '';
  172. $data['L_PAYMENTREQUEST_0_NAME' . $i] = $voucher['description'];
  173. $data['L_PAYMENTREQUEST_0_NUMBER' . $i] = 'VOUCHER';
  174. $data['L_PAYMENTREQUEST_0_QTY' . $i] = 1;
  175. $data['L_PAYMENTREQUEST_0_AMT' . $i] = $this->currency->format($voucher['amount'], false, false, false);
  176. $i++;
  177. }
  178. }
  179. // Totals
  180. $this->load->model('extension/extension');
  181. $total_data = array();
  182. $total = 0;
  183. $taxes = $this->cart->getTaxes();
  184. // Display prices
  185. if (($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) {
  186. $sort_order = array();
  187. $results = $this->model_extension_extension->getExtensions('total');
  188. foreach ($results as $key => $value) {
  189. $sort_order[$key] = $this->config->get($value['code'] . '_sort_order');
  190. }
  191. array_multisort($sort_order, SORT_ASC, $results);
  192. foreach ($results as $result) {
  193. if ($this->config->get($result['code'] . '_status')) {
  194. $this->load->model('total/' . $result['code']);
  195. $this->{'model_total_' . $result['code']}->getTotal($total_data, $total, $taxes);
  196. }
  197. $sort_order = array();
  198. foreach ($total_data as $key => $value) {
  199. $sort_order[$key] = $value['sort_order'];
  200. }
  201. array_multisort($sort_order, SORT_ASC, $total_data);
  202. }
  203. }
  204. foreach ($total_data as $total_row) {
  205. if (!in_array($total_row['code'], array('total', 'sub_total'))) {
  206. if ($total_row['value'] != 0) {
  207. $item_price = $this->currency->format($total_row['value'], false, false, false);
  208. $data['L_PAYMENTREQUEST_0_NUMBER' . $i] = $total_row['code'];
  209. $data['L_PAYMENTREQUEST_0_NAME' . $i] = $total_row['title'];
  210. $data['L_PAYMENTREQUEST_0_AMT' . $i] = $this->currency->format($total_row['value'], false, false, false);
  211. $data['L_PAYMENTREQUEST_0_QTY' . $i] = 1;
  212. $item_total = $item_total + $item_price;
  213. $i++;
  214. }
  215. }
  216. }
  217. $data['PAYMENTREQUEST_0_ITEMAMT'] = number_format($item_total, 2, '.', '');
  218. $data['PAYMENTREQUEST_0_AMT'] = number_format($item_total, 2, '.', '');
  219. $z = 0;
  220. $recurring_products = $this->cart->getRecurringProducts();
  221. if ($recurring_products) {
  222. $this->language->load('payment/pp_express');
  223. foreach ($recurring_products as $item) {
  224. $data['L_BILLINGTYPE' . $z] = 'RecurringPayments';
  225. if ($item['recurring']['trial']) {
  226. $trial_amt = $this->currency->format($this->tax->calculate($item['recurring']['trial_price'], $item['tax_class_id'], $this->config->get('config_tax')), false, false, false) * $item['quantity'] . ' ' . $this->currency->getCode();
  227. $trial_text = sprintf($this->language->get('text_trial'), $trial_amt, $item['recurring']['trial_cycle'], $item['recurring']['trial_frequency'], $item['recurring']['trial_duration']);
  228. } else {
  229. $trial_text = '';
  230. }
  231. $recurring_amt = $this->currency->format($this->tax->calculate($item['recurring']['price'], $item['tax_class_id'], $this->config->get('config_tax')), false, false, false) * $item['quantity'] . ' ' . $this->currency->getCode();
  232. $recurring_description = $trial_text . sprintf($this->language->get('text_recurring'), $recurring_amt, $item['recurring']['cycle'], $item['recurring']['frequency']);
  233. if ($item['recurring']['duration'] > 0) {
  234. $recurring_description .= sprintf($this->language->get('text_length'), $item['recurring']['duration']);
  235. }
  236. $data['L_BILLINGAGREEMENTDESCRIPTION' . $z] = $recurring_description;
  237. $z++;
  238. }
  239. }
  240. return $data;
  241. }
  242. public function getTransactionRow($transaction_id) {
  243. $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "paypal_order_transaction` `pt` LEFT JOIN `" . DB_PREFIX . "paypal_order` `po` ON `pt`.`paypal_order_id` = `po`.`paypal_order_id` WHERE `pt`.`transaction_id` = '" . $this->db->escape($transaction_id) . "' LIMIT 1");
  244. if ($qry->num_rows > 0) {
  245. return $qry->row;
  246. } else {
  247. return false;
  248. }
  249. }
  250. public function totalCaptured($paypal_order_id) {
  251. $qry = $this->db->query("SELECT SUM(`amount`) AS `amount` FROM `" . DB_PREFIX . "paypal_order_transaction` WHERE `paypal_order_id` = '" . (int)$paypal_order_id . "' AND `pending_reason` != 'authorization' AND `pending_reason` != 'paymentreview' AND (`payment_status` = 'Partially-Refunded' OR `payment_status` = 'Completed' OR `payment_status` = 'Pending') AND `transaction_entity` = 'payment'");
  252. return $qry->row['amount'];
  253. }
  254. public function totalRefundedOrder($paypal_order_id) {
  255. $qry = $this->db->query("SELECT SUM(`amount`) AS `amount` FROM `" . DB_PREFIX . "paypal_order_transaction` WHERE `paypal_order_id` = '" . (int)$paypal_order_id . "' AND `payment_status` = 'Refunded'");
  256. return $qry->row['amount'];
  257. }
  258. public function updateOrder($capture_status, $order_id) {
  259. $this->db->query("UPDATE `" . DB_PREFIX . "paypal_order` SET `date_modified` = now(), `capture_status` = '" . $this->db->escape($capture_status) . "' WHERE `order_id` = '" . (int)$order_id . "'");
  260. }
  261. public function recurringCancel($ref) {
  262. $data = array(
  263. 'METHOD' => 'ManageRecurringPaymentsProfileStatus',
  264. 'PROFILEID' => $ref,
  265. 'ACTION' => 'Cancel'
  266. );
  267. return $this->call($data);
  268. }
  269. public function recurringPayments() {
  270. /*
  271. * Used by the checkout to state the module
  272. * supports recurring recurrings.
  273. */
  274. return true;
  275. }
  276. }