2 declare(strict_types
=1);
4 use wcf\data\
object\type\ObjectTypeCache
;
5 use wcf\system\exception\SystemException
;
6 use wcf\system\payment\type\IPaymentType
;
7 use wcf\util\HTTPRequest
;
8 use wcf\util\StringUtil
;
11 * Handles Paypal callbacks.
14 * @copyright 2001-2018 WoltLab GmbH
15 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
16 * @package WoltLabSuite\Core\Action
18 class PaypalCallbackAction
extends AbstractAction
{
22 public function execute() {
28 // post back to paypal to validate
29 /** @noinspection PhpUnusedLocalVariableInspection */
32 $url = 'https://www.paypal.com/cgi-bin/webscr';
33 if (!empty($_POST['test_ipn'])) {
34 // IPN simulator notification
35 $url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
38 $request = new HTTPRequest($url, [], array_merge(['cmd' => '_notify-validate'], $_POST));
40 $reply = $request->getReply();
41 $content = $reply['body'];
43 catch (SystemException
$e) {
44 throw new SystemException('connection to paypal.com failed: ' . $e->getMessage());
47 if (strpos($content, "VERIFIED") === false) {
48 throw new SystemException('request not validated');
52 if (!empty($_POST['charset']) && strtoupper($_POST['charset']) != 'UTF-8') {
53 foreach ($_POST as &$value) {
54 $value = StringUtil
::convertEncoding(strtoupper($_POST['charset']), 'UTF-8', $value);
58 // Check that receiver_email is your Primary PayPal email
59 if (strtolower($_POST['business']) != strtolower(PAYPAL_EMAIL_ADDRESS
) && (strtolower($_POST['receiver_email']) != strtolower(PAYPAL_EMAIL_ADDRESS
))) {
60 throw new SystemException('invalid business or receiver_email');
64 if (!isset($_POST['custom'])) {
65 throw new SystemException('invalid custom item');
67 $tokenParts = explode(':', $_POST['custom'], 2);
68 if (count($tokenParts) != 2) {
69 throw new SystemException('invalid custom item');
71 // get payment type object type
72 $objectType = ObjectTypeCache
::getInstance()->getObjectType(intval($tokenParts[0]));
73 if ($objectType === null ||
!($objectType->getProcessor() instanceof IPaymentType
)) {
74 throw new SystemException('invalid payment type id');
76 $processor = $objectType->getProcessor();
79 $transactionType = (!empty($_POST['txn_type']) ?
$_POST['txn_type'] : '');
80 $paymentStatus = (!empty($_POST['payment_status']) ?
$_POST['payment_status'] : '');
83 if ($transactionType == 'web_accept' ||
$transactionType == 'subscr_payment') {
84 if ($paymentStatus == 'Completed') {
85 $status = 'completed';
88 if ($paymentStatus == 'Refunded' ||
$paymentStatus == 'Reversed') {
91 if ($paymentStatus == 'Canceled_Reversal') {
92 $status = 'canceled_reversal';
96 $processor->processTransaction(ObjectTypeCache
::getInstance()->getObjectTypeIDByName('com.woltlab.wcf.payment.method', 'com.woltlab.wcf.payment.method.paypal'), $tokenParts[1], $_POST['mc_gross'], $_POST['mc_currency'], $_POST['txn_id'], $status, $_POST);
99 catch (SystemException
$e) {
100 @header
('HTTP/1.1 500 Internal Server Error');
101 echo $e->getMessage();
102 $e->getExceptionID(); // log error