File indexing completed on 2025-05-04 05:32:14

0001 <?php
0002 /**
0003  *  ocs-webserver
0004  *
0005  *  Copyright 2016 by pling GmbH.
0006  *
0007  *    This file is part of ocs-webserver.
0008  *
0009  *    This program is free software: you can redistribute it and/or modify
0010  *    it under the terms of the GNU Affero General Public License as
0011  *    published by the Free Software Foundation, either version 3 of the
0012  *    License, or (at your option) any later version.
0013  *
0014  *    This program is distributed in the hope that it will be useful,
0015  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017  *    GNU Affero General Public License for more details.
0018  *
0019  *    You should have received a copy of the GNU Affero General Public License
0020  *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
0021  **/
0022 
0023 abstract class Local_Payment_PayPal_SubscriptionCancel_Ipn extends Local_Payment_PayPal_Base
0024 {
0025 
0026     const VERIFIED = 'VERIFIED';
0027 
0028     /** @var \Zend_Config */
0029     protected $_config;
0030     /** @var \Zend_Log */
0031     protected $_logger;
0032     /** @var  array */
0033     protected $_dataIpn;
0034     /** @var  \Local_Payment_PayPal_PaymentInterface */
0035     protected $_ipnMessage;
0036 
0037     protected $_dataRaw;
0038 
0039     /**
0040      * @param $rawData
0041      *
0042      * @throws Exception
0043      */
0044     public function processIpn($rawData)
0045     {
0046         $this->_config = Zend_Registry::get('config');
0047         $this->_logger = Zend_Registry::get('logger');
0048 
0049         if (false === $this->verifyIpnOrigin($rawData)) {
0050             $this->_logger->err(' ' . __FUNCTION__ . '::Abort Subscription IPN processing. IPN not verified: ' . $rawData);
0051             $this->_logger->info(' ' . __FUNCTION__ . '::Abort Subscription IPN processing. IPN not verified: ' . $rawData);
0052 
0053             return;
0054         }
0055 
0056         $this->_dataRaw = $rawData;
0057         $this->_dataIpn = $this->_parseRawMessage($rawData);
0058         $this->_ipnMessage = Local_Payment_PayPal_Response::buildResponse($this->_dataIpn);
0059 
0060         if (false === $this->validateTransaction()) {
0061             $this->_logger->err(' ' . __FUNCTION__ . '::Abort Subscription IPN processing. Transaction not valid:' . $rawData);
0062 
0063             return;
0064         }
0065 
0066         $this->processSubscriptionCancel();
0067     }
0068 
0069     /**
0070      * @param string $rawDataIpn
0071      *
0072      * @return bool
0073      */
0074     public function verifyIpnOrigin($rawDataIpn)
0075     {
0076         $raw_post_array = explode('&', $rawDataIpn);
0077         $myPost = array();
0078         foreach ($raw_post_array as $keyval) {
0079             $keyval = explode('=', $keyval);
0080             if (count($keyval) == 2) {
0081                 $myPost[$keyval[0]] = urldecode($keyval[1]);
0082             }
0083         }
0084         // read the IPN message sent from PayPal and prepend 'cmd=_notify-validate'
0085         $req = 'cmd=_notify-validate';
0086         if (function_exists('get_magic_quotes_gpc')) {
0087             $get_magic_quotes_exists = true;
0088         }
0089         foreach ($myPost as $key => $value) {
0090             if ($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
0091                 $value = urlencode(stripslashes($value));
0092             } else {
0093                 $value = urlencode($value);
0094             }
0095             $req .= "&$key=$value";
0096         }
0097 
0098         // Step 2: POST IPN data back to PayPal to validate
0099         $url = $this->_config->third_party->paypal->masspay->ipn->endpoint . "/webscr";
0100         //$ch = curl_init('https://ipnpb.paypal.com/cgi-bin/webscr');
0101         $ch = curl_init($url);
0102         curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
0103         curl_setopt($ch, CURLOPT_POST, 1);
0104         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
0105         curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
0106         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
0107         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
0108         curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
0109         curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
0110         // In wamp-like environments that do not come bundled with root authority certificates,
0111         // please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set
0112         // the directory path of the certificate as shown below:
0113         // curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
0114         if (!($res = curl_exec($ch))) {
0115             // error_log("Got " . curl_error($ch) . " when processing IPN data");
0116             $this->_logger->err(" " . __FUNCTION__ . "Got " . curl_error($ch) . " when processing IPN data");
0117             $this->_logger->info(" " . __FUNCTION__ . "Got " . curl_error($ch) . " when processing IPN data");
0118             curl_close($ch);
0119             exit;
0120         }
0121         curl_close($ch);
0122 
0123         if (strcmp($res, "VERIFIED") == 0) {
0124             // The IPN is verified, process it
0125             return true;
0126         } else if (strcmp($res, "INVALID") == 0) {
0127             // IPN invalid, log for manual investigation
0128             return false;
0129         }
0130 
0131         return false;
0132     }
0133 
0134     /**
0135      * @return bool
0136      */
0137     protected function validateTransaction()
0138     {
0139         // Make sure the receiver email address is one of yours and the
0140         // amount of money is correct
0141 
0142         //return $this->_checkEmail() AND $this->_checkTxnId() AND $this->_checkAmount();
0143         return true;
0144     }
0145 
0146     protected function processSubscriptionCancel()
0147     {
0148         $this->_logger->info(' ' . __FUNCTION__ . ' IPN: ' . print_r($this->_ipnMessage, true));
0149         
0150         $this->_processSubscriptionCancel();
0151         
0152         $this->_logger->info(' ' . __FUNCTION__ . ' DONE');
0153     }
0154 
0155     /**
0156      * Transaction/Payment completed.
0157      *
0158      * For Mass Payments, this means that all of your payments have been claimed,
0159      * or after a period of 30 days, unclaimed payments have been returned to you.
0160      */
0161     protected function _processSubscriptionCancel()
0162     {
0163         $this->_logger->info(' ' . __FUNCTION__ . ' set Status');
0164 
0165         $Table = new Default_Model_DbTable_Support();
0166         $Table->deactivateSupportSubscriptionSignupFromResponse($this->_ipnMessage);
0167     }
0168 
0169     public function getCharset($rawDataIpn)
0170     {
0171         $matches = array();
0172 
0173         preg_match('|charset=(.*?)\&|', $rawDataIpn, $matches);
0174 
0175         return $matches[1];
0176     }
0177 
0178     /**
0179      * @param string $requestData
0180      * @param string $url
0181      *
0182      * @return string
0183      * @throws Local_Payment_Exception
0184      * @throws Zend_Http_Client_Exception
0185      */
0186     protected function _makeRequest($requestData, $url)
0187     {
0188         $http = new Zend_Http_Client($url);
0189         $http->setMethod(Zend_Http_Client::POST);
0190         $http->setRawData($requestData);
0191 
0192         try {
0193             $response = $http->request();
0194         } catch (Zend_Http_Client_Exception $e) {
0195             throw new Local_Payment_Exception('Error while request PayPal website.', 0, $e);
0196         }
0197 
0198         if (false === $response) {
0199             $this->_logger->err(__FUNCTION__ . "::Error while request PayPal Website.\n Server replay was: " . $http->getLastResponse()
0200                                                                                                                     ->getStatus()
0201                 . ". " . $http->getLastResponse()->getMessage() . "\n");
0202             $this->_logger->err(__FUNCTION__ . '::Last Request: ' . print_r($http->getLastRequest(), true));
0203             $this->_logger->err(__FUNCTION__ . '::Headers: ' . print_r($response->getHeaders(), true));
0204             $this->_logger->err(__FUNCTION__ . '::Body: ' . print_r($response->getBody(), true) . "\n");
0205         } else {
0206             $this->_logger->debug(__FUNCTION__ . '::Last Request: ' . print_r($http->getLastRequest(), true));
0207             $this->_logger->debug(__FUNCTION__ . '::Headers: ' . print_r($response->getHeaders(), true));
0208             $this->_logger->debug(__FUNCTION__ . '::Body: ' . print_r($response->getBody(), true) . "\n");
0209         }
0210 
0211         return $response->getBody();
0212     }
0213 
0214     /**
0215      * Check email address for validity.
0216      * Override this method to make sure you are the one being paid.
0217      * Throw an Exception if data is invalid or other things go wrong.
0218      *
0219      * $this->_dataIpn['receiver_email'] = The email who is about to receive payment.
0220      */
0221     protected function _checkEmail()
0222     {
0223         // check that receiver_email is your Primary PayPal email
0224 
0225         $this->_logger->info('Not doing _checkEmail(' . $this->_dataIpn['receiver_email'] . ')');
0226 
0227         return false;
0228     }
0229 
0230     /**
0231      * Check txnId has not already been used.
0232      * Override this method to ensure txnId is not a duplicate.
0233      * Throw an Exception if data is invalid or other things go wrong.
0234      *
0235      * $this->_dataIpn['txn_id'] = The transaction ID from paypal.
0236      */
0237     protected function _checkTxnId()
0238     {
0239         // check that txn_id has not been previously processed
0240 
0241         $this->_logger->info('Not doing _checkTxnId(' . $this->_ipnMessage->getTransactionId() . ')');
0242 
0243         return false;
0244     }
0245 
0246     /**
0247      * Check that the amount/currency is correct for item_id.
0248      * You should override this method to ensure the amount is correct.
0249      * Throw an Exception if data is invalid or other things go wrong.
0250      *
0251      * $this->_dataIpn['item_number'] = The item number
0252      * $this->_dataIpn['mc_gross']    = The amount being paid
0253      * $this->_dataIpn['mc_currency'] = Currency code of amount
0254      */
0255     protected function _checkAmount()
0256     {
0257         // check that payment_amount/payment_currency are correct
0258 
0259         $this->_logger->info('Not doing _checkAmount(' . $this->_dataIpn['mc_gross'] . ', ' . $this->_dataIpn['mc_currency'] . ')');
0260 
0261         return false;
0262     }
0263 
0264 }