Merge branch 'master' into next
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / action / PaypalCallbackAction.class.php
1 <?php
2 declare(strict_types=1);
3 namespace wcf\action;
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;
9
10 /**
11 * Handles Paypal callbacks.
12 *
13 * @author Marcel Werk
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
17 */
18 class PaypalCallbackAction extends AbstractAction {
19 /**
20 * @inheritDoc
21 */
22 public function execute() {
23 parent::execute();
24
25 // check response
26 $processor = null;
27 try {
28 // post back to paypal to validate
29 /** @noinspection PhpUnusedLocalVariableInspection */
30 $content = '';
31 try {
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';
36 }
37
38 $request = new HTTPRequest($url, [], array_merge(['cmd' => '_notify-validate'], $_POST));
39 $request->execute();
40 $reply = $request->getReply();
41 $content = $reply['body'];
42 }
43 catch (SystemException $e) {
44 throw new SystemException('connection to paypal.com failed: ' . $e->getMessage());
45 }
46
47 if (strpos($content, "VERIFIED") === false) {
48 throw new SystemException('request not validated');
49 }
50
51 // fix encoding
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);
55 }
56 }
57
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');
61 }
62
63 // get token
64 if (!isset($_POST['custom'])) {
65 throw new SystemException('invalid custom item');
66 }
67 $tokenParts = explode(':', $_POST['custom'], 2);
68 if (count($tokenParts) != 2) {
69 throw new SystemException('invalid custom item');
70 }
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');
75 }
76 $processor = $objectType->getProcessor();
77
78 // get status
79 $transactionType = (!empty($_POST['txn_type']) ? $_POST['txn_type'] : '');
80 $paymentStatus = (!empty($_POST['payment_status']) ? $_POST['payment_status'] : '');
81
82 $status = '';
83 if ($transactionType == 'web_accept' || $transactionType == 'subscr_payment') {
84 if ($paymentStatus == 'Completed') {
85 $status = 'completed';
86 }
87 }
88 if ($paymentStatus == 'Refunded' || $paymentStatus == 'Reversed') {
89 $status = 'reversed';
90 }
91 if ($paymentStatus == 'Canceled_Reversal') {
92 $status = 'canceled_reversal';
93 }
94
95 if ($status) {
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);
97 }
98 }
99 catch (SystemException $e) {
100 @header('HTTP/1.1 500 Internal Server Error');
101 echo $e->getMessage();
102 $e->getExceptionID(); // log error
103 exit;
104 }
105 }
106 }