public function processIpn(Engine_Payment_Ipn $ipn)
 {
     $rawData = $ipn->getRawData();
     // Process: type
     $data = $rawData;
     return $data;
 }
 public function processIpn(Engine_Payment_Ipn $ipn)
 {
     // Validate ----------------------------------------------------------------
     // Get raw data
     $rawData = $ipn->getRawData();
     // Log raw data
     //if( 'development' === APPLICATION_ENV ) {
     $this->_log(print_r($rawData, true), Zend_Log::DEBUG);
     //}
     // Check a couple things in advance
     if (!empty($rawData['test_ipn']) && !$this->getTestMode()) {
         throw new Engine_Payment_Gateway_Exception('Test IPN sent in non-test mode');
     }
     // @todo check the email address of the account?
     // Build url and post data
     $parsedUrl = parse_url($this->getGatewayUrl());
     $rawData = array_merge(array('cmd' => '_notify-validate'), $rawData);
     foreach ($rawData as $key => $value) {
         $rawData[$key] = stripslashes($value);
     }
     $postString = http_build_query($rawData, '', '&');
     if (empty($parsedUrl['host'])) {
         $this->_throw(sprintf('Invalid host in gateway url: %s', $this->getGatewayUrl()));
         return false;
     }
     if (empty($parsedUrl['path'])) {
         $parsedUrl['path'] = '/';
     }
     // Open socket
     $fp = fsockopen('ssl://' . $parsedUrl['host'], 443, $errNum, $errStr, 30);
     if (!$fp) {
         $this->_throw(sprintf('Unable to open socket: [%d] %s', $errNum, $errStr));
     }
     stream_set_blocking($fp, true);
     fputs($fp, "POST {$parsedUrl['path']} HTTP/1.1\r\n");
     fputs($fp, "Host: {$parsedUrl['host']}\r\n");
     fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
     fputs($fp, "Content-length: " . strlen($postString) . "\r\n");
     fputs($fp, "Connection: close\r\n\r\n");
     fputs($fp, $postString . "\r\n\r\n");
     $response = '';
     while (!feof($fp)) {
         $response .= fgets($fp, 1024);
     }
     fclose($fp);
     if (!stripos($response, 'VERIFIED')) {
         $this->_log($response);
         $this->_throw(sprintf('IPN Validation Failed: %s %s', $parsedUrl['host'], $parsedUrl['path']));
         return false;
     }
     // Success!
     $this->_log('IPN Validation Succeeded');
     // Process -----------------------------------------------------------------
     $rawData = $ipn->getRawData();
     $data = $rawData;
     return $data;
 }
 public function processIpn(Engine_Payment_Ipn $ipn)
 {
     // Validate ----------------------------------------------------------------
     // Get raw data
     $rawData = $ipn->getRawData();
     // Log raw data
     //if( 'development' === APPLICATION_ENV ) {
     $this->_log(print_r($rawData, true), Zend_Log::DEBUG);
     //}
     // Success!
     $this->_log('IPN Validation Succeeded');
     // Process -----------------------------------------------------------------
     $rawData = $ipn->getRawData();
     $data = $rawData;
     return $data;
 }
 public function processIpn(Engine_Payment_Ipn $ipn)
 {
     // Validate ----------------------------------------------------------------
     // Get raw data
     $rawData = $ipn->getRawData();
     // Log raw data
     //if( 'development' === APPLICATION_ENV ) {
     $this->_log(print_r($rawData, true), Zend_Log::DEBUG);
     //}
     // Check gateway for info
     if (null == ($vendorIdentity = $this->getVendorIdentity())) {
         $this->_throw('Unable to validate IPN: vendor identity is missing.');
         return false;
     }
     if (null == ($vendorSecret = $this->getVendorSecret())) {
         $this->_throw('Unable to validate IPN: vendor secret is missing.');
         return false;
     }
     // Check for empty parameters
     if (!isset($rawData['sale_id'])) {
         $this->_throw('Unable to validate IPN: sale_id is missing.');
         return false;
     }
     if (!isset($rawData['vendor_id'])) {
         $this->_throw('Unable to validate IPN: vendor_id is missing.');
         return false;
     }
     if (!isset($rawData['invoice_id'])) {
         $this->_throw('Unable to validate IPN: invoice_id is missing.');
         return false;
     }
     if (!isset($rawData['md5_hash'])) {
         $this->_throw('Unable to validate IPN: md5_hash is missing.');
         return false;
     }
     // Check vendor identity matches
     if ($vendorIdentity !== $rawData['vendor_id']) {
         $this->_throw(sprintf('Unable to validate IPN: vendor identities do not match - given %s, expected %s', $rawData['vendor_id'], $vendorIdentity));
         return false;
     }
     // Validate hash
     $givenHash = strtoupper($rawData['md5_hash']);
     $expectedHash = strtoupper(md5($rawData['sale_id'] . $rawData['vendor_id'] . $rawData['invoice_id'] . $vendorSecret));
     if ($givenHash !== $expectedHash) {
         $this->_throw(sprintf('Unable to validate IPN: hashes do not match - given %s, expected %s', $givenHash, $expectedHash));
         return false;
     }
     // Process data ------------------------------------------------------------
     $data = $rawData;
     return $data;
 }
 /**
  * Process an IPN
  *
  * @param Engine_Payment_Ipn $ipn
  * @return Engine_Payment_Plugin_Abstract
  */
 public function onIpn(Engine_Payment_Ipn $ipn)
 {
     $rawData = $ipn->getRawData();
     $ordersTable = Engine_Api::_()->getDbtable('orders', 'payment');
     $transactionsTable = Engine_Api::_()->getDbtable('transactions', 'payment');
     // Find transactions -------------------------------------------------------
     $transactionId = null;
     $transaction = null;
     // Fetch by invoice_id
     if (!empty($rawData['invoice_id'])) {
         $transaction = $transactionsTable->fetchRow(array('gateway_id = ?' => $this->_gatewayInfo->gateway_id, 'gateway_transaction_id = ?' => $rawData['invoice_id']));
     }
     if ($transaction && !empty($transaction->gateway_transaction_id)) {
         $transactionId = $transaction->gateway_transaction_id;
     } else {
         $transactionId = @$rawData['invoice_id'];
     }
     // Fetch order -------------------------------------------------------------
     $order = null;
     // Get order by vendor_order_id
     if (!$order && !empty($rawData['vendor_order_id'])) {
         $order = $ordersTable->find($rawData['vendor_order_id'])->current();
     }
     // Get order by invoice_id
     if (!$order && $transactionId) {
         $order = $ordersTable->fetchRow(array('gateway_id = ?' => $this->_gatewayInfo->gateway_id, 'gateway_transaction_id = ?' => $transactionId));
     }
     // Get order by sale_id
     if (!$order && !empty($rawData['sale_id'])) {
         $order = $ordersTable->fetchRow(array('gateway_id = ?' => $this->_gatewayInfo->gateway_id, 'gateway_order_id = ?' => $rawData['sale_id']));
     }
     // Get order by order_id through transaction
     if (!$order && $transaction && !empty($transaction->order_id)) {
         $order = $ordersTable->find($transaction->order_id)->current();
     }
     // Update order with order/transaction id if necessary
     $orderUpdated = false;
     if (!empty($rawData['invoice_id']) && empty($order->gateway_transaction_id)) {
         $orderUpdated = true;
         $order->gateway_transaction_id = $rawData['invoice_id'];
     }
     if (!empty($rawData['sale_id']) && empty($order->gateway_order_id)) {
         $orderUpdated = true;
         $order->gateway_order_id = $rawData['sale_id'];
     }
     if ($orderUpdated) {
         $order->save();
     }
     // Process generic IPN data ------------------------------------------------
     // Build transaction info
     if (!empty($rawData['invoice_id'])) {
         $transactionData = array('gateway_id' => $this->_gatewayInfo->gateway_id);
         // Get timestamp
         if (!empty($rawData['payment_date'])) {
             $transactionData['timestamp'] = date('Y-m-d H:i:s', strtotime($rawData['timestamp']));
         } else {
             $transactionData['timestamp'] = new Zend_Db_Expr('NOW()');
         }
         // Get amount
         if (!empty($rawData['invoice_list_amount'])) {
             $transactionData['amount'] = $rawData['invoice_list_amount'];
         } else {
             if ($transaction) {
                 $transactionData['amount'] = $transaction->amount;
             } else {
                 if (!empty($rawData['item_list_amount_1'])) {
                     // For recurring success
                     $transactionData['amount'] = $rawData['item_list_amount_1'];
                 }
             }
         }
         // Get currency
         if (!empty($rawData['list_currency'])) {
             $transactionData['currency'] = $rawData['list_currency'];
         } else {
             if ($transaction) {
                 $transactionData['currency'] = $transaction->currency;
             }
         }
         // Get order/user
         if ($order) {
             $transactionData['user_id'] = $order->user_id;
             $transactionData['order_id'] = $order->order_id;
         }
         // Get transactions
         if ($transactionId) {
             $transactionData['gateway_transaction_id'] = $transactionId;
         }
         if (!empty($rawData['sale_id'])) {
             $transactionData['gateway_order_id'] = $rawData['sale_id'];
         }
         // Get payment_status
         if (!empty($rawData['invoice_status'])) {
             if ($rawData['invoice_status'] == 'declined') {
                 $transactionData['type'] = 'payment';
                 $transactionData['state'] = 'failed';
             } else {
                 if ($rawData['fraud_status'] == 'fail') {
                     $transactionData['type'] = 'payment';
                     $transactionData['state'] = 'failed-fraud';
                 } else {
                     if ($rawData['fraud_status'] == 'wait') {
                         $transactionData['type'] = 'payment';
                         $transactionData['state'] = 'pending-fraud';
                     } else {
                         $transactionData['type'] = 'payment';
                         $transactionData['state'] = 'okay';
                     }
                 }
             }
         }
         if ($transaction && ($transaction->type == 'refund' || $transaction->state == 'refunded')) {
             $transactionData['type'] = $transaction->type;
             $transactionData['state'] = $transaction->state;
         }
         // Special case for refund_issued
         $childTransactionData = array();
         if ($rawData['message_type'] == 'REFUND_ISSUED') {
             $childTransactionData = $transactionData;
             $childTransactionData['gateway_parent_transaction_id'] = $childTransactionData['gateway_transaction_id'];
             //unset($childTransactionData['gateway_transaction_id']); // Should we unset this?
             $childTransactionData['amount'] = -$childTransactionData['amount'];
             $childTransactionData['type'] = 'refund';
             $childTransactionData['state'] = 'refunded';
             // Update parent transaction
             $transactionData['state'] = 'refunded';
         }
         // Insert or update transactions
         if (!$transaction) {
             $transactionsTable->insert($transactionData);
         } else {
             unset($transactionData['timestamp']);
             $transaction->setFromArray($transactionData);
             $transaction->save();
         }
         // Insert new child transaction
         if ($childTransactionData) {
             $childTransactionExists = $transactionsTable->select()->from($transactionsTable, new Zend_Db_Expr('TRUE'))->where('gateway_transaction_id = ?', $childTransactionData['gateway_transaction_id'])->where('type = ?', $childTransactionData['type'])->where('state = ?', $childTransactionData['state'])->limit(1)->query()->fetchColumn();
             if (!$childTransactionExists) {
                 $transactionsTable->insert($childTransactionData);
             }
         }
     }
     // Process specific IPN data -----------------------------------------------
     if ($order) {
         $ipnProcessed = false;
         // Subscription IPN
         if ($order->source_type == 'payment_subscription') {
             $this->onSubscriptionTransactionIpn($order, $ipn);
             $ipnProcessed = true;
         } else {
             // Custom item-type IPN
             if (Engine_Api::_()->hasItemType($order->source_type) && !empty($order->source_id)) {
                 $orderSourceObject = Engine_Api::_()->getItem($order->source_type, $order->source_id);
                 if (method_exists($orderSourceObject, 'onPaymentIpn')) {
                     $ipnProcessed = (bool) $orderSourceObject->onPaymentIpn($order, $ipn);
                 } else {
                     throw new Engine_Payment_Plugin_Exception(sprintf('Custom order ' . 'item "%s" does not implement onPaymentIpn() method', $order->source_type));
                 }
             } else {
                 $eventName = 'onPaymentIpn_' . Engine_Api::inflect($order->source_type);
                 $response = Engine_Hooks_Dispatcher::getInstance()->callEvent($eventName, array('order' => $order, 'ipn' => $ipn));
                 if (false != $response->getResponse()) {
                     // Okay
                     $ipnProcessed = true;
                 }
             }
         }
         // Unknown IPN - could not be processed
         if (!$ipnProcessed) {
             throw new Engine_Payment_Plugin_Exception('Unknown order type for IPN');
         }
     } else {
         throw new Engine_Payment_Plugin_Exception('Unknown or unsupported IPN ' . 'type, or missing transaction or order ID');
     }
     return $this;
 }
