Test Failed
Push — master ( 315839...9b266f )
by Devin
05:39
created

Give_Stripe_Gateway::set_api_version()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 32

Duplication

Lines 32
Ratio 100 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 0
dl 32
loc 32
rs 9.408
c 0
b 0
f 0
1
<?php
2
/**
3
 * Give - Stripe Core Gateway
4
 *
5
 * @since 2.5.0
6
 *
7
 * @package    Give
8
 * @subpackage Stripe Core
9
 * @copyright  Copyright (c) 2019, GiveWP
10
 * @license    https://opensource.org/licenses/gpl-license GNU Public License
11
 */
12
13
// Exit, if accessed directly.
14
if ( ! defined( 'ABSPATH' ) ) {
15
	exit;
16
}
17
18
/**
19
 * Check for class Give_Stripe_Gateway exists.
20
 *
21
 * @since 2.5.0
22
 */
23
if ( ! class_exists( 'Give_Stripe_Gateway' ) ) {
24
25
	class Give_Stripe_Gateway {
26
27
		/**
28
		 * Default Gateway ID.
29
		 *
30
		 * @since  2.5.0
31
		 * @access public
32
		 *
33
		 * @var string
34
		 */
35
		public $id;
36
37
		/**
38
		 * Set Latest Stripe Version.
39
		 *
40
		 * @since  2.5.0
41
		 * @access public
42
		 *
43
		 * @var string
44
		 */
45
		public $api_version = '2019-03-14';
46
47
		/**
48
		 * Secret API Key.
49
		 *
50
		 * @access private
51
		 *
52
		 * @var string
53
		 */
54
		private $secret_key = '';
55
56
		/**
57
		 * Payment Intent.
58
		 *
59
		 * @since  2.5.0
60
		 * @access public
61
		 *
62
		 * @var \Stripe\PaymentIntent
63
		 */
64
		public $payment_intent;
65
66
		/**
67
		 * Stripe Payment Method Object.
68
		 *
69
		 * @since  2.5.0
70
		 * @access public
71
		 *
72
		 * @var Give_Stripe_Payment_Method
73
		 */
74
		public $payment_method;
75
76
		/**
77
		 * Give_Stripe_Gateway constructor.
78
		 *
79
		 * @since  2.5.0
80
		 * @access public
81
		 *
82
		 * @return bool|void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
83
		 */
84
		public function __construct() {
85
86
			// Set secret key received from Stripe.
87
			$this->secret_key = give_stripe_get_secret_key();
88
89
			// Set API Version.
90
			$this->set_api_version();
91
92
			// Call Payment Intent Class to utilize.
93
			$this->payment_intent = new Give_Stripe_Payment_Intent();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Give_Stripe_Payment_Intent() of type object<Give_Stripe_Payment_Intent> is incompatible with the declared type object<Stripe\PaymentIntent> of property $payment_intent.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
94
			$this->payment_method = new Give_Stripe_Payment_Method();
95
96
			add_action( "give_gateway_{$this->id}", array( $this, 'process_payment' ) );
97
98
		}
99
100
		/**
101
		 * This function will help to set the latest Stripe API version.
102
		 *
103
		 * @since  2.5.0
104
		 * @access public
105
		 *
106
		 * @return void
107
		 */
108 View Code Duplication
		public function set_api_version() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
109
110
			// Set Application Info.
111
			give_stripe_set_app_info();
112
113
			try {
114
115
				// Set API Version to latest.
116
				\Stripe\Stripe::setApiVersion( $this->api_version );
117
118
			} catch ( \Stripe\Error\Base $e ) {
119
120
				// Log Error.
121
				$this->log_error( $e );
122
123
			} catch ( Exception $e ) {
124
125
				// Something went wrong outside of Stripe.
126
				give_record_gateway_error(
127
					__( 'Stripe Error', 'give' ),
128
					sprintf(
129
						/* translators: %s Exception Message Body */
130
						__( 'Unable to set Stripe API Version. Details: %s', 'give' ),
131
						$e->getMessage()
132
					)
133
				);
134
				give_set_error( 'stripe_error', __( 'An error occurred while processing the donation. Please try again.', 'give' ) );
135
136
				// Send donor back to checkout page on error.
137
				$this->send_back_to_checkout();
138
			}
139
		}
140
141
		/**
142
		 * Send back to checkout based on the gateway id.
143
		 *
144
		 * @since  2.5.0
145
		 * @access public
146
		 *
147
		 * @return void
148
		 */
149
		public function send_back_to_checkout() {
150
			give_send_back_to_checkout( '?payment-mode=' . $this->id );
151
		}
152
153
		/**
154
		 * This function will be used to fetch token details from token id.
155
		 *
156
		 * @param string $id   Stripe Token ID.
157
		 * @param array  $args Additional arguments.
158
		 *
159
		 * @since  2.5.0
160
		 * @access public
161
		 *
162
		 * @return \Stripe\Token
163
		 */
164
		public function get_token_details( $id, $args = array() ) {
165
166
			// Set Application Info.
167
			give_stripe_set_app_info();
168
169
			try {
170
171
				$args = wp_parse_args( $args, give_stripe_get_connected_account_options() );
172
173
				// Retrieve Token Object.
174
				return \Stripe\Token::retrieve( $id, $args );
175
176
			} catch ( \Stripe\Error\Base $e ) {
177
				$this->log_error( $e );
178
			} catch ( Exception $e ) {
179
180
				// Something went wrong outside of Stripe.
181
				give_record_gateway_error(
182
					__( 'Stripe Token Error', 'give' ),
183
					sprintf(
184
						/* translators: %s Exception Message Body */
185
						__( 'Unable to retrieve token. Details: %s', 'give' ),
186
						$e->getMessage()
187
					)
188
				);
189
				give_set_error( 'stripe_error', __( 'An error occurred while processing the donation. Please try again.', 'give' ) );
190
191
				// Send donor back to checkout page on error.
192
				$this->send_back_to_checkout();
193
			}
194
		}
195
196
		/**
197
		 * This function will be used to fetch source details from source id.
198
		 *
199
		 * @param string $id Stripe Source ID.
200
		 *
201
		 * @since  2.5.0
202
		 * @access public
203
		 *
204
		 * @return \Stripe\Source
205
		 */
206 View Code Duplication
		public function get_source_details( $id ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
207
208
			// Set Application Info.
209
			give_stripe_set_app_info();
210
211
			try {
212
213
				// Retrieve Source Object.
214
				return \Stripe\Source::retrieve( $id, give_stripe_get_connected_account_options() );
215
216
			} catch ( \Stripe\Error\Base $e ) {
217
				$this->log_error( $e );
218
			} catch ( Exception $e ) {
219
220
				// Something went wrong outside of Stripe.
221
				give_record_gateway_error(
222
					__( 'Stripe Source Error', 'give' ),
223
					sprintf(
224
						/* translators: %s Exception Message Body */
225
						__( 'Unable to retrieve source. Details: %s', 'give' ),
226
						$e->getMessage()
227
					)
228
				);
229
				give_set_error( 'stripe_error', __( 'An error occurred while processing the donation. Please try again.', 'give' ) );
230
231
				// Send donor back to checkout page on error.
232
				$this->send_back_to_checkout();
233
			}
234
		}
235
236
		/**
237
		 * This function will prepare source based on the parameters provided.
238
		 *
239
		 * @param array $args List of arguments \Stripe\Source::create() supports.
240
		 *
241
		 * @since  2.5.0
242
		 * @access public
243
		 *
244
		 * @return \Stripe\Source
245
		 */
246 View Code Duplication
		public function prepare_source( $args ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
247
248
			// Set Application Info.
249
			give_stripe_set_app_info();
250
251
			try {
252
253
				// Create Source Object.
254
				return \Stripe\Source::create( $args, give_stripe_get_connected_account_options() );
255
256
			} catch ( \Stripe\Error\Base $e ) {
257
				$this->log_error( $e );
258
			} catch ( Exception $e ) {
259
260
				// Something went wrong outside of Stripe.
261
				give_record_gateway_error(
262
					__( 'Stripe Error', 'give' ),
263
					sprintf(
264
						/* translators: %s Exception Message Body */
265
						__( 'Unable to create source. Details: %s', 'give' ),
266
						$e->getMessage()
267
					)
268
				);
269
				give_set_error( 'stripe_error', __( 'An error occurred while processing the donation. Please try again.', 'give' ) );
270
271
				// Send donor back to checkout page on error.
272
				$this->send_back_to_checkout();
273
			}
274
		}
275
276
		/**
277
		 * Get Customer's card.
278
		 *
279
		 * @param \Stripe\Customer $stripe_customer Stripe Customer Object.
280
		 * @param string           $id              Source or Token ID.
281
		 *
282
		 * @since 2.5.0
283
		 *
284
		 * @return \Stripe\Source|bool
285
		 */
286
		public function get_customer_card( $stripe_customer, $id ) {
287
288
			$card_exists = false;
289
			$all_sources = $stripe_customer->sources->all();
290
291
			if ( give_stripe_is_checkout_enabled() && 'stripe' === $this->id ) {
292
				$card = $this->get_token_details( $id );
293
			} else {
294
				$card = $this->get_source_details( $id );
295
			}
296
297
			$source_list = wp_list_pluck( $all_sources->data, 'id' );
298
299
			// Check whether the source is already attached to customer or not.
300
			if ( in_array( $id, $source_list, true ) ) {
301
				$card_exists = true;
302
			}
303
304
			// Create the card if none found above.
305
			if ( ! $card_exists ) {
306
				try {
307
308
					// Attach Source to existing Customer.
309
					$card = $stripe_customer->sources->create( array(
310
						'source' => $id,
311
					) );
312
313
				} catch ( \Stripe\Error\Base $e ) {
314
315
					// Log Error.
316
					$this->log_error( $e );
317
318
				} catch ( Exception $e ) {
319
320
					give_record_gateway_error(
321
						__( 'Stripe Card Error', 'give' ),
322
						sprintf(
323
							/* translators: %s Exception Error Message */
324
							__( 'The Stripe Gateway returned an error while processing a donation. Details: %s', 'give' ),
325
							$e->getMessage()
326
						)
327
					);
328
329
					// Send donor back to checkout page on error.
330
					$this->send_back_to_checkout();
331
				}
332
			}
333
334
			// Return Card Details, if exists.
335
			if ( ! empty( $card->id ) ) {
336
				return $card;
337
			} else {
338
339
				give_set_error( 'stripe_error', __( 'An error occurred while processing the donation. Please try again.', 'give' ) );
340
				give_record_gateway_error( __( 'Stripe Error', 'give' ), __( 'An error occurred retrieving or creating the ', 'give' ) );
341
342
				// Send donor back to checkout page on error.
343
				$this->send_back_to_checkout();
344
345
				return false;
346
			}
347
		}
348
349
		/**
350
		 * Save Stripe Customer ID.
351
		 *
352
		 * @param string $stripe_customer_id Customer ID.
353
		 * @param int    $payment_id         Payment ID.
354
		 *
355
		 * @since 2.5.0
356
		 */
357
		public function save_stripe_customer_id( $stripe_customer_id, $payment_id ) {
358
359
			// Update customer meta.
360
			if ( class_exists( 'Give_DB_Donor_Meta' ) ) {
361
362
				$donor_id = give_get_payment_donor_id( $payment_id );
363
364
				// Get the Give donor.
365
				$donor = new Give_Donor( $donor_id );
366
367
				// Update donor meta.
368
				$donor->update_meta( give_stripe_get_customer_key(), $stripe_customer_id );
369
370
			} elseif ( is_user_logged_in() ) {
371
372
				// Support saving to legacy method of user method.
373
				update_user_meta( get_current_user_id(), give_stripe_get_customer_key(), $stripe_customer_id );
374
375
			}
376
377
		}
378
379
		/**
380
		 * Log a Stripe Error.
381
		 *
382
		 * Logs in the Give db the error and also displays the error message to the donor.
383
		 *
384
		 * @param \Stripe\Error\Base|\Stripe\Error\Card $exception    Exception.
385
		 *
386
		 * @since 2.5.0
387
		 *
388
		 * @return bool
389
		 */
390
		public function log_error( $exception ) {
391
392
			$log_message = __( 'The Stripe payment gateway returned an error while processing the donation.', 'give' ) . '<br><br>';
393
			$exception_message = $exception->getMessage();
394
395
			// Bad Request of some sort.
396
			if ( ! empty( $exception_message ) ) {
397
				$log_message .= sprintf(
398
					/* translators: %s Exception Message */
399
					__( 'Message: %s', 'give' ),
400
					$exception_message
401
				) . '<br><br>';
402
403
				$trace_string = $exception->getTraceAsString();
404
405
				if ( ! empty( $trace_string ) ) {
406
					$log_message .= sprintf(
407
						/* translators: %s Trace String */
408
						__( 'Code: %s', 'give' ),
409
						$trace_string
410
					);
411
				}
412
413
				give_set_error( 'stripe_request_error', $exception_message );
414
			} else {
415
				give_set_error( 'stripe_request_error', __( 'The Stripe API request was invalid, please try again.', 'give' ) );
416
			}
417
418
			// Log it with DB.
419
			give_record_gateway_error( __( 'Stripe Error', 'give' ), $log_message );
420
421
			// Send donor back to checkout page on error.
422
			$this->send_back_to_checkout();
423
424
			return false;
425
426
		}
427
428
		/**
429
		 * Format currency for Stripe.
430
		 *
431
		 * @see https://support.stripe.com/questions/which-zero-decimal-currencies-does-stripe-support
432
		 *
433
		 * @param float $amount Donation amount.
434
		 *
435
		 * @return mixed
436
		 */
437
		public function format_amount( $amount ) {
438
439
			// Get the donation amount.
440
			if ( give_stripe_is_zero_decimal_currency() ) {
441
				return $amount;
442
			} else {
443
				return $amount * 100;
444
			}
445
		}
446
447
		/**
448
		 * Verify Payment.
449
		 *
450
		 * @param int            $payment_id         Payment ID.
451
		 * @param string         $stripe_customer_id Customer ID.
452
		 * @param \Stripe\Charge $charge             Stripe Charge Object.
453
		 */
454
		public function verify_payment( $payment_id, $stripe_customer_id, $charge ) {
455
456
			// Sanity checks: verify all vars exist.
457
			if ( $payment_id && ( ! empty( $stripe_customer_id ) || ! empty( $charge ) ) ) {
458
459
				/**
460
				 * This action hook is used to perform some additional steps to verify the payment.
461
				 *
462
				 * @param int            $payment_id         Payment ID.
463
				 * @param string         $stripe_customer_id Customer ID.
464
				 * @param \Stripe\Charge $charge             Stripe Charge Object.
465
				 *
466
				 * @since 2.5.0
467
				 */
468
				do_action( 'give_stripe_verify_payment', $payment_id, $stripe_customer_id, $charge );
469
470
				// @TODO use Stripe's API here to retrieve the invoice then confirm it has been paid.
471
				// Regular payment, publish it.
472
				give_update_payment_status( $payment_id, 'publish' );
473
474
				// Save Stripe customer id.
475
				$this->save_stripe_customer_id( $stripe_customer_id, $payment_id );
476
477
				// Send them to success page.
478
				give_send_to_success_page();
479
480
			} else {
481
482
				give_set_error( 'payment_not_recorded', __( 'Your donation could not be recorded, please contact the site administrator.', 'give' ) );
483
484
				// If errors are present, send the user back to the purchase page so they can be corrected.
485
				$this->send_back_to_checkout();
486
487
			} // End if().
488
		}
489
490
		/**
491
		 * This function will prepare metadata to send to Stripe.
492
		 *
493
		 * @param int $donation_id Donation ID.
494
		 *
495
		 * @since  2.5.0
496
		 * @access public
497
		 *
498
		 * @return array
499
		 */
500
		public function prepare_metadata( $donation_id = 0 ) {
501
502
			if ( ! $donation_id ) {
503
				return array();
504
			}
505
506
			$form_id = give_get_payment_form_id( $donation_id );
507
			$email   = give_get_payment_user_email( $donation_id );
508
509
			$args = array(
510
				'Email'            => $email,
511
				'Donation Post ID' => $donation_id,
512
			);
513
514
			// Add Sequential Metadata.
515
			$seq_donation_id = give_stripe_get_sequential_id( $donation_id );
516
			if ( $seq_donation_id ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $seq_donation_id of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
517
				$args['Sequential ID'] = $seq_donation_id;
518
			}
519
520
			// Add custom FFM fields to Stripe metadata.
521
			$args = array_merge( $args, give_stripe_get_custom_ffm_fields( $form_id, $donation_id ) );
522
523
			// Limit metadata passed to Stripe as maximum of 20 metadata is only allowed.
524
			if ( count( $args ) > 20 ) {
525
				$args = array_slice( $args, 0, 19, false );
526
				$args = array_merge(
527
					$args,
528
					array(
529
						'More Details' => esc_url_raw( admin_url( 'edit.php?post_type=give_forms&page=give-payment-history&view=view-payment-details&id=' . $donation_id ) ),
530
					)
531
				);
532
			}
533
534
			return $args;
535
		}
536
537
		/**
538
		 * This function will help to charge with Stripe.
539
		 *
540
		 * @param int   $donation_id Donation ID with pending status.
541
		 * @param array $charge_args List of charge arguments.
542
		 *
543
		 * @since  2.5.0
544
		 * @access public
545
		 *
546
		 * @return \Stripe\Charge
547
		 */
548
		public function create_charge( $donation_id, $charge_args ) {
549
550
			// Set App Info to Stripe.
551
			give_stripe_set_app_info();
552
553
			try {
554
555
				$charge_args = apply_filters( "give_{$this->id}_create_charge_args", $charge_args );
556
557
				// Charge application fee, only if the Stripe premium add-on is not active.
558
				if ( ! defined( 'GIVE_STRIPE_VERSION' ) ) {
559
					// Set Application Fee Amount.
560
					$charge_args['application_fee_amount'] = give_stripe_get_application_fee_amount( $charge_args['amount'] );
561
				}
562
563
				$charge = \Stripe\Charge::create(
564
					$charge_args,
565
					give_stripe_get_connected_account_options()
566
				);
567
568
				// Add note for the charge.
569
				// Save Stripe's charge ID to the transaction.
570
				if ( ! empty( $charge ) ) {
571
					give_insert_payment_note( $donation_id, 'Stripe Charge ID: ' . $charge->id );
572
					give_set_payment_transaction_id( $donation_id, $charge->id );
573
				}
574
575
				return $charge;
576
577
			} catch ( \Stripe\Error\Base $e ) {
578
				Give_Stripe_Logger::log_error( $e, $this->id );
579
			} catch ( Exception $e ) {
580
581
				give_record_gateway_error(
582
					__( 'Stripe Charge Error', 'give' ),
583
					sprintf(
584
						/* translators: %s Exception Error Message */
585
						__( 'Unable to create a successful charge. Details: %s', 'give' ),
586
						$e
587
					)
588
				);
589
				give_set_error( 'stripe_charge_error', __( 'Error processing donation with Stripe. Please try again.', 'give' ) );
590
				return false;
591
			} // End try().
592
		}
593
594
		/**
595
		 * Create Source for Stripe 3D Secure Payments.
596
		 *
597
		 * @param int $donation_id Donation ID.
598
		 * @param int $source_id   Source ID/Object.
599
		 *
600
		 * @since  1.6
601
		 * @access public
602
	 	 *
603
		 * @return bool|\Stripe\Source
604
		 */
605
		public function create_3d_secure_source( $donation_id, $source_id ) {
606
			$form_id         = give_get_payment_form_id( $donation_id );
607
			$customer_id     = give_get_payment_meta( $donation_id, '_give_stripe_customer_id', true );
0 ignored issues
show
Unused Code introduced by
$customer_id is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
608
			$donation_amount = give_donation_amount( $donation_id );
609
610
			// Prepare basic source args.
611
			$source_args = array(
612
				'amount'               => $this->format_amount( $donation_amount ),
613
				'currency'             => give_get_currency( $form_id ),
614
				'type'                 => 'three_d_secure',
615
				'three_d_secure'       => array(
616
					'card'     => $source_id,
617
				),
618
				'statement_descriptor' => give_stripe_get_statement_descriptor(),
619
				'redirect'             => array(
620
					'return_url' => add_query_arg(
621
						array(
622
							'give-listener' => 'stripe_three_d_secure',
623
							'donation_id'   => $donation_id,
624
						),
625
						give_get_success_page_uri()
626
					),
627
				),
628
			);
629
630
			$source = $this->prepare_source( $source_args );
631
632
			// Add donation note for 3D secure source ID.
633
			if ( ! empty( $source->id ) ) {
634
				give_insert_payment_note( $donation_id, 'Stripe 3D Secure Source ID: ' . $source->id );
635
			}
636
637
			// Save 3D secure source id to donation.
638
			give_update_payment_meta( $donation_id, '_give_stripe_3dsecure_source_id', $source->id );
639
640
			return $source;
641
		}
642
643
		/**
644
		 * Is 3D secure payment required?
645
		 *
646
		 * @param \Stripe\Source $source_object Stripe Source Object.
647
		 *
648
		 * @since  1.6
649
		 * @access public
650
		 *
651
	 	 * @return bool
652
		 */
653
		public function is_3d_secure_required( $source_object ) {
654
655
			$is_3d_secure_enabled = give_is_setting_enabled( give_get_option( 'stripe_enable_three_d_secure_payments', '' ) );
656
657
			if ( $is_3d_secure_enabled ) {
658
				return apply_filters(
659
					'give_stripe_3d_secure_required',
660
					(
661
						! empty( $source_object->type ) &&
662
						'card' === $source_object->type &&
663
						'required' === $source_object->card->three_d_secure
664
					),
665
					$source_object
666
				);
667
			}
668
669
			return false;
670
		}
671
672
		/**
673
		 * Process One Time Charge.
674
		 *
675
		 * @param array  $donation_data      List of donation data.
676
		 * @param string $stripe_customer_id Customer ID.
677
		 *
678
		 * @return bool|\Stripe\Charge
679
		 */
680
		public function process_charge( $donation_data, $stripe_customer_id ) {
681
682
			$form_id     = ! empty( $donation_data['post_data']['give-form-id'] ) ? intval( $donation_data['post_data']['give-form-id'] ) : 0;
683
			$donation_id = ! empty( $donation_data['donation_id'] ) ? intval( $donation_data['donation_id'] ) : 0;
684
			$source_id   = ! empty( $donation_data['source_id'] ) ? $donation_data['source_id'] : 0;
685
			$description = ! empty( $donation_data['description'] ) ? $donation_data['description'] : false;
686
687
			// Process the charge.
688
			$amount = $this->format_amount( $donation_data['price'] );
689
690
			$charge_args = array(
691
				'amount'               => $amount,
692
				'currency'             => give_get_currency( $form_id ),
693
				'customer'             => $stripe_customer_id,
694
				'description'          => html_entity_decode( $description, ENT_COMPAT, 'UTF-8' ),
695
				'statement_descriptor' => give_stripe_get_statement_descriptor( $donation_data ),
696
				'metadata'             => $this->prepare_metadata( $donation_id ),
697
				'source'               => $source_id,
698
			);
699
700
			// Create charge with general gateway fn.
701
			$charge = $this->create_charge( $donation_id, $charge_args );
702
703
			// Return charge if set.
704
			if ( isset( $charge ) ) {
705
				return $charge;
706
			} else {
707
				return false;
708
			}
709
		}
710
	}
711
}
712