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 }