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; }
/** * 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; }