Issues (12)

src/PushController.php (1 issue)

Severity
1
<?php
2
/**
3
 * Push Controller
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2022 Pronamic
7
 * @license   GPL-3.0-or-later
8
 * @package   Pronamic\WordPress\Pay\Gateways\DigiWallet
9
 */
10
11
namespace Pronamic\WordPress\Pay\Gateways\Buckaroo;
12
13
use Pronamic\WordPress\Pay\Payments\Payment;
14
use Pronamic\WordPress\Pay\Plugin;
15
16
/**
17
 * Push Controller
18
 *
19
 * @author  Remco Tolsma
20
 * @version 1.0.0
21
 * @since   1.0.0
22
 */
23
class PushController {
24
	/**
25
	 * Setup.
26
	 *
27
	 * @return void
28
	 */
29
	public function setup() {
30
		\add_action( 'rest_api_init', array( $this, 'rest_api_init' ) );
31
32
		\add_action( 'wp_loaded', array( $this, 'wp_loaded' ) );
33
	}
34
35
	/**
36
	 * REST API init.
37
	 *
38
	 * @link https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/
39
	 * @link https://developer.wordpress.org/reference/hooks/rest_api_init/
40
	 * @return void
41
	 */
42
	public function rest_api_init() {
43
		\register_rest_route(
44
			Integration::REST_ROUTE_NAMESPACE,
45
			'/push',
46
			array(
47
				'methods'             => array(
48
					'GET',
49
					'POST',
50
				),
51
				'callback'            => array( $this, 'rest_api_buckaroo_push' ),
52
				'permission_callback' => '__return_true',
53
			)
54
		);
55
	}
56
57
	/**
58
	 * REST API Buckaroo push handler.
59
	 *
60
	 * @param \WP_REST_Request $request Request.
61
	 * @return object
62
	 * @throws \Exception Throws exception when something unexpected happens ;-).
63
	 */
64
	public function rest_api_buckaroo_push( \WP_REST_Request $request ) {
65
		if ( $request->is_json_content_type() ) {
66
			return $this->handle_json_push( $request );
67
		}
68
69
		$content_type = $request->get_content_type();
70
71
		if ( null !== $content_type && 'application/x-www-form-urlencoded' === $content_type['value'] ) {
72
			return $this->handle_http_post_push( $request );
73
		}
74
75
		return new \WP_Error(
76
			'pronamic_pay_buckaroo_push_unknown_content_type',
77
			\sprintf(
78
				'Unknown Buckaroo push request content type: %s.',
79
				(string) $request->get_header( 'Content-Type' )
80
			),
81
			array( 'status' => 500 )
82
		);
83
	}
84
85
	/**
86
	 * Handle JSON push.
87
	 *
88
	 * @link https://dev.buckaroo.nl/PaymentMethods/Description/ideal
89
	 * @param \WP_REST_Request $request Request.
90
	 * @return object|\WP_Error
91
	 */
92
	private function handle_json_push( \WP_REST_Request $request ) {
93
		$json = $request->get_body();
94
95
		$data = \json_decode( $json );
96
97
		$transaction_key = $data->Transaction->Key;
98
99
		/**
100
		 * Process Refunds.
101
		 *
102
		 * @link https://support.buckaroo.nl/categorie%C3%ABn/integratie/transactietypes-overzicht
103
		 * @link https://dev.buckaroo.nl/PaymentMethods/Description/ideal
104
		 */
105
		foreach ( $data->Transaction->RelatedTransactions as $related_transaction ) {
106
			if ( 'refund' === $related_transaction->RelationType ) {
107
				$transaction_key = $related_transaction->RelatedTransactionKey;
108
			}
109
		}
110
111
		return $this->handle_transaction_key( $transaction_key );
112
	}
113
114
	/**
115
	 * Handle HTTP POST push.
116
	 *
117
	 * @param \WP_REST_Request $request Request.
118
	 * @return object|\WP_Error
119
	 */
120
	public function handle_http_post_push( \WP_REST_Request $request ) {
121
		$parameters = $request->get_params();
122
123
		$parameters = \array_change_key_case( $parameters, \CASE_LOWER );
124
125
		if ( ! \array_key_exists( 'brq_transactions', $parameters ) ) {
126
			return new \WP_Error(
127
				'rest_buckaroo_no_transactions_parameter',
128
				\__( 'The BRQ_TRANSACTIONS parameter is missing from the Buckaroo push request.', 'pronamic_ideal ' )
129
			);
130
		}
131
132
		/**
133
		 * The unique key for the transaction
134
		 * Important: the payment response also contains a parameter named
135
		 * brq_transactions, but may contain multiple transaction keys.
136
		 * The same field in the push response will always contain one single
137
		 * transaction key. For consistence, both fields have the same name.
138
		 *
139
		 * @link https://www.pronamic.nl/wp-content/uploads/2013/04/BPE-3.0-Gateway-HTML.1.02.pdf
140
		 */
141
		$transaction_key = $parameters['brq_transactions'];
142
143
		return $this->handle_transaction_key( $transaction_key );
144
	}
145
146
	/**
147
	 * Handle JSON request for specified transaction key.
148
	 *
149
	 * @param string $transaction_key Transaction key.
150
	 * @return object|\WP_Error
151
	 */
152
	private function handle_transaction_key( $transaction_key ) {
153
		$payment = \get_pronamic_payment_by_transaction_id( $transaction_key );
154
155
		if ( null === $payment ) {
156
			return new \WP_Error(
157
				'rest_buckaroo_unknown_transaction',
158
				\sprintf(
159
					/* translators: %s: Buckaroo transaction key. */
160
					\__( 'Unable to find payment for transaction key: %s.', 'pronamic_ideal ' ),
161
					$transaction_key
162
				),
163
				array( 'status' => 400 )
164
			);
165
		}
166
167
		// Add note.
168
		$note = \__( 'Push URL requested by Buckaroo.', 'pronamic_ideal' );
169
170
		$payment->add_note( $note );
171
172
		/**
173
		 * Log Buckaroo push URL request for payment.
174
		 *
175
		 * @param Payment $payment Payment.
176
		 */
177
		\do_action( 'pronamic_pay_webhook_log_payment', $payment );
178
179
		// Update payment.
180
		Plugin::update_payment( $payment, false );
181
182
		return \rest_ensure_response(
183
			array(
184
				'success'         => true,
185
				'transaction_key' => $transaction_key,
186
			)
187
		);
188
	}
189
190
	/**
191
	 * WordPress loaded, check for deprecated webhook call.
192
	 *
193
	 * @link https://github.com/WordPress/WordPress/blob/5.3/wp-includes/rest-api.php#L277-L309
194
	 * @return void
195
	 */
196
	public function wp_loaded() {
197
		if ( ! filter_has_var( INPUT_GET, 'buckaroo_push' ) ) {
198
			return;
199
		}
200
201
		\rest_get_server()->serve_request( '/pronamic-pay/buckaroo/v1/push' );
202
203
		exit;
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
204
	}
205
}
206