Объясните, как работает PayPal (процесс IPN и PDT). Глава первая Глава третья
Глава вторая
Эта глава представляет реальный проект: «регистрация с оплатой», от начала до конца, чтобы лучше объяснить настройку учетной записи PayPal и интеграцию с формой регистрации и базой данных.
Сценарий проекта
- Во-первых, у нас есть форма регистрации.
- После правильного заполнения формы (все проверки пройдены), пользователь нажимает кнопку «Зарегистрироваться».
- Затем перенаправьте на PayPal, пользователь оплатит регистрационный взнос.
- После оплаты PayPal перенаправит на страницу результатов и через 10 секунд автоматически перенаправит обратно на наш сайт, после чего PayPal PDT обработает платежную запись.
- Но пользователь может закрыть браузер, поэтому мы должны внедрить PayPal IPN для плана резервного копирования.
Структура базы данных
Диаграмма ER:
- таблица temp_register: временное хранилище учетной записи и пароля пользователя, дождитесь оплаты. Если оплачено, кортеж будет удален и перемещен в таблицу пользователей.
- Таблица платежей: uid — это внешний ключ, ссылающийся на пользователей, для связи информации о пользователе и информации о платеже.
- Таблица пользователей: хранит информацию о пользователях, токен является токеном подтверждения в электронном письме с подтверждением. Если пользователь подтвердил свою учетную запись, будет установлено значение 1.
Схема базы данных:
CREATE TABLE IF NOT EXISTS `payment` ( `payId` int(11) NOT NULL AUTO_INCREMENT, `timestamp` bigint(20) DEFAULT NULL, `paid` float DEFAULT NULL COMMENT 'user paid amount returned by paypal', `bankFee` float DEFAULT NULL, `currency` varchar(4) DEFAULT NULL, `txnId` varchar(32) DEFAULT NULL COMMENT 'Transaction ID: specify single unique transaction from paypal. if this field is NOT NULL, means this payment has been process already. So if IPN returns to PHP, we can refuse to update our database.', `status` varchar(16) DEFAULT NULL, `uid` int(11) DEFAULT NULL COMMENT 'FK to users PK', PRIMARY KEY (`payId`), KEY `uid` (`uid`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; CREATE TABLE IF NOT EXISTS `temp_register` ( `tRegId` int(11) NOT NULL AUTO_INCREMENT, `fullName` varchar(255) DEFAULT NULL, `uAcc` varchar(255) DEFAULT NULL, `uPwd` varchar(32) DEFAULT NULL, PRIMARY KEY (`tRegId`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='prevent unpaid user take uAcc(UNIQUE) in our users table' AUTO_INCREMENT=1 ; CREATE TABLE IF NOT EXISTS `users` ( `uid` int(11) NOT NULL AUTO_INCREMENT, `fullName` varchar(255) DEFAULT NULL, `uAcc` varchar(255) NOT NULL, `uPwd` varchar(32) NOT NULL, `token` varchar(32) DEFAULT NULL, `verified` tinyint(1) NOT NULL DEFAULT '0', `priviledge` enum('delegate','admin','developer') NOT NULL DEFAULT 'delegate', PRIMARY KEY (`uid`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; ALTER TABLE `payment` ADD CONSTRAINT `payment_ibfk_1` FOREIGN KEY (`uid`) REFERENCES `users` (`uid`);
Пользовательский интерфейс
Рабочий процесс проекта
- Заполните форму, и все входные данные будут проверены.
- Нажмите кнопку Зарегистрироваться, перенаправьте на PayPal.
- Песочница PayPal «Pay Now»:
- Перенаправить страницу результатов PayPal.
- Дождитесь перенаправления (PDT работает), покажите страницу успеха / сбоя или закройте браузер (IPN работает).
Настройка PayPal Sandbox
Прежде чем мы начнем кодировать, нам нужно сначала настроить учетную запись PayPal Sandbox.
Предположим, вы зарегистрировали учетную запись разработчика PayPal и создали одну учетную запись бизнес-пользователя и одну учетную запись покупателя в Sandbox.
Затем выберите бизнес-аккаунт и нажмите кнопку «Войти в тестовый сайт песочницы».
Вы можете увидеть всплывающую страницу главной панели:
Затем вы можете увидеть всю информацию и настройки продаж.
Итак, давайте настроим все три варианта по порядку.
1. Включить PDT и настройки
Настройте функцию вызова вашего PDT-обработчика.
2. Включить IPN и настройки
Настройте свой IPN обработчик вызова функции URL.
2. Создайте кнопку PayPal и настройки параметров PayPal
После сохранения изменений вы можете увидеть исходный код кнопки PayPal:
Легко узнать, что кнопка на самом деле является формой, поэтому нам нужно POST-данные, используя ее входные данные.
Когда мы генерируем нашу кнопку «зарегистрироваться», URL перенаправления должен содержать «& cmd = _s-xclick» и «& hosted_button_id = HA9DZBCKXKCL2».
Теперь учетная запись PayPal Sandbox настроена. Затем начните кодировать ваши обработчики PDT и IPN.
Функция обработчика PDT
Исходный код:
/** * PAYPAL: PDT HANDLER: * ==================== * called by PayPal, send tokens back * get payment details and payment result * @return $ret array contains result true/false, and user account or error message */ private function _PDT() { // some indexes can not be missing: $ruler = array( 'tx', // token from paypal ); if(count(array_diff($ruler, array_keys($_GET)))) { return array('result' => false, 'error' => 'Index missing ... ', 'index' => $_GET, 'missing' => array_diff($ruler, array_keys($_GET))); } // read the post from PayPal system and add 'cmd' $req = 'cmd=_notify-synch'; // get token and prepare request url (send back to paypal) $tx_token = $_GET['tx'];$auth_token = "_PJaHiwRfwMmWzW-9nuPuSguYxC-1d9KpxaasaNANtIvyOcmqY6jXNkRmxW"; // $auth_token = "OxDenzKmrWPyEXU0YzIg2zs-VAe7ufCADyjbfxF_RpREL4rLEslZrSa21R4"; $req .= "&tx=$tx_token&at=$auth_token"; // post back to PayPal system to validate $header = "POST /cgi-bin/webscr HTTP/1.0rn"; $header .= "Host: www.sandbox.paypal.comrn"; // $header .= "Host: www.paypal.comrn"; $header .= "Content-Type: application/x-www-form-urlencodedrn"; $header .= "Content-Length: " . strlen($req) . "rnrn"; $fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30); // open socket // $fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30); // open socket if (!$fp) { // HTML FAIL return array('result' => false, 'error' => 'HTTP error ... '); } else { fputs ($fp, $header . $req); // read the body data $res = ''; $headerdone = false; while (!feof($fp)) { $line = fgets ($fp, 1024); if (strcmp($line, "rn") == 0) { $headerdone = true; // read the header } else if ($headerdone) { $res .= $line; // header has been read. now read the contents } } // parse the data $lines = explode("n", $res); $keyarray = array(); if (strcmp ($lines[0], "SUCCESS") == 0) { for ($i=1; $i_validatePaypal($keyarray); } // log for manual investigation else if (strcmp ($lines[0], "FAIL") == 0) { // skipped return array('result' => false, 'error' => 'Transaction failed ... '); } } fclose ($fp); return $ret; }
Объяснение:
PayPal вызывает функцию PDTHandler (), затем эта функция-обработчик обрабатывает _PDT (). Как видите, он получает параметры, предоставленные PayPal, с URL ($ _GET). Таким образом, мы отправляем токен и отправляем обратно в PayPal через fsock ssl. Затем PayPal вернет платежную запись и результат платежа (SUCCESS / FAIL). _PDT () передает эти данные в _validatePaypal (), которая сохраняет данные в базе данных. Затем перенаправьте страницу в соответствии с возвратом.
Функция обработчика IPN
Исходный код:
/** * PAYPAL: IPN HANDLER: * ==================== * called by PayPal, send POSTed payment data back (handshake) * get payment result * return: payment VERIFIED: array('result' => true/false, and other user details) * payment INVALID: false // no further process (see handler in Register Module) * TODO: return true if success, then send email to buyers */ private function _IPN() { // get IPN data $postData = $_POST;// read the post from PayPal system and add 'cmd' $req = 'cmd=' . urlencode('_notify-validate'); foreach ($postData as $key => $value) { $value = urlencode(stripslashes($value)); $req .= "&$key=$value"; } // CURL: copy from paypal sample code $url= 'https://www.sandbox.paypal.com/cgi-bin/webscr'; // $url= 'https://www.paypal.com/cgi-bin/webscr'; $curl_result=$curl_err=''; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $req); curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/x-www-form-urlencoded", "Content-Length: " . strlen($req))); curl_setopt($ch, CURLOPT_HEADER , array('Host: www.sandbox.paypal.com')); // curl_setopt($ch, CURLOPT_HEADER , array('Host: www.paypal.com')); curl_setopt($ch, CURLOPT_VERBOSE, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_TIMEOUT, 30); $res = @curl_exec($ch); $curl_err = curl_error($ch); curl_close($ch); $keyarray = $postData; if (strcmp (substr($res, '-8'), "VERIFIED") == 0) { // validate paypal information return $this->_validatePaypal($keyarray); } elseif (strcmp (substr($res, '-7'), "INVALID") == 0) { // log for manual investigation return false; } // return $ret; // Do not need to return, because IPN runs in background }
Объяснение:
PayPal вызывает функцию IPNHandler (), затем эта функция-обработчик обрабатывает _ IPN (). Как видите, он получает данные, предоставленные PayPal, из запроса ($ _POST). Поэтому мы отправляем платежные реквизиты обратно в PayPal через cURL, это процесс рукопожатия. Затем PayPal отправляет обратно результат платежа (ПРОВЕРЕНО / НЕВЕРНО). Если это проверено, _IPN () передает эти данные _validatePaypal (), который сохраняет данные в базу данных.
В zip-файле он содержит шаблоны, файлы javascript, css, bootstrap, jquery, плагин отладки и плагин smarty, а также весь основной исходный код php.