This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
1 | <?php |
||||
2 | /** |
||||
3 | * Paypal payment gateway |
||||
4 | * |
||||
5 | */ |
||||
6 | |||||
7 | defined( 'ABSPATH' ) || exit; |
||||
8 | |||||
9 | /** |
||||
10 | * Paypal Payment Gateway class. |
||||
11 | * |
||||
12 | */ |
||||
13 | class GetPaid_Paypal_Gateway extends GetPaid_Payment_Gateway { |
||||
14 | |||||
15 | /** |
||||
16 | * Payment method id. |
||||
17 | * |
||||
18 | * @var string |
||||
19 | */ |
||||
20 | public $id = 'paypal'; |
||||
21 | |||||
22 | /** |
||||
23 | * An array of features that this gateway supports. |
||||
24 | * |
||||
25 | * @var array |
||||
26 | */ |
||||
27 | protected $supports = array( 'subscription', 'sandbox', 'single_subscription_group', 'refunds' ); |
||||
28 | |||||
29 | /** |
||||
30 | * Payment method order. |
||||
31 | * |
||||
32 | * @var int |
||||
33 | */ |
||||
34 | public $order = 1; |
||||
35 | |||||
36 | /** |
||||
37 | * Stores line items to send to PayPal. |
||||
38 | * |
||||
39 | * @var array |
||||
40 | */ |
||||
41 | protected $line_items = array(); |
||||
42 | |||||
43 | /** |
||||
44 | * Endpoint for requests from PayPal. |
||||
45 | * |
||||
46 | * @var string |
||||
47 | */ |
||||
48 | protected $notify_url; |
||||
49 | |||||
50 | /** |
||||
51 | * Endpoint for requests to PayPal. |
||||
52 | * |
||||
53 | * @var string |
||||
54 | */ |
||||
55 | protected $endpoint; |
||||
56 | |||||
57 | /** |
||||
58 | * Currencies this gateway is allowed for. |
||||
59 | * |
||||
60 | * @var array |
||||
61 | */ |
||||
62 | public $currencies = array( 'AUD', 'BRL', 'CAD', 'MXN', 'NZD', 'HKD', 'SGD', 'USD', 'EUR', 'JPY', 'TRY', 'NOK', 'CZK', 'DKK', 'HUF', 'ILS', 'MYR', 'PHP', 'PLN', 'SEK', 'CHF', 'TWD', 'THB', 'GBP', 'RMB', 'RUB', 'INR' ); |
||||
63 | |||||
64 | /** |
||||
65 | * URL to view a transaction. |
||||
66 | * |
||||
67 | * @var string |
||||
68 | */ |
||||
69 | public $view_transaction_url = 'https://www.{sandbox}paypal.com/activity/payment/%s'; |
||||
70 | |||||
71 | /** |
||||
72 | * URL to view a subscription. |
||||
73 | * |
||||
74 | * @var string |
||||
75 | */ |
||||
76 | public $view_subscription_url = 'https://www.{sandbox}paypal.com/cgi-bin/webscr?cmd=_profile-recurring-payments&encrypted_profile_id=%s'; |
||||
77 | |||||
78 | /** |
||||
79 | * Class constructor. |
||||
80 | */ |
||||
81 | public function __construct() { |
||||
82 | parent::__construct(); |
||||
83 | |||||
84 | $this->title = __( 'PayPal Standard', 'invoicing' ); |
||||
85 | $this->method_title = __( 'PayPal Standard', 'invoicing' ); |
||||
86 | $this->checkout_button_text = __( 'Proceed to PayPal', 'invoicing' ); |
||||
87 | $this->notify_url = wpinv_get_ipn_url( $this->id ); |
||||
88 | |||||
89 | add_filter( 'wpinv_subscription_cancel_url', array( $this, 'filter_cancel_subscription_url' ), 10, 2 ); |
||||
90 | add_filter( 'getpaid_paypal_args', array( $this, 'process_subscription' ), 10, 2 ); |
||||
91 | add_filter( 'getpaid_get_paypal_connect_url', array( $this, 'maybe_get_connect_url' ), 10, 2 ); |
||||
92 | add_action( 'getpaid_authenticated_admin_action_connect_paypal', array( $this, 'connect_paypal' ) ); |
||||
93 | add_action( 'wpinv_paypal_connect', array( $this, 'display_connect_buttons' ) ); |
||||
94 | |||||
95 | if ( $this->enabled ) { |
||||
96 | add_filter( 'getpaid_paypal_sandbox_notice', array( $this, 'sandbox_notice' ) ); |
||||
97 | add_action( 'getpaid_paypal_subscription_cancelled', array( $this, 'subscription_cancelled' ) ); |
||||
98 | add_action( 'getpaid_delete_subscription', array( $this, 'subscription_cancelled' ) ); |
||||
99 | add_action( 'getpaid_refund_invoice_remotely', array( $this, 'refund_invoice' ) ); |
||||
100 | } |
||||
101 | } |
||||
102 | |||||
103 | /** |
||||
104 | * Process Payment. |
||||
105 | * |
||||
106 | * |
||||
107 | * @param WPInv_Invoice $invoice Invoice. |
||||
108 | * @param array $submission_data Posted checkout fields. |
||||
109 | * @param GetPaid_Payment_Form_Submission $submission Checkout submission. |
||||
110 | * @return array |
||||
111 | */ |
||||
112 | public function process_payment( $invoice, $submission_data, $submission ) { |
||||
113 | |||||
114 | // Get redirect url. |
||||
115 | $paypal_redirect = $this->get_request_url( $invoice ); |
||||
116 | |||||
117 | // Add a note about the request url. |
||||
118 | $invoice->add_note( |
||||
119 | sprintf( |
||||
120 | __( 'Redirecting to PayPal: %s', 'invoicing' ), |
||||
121 | esc_url( $paypal_redirect ) |
||||
122 | ), |
||||
123 | false, |
||||
124 | false, |
||||
125 | true |
||||
126 | ); |
||||
127 | |||||
128 | // Redirect to PayPal |
||||
129 | wp_redirect( $paypal_redirect ); |
||||
130 | exit; |
||||
0 ignored issues
–
show
|
|||||
131 | |||||
132 | } |
||||
133 | |||||
134 | /** |
||||
135 | * Get the PayPal request URL for an invoice. |
||||
136 | * |
||||
137 | * @param WPInv_Invoice $invoice Invoice object. |
||||
138 | * @return string |
||||
139 | */ |
||||
140 | public function get_request_url( $invoice ) { |
||||
141 | |||||
142 | // Endpoint for this request |
||||
143 | $this->endpoint = $this->is_sandbox( $invoice ) ? 'https://www.sandbox.paypal.com/cgi-bin/webscr?test_ipn=1&' : 'https://www.paypal.com/cgi-bin/webscr?'; |
||||
144 | |||||
145 | // Retrieve paypal args. |
||||
146 | $paypal_args = map_deep( $this->get_paypal_args( $invoice ), 'urlencode' ); |
||||
147 | |||||
148 | if ( $invoice->is_recurring() ) { |
||||
149 | $paypal_args['bn'] = 'GetPaid_Subscribe_WPS_US'; |
||||
150 | } else { |
||||
151 | $paypal_args['bn'] = 'GetPaid_ShoppingCart_WPS_US'; |
||||
152 | } |
||||
153 | |||||
154 | return add_query_arg( $paypal_args, $this->endpoint ); |
||||
155 | |||||
156 | } |
||||
157 | |||||
158 | /** |
||||
159 | * Get PayPal Args for passing to PP. |
||||
160 | * |
||||
161 | * @param WPInv_Invoice $invoice Invoice object. |
||||
162 | * @return array |
||||
163 | */ |
||||
164 | protected function get_paypal_args( $invoice ) { |
||||
165 | |||||
166 | // Whether or not to send the line items as one item. |
||||
167 | $force_one_line_item = apply_filters( 'getpaid_paypal_force_one_line_item', true, $invoice ); |
||||
168 | |||||
169 | if ( $invoice->is_recurring() || ( wpinv_use_taxes() && wpinv_prices_include_tax() ) ) { |
||||
170 | $force_one_line_item = true; |
||||
171 | } |
||||
172 | |||||
173 | $paypal_args = apply_filters( |
||||
174 | 'getpaid_paypal_args', |
||||
175 | array_merge( |
||||
176 | $this->get_transaction_args( $invoice ), |
||||
177 | $this->get_line_item_args( $invoice, $force_one_line_item ) |
||||
178 | ), |
||||
179 | $invoice |
||||
180 | ); |
||||
181 | |||||
182 | return $this->fix_request_length( $invoice, $paypal_args ); |
||||
183 | } |
||||
184 | |||||
185 | /** |
||||
186 | * Get transaction args for paypal request. |
||||
187 | * |
||||
188 | * @param WPInv_Invoice $invoice Invoice object. |
||||
189 | * @return array |
||||
190 | */ |
||||
191 | protected function get_transaction_args( $invoice ) { |
||||
192 | |||||
193 | $email = $this->is_sandbox( $invoice ) ? wpinv_get_option( 'paypal_sandbox_email', wpinv_get_option( 'paypal_email', '' ) ) : wpinv_get_option( 'paypal_email', '' ); |
||||
194 | return array( |
||||
195 | 'cmd' => '_cart', |
||||
196 | 'business' => $email, |
||||
197 | 'no_shipping' => '1', |
||||
198 | 'shipping' => '0', |
||||
199 | 'no_note' => '1', |
||||
200 | 'charset' => 'utf-8', |
||||
201 | 'rm' => is_ssl() ? 2 : 1, |
||||
202 | 'upload' => 1, |
||||
203 | 'currency_code' => $invoice->get_currency(), // https://developer.paypal.com/docs/nvp-soap-api/currency-codes/#paypal |
||||
204 | 'return' => esc_url_raw( $this->get_return_url( $invoice ) ), |
||||
205 | 'cancel_return' => esc_url_raw( $invoice->get_checkout_payment_url() ), |
||||
206 | 'notify_url' => getpaid_limit_length( $this->notify_url, 255 ), |
||||
207 | 'invoice' => getpaid_limit_length( $invoice->get_number(), 127 ), |
||||
208 | 'custom' => $invoice->get_id(), |
||||
209 | 'first_name' => getpaid_limit_length( $invoice->get_first_name(), 32 ), |
||||
210 | 'last_name' => getpaid_limit_length( $invoice->get_last_name(), 64 ), |
||||
211 | 'country' => getpaid_limit_length( $invoice->get_country(), 2 ), |
||||
212 | 'email' => getpaid_limit_length( $invoice->get_email(), 127 ), |
||||
213 | 'cbt' => get_bloginfo( 'name' ), |
||||
214 | ); |
||||
215 | |||||
216 | } |
||||
217 | |||||
218 | /** |
||||
219 | * Get line item args for paypal request. |
||||
220 | * |
||||
221 | * @param WPInv_Invoice $invoice Invoice object. |
||||
222 | * @param bool $force_one_line_item Create only one item for this invoice. |
||||
223 | * @return array |
||||
224 | */ |
||||
225 | protected function get_line_item_args( $invoice, $force_one_line_item = false ) { |
||||
226 | |||||
227 | // Maybe send invoice as a single item. |
||||
228 | if ( $force_one_line_item ) { |
||||
229 | return $this->get_line_item_args_single_item( $invoice ); |
||||
230 | } |
||||
231 | |||||
232 | // Send each line item individually. |
||||
233 | $line_item_args = array(); |
||||
234 | |||||
235 | // Prepare line items. |
||||
236 | $this->prepare_line_items( $invoice ); |
||||
237 | |||||
238 | // Add taxes to the cart |
||||
239 | if ( wpinv_use_taxes() && $invoice->is_taxable() ) { |
||||
240 | $line_item_args['tax_cart'] = wpinv_sanitize_amount( (float) $invoice->get_total_tax(), 2 ); |
||||
0 ignored issues
–
show
The call to
wpinv_sanitize_amount() has too many arguments starting with 2 .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||
241 | } |
||||
242 | |||||
243 | // Add discount. |
||||
244 | if ( $invoice->get_total_discount() > 0 ) { |
||||
245 | $line_item_args['discount_amount_cart'] = wpinv_sanitize_amount( (float) $invoice->get_total_discount(), 2 ); |
||||
246 | } |
||||
247 | |||||
248 | return array_merge( $line_item_args, $this->get_line_items() ); |
||||
249 | |||||
250 | } |
||||
251 | |||||
252 | /** |
||||
253 | * Get line item args for paypal request as a single line item. |
||||
254 | * |
||||
255 | * @param WPInv_Invoice $invoice Invoice object. |
||||
256 | * @return array |
||||
257 | */ |
||||
258 | protected function get_line_item_args_single_item( $invoice ) { |
||||
259 | $this->delete_line_items(); |
||||
260 | |||||
261 | $item_name = wp_sprintf( __( 'Invoice %s', 'invoicing' ), $invoice->get_number() ); |
||||
262 | $this->add_line_item( $item_name, 1, wpinv_round_amount( (float) $invoice->get_total(), 2, true ), $invoice->get_id() ); |
||||
0 ignored issues
–
show
It seems like
wpinv_round_amount((doub...->get_total(), 2, true) can also be of type string ; however, parameter $amount of GetPaid_Paypal_Gateway::add_line_item() does only seem to accept double , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
263 | |||||
264 | return $this->get_line_items(); |
||||
265 | } |
||||
266 | |||||
267 | /** |
||||
268 | * Return all line items. |
||||
269 | */ |
||||
270 | protected function get_line_items() { |
||||
271 | return $this->line_items; |
||||
272 | } |
||||
273 | |||||
274 | /** |
||||
275 | * Remove all line items. |
||||
276 | */ |
||||
277 | protected function delete_line_items() { |
||||
278 | $this->line_items = array(); |
||||
279 | } |
||||
280 | |||||
281 | /** |
||||
282 | * Prepare line items to send to paypal. |
||||
283 | * |
||||
284 | * @param WPInv_Invoice $invoice Invoice object. |
||||
285 | */ |
||||
286 | protected function prepare_line_items( $invoice ) { |
||||
287 | $this->delete_line_items(); |
||||
288 | |||||
289 | // Items. |
||||
290 | foreach ( $invoice->get_items() as $item ) { |
||||
291 | $amount = $item->get_price(); |
||||
292 | $quantity = $invoice->get_template() == 'amount' ? 1 : $item->get_quantity(); |
||||
293 | $this->add_line_item( $item->get_raw_name(), $quantity, $amount, $item->get_id() ); |
||||
294 | } |
||||
295 | |||||
296 | // Fees. |
||||
297 | foreach ( $invoice->get_fees() as $fee => $data ) { |
||||
298 | $this->add_line_item( $fee, 1, wpinv_sanitize_amount( $data['initial_fee'] ) ); |
||||
299 | } |
||||
300 | |||||
301 | } |
||||
302 | |||||
303 | /** |
||||
304 | * Add PayPal Line Item. |
||||
305 | * |
||||
306 | * @param string $item_name Item name. |
||||
307 | * @param float $quantity Item quantity. |
||||
308 | * @param float $amount Amount. |
||||
309 | * @param string $item_number Item number. |
||||
310 | */ |
||||
311 | protected function add_line_item( $item_name, $quantity = 1, $amount = 0.0, $item_number = '' ) { |
||||
312 | $index = ( count( $this->line_items ) / 4 ) + 1; |
||||
313 | |||||
314 | /** |
||||
315 | * Prevent error "Things don't appear to be working at the moment. (https://www.sandbox.paypal.com/webapps/hermes/error)" |
||||
316 | */ |
||||
317 | $item_name = str_replace( "#", "", $item_name ); |
||||
318 | |||||
319 | $item = apply_filters( |
||||
320 | 'getpaid_paypal_line_item', |
||||
321 | array( |
||||
322 | 'item_name' => html_entity_decode( getpaid_limit_length( $item_name ? wp_strip_all_tags( $item_name ) : __( 'Item', 'invoicing' ), 127 ), ENT_NOQUOTES, 'UTF-8' ), |
||||
323 | 'quantity' => (float) $quantity, |
||||
324 | 'amount' => wpinv_sanitize_amount( (float) $amount, 2 ), |
||||
0 ignored issues
–
show
The call to
wpinv_sanitize_amount() has too many arguments starting with 2 .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||
325 | 'item_number' => $item_number, |
||||
326 | ), |
||||
327 | $item_name, |
||||
328 | $quantity, |
||||
329 | $amount, |
||||
330 | $item_number |
||||
331 | ); |
||||
332 | |||||
333 | $this->line_items[ 'item_name_' . $index ] = getpaid_limit_length( $item['item_name'], 127 ); |
||||
334 | $this->line_items[ 'quantity_' . $index ] = $item['quantity']; |
||||
335 | |||||
336 | // The price or amount of the product, service, or contribution, not including shipping, handling, or tax. |
||||
337 | $this->line_items[ 'amount_' . $index ] = $item['amount'] * $item['quantity']; |
||||
338 | $this->line_items[ 'item_number_' . $index ] = getpaid_limit_length( $item['item_number'], 127 ); |
||||
339 | } |
||||
340 | |||||
341 | /** |
||||
342 | * If the default request with line items is too long, generate a new one with only one line item. |
||||
343 | * |
||||
344 | * https://support.microsoft.com/en-us/help/208427/maximum-url-length-is-2-083-characters-in-internet-explorer. |
||||
345 | * |
||||
346 | * @param WPInv_Invoice $invoice Invoice to be sent to Paypal. |
||||
347 | * @param array $paypal_args Arguments sent to Paypal in the request. |
||||
348 | * @return array |
||||
349 | */ |
||||
350 | protected function fix_request_length( $invoice, $paypal_args ) { |
||||
351 | $max_paypal_length = 2083; |
||||
352 | $query_candidate = http_build_query( $paypal_args, '', '&' ); |
||||
353 | |||||
354 | if ( strlen( $this->endpoint . $query_candidate ) <= $max_paypal_length ) { |
||||
355 | return $paypal_args; |
||||
356 | } |
||||
357 | |||||
358 | return apply_filters( |
||||
359 | 'getpaid_paypal_args', |
||||
360 | array_merge( |
||||
361 | $this->get_transaction_args( $invoice ), |
||||
362 | $this->get_line_item_args( $invoice, true ) |
||||
363 | ), |
||||
364 | $invoice |
||||
365 | ); |
||||
366 | |||||
367 | } |
||||
368 | |||||
369 | /** |
||||
370 | * Processes recurring invoices. |
||||
371 | * |
||||
372 | * @param array $paypal_args PayPal args. |
||||
373 | * @param WPInv_Invoice $invoice Invoice object. |
||||
374 | */ |
||||
375 | public function process_subscription( $paypal_args, $invoice ) { |
||||
376 | |||||
377 | // Make sure this is a subscription. |
||||
378 | if ( ! $invoice->is_recurring() || ! $subscription = getpaid_get_invoice_subscription( $invoice ) ) { |
||||
379 | return $paypal_args; |
||||
380 | } |
||||
381 | |||||
382 | // It's a subscription |
||||
383 | $paypal_args['cmd'] = '_xclick-subscriptions'; |
||||
384 | |||||
385 | // Subscription name. |
||||
386 | $paypal_args['item_name'] = wp_sprintf( __( 'Invoice %s', 'invoicing' ), $invoice->get_number() ); |
||||
387 | |||||
388 | // Get subscription args. |
||||
389 | $period = strtoupper( substr( $subscription->get_period(), 0, 1 ) ); |
||||
390 | $interval = (int) $subscription->get_frequency(); |
||||
391 | $bill_times = (int) $subscription->get_bill_times(); |
||||
392 | $initial_amount = (float) wpinv_sanitize_amount( $invoice->get_initial_total(), 2 ); |
||||
0 ignored issues
–
show
The call to
wpinv_sanitize_amount() has too many arguments starting with 2 .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||
393 | $recurring_amount = (float) wpinv_sanitize_amount( $invoice->get_recurring_total(), 2 ); |
||||
394 | $subscription_item = $invoice->get_recurring( true ); |
||||
395 | |||||
396 | // Convert 365 days to 1 year. |
||||
397 | if ( 'D' == $period && 365 == $interval ) { |
||||
398 | $period = 'Y'; |
||||
399 | $interval = 1; |
||||
400 | } |
||||
401 | |||||
402 | if ( $subscription_item->has_free_trial() ) { |
||||
403 | |||||
404 | $paypal_args['a1'] = 0 == $initial_amount ? 0 : $initial_amount; |
||||
405 | |||||
406 | // Trial period length. |
||||
407 | $paypal_args['p1'] = $subscription_item->get_trial_interval(); |
||||
408 | |||||
409 | // Trial period. |
||||
410 | $paypal_args['t1'] = $subscription_item->get_trial_period(); |
||||
411 | |||||
412 | } elseif ( $initial_amount != $recurring_amount ) { |
||||
413 | |||||
414 | // No trial period, but initial amount includes a sign-up fee and/or other items, so charge it as a separate period. |
||||
415 | |||||
416 | if ( 1 == $bill_times ) { |
||||
417 | $param_number = 3; |
||||
418 | } else { |
||||
419 | $param_number = 1; |
||||
420 | } |
||||
421 | |||||
422 | $paypal_args[ 'a' . $param_number ] = $initial_amount ? $initial_amount : 0; |
||||
423 | |||||
424 | // Sign Up interval |
||||
425 | $paypal_args[ 'p' . $param_number ] = $interval; |
||||
426 | |||||
427 | // Sign Up unit of duration |
||||
428 | $paypal_args[ 't' . $param_number ] = $period; |
||||
429 | |||||
430 | } |
||||
431 | |||||
432 | // We have a recurring payment |
||||
433 | if ( ! isset( $param_number ) || 1 == $param_number ) { |
||||
434 | |||||
435 | // Subscription price |
||||
436 | $paypal_args['a3'] = $recurring_amount; |
||||
437 | |||||
438 | // Subscription duration |
||||
439 | $paypal_args['p3'] = $interval; |
||||
440 | |||||
441 | // Subscription period |
||||
442 | $paypal_args['t3'] = $period; |
||||
443 | |||||
444 | } |
||||
445 | |||||
446 | // Recurring payments |
||||
447 | if ( 1 == $bill_times || ( $initial_amount != $recurring_amount && ! $subscription_item->has_free_trial() && 2 == $bill_times ) ) { |
||||
448 | |||||
449 | // Non-recurring payments |
||||
450 | $paypal_args['src'] = 0; |
||||
451 | |||||
452 | } else { |
||||
453 | |||||
454 | $paypal_args['src'] = 1; |
||||
455 | |||||
456 | if ( $bill_times > 0 ) { |
||||
457 | |||||
458 | // An initial period is being used to charge a sign-up fee |
||||
459 | if ( $initial_amount != $recurring_amount && ! $subscription_item->has_free_trial() ) { |
||||
460 | $bill_times--; |
||||
461 | } |
||||
462 | |||||
463 | // Make sure it's not over the max of 52 |
||||
464 | $paypal_args['srt'] = ( $bill_times <= 52 ? absint( $bill_times ) : 52 ); |
||||
465 | |||||
466 | } |
||||
467 | } |
||||
468 | |||||
469 | // Force return URL so that order description & instructions display |
||||
470 | $paypal_args['rm'] = 2; |
||||
471 | |||||
472 | // Get rid of redudant items. |
||||
473 | foreach ( array( 'item_name_1', 'quantity_1', 'amount_1', 'item_number_1' ) as $arg ) { |
||||
474 | |||||
475 | if ( isset( $paypal_args[ $arg ] ) ) { |
||||
476 | unset( $paypal_args[ $arg ] ); |
||||
477 | } |
||||
478 | } |
||||
479 | |||||
480 | return apply_filters( |
||||
481 | 'getpaid_paypal_subscription_args', |
||||
482 | $paypal_args, |
||||
483 | $invoice |
||||
484 | ); |
||||
485 | |||||
486 | } |
||||
487 | |||||
488 | /** |
||||
489 | * Refunds an invoice remotely. |
||||
490 | * |
||||
491 | * @since 2.8.24 |
||||
492 | * @param WPInv_Invoice $invoice Invoice object. |
||||
493 | */ |
||||
494 | public function refund_invoice( $invoice ) { |
||||
495 | |||||
496 | if ( $invoice->get_gateway() !== $this->id ) { |
||||
497 | return; |
||||
498 | } |
||||
499 | |||||
500 | $mode = $this->is_sandbox( $invoice ) ? 'sandbox' : 'live'; |
||||
501 | $result = GetPaid_PayPal_API::refund_capture( $invoice->get_transaction_id(), array(), $mode ); |
||||
502 | |||||
503 | if ( is_wp_error( $result ) ) { |
||||
504 | $invoice->add_system_note( |
||||
505 | sprintf( |
||||
506 | // translators: %s is the error message. |
||||
507 | __( 'An error occured while trying to refund invoice #%1$s in PayPal: %2$s', 'invoicing' ), |
||||
508 | $invoice->get_id(), |
||||
509 | $result->get_error_message() |
||||
510 | ) |
||||
511 | ); |
||||
512 | } else { |
||||
513 | $invoice->add_system_note( |
||||
514 | sprintf( |
||||
515 | // translators: %s is the refund ID. |
||||
516 | __( 'Successfully refunded invoice #%1$s in PayPal. Refund ID: %2$s', 'invoicing' ), |
||||
517 | $invoice->get_id(), |
||||
518 | $result->id |
||||
0 ignored issues
–
show
|
|||||
519 | ) |
||||
520 | ); |
||||
521 | } |
||||
522 | } |
||||
523 | |||||
524 | /** |
||||
525 | * Cancels a subscription remotely. |
||||
526 | * |
||||
527 | * @since 2.8.24 |
||||
528 | * @param WPInv_Subscription $subscription Subscription object. |
||||
529 | */ |
||||
530 | public function subscription_cancelled( $subscription ) { |
||||
531 | |||||
532 | if ( $subscription->get_gateway() != $this->id ) { |
||||
533 | return; |
||||
534 | } |
||||
535 | |||||
536 | $invoice = $subscription->get_parent_invoice(); |
||||
537 | |||||
538 | // Abort if the parent invoice does not exist. |
||||
539 | if ( ! $invoice->exists() ) { |
||||
540 | return; |
||||
541 | } |
||||
542 | |||||
543 | $mode = $this->is_sandbox( $invoice ) ? 'sandbox' : 'live'; |
||||
544 | $result = GetPaid_PayPal_API::cancel_subscription( |
||||
545 | $invoice->get_remote_subscription_id(), |
||||
546 | array( |
||||
547 | 'reason' => __(' Customer requested cancellation', 'invoicing' ), |
||||
548 | ), |
||||
549 | $mode |
||||
550 | ); |
||||
551 | |||||
552 | if ( is_wp_error( $result ) ) { |
||||
553 | |||||
554 | $error = sprintf( |
||||
555 | // translators: %s is the subscription ID. |
||||
556 | __( 'An error occured while trying to cancel subscription #%s in PayPal.', 'invoicing' ), |
||||
557 | $subscription->get_id() |
||||
558 | ); |
||||
559 | |||||
560 | getpaid_admin()->show_error( $error . ' ' . $result->get_error_message() ); |
||||
561 | |||||
562 | if ( ! is_admin() ) { |
||||
563 | wpinv_set_error( $result->get_error_code(), $error ); |
||||
564 | } |
||||
565 | |||||
566 | return; |
||||
567 | } |
||||
568 | |||||
569 | if ( is_admin() ) { |
||||
570 | getpaid_admin()->show_success( |
||||
571 | sprintf( |
||||
572 | // translators: %s is the subscription ID. |
||||
573 | __( 'Successfully cancelled subscription #%s in PayPal.', 'invoicing' ), |
||||
574 | $subscription->get_id() |
||||
575 | ) |
||||
576 | ); |
||||
577 | } |
||||
578 | |||||
579 | } |
||||
580 | |||||
581 | /** |
||||
582 | * Processes ipns and marks payments as complete. |
||||
583 | * |
||||
584 | * @return void |
||||
585 | */ |
||||
586 | public function verify_ipn() { |
||||
587 | new GetPaid_Paypal_Gateway_IPN_Handler( $this ); |
||||
588 | } |
||||
589 | |||||
590 | /** |
||||
591 | * Returns a sandbox notice. |
||||
592 | */ |
||||
593 | public function sandbox_notice() { |
||||
594 | |||||
595 | return sprintf( |
||||
596 | __( 'SANDBOX ENABLED. You can use sandbox testing accounts only. See the %1$sPayPal Sandbox Testing Guide%2$s for more details.', 'invoicing' ), |
||||
597 | '<a href="https://developer.paypal.com/docs/classic/lifecycle/ug_sandbox/">', |
||||
598 | '</a>' |
||||
599 | ); |
||||
600 | |||||
601 | } |
||||
602 | |||||
603 | /** |
||||
604 | * Filters the gateway settings. |
||||
605 | * |
||||
606 | * @param array $admin_settings |
||||
607 | */ |
||||
608 | public function admin_settings( $admin_settings ) { |
||||
609 | |||||
610 | $currencies = sprintf( |
||||
611 | __( 'Supported Currencies: %s', 'invoicing' ), |
||||
612 | implode( ', ', $this->currencies ) |
||||
613 | ); |
||||
614 | |||||
615 | $admin_settings['paypal_active']['desc'] .= " ($currencies)"; |
||||
616 | $admin_settings['paypal_desc']['std'] = __( 'Pay via PayPal: you can pay with your credit card if you don\'t have a PayPal account.', 'invoicing' ); |
||||
617 | |||||
618 | // Access tokens. |
||||
619 | $live_email = wpinv_get_option( 'paypal_email' ); |
||||
0 ignored issues
–
show
|
|||||
620 | $sandbox_email = wpinv_get_option( 'paypal_sandbox_email' ); |
||||
0 ignored issues
–
show
|
|||||
621 | |||||
622 | $admin_settings['paypal_connect'] = array( |
||||
623 | 'type' => 'hook', |
||||
624 | 'id' => 'paypal_connect', |
||||
625 | 'name' => __( 'Connect to PayPal', 'invoicing' ), |
||||
626 | ); |
||||
627 | |||||
628 | $admin_settings['paypal_email'] = array( |
||||
629 | 'type' => 'text', |
||||
630 | 'class' => 'live-auth-data', |
||||
631 | 'id' => 'paypal_email', |
||||
632 | 'name' => __( 'Live Email Address', 'invoicing' ), |
||||
633 | 'desc' => __( 'The email address of your PayPal account.', 'invoicing' ), |
||||
634 | ); |
||||
635 | |||||
636 | $admin_settings['paypal_sandbox_email'] = array( |
||||
637 | 'type' => 'text', |
||||
638 | 'class' => 'sandbox-auth-data', |
||||
639 | 'id' => 'paypal_sandbox_email', |
||||
640 | 'name' => __( 'Sandbox Email Address', 'invoicing' ), |
||||
641 | 'desc' => __( 'The email address of your sandbox PayPal account.', 'invoicing' ), |
||||
642 | 'std' => wpinv_get_option( 'paypal_email', '' ), |
||||
643 | ); |
||||
644 | |||||
645 | // Client ID and secret. |
||||
646 | $admin_settings['paypal_client_id'] = array( |
||||
647 | 'type' => 'text', |
||||
648 | 'class' => 'live-auth-data', |
||||
649 | 'id' => 'paypal_client_id', |
||||
650 | 'name' => __( 'Live Client ID', 'invoicing' ), |
||||
651 | 'desc' => __( 'The client ID of your PayPal account. You can retrieve this from your PayPal developer account.', 'invoicing' ), |
||||
652 | ); |
||||
653 | |||||
654 | $admin_settings['paypal_sandbox_client_id'] = array( |
||||
655 | 'type' => 'text', |
||||
656 | 'class' => 'sandbox-auth-data', |
||||
657 | 'id' => 'paypal_sandbox_client_id', |
||||
658 | 'name' => __( 'Sandbox Client ID', 'invoicing' ), |
||||
659 | 'desc' => __( 'The client ID of your sandbox PayPal account. You can retrieve this from your PayPal developer account.', 'invoicing' ), |
||||
660 | 'std' => wpinv_get_option( 'paypal_client_id', '' ), |
||||
661 | ); |
||||
662 | |||||
663 | $admin_settings['paypal_secret'] = array( |
||||
664 | 'type' => 'text', |
||||
665 | 'class' => 'live-auth-data', |
||||
666 | 'id' => 'paypal_secret', |
||||
667 | 'name' => __( 'Live Secret', 'invoicing' ), |
||||
668 | 'desc' => __( 'The secret of your PayPal account. You can retrieve this from your PayPal developer account.', 'invoicing' ), |
||||
669 | ); |
||||
670 | |||||
671 | $admin_settings['paypal_sandbox_secret'] = array( |
||||
672 | 'type' => 'text', |
||||
673 | 'class' => 'sandbox-auth-data', |
||||
674 | 'id' => 'paypal_sandbox_secret', |
||||
675 | 'name' => __( 'Sandbox Secret', 'invoicing' ), |
||||
676 | 'desc' => __( 'The secret of your sandbox PayPal account. You can retrieve this from your PayPal developer account.', 'invoicing' ), |
||||
677 | ); |
||||
678 | |||||
679 | $admin_settings['paypal_ipn_url'] = array( |
||||
680 | 'type' => 'ipn_url', |
||||
681 | 'id' => 'paypal_ipn_url', |
||||
682 | 'name' => __( 'IPN Url', 'invoicing' ), |
||||
683 | 'std' => $this->notify_url, |
||||
684 | 'desc' => __( "If you've not enabled IPNs in your paypal account, use the above URL to enable them.", 'invoicing' ) . ' <a href="https://developer.paypal.com/docs/api-basics/notifications/ipn/"><em>' . __( 'Learn more.', 'invoicing' ) . '</em></a>', |
||||
685 | 'readonly' => true, |
||||
686 | ); |
||||
687 | |||||
688 | return $admin_settings; |
||||
689 | } |
||||
690 | |||||
691 | /** |
||||
692 | * Retrieves the URL to cancel a subscription. |
||||
693 | * |
||||
694 | * @param string $url |
||||
695 | * @param WPInv_Subscription $subscription |
||||
696 | */ |
||||
697 | public function filter_cancel_subscription_url( $url, $subscription ) { |
||||
698 | |||||
699 | if ( $this->id !== $subscription->get_gateway() ) { |
||||
700 | return $url; |
||||
701 | } |
||||
702 | |||||
703 | // Get the PayPal profile ID. |
||||
704 | $profile_id = $subscription->get_profile_id(); |
||||
705 | |||||
706 | // Bail if no profile ID. |
||||
707 | if ( empty( $profile_id ) ) { |
||||
708 | return $url; |
||||
709 | } |
||||
710 | |||||
711 | $cancel_url = 'https://www.paypal.com/myaccount/autopay/connect/%s/cancel'; |
||||
712 | if ( $this->is_sandbox( $subscription->get_parent_payment() ) ) { |
||||
713 | $cancel_url = 'https://www.sandbox.paypal.com/myaccount/autopay/connect/%s/cancel'; |
||||
714 | } |
||||
715 | |||||
716 | return sprintf( $cancel_url, $profile_id ); |
||||
717 | } |
||||
718 | |||||
719 | /** |
||||
720 | * Retrieves the PayPal connect URL when using the setup wizzard. |
||||
721 | * |
||||
722 | * |
||||
723 | * @param array $data |
||||
724 | * @return string |
||||
725 | */ |
||||
726 | public static function maybe_get_connect_url( $url = '', $data = array() ) { |
||||
727 | return self::get_connect_url( false, urldecode( $data['redirect'] ) ); |
||||
728 | } |
||||
729 | |||||
730 | /** |
||||
731 | * Retrieves the PayPal connect URL. |
||||
732 | * |
||||
733 | * |
||||
734 | * @param bool $is_sandbox |
||||
735 | * @param string $redirect |
||||
736 | * @return string |
||||
737 | */ |
||||
738 | public static function get_connect_url( $is_sandbox, $redirect = '' ) { |
||||
739 | |||||
740 | $redirect_url = add_query_arg( |
||||
741 | array( |
||||
742 | 'getpaid-admin-action' => 'connect_paypal', |
||||
743 | 'page' => 'wpinv-settings', |
||||
744 | 'live_mode' => (int) empty( $is_sandbox ), |
||||
745 | 'tab' => 'gateways', |
||||
746 | 'section' => 'paypal', |
||||
747 | 'getpaid-nonce' => wp_create_nonce( 'getpaid-nonce' ), |
||||
748 | 'redirect' => urlencode( $redirect ), |
||||
749 | ), |
||||
750 | admin_url( 'admin.php' ) |
||||
751 | ); |
||||
752 | |||||
753 | return add_query_arg( |
||||
754 | array( |
||||
755 | 'live_mode' => (int) empty( $is_sandbox ), |
||||
756 | 'redirect_url' => urlencode( str_replace( '&', '&', $redirect_url ) ), |
||||
757 | ), |
||||
758 | 'https://ayecode.io/oauth/paypal' |
||||
759 | ); |
||||
760 | |||||
761 | } |
||||
762 | |||||
763 | /** |
||||
764 | * Generates settings page js. |
||||
765 | * |
||||
766 | * @return void |
||||
767 | */ |
||||
768 | public static function display_connect_buttons() { |
||||
769 | |||||
770 | ?> |
||||
771 | <div class="wpinv-paypal-connect-live"> |
||||
772 | <a class="button button-primary" href="<?php echo esc_url( self::get_connect_url( false ) ); ?>"><?php esc_html_e( 'Connect to PayPal', 'invoicing' ); ?></a> |
||||
773 | </div> |
||||
774 | <div class="wpinv-paypal-connect-sandbox"> |
||||
775 | <a class="button button-primary" href="<?php echo esc_url( self::get_connect_url( true ) ); ?>"><?php esc_html_e( 'Connect to PayPal Sandbox', 'invoicing' ); ?></a> |
||||
776 | </div> |
||||
777 | |||||
778 | <script> |
||||
779 | jQuery(document).ready(function() { |
||||
780 | |||||
781 | jQuery( '#wpinv-settings-paypal_sandbox' ).on ( 'change', function( e ) { |
||||
782 | |||||
783 | jQuery( '.wpinv-paypal-connect-live, .live-auth-data' ).toggle( ! this.checked ) |
||||
784 | jQuery( '.wpinv-paypal-connect-sandbox, .sandbox-auth-data' ).toggle( this.checked ) |
||||
785 | |||||
786 | if ( this.checked ) { |
||||
787 | |||||
788 | if ( jQuery('#wpinv-settings-paypal_sandbox_email').val().length > 0 ) { |
||||
789 | jQuery('.wpinv-paypal-connect-sandbox').closest('tr').hide() |
||||
790 | } else { |
||||
791 | jQuery('.wpinv-paypal-connect-sandbox').closest('tr').show() |
||||
792 | } |
||||
793 | } else { |
||||
794 | if ( jQuery('#wpinv-settings-paypal_email').val().length > 0 ) { |
||||
795 | jQuery('.wpinv-paypal-connect-live').closest('tr').hide() |
||||
796 | } else { |
||||
797 | jQuery('.wpinv-paypal-connect-live').closest('tr').show() |
||||
798 | } |
||||
799 | } |
||||
800 | }) |
||||
801 | |||||
802 | // Set initial state. |
||||
803 | jQuery( '#wpinv-settings-paypal_sandbox' ).trigger( 'change' ) |
||||
804 | |||||
805 | }); |
||||
806 | </script> |
||||
807 | <?php |
||||
808 | } |
||||
809 | |||||
810 | /** |
||||
811 | * Connects to PayPal. |
||||
812 | * |
||||
813 | * @param array $data Connection data. |
||||
814 | * @return void |
||||
815 | */ |
||||
816 | public function connect_paypal( $data ) { |
||||
817 | |||||
818 | $sandbox = $this->is_sandbox(); |
||||
819 | $data = wp_unslash( $data ); |
||||
820 | $access_token = empty( $data['access_token'] ) ? '' : sanitize_text_field( $data['access_token'] ); |
||||
821 | |||||
822 | if ( isset( $data['live_mode'] ) ) { |
||||
823 | $sandbox = empty( $data['live_mode'] ); |
||||
824 | } |
||||
825 | |||||
826 | wpinv_update_option( 'paypal_sandbox', (int) $sandbox ); |
||||
827 | wpinv_update_option( 'paypal_active', 1 ); |
||||
828 | |||||
829 | if ( ! empty( $data['error_description'] ) ) { |
||||
830 | getpaid_admin()->show_error( wp_kses_post( urldecode( $data['error_description'] ) ) ); |
||||
831 | } else { |
||||
832 | |||||
833 | // Retrieve the user info. |
||||
834 | $user_info = wp_remote_get( |
||||
835 | ! $sandbox ? 'https://api-m.paypal.com/v1/identity/oauth2/userinfo?schema=paypalv1.1' : 'https://api-m.sandbox.paypal.com/v1/identity/oauth2/userinfo?schema=paypalv1.1', |
||||
836 | array( |
||||
837 | |||||
838 | 'headers' => array( |
||||
839 | 'Authorization' => 'Bearer ' . $access_token, |
||||
840 | 'Content-type' => 'application/json', |
||||
841 | ), |
||||
842 | |||||
843 | ) |
||||
844 | ); |
||||
845 | |||||
846 | if ( is_wp_error( $user_info ) ) { |
||||
847 | getpaid_admin()->show_error( wp_kses_post( $user_info->get_error_message() ) ); |
||||
848 | } else { |
||||
849 | |||||
850 | // Create application. |
||||
851 | $user_info = json_decode( wp_remote_retrieve_body( $user_info ) ); |
||||
852 | |||||
853 | if ( $sandbox ) { |
||||
854 | wpinv_update_option( 'paypal_sandbox_email', sanitize_email( $user_info->emails[0]->value ) ); |
||||
855 | wpinv_update_option( 'paypal_sandbox_refresh_token', sanitize_text_field( urldecode( $data['refresh_token'] ) ) ); |
||||
856 | set_transient( 'getpaid_paypal_sandbox_access_token', sanitize_text_field( urldecode( $data['access_token'] ) ), (int) $data['expires_in'] ); |
||||
857 | getpaid_admin()->show_success( __( 'Successfully connected your PayPal sandbox account', 'invoicing' ) ); |
||||
858 | } else { |
||||
859 | wpinv_update_option( 'paypal_email', sanitize_email( $user_info->emails[0]->value ) ); |
||||
860 | wpinv_update_option( 'paypal_refresh_token', sanitize_text_field( urldecode( $data['refresh_token'] ) ) ); |
||||
861 | set_transient( 'getpaid_paypal_access_token', sanitize_text_field( urldecode( $data['access_token'] ) ), (int) $data['expires_in'] ); |
||||
862 | getpaid_admin()->show_success( __( 'Successfully connected your PayPal account', 'invoicing' ) ); |
||||
863 | } |
||||
864 | } |
||||
865 | } |
||||
866 | |||||
867 | $redirect = empty( $data['redirect'] ) ? admin_url( 'admin.php?page=wpinv-settings&tab=gateways§ion=paypal' ) : urldecode( $data['redirect'] ); |
||||
868 | |||||
869 | if ( isset( $data['step'] ) ) { |
||||
870 | $redirect = add_query_arg( 'step', $data['step'], $redirect ); |
||||
871 | } |
||||
872 | wp_redirect( $redirect ); |
||||
873 | exit; |
||||
0 ignored issues
–
show
|
|||||
874 | } |
||||
875 | |||||
876 | } |
||||
877 |
In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.