pp_express.php (14776B)
1 <?php 2 class ModelExtensionPaymentPPExpress extends Model { 3 public function install() { 4 $this->db->query(" 5 CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "paypal_order` ( 6 `paypal_order_id` int(11) NOT NULL AUTO_INCREMENT, 7 `order_id` int(11) NOT NULL, 8 `date_added` DATETIME NOT NULL, 9 `date_modified` DATETIME NOT NULL, 10 `capture_status` ENUM('Complete','NotComplete') DEFAULT NULL, 11 `currency_code` CHAR(3) NOT NULL, 12 `authorization_id` VARCHAR(30) NOT NULL, 13 `total` DECIMAL( 10, 2 ) NOT NULL, 14 PRIMARY KEY (`paypal_order_id`) 15 ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci 16 "); 17 18 $this->db->query(" 19 CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "paypal_order_transaction` ( 20 `paypal_order_transaction_id` int(11) NOT NULL AUTO_INCREMENT, 21 `paypal_order_id` int(11) NOT NULL, 22 `transaction_id` CHAR(20) NOT NULL, 23 `parent_id` CHAR(20) NOT NULL, 24 `date_added` DATETIME NOT NULL, 25 `note` VARCHAR(255) NOT NULL, 26 `msgsubid` CHAR(38) NOT NULL, 27 `receipt_id` CHAR(20) NOT NULL, 28 `payment_type` ENUM('none','echeck','instant', 'refund', 'void') DEFAULT NULL, 29 `payment_status` CHAR(20) NOT NULL, 30 `pending_reason` CHAR(50) NOT NULL, 31 `transaction_entity` CHAR(50) NOT NULL, 32 `amount` DECIMAL( 10, 2 ) NOT NULL, 33 `debug_data` TEXT NOT NULL, 34 `call_data` TEXT NOT NULL, 35 PRIMARY KEY (`paypal_order_transaction_id`) 36 ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci 37 "); 38 39 $this->load->model('setting/setting'); 40 41 $defaults = array(); 42 43 // Order Status defaults 44 $defaults['payment_pp_express_canceled_reversal_status_id'] = 9; 45 $defaults['payment_pp_express_completed_status_id'] = 5; 46 $defaults['payment_pp_express_denied_status_id'] = 8; 47 $defaults['payment_pp_express_expired_status_id'] = 14; 48 $defaults['payment_pp_express_failed_status_id'] = 10; 49 $defaults['payment_pp_express_pending_status_id'] = 1; 50 $defaults['payment_pp_express_processed_status_id'] = 15; 51 $defaults['payment_pp_express_refunded_status_id'] = 11; 52 $defaults['payment_pp_express_reversed_status_id'] = 12; 53 $defaults['payment_pp_express_voided_status_id'] = 16; 54 55 $defaults['payment_pp_express_incontext_disable'] = 0; 56 $defaults['payment_pp_express_status'] = 0; 57 $defaults['payment_pp_express_currency'] = "USD"; 58 59 $this->model_setting_setting->editSetting('payment_pp_express', $defaults); 60 } 61 62 public function uninstall() { 63 $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "paypal_order_transaction`"); 64 $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "paypal_order`"); 65 } 66 67 public function getPayPalOrder($order_id) { 68 $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "paypal_order` WHERE `order_id` = '" . (int)$order_id . "'"); 69 70 return $query->row; 71 } 72 73 public function editPayPalOrderStatus($order_id, $capture_status) { 74 $this->db->query("UPDATE `" . DB_PREFIX . "paypal_order` SET `capture_status` = '" . $this->db->escape($capture_status) . "', `date_modified` = NOW() WHERE `order_id` = '" . (int)$order_id . "'"); 75 } 76 77 public function addTransaction($transaction_data, $request_data = array()) { 78 if ($request_data) { 79 $serialized_data = json_encode($request_data); 80 81 $this->db->query("UPDATE " . DB_PREFIX . "paypal_order_transaction SET call_data = '" . $this->db->escape($serialized_data) . "' WHERE paypal_order_transaction_id = " . (int)$paypal_order_transaction_id . " LIMIT 1"); 82 } 83 84 85 86 $this->db->query("INSERT INTO `" . DB_PREFIX . "paypal_order_transaction` SET `paypal_order_id` = '" . (int)$transaction_data['paypal_order_id'] . "', `transaction_id` = '" . $this->db->escape($transaction_data['transaction_id']) . "', `parent_id` = '" . $this->db->escape($transaction_data['parent_id']) . "', `date_added` = NOW(), `note` = '" . $this->db->escape($transaction_data['note']) . "', `msgsubid` = '" . $this->db->escape($transaction_data['msgsubid']) . "', `receipt_id` = '" . $this->db->escape($transaction_data['receipt_id']) . "', `payment_type` = '" . $this->db->escape($transaction_data['payment_type']) . "', `payment_status` = '" . $this->db->escape($transaction_data['payment_status']) . "', `pending_reason` = '" . $this->db->escape($transaction_data['pending_reason']) . "', `transaction_entity` = '" . $this->db->escape($transaction_data['transaction_entity']) . "', `amount` = '" . (float)$transaction_data['amount'] . "', `debug_data` = '" . $this->db->escape($transaction_data['debug_data']) . "'"); 87 88 return $this->db->getLastId(); 89 } 90 91 public function updateTransaction($transaction) { 92 $this->db->query("UPDATE " . DB_PREFIX . "paypal_order_transaction SET paypal_order_id = " . (int)$transaction['paypal_order_id'] . ", transaction_id = '" . $this->db->escape($transaction['transaction_id']) . "', parent_id = '" . $this->db->escape($transaction['parent_id']) . "', date_added = '" . $this->db->escape($transaction['date_added']) . "', note = '" . $this->db->escape($transaction['note']) . "', msgsubid = '" . $this->db->escape($transaction['msgsubid']) . "', receipt_id = '" . $this->db->escape($transaction['receipt_id']) . "', payment_type = '" . $this->db->escape($transaction['payment_type']) . "', payment_status = '" . $this->db->escape($transaction['payment_status']) . "', pending_reason = '" . $this->db->escape($transaction['pending_reason']) . "', transaction_entity = '" . $this->db->escape($transaction['transaction_entity']) . "', amount = '" . $this->db->escape($transaction['amount']) . "', debug_data = '" . $this->db->escape($transaction['debug_data']) . "', call_data = '" . $this->db->escape($transaction['call_data']) . "' WHERE paypal_order_transaction_id = '" . (int)$transaction['paypal_order_transaction_id'] . "'"); 93 } 94 95 public function getPaypalOrderByTransactionId($transaction_id) { 96 $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "paypal_order_transaction WHERE transaction_id = '" . $this->db->escape($transaction_id) . "'"); 97 98 return $query->rows; 99 } 100 101 public function getFailedTransaction($paypal_order_transaction_id) { 102 $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "paypal_order_transaction WHERE paypal_order_transaction_id = '" . (int)$paypal_order_transaction_id . "'"); 103 104 return $query->row; 105 } 106 107 public function getLocalTransaction($transaction_id) { 108 $result = $this->db->query("SELECT * FROM " . DB_PREFIX . "paypal_order_transaction WHERE transaction_id = '" . $this->db->escape($transaction_id) . "'")->row; 109 110 if ($result) { 111 return $result; 112 } else { 113 return false; 114 } 115 } 116 117 public function getTransaction($transaction_id) { 118 $call_data = array( 119 'METHOD' => 'GetTransactionDetails', 120 'TRANSACTIONID' => $transaction_id, 121 ); 122 123 return $this->call($call_data); 124 } 125 126 public function getCurrencies() { 127 return array( 128 'AUD', 129 'BRL', 130 'CAD', 131 'CZK', 132 'DKK', 133 'EUR', 134 'HKD', 135 'HUF', 136 'ILS', 137 'JPY', 138 'MYR', 139 'MXN', 140 'NOK', 141 'NZD', 142 'PHP', 143 'PLN', 144 'GBP', 145 'SGD', 146 'SEK', 147 'CHF', 148 'TWD', 149 'THB', 150 'TRY', 151 'USD', 152 ); 153 } 154 155 public function getOrderId($transaction_id) { 156 $query = $this->db->query("SELECT `o`.`order_id` FROM `" . DB_PREFIX . "paypal_order_transaction` `ot` LEFT JOIN `" . DB_PREFIX . "paypal_order` `o` ON `o`.`paypal_order_id` = `ot`.`paypal_order_id` WHERE `ot`.`transaction_id` = '" . $this->db->escape($transaction_id) . "' LIMIT 1"); 157 158 return $query->row['order_id']; 159 } 160 161 public function getCapturedTotal($paypal_order_id) { 162 $query = $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 (`payment_status` = 'Partially-Refunded' OR `payment_status` = 'Completed' OR `payment_status` = 'Pending') AND `transaction_entity` = 'payment'"); 163 164 return $query->row['amount']; 165 } 166 167 public function getRefundedTotal($paypal_order_id) { 168 $query = $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' AND `parent_id` != ''"); 169 170 return $query->row['amount']; 171 } 172 173 public function getRefundedTotalByParentId($transaction_id) { 174 $query = $this->db->query("SELECT SUM(`amount`) AS `amount` FROM `" . DB_PREFIX . "paypal_order_transaction` WHERE `parent_id` = '" . $this->db->escape($transaction_id) . "' AND `payment_type` = 'refund'"); 175 176 return $query->row['amount']; 177 } 178 179 public function cleanReturn($data) { 180 $data = explode('&', $data); 181 182 $arr = array(); 183 184 foreach ($data as $k => $v) { 185 $tmp = explode('=', $v); 186 $arr[$tmp[0]] = urldecode($tmp[1]); 187 } 188 189 return $arr; 190 } 191 192 public function log($data, $title = null) { 193 if ($this->config->get('payment_pp_express_debug')) { 194 $this->log->write('PayPal Express debug (' . $title . '): ' . json_encode($data)); 195 } 196 } 197 198 public function getOrder($order_id) { 199 $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "paypal_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1"); 200 201 if ($qry->num_rows) { 202 $order = $qry->row; 203 $order['transactions'] = $this->getTransactions($order['paypal_order_id']); 204 $order['captured'] = $this->totalCaptured($order['paypal_order_id']); 205 return $order; 206 } else { 207 return false; 208 } 209 } 210 211 public function totalCaptured($paypal_order_id) { 212 $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 (`payment_status` = 'Partially-Refunded' OR `payment_status` = 'Completed' OR `payment_status` = 'Pending') AND `transaction_entity` = 'payment'"); 213 214 return $qry->row['amount']; 215 } 216 217 public function getTransactions($paypal_order_id) { 218 $query = $this->db->query("SELECT `ot`.*, (SELECT COUNT(`ot2`.`paypal_order_id`) FROM `" . DB_PREFIX . "paypal_order_transaction` `ot2` WHERE `ot2`.`parent_id` = `ot`.`transaction_id`) AS `children` FROM `" . DB_PREFIX . "paypal_order_transaction` `ot` WHERE `paypal_order_id` = '" . (int)$paypal_order_id . "' ORDER BY `date_added` ASC"); 219 220 return $query->rows; 221 } 222 223 public function getTokens($test) { 224 if ($test == 'sandbox') { 225 $endpoint = 'https://api.sandbox.paypal.com/v1/oauth2/token'; 226 $client_id = 'Ad3QTBAHwhuNI_blejO4_RqvES74yWRUC61c5QVNDbxkq9csbLpDZogWp_0n'; 227 $client_secret = 'EGqgGxCqjs1GIa5l1Ex_Flq0Mb2oMT3rJu2kwz6FuF9QKyxCg6qNqyddxCCW'; 228 } else { 229 $endpoint = 'https://api.paypal.com/v1/oauth2/token'; 230 $client_id = 'AWyAiBCUYsE156N8YpiiISQpSpep2HPoXXPrf33VBeYleE0SQJg40pgEqZvq'; 231 $client_secret = 'EEkc6xB30fDkgUO_YldWWHxKDquY7LBRId6FJ-parAR1CsVpK35zB6U0SIh4'; 232 } 233 234 $request = ''; 235 $request .= 'client_id=' . $client_id; 236 $request .= '&client_secret=' . $client_secret; 237 $request .= '&grant_type=client_credentials'; 238 239 $additional_opts = array( 240 CURLOPT_USERPWD => $client_id . ':' . $client_secret, 241 CURLOPT_POST => true, 242 CURLOPT_POSTFIELDS => $request 243 ); 244 245 $curl = $this->curl($endpoint, $additional_opts); 246 247 $this->log('cURL Response 1: ' . print_r($curl, 1)); 248 249 return $curl; 250 } 251 252 public function getUserInfo($merchant_id, $test, $access_token) { 253 if ($test == 'sandbox') { 254 $endpoint = 'https://api.sandbox.paypal.com/v1/customer/partners/T4E8WSXT43QPJ/merchant-integrations'; 255 } else { 256 $endpoint = 'https://api.paypal.com/v1/customer/partners/9PDNYE4RZBVFJ/merchant-integrations'; 257 } 258 259 $endpoint1 = $endpoint . '?tracking_id=' . $merchant_id; 260 261 $header = array(); 262 $header[] = 'Content-Type: application/json'; 263 $header[] = 'Authorization: Bearer ' . $access_token; 264 $header[] = 'PAYPAL_SERVICE_VERSION:1.2.0'; 265 266 $additional_opts = array( 267 CURLOPT_HTTPHEADER => $header, 268 ); 269 270 $curl = $this->curl($endpoint1, $additional_opts); 271 272 $this->log('cURL Response 2: ' . print_r($curl, 1)); 273 274 if (isset($curl->merchant_id)) { 275 $endpoint2 = $endpoint . '/' . $curl->merchant_id; 276 $curl2 = $this->curl($endpoint2, $additional_opts); 277 278 $this->log('cURL Response 3: ' . print_r($curl2, 1)); 279 280 if (isset($curl2->api_credentials->signature)) { 281 return $curl2->api_credentials->signature; 282 } else { 283 return; 284 } 285 } else { 286 return; 287 } 288 } 289 290 public function call($data) { 291 if ($this->config->get('payment_pp_express_test') == 1) { 292 $api_endpoint = 'https://api-3t.sandbox.paypal.com/nvp'; 293 $user = $this->config->get('payment_pp_express_sandbox_username'); 294 $password = $this->config->get('payment_pp_express_sandbox_password'); 295 $signature = $this->config->get('payment_pp_express_sandbox_signature'); 296 } else { 297 $api_endpoint = 'https://api-3t.paypal.com/nvp'; 298 $user = $this->config->get('payment_pp_express_username'); 299 $password = $this->config->get('payment_pp_express_password'); 300 $signature = $this->config->get('payment_pp_express_signature'); 301 } 302 303 $settings = array( 304 'USER' => $user, 305 'PWD' => $password, 306 'SIGNATURE' => $signature, 307 'VERSION' => '84', 308 'BUTTONSOURCE' => 'OpenCart_Cart_EC', 309 ); 310 311 $this->log($data, 'Call data'); 312 313 $defaults = array( 314 CURLOPT_POST => 1, 315 CURLOPT_HEADER => 0, 316 CURLOPT_URL => $api_endpoint, 317 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", 318 CURLOPT_FRESH_CONNECT => 1, 319 CURLOPT_RETURNTRANSFER => 1, 320 CURLOPT_FORBID_REUSE => 1, 321 CURLOPT_TIMEOUT => 0, 322 CURLOPT_SSL_VERIFYPEER => 0, 323 CURLOPT_SSL_VERIFYHOST => 0, 324 CURLOPT_POSTFIELDS => http_build_query(array_merge($data, $settings), '', "&") 325 ); 326 327 $ch = curl_init(); 328 329 curl_setopt_array($ch, $defaults); 330 331 if (!$result = curl_exec($ch)) { 332 $log_data = array( 333 'curl_error' => curl_error($ch), 334 'curl_errno' => curl_errno($ch) 335 ); 336 337 $this->log($log_data, 'CURL failed'); 338 return false; 339 } 340 341 $this->log($result, 'Result'); 342 343 curl_close($ch); 344 345 return $this->cleanReturn($result); 346 } 347 348 private function curl($endpoint, $additional_opts = array()) { 349 $default_opts = array( 350 CURLOPT_PORT => 443, 351 CURLOPT_HEADER => 0, 352 CURLOPT_SSL_VERIFYPEER => 0, 353 CURLOPT_RETURNTRANSFER => 1, 354 CURLOPT_FORBID_REUSE => 1, 355 CURLOPT_FRESH_CONNECT => 1, 356 CURLOPT_URL => $endpoint, 357 ); 358 359 $ch = curl_init($endpoint); 360 361 $opts = $default_opts + $additional_opts; 362 363 curl_setopt_array($ch, $opts); 364 365 $response = json_decode(curl_exec($ch)); 366 367 curl_close($ch); 368 369 return $response; 370 } 371 }