Exemple #6
0
 /**
  * Process an IPN
  *
  * @param Engine_Payment_Ipn $ipn
  * @return Engine_Payment_Plugin_Abstract
  */
 public function onIpn(Engine_Payment_Ipn $ipn)
 {
     $rawData = $ipn->getRawData();
     $ordersTable = Engine_Api::_()->getDbtable('orders', 'payment');
     $transactionsTable = Engine_Api::_()->getDbtable('transactions', 'payment');
     // Find transactions -------------------------------------------------------
     $transactionId = null;
     $parentTransactionId = null;
     $transaction = null;
     $parentTransaction = null;
     // Fetch by txn_id
     if (!empty($rawData['txn_id'])) {
         $transaction = $transactionsTable->fetchRow(array('gateway_id = ?' => $this->_gatewayInfo->gateway_id, 'gateway_transaction_id = ?' => $rawData['txn_id']));
         $parentTransaction = $transactionsTable->fetchRow(array('gateway_id = ?' => $this->_gatewayInfo->gateway_id, 'gateway_parent_transaction_id = ?' => $rawData['txn_id']));
     }
     // Fetch by parent_txn_id
     if (!empty($rawData['parent_txn_id'])) {
         if (!$transaction) {
             $parentTransaction = $transactionsTable->fetchRow(array('gateway_id = ?' => $this->_gatewayInfo->gateway_id, 'gateway_parent_transaction_id = ?' => $rawData['parent_txn_id']));
         }
         if (!$parentTransaction) {
             $parentTransaction = $transactionsTable->fetchRow(array('gateway_id = ?' => $this->_gatewayInfo->gateway_id, 'gateway_transaction_id = ?' => $rawData['parent_txn_id']));
         }
     }
     // Fetch by transaction->gateway_parent_transaction_id
     if ($transaction && !$parentTransaction && !empty($transaction->gateway_parent_transaction_id)) {
         $parentTransaction = $transactionsTable->fetchRow(array('gateway_id = ?' => $this->_gatewayInfo->gateway_id, 'gateway_parent_transaction_id = ?' => $transaction->gateway_parent_transaction_id));
     }
     // Fetch by parentTransaction->gateway_transaction_id
     if ($parentTransaction && !$transaction && !empty($parentTransaction->gateway_transaction_id)) {
         $transaction = $transactionsTable->fetchRow(array('gateway_id = ?' => $this->_gatewayInfo->gateway_id, 'gateway_parent_transaction_id = ?' => $parentTransaction->gateway_transaction_id));
     }
     // Get transaction id
     if ($transaction) {
         $transactionId = $transaction->gateway_transaction_id;
     } else {
         if (!empty($rawData['txn_id'])) {
             $transactionId = $rawData['txn_id'];
         }
     }
     // Get parent transaction id
     if ($parentTransaction) {
         $parentTransactionId = $parentTransaction->gateway_transaction_id;
     } else {
         if ($transaction && !empty($transaction->gateway_parent_transaction_id)) {
             $parentTransactionId = $transaction->gateway_parent_transaction_id;
         } else {
             if (!empty($rawData['parent_txn_id'])) {
                 $parentTransactionId = $rawData['parent_txn_id'];
             }
         }
     }
     // Fetch order -------------------------------------------------------------
     $order = null;
     // Transaction IPN - get order by invoice
     if (!$order && !empty($rawData['invoice'])) {
         $order = $ordersTable->find($rawData['invoice'])->current();
     }
     // Subscription IPN - get order by recurring_payment_id
     if (!$order && !empty($rawData['recurring_payment_id'])) {
         // Get attached order
         $order = $ordersTable->fetchRow(array('gateway_id = ?' => $this->_gatewayInfo->gateway_id, 'gateway_order_id = ?' => $rawData['recurring_payment_id']));
     }
     // Subscription IPN - get order by rp_invoice_id
     //if( !$order && !empty($rawData['rp_invoice_id']) ) {
     //
     //}
     // Transaction IPN - get order by parent_txn_id
     if (!$order && $parentTransactionId) {
         $order = $ordersTable->fetchRow(array('gateway_id = ?' => $this->_gatewayInfo->gateway_id, 'gateway_transaction_id = ?' => $parentTransactionId));
     }
     // Transaction IPN - get order by txn_id
     if (!$order && $transactionId) {
         $order = $ordersTable->fetchRow(array('gateway_id = ?' => $this->_gatewayInfo->gateway_id, 'gateway_transaction_id = ?' => $transactionId));
     }
     // Transaction IPN - get order through transaction
     if (!$order && !empty($transaction->order_id)) {
         $order = $ordersTable->find($parentTransaction->order_id)->current();
     }
     // Transaction IPN - get order through parent transaction
     if (!$order && !empty($parentTransaction->order_id)) {
         $order = $ordersTable->find($parentTransaction->order_id)->current();
     }
     // Process generic IPN data ------------------------------------------------
     // Build transaction info
     if (!empty($rawData['txn_id'])) {
         $transactionData = array('gateway_id' => $this->_gatewayInfo->gateway_id);
         // Get timestamp
         if (!empty($rawData['payment_date'])) {
             $transactionData['timestamp'] = date('Y-m-d H:i:s', strtotime($rawData['payment_date']));
         } else {
             $transactionData['timestamp'] = new Zend_Db_Expr('NOW()');
         }
         // Get amount
         if (!empty($rawData['mc_gross'])) {
             $transactionData['amount'] = $rawData['mc_gross'];
         }
         // Get currency
         if (!empty($rawData['mc_currency'])) {
             $transactionData['currency'] = $rawData['mc_currency'];
         }
         // Get order/user
         if ($order) {
             $transactionData['user_id'] = $order->user_id;
             $transactionData['order_id'] = $order->order_id;
         }
         // Get transactions
         if ($transactionId) {
             $transactionData['gateway_transaction_id'] = $transactionId;
         }
         if ($parentTransactionId) {
             $transactionData['gateway_parent_transaction_id'] = $parentTransactionId;
         }
         // Get payment_status
         switch ($rawData['payment_status']) {
             case 'Canceled_Reversal':
                 // @todo make sure this works
             // @todo make sure this works
             case 'Completed':
             case 'Created':
             case 'Processed':
                 $transactionData['type'] = 'payment';
                 $transactionData['state'] = 'okay';
                 break;
             case 'Denied':
             case 'Expired':
             case 'Failed':
             case 'Voided':
                 $transactionData['type'] = 'payment';
                 $transactionData['state'] = 'failed';
                 break;
             case 'Pending':
                 $transactionData['type'] = 'payment';
                 $transactionData['state'] = 'pending';
                 break;
             case 'Refunded':
                 $transactionData['type'] = 'refund';
                 $transactionData['state'] = 'refunded';
                 break;
             case 'Reversed':
                 $transactionData['type'] = 'reversal';
                 $transactionData['state'] = 'reversed';
                 break;
             default:
                 $transactionData = 'unknown';
                 break;
         }
         // Insert new transaction
         if (!$transaction) {
             $transactionsTable->insert($transactionData);
         } else {
             unset($transactionData['timestamp']);
             $transaction->setFromArray($transactionData);
             $transaction->save();
         }
         // Update parent transaction on refund?
         if ($parentTransaction && in_array($transactionData['type'], array('refund', 'reversal'))) {
             $parentTransaction->state = $transactionData['state'];
             $parentTransaction->save();
         }
     }
     // Process specific IPN data -----------------------------------------------
     if ($order) {
         $ipnProcessed = false;
         // Subscription IPN
         if ($order->source_type == 'payment_subscription') {
             $this->onSubscriptionTransactionIpn($order, $ipn);
             $ipnProcessed = true;
         } else {
             // Custom item-type IPN
             if (Engine_Api::_()->hasItemType($order->source_type) && !empty($order->source_id)) {
                 $orderSourceObject = Engine_Api::_()->getItem($order->source_type, $order->source_id);
                 if (method_exists($orderSourceObject, 'onPaymentIpn')) {
                     $ipnProcessed = (bool) $orderSourceObject->onPaymentIpn($order, $ipn);
                 } else {
                     throw new Engine_Payment_Plugin_Exception(sprintf('Custom order ' . 'item "%s" does not implement onPaymentIpn() method', $order->source_type));
                 }
             } else {
                 $eventName = 'onPaymentIpn_' . Engine_Api::inflect($order->source_type);
                 $response = Engine_Hooks_Dispatcher::getInstance()->callEvent($eventName, array('order' => $order, 'ipn' => $ipn));
                 if (false != $response->getResponse()) {
                     // Okay
                     $ipnProcessed = true;
                 }
             }
         }
         // Unknown IPN - could not be processed
         if (!$ipnProcessed) {
             throw new Engine_Payment_Plugin_Exception('Unknown order type for IPN');
         }
     } else {
         throw new Engine_Payment_Plugin_Exception('Unknown or unsupported IPN ' . 'type, or missing transaction or order ID');
     }
     return $this;
 }
 /**
  * Create an ipn object from specified parameters
  *
  * @return Engine_Payment_Ipn
  */
 public function createIpn(array $params)
 {
     $ipn = new Engine_Payment_Ipn($params);
     $ipn->process($this->getGateway());
     return $ipn;
 }