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

Give_Stripe_Card   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 343
Duplicated Lines 4.37 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 15
loc 343
rs 10
c 0
b 0
f 0
wmc 27
lcom 1
cbo 4

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
B check_for_source() 0 50 6
A prepare_card_data() 0 18 1
C process_payment() 15 139 9
C listen_stripe_3dsecure_payment() 0 79 10

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * Give - Stripe Card Payments
4
 *
5
 * @package    Give
6
 * @subpackage Stripe Core
7
 * @copyright  Copyright (c) 2019, GiveWP
8
 * @license    https://opensource.org/licenses/gpl-license GNU Public License
9
 */
10
11
// Exit if accessed directly.
12
if ( ! defined( 'ABSPATH' ) ) {
13
	exit;
14
}
15
16
/**
17
 * Check for Give_Stripe_Card existence.
18
 *
19
 * @since 2.5.0
20
 */
21
if ( ! class_exists( 'Give_Stripe_Card' ) ) {
22
23
	/**
24
	 * Class Give_Stripe_Card.
25
	 *
26
	 * @since 2.5.0
27
	 */
28
	class Give_Stripe_Card extends Give_Stripe_Gateway {
29
30
		/**
31
		 * Give_Stripe_Card constructor.
32
		 *
33
		 * @since  2.5.0
34
		 * @access public
35
		 */
36
		public function __construct() {
37
38
			$this->id = 'stripe';
39
40
			parent::__construct();
41
		}
42
43
		/**
44
		 * Check for the Stripe Source.
45
		 *
46
		 * @param array $donation_data List of Donation Data.
47
		 *
48
		 * @since 2.0.6
49
		 *
50
		 * @return string
51
		 */
52
		public function check_for_source( $donation_data ) {
53
54
			$source_id          = $donation_data['post_data']['give_stripe_payment_method'];
55
			$stripe_js_fallback = give_get_option( 'stripe_js_fallback' );
56
57
			if ( ! isset( $source_id ) ) {
58
59
				// check for fallback mode.
60
				if ( ! empty( $stripe_js_fallback ) ) {
61
62
					$card_data = $this->prepare_card_data( $donation_data );
63
64
					// Set Application Info.
65
					give_stripe_set_app_info();
66
67
					try {
68
69
						$source = \Stripe\Source::create( array(
70
							'card' => $card_data,
71
						) );
72
						$source_id = $source->id;
73
74
					} catch ( \Stripe\Error\Base $e ) {
75
						$this->log_error( $e );
76
77
					} catch ( Exception $e ) {
78
79
						give_record_gateway_error(
80
							__( 'Stripe Error', 'give' ),
81
							sprintf(
82
								/* translators: %s Exception Message Body */
83
								__( 'The Stripe Gateway returned an error while creating the customer payment source. Details: %s', 'give' ),
84
								$e->getMessage()
85
							)
86
						);
87
						give_set_error( 'stripe_error', __( 'An occurred while processing the donation with the gateway. Please try your donation again.', 'give' ) );
88
						give_send_back_to_checkout( "?payment-mode={$this->id}&form_id={$donation_data['post_data']['give-form-id']}" );
89
					}
90
				} elseif ( ! $this->is_stripe_popup_enabled() ) {
0 ignored issues
show
Bug introduced by
The method is_stripe_popup_enabled() does not seem to exist on object<Give_Stripe_Card>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
91
92
					// No Stripe source and fallback mode is disabled.
93
					give_set_error( 'no_token', __( 'Missing Stripe Source. Please contact support.', 'give' ) );
94
					give_record_gateway_error( __( 'Missing Stripe Source', 'give' ), __( 'A Stripe token failed to be generated. Please check Stripe logs for more information.', 'give' ) );
95
96
				}
97
			} // End if().
98
99
			return $source_id;
100
101
		}
102
103
		/**
104
		 * Process the POST Data for the Credit Card Form, if a source was not supplied.
105
		 *
106
		 * @since 2.5.0
107
		 *
108
		 * @param array $donation_data List of donation data.
109
		 *
110
		 * @return array The credit card data from the $_POST
111
		 */
112
		public function prepare_card_data( $donation_data ) {
113
114
			$card_data = array(
115
				'number'          => $donation_data['card_info']['card_number'],
116
				'name'            => $donation_data['card_info']['card_name'],
117
				'exp_month'       => $donation_data['card_info']['card_exp_month'],
118
				'exp_year'        => $donation_data['card_info']['card_exp_year'],
119
				'cvc'             => $donation_data['card_info']['card_cvc'],
120
				'address_line1'   => $donation_data['card_info']['card_address'],
121
				'address_line2'   => $donation_data['card_info']['card_address_2'],
122
				'address_city'    => $donation_data['card_info']['card_city'],
123
				'address_zip'     => $donation_data['card_info']['card_zip'],
124
				'address_state'   => $donation_data['card_info']['card_state'],
125
				'address_country' => $donation_data['card_info']['card_country'],
126
			);
127
128
			return $card_data;
129
		}
130
131
		/**
132
		 * This function will be used for donation processing.
133
		 *
134
		 * @param array $donation_data List of donation data.
135
		 *
136
		 * @since  2.5.0
137
		 * @access public
138
		 *
139
		 * @return void
140
		 */
141
		public function process_payment( $donation_data ) {
142
143
			// Bailout, if the current gateway and the posted gateway mismatched.
144
			if ( 'stripe' !== $donation_data['post_data']['give-gateway'] ) {
145
				return;
146
			}
147
148
			// Make sure we don't have any left over errors present.
149
			give_clear_errors();
150
151
			$payment_method_id = ! empty( $donation_data['post_data']['give_stripe_payment_method'] )
152
				? $donation_data['post_data']['give_stripe_payment_method']
153
				: $this->check_for_source( $donation_data );
154
155
			// Any errors?
156
			$errors = give_get_errors();
157
158
			// No errors, proceed.
159
			if ( ! $errors ) {
160
161
				$form_id          = ! empty( $donation_data['post_data']['give-form-id'] ) ? intval( $donation_data['post_data']['give-form-id'] ) : 0;
162
				$price_id         = ! empty( $donation_data['post_data']['give-price-id'] ) ? $donation_data['post_data']['give-price-id'] : 0;
163
				$donor_email      = ! empty( $donation_data['post_data']['give_email'] ) ? $donation_data['post_data']['give_email'] : 0;
164
				$donation_summary = give_payment_gateway_donation_summary( $donation_data, false );
165
166
				// Get an existing Stripe customer or create a new Stripe Customer and attach the source to customer.
167
				$give_stripe_customer = new Give_Stripe_Customer( $donor_email, $payment_method_id );
168
				$stripe_customer      = $give_stripe_customer->customer_data;
0 ignored issues
show
Unused Code introduced by
$stripe_customer 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...
169
				$stripe_customer_id   = $give_stripe_customer->get_id();
170
171
				// We have a Stripe customer, charge them.
172
				if ( $stripe_customer_id ) {
173
174
					// Proceed to get stripe source/payment method details.
175
					$payment_method    = $give_stripe_customer->attached_payment_method;
176
					$payment_method_id = $payment_method->id;
177
178
					// Setup the payment details.
179
					$payment_data = array(
180
						'price'           => $donation_data['price'],
181
						'give_form_title' => $donation_data['post_data']['give-form-title'],
182
						'give_form_id'    => $form_id,
183
						'give_price_id'   => $price_id,
184
						'date'            => $donation_data['date'],
185
						'user_email'      => $donation_data['user_email'],
186
						'purchase_key'    => $donation_data['purchase_key'],
187
						'currency'        => give_get_currency( $form_id ),
188
						'user_info'       => $donation_data['user_info'],
189
						'status'          => 'pending',
190
						'gateway'         => $this->id,
191
					);
192
193
					// Record the pending payment in Give.
194
					$donation_id = give_insert_payment( $payment_data );
195
196
					// Assign required data to array of donation data for future reference.
197
					$donation_data['donation_id'] = $donation_id;
198
					$donation_data['description'] = $donation_summary;
199
					$donation_data['source_id']   = $payment_method_id;
200
201
					// Save Stripe Customer ID to Donation note, Donor and Donation for future reference.
202
					give_insert_payment_note( $donation_id, 'Stripe Customer ID: ' . $stripe_customer_id );
0 ignored issues
show
Security Bug introduced by
It seems like $donation_id defined by give_insert_payment($payment_data) on line 194 can also be of type false; however, give_insert_payment_note() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
203
					$this->save_stripe_customer_id( $stripe_customer_id, $donation_id );
0 ignored issues
show
Security Bug introduced by
It seems like $donation_id defined by give_insert_payment($payment_data) on line 194 can also be of type false; however, Give_Stripe_Gateway::save_stripe_customer_id() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
204
					give_update_meta( $donation_id, '_give_stripe_customer_id', $stripe_customer_id );
0 ignored issues
show
Security Bug introduced by
It seems like $donation_id defined by give_insert_payment($payment_data) on line 194 can also be of type false; however, give_update_meta() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
205
206
					// Save Source ID to donation note and DB.
207
					give_insert_payment_note( $donation_id, 'Stripe Source/Payment Method ID: ' . $payment_method_id );
0 ignored issues
show
Security Bug introduced by
It seems like $donation_id defined by give_insert_payment($payment_data) on line 194 can also be of type false; however, give_insert_payment_note() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
208
					give_update_meta( $donation_id, '_give_stripe_source_id', $payment_method_id );
0 ignored issues
show
Security Bug introduced by
It seems like $donation_id defined by give_insert_payment($payment_data) on line 194 can also be of type false; however, give_update_meta() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
209
210
					// Save donation summary to donation.
211
					give_update_meta( $donation_id, '_give_stripe_donation_summary', $donation_summary );
0 ignored issues
show
Security Bug introduced by
It seems like $donation_id defined by give_insert_payment($payment_data) on line 194 can also be of type false; however, give_update_meta() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
212
213
214
					if ( give_stripe_is_checkout_enabled() ) {
215
216
						// Process charge w/ support for preapproval.
217
						$charge = $this->process_charge( $donation_data, $stripe_customer_id );
218
219
						// Verify the Stripe payment.
220
						$this->verify_payment( $donation_id, $stripe_customer_id, $charge );
0 ignored issues
show
Security Bug introduced by
It seems like $donation_id defined by give_insert_payment($payment_data) on line 194 can also be of type false; however, Give_Stripe_Gateway::verify_payment() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
Security Bug introduced by
It seems like $charge defined by $this->process_charge($d...a, $stripe_customer_id) on line 217 can also be of type false; however, Give_Stripe_Gateway::verify_payment() does only seem to accept object<Stripe\Charge>, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
221
					} else {
222
223
						/**
224
						 * This filter hook is used to update the payment intent arguments.
225
						 *
226
						 * @since 2.5.0
227
						 */
228
						$intent_args = apply_filters(
229
							'give_stripe_create_intent_args',
230
							array(
231
								'amount'               => $this->format_amount( $donation_data['price'] ),
232
								'currency'             => give_get_currency( $form_id ),
233
								'payment_method_types' => [ 'card' ],
234
								'statement_descriptor' => give_stripe_get_statement_descriptor(),
235
								'receipt_email'        => $donation_data['user_email'],
236
								'description'          => give_payment_gateway_donation_summary( $donation_data ),
237
								'metadata'             => $this->prepare_metadata( $donation_id ),
0 ignored issues
show
Security Bug introduced by
It seems like $donation_id defined by give_insert_payment($payment_data) on line 194 can also be of type false; however, Give_Stripe_Gateway::prepare_metadata() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
238
								'customer'             => $stripe_customer_id,
239
								'payment_method'       => $payment_method_id,
240
								'confirm'              => true,
241
								'return_url'           => give_get_success_page_uri(),
242
							)
243
						);
244
						$intent     = $this->payment_intent->create( $intent_args );
245
246
						// Save Payment Intent Client Secret to donation note and DB.
247
						give_insert_payment_note( $donation_id, 'Stripe Payment Intent Client Secret: ' . $intent->client_secret );
0 ignored issues
show
Security Bug introduced by
It seems like $donation_id defined by give_insert_payment($payment_data) on line 194 can also be of type false; however, give_insert_payment_note() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
248
						give_update_meta( $donation_id, '_give_stripe_payment_intent_client_secret', $intent->client_secret );
0 ignored issues
show
Security Bug introduced by
It seems like $donation_id defined by give_insert_payment($payment_data) on line 194 can also be of type false; however, give_update_meta() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
249
250
						// Set Payment Intent ID as transaction ID for the donation.
251
						give_set_payment_transaction_id( $donation_id, $intent->id );
0 ignored issues
show
Security Bug introduced by
It seems like $donation_id defined by give_insert_payment($payment_data) on line 194 can also be of type false; however, give_set_payment_transaction_id() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
252
						give_insert_payment_note( $donation_id, 'Stripe Charge/Payment Intent ID: ' . $intent->id );
0 ignored issues
show
Security Bug introduced by
It seems like $donation_id defined by give_insert_payment($payment_data) on line 194 can also be of type false; however, give_insert_payment_note() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
253
254
						// Process additional steps for SCA or 3D secure.
255
						give_stripe_process_additional_authentication( $donation_id, $intent );
0 ignored issues
show
Security Bug introduced by
It seems like $donation_id defined by give_insert_payment($payment_data) on line 194 can also be of type false; however, give_stripe_process_additional_authentication() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
Documentation introduced by
$intent is of type object<Stripe\StripeObject>|array, but the function expects a object<Stripe\PaymentIntent>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
256
257
						// Send them to success page.
258
						give_send_to_success_page();
259
260
					}
261 View Code Duplication
				} else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
262
263
					// No customer, failed.
264
					give_record_gateway_error(
265
						__( 'Stripe Customer Creation Failed', 'give' ),
266
						sprintf(
267
							/* translators: %s Donation Data */
268
							__( 'Customer creation failed while processing the donation. Details: %s', 'give' ),
269
							wp_json_encode( $donation_data )
270
						)
271
					);
272
					give_set_error( 'stripe_error', __( 'The Stripe Gateway returned an error while processing the donation.', 'give' ) );
273
					give_send_back_to_checkout( '?payment-mode=' . give_clean( $_GET['payment-mode'] ) );
274
275
				} // End if().
276
			} else {
277
				give_send_back_to_checkout( '?payment-mode=' . give_clean( $_GET['payment-mode'] ) );
278
			} // End if().
279
		}
280
281
		/**
282
		 * Authorise Donation to successfully complete the donation.
283
		 *
284
		 * @since  1.6
285
		 * @access public
286
		 *
287
		 * @todo remove this function when payment intent is supported with subscriptions.
288
		 *
289
		 * @return void
290
		 */
291
		public function listen_stripe_3dsecure_payment() {
292
293
			// Sanitize the parameter received from query string.
294
			$data = give_clean( $_GET ); // WPCS: input var ok.
295
296
			// Must be a stripe three-d-secure listener to proceed.
297
			if ( ! isset( $data['give-listener'] ) || 'stripe_three_d_secure' !== $data['give-listener'] ) {
298
				return;
299
			}
300
301
			$donation_id = ! empty( $data['donation_id'] ) ? $data['donation_id'] : '';
302
			$source_id   = ! empty( $data['source'] ) ? $data['source'] : '';
303
			$description = give_get_meta( $donation_id, '_give_stripe_donation_summary', true );
304
			$customer_id = give_get_meta( $donation_id, '_give_stripe_customer_id', true );
305
306
			// Get Source Object from source id.
307
			$source_object = $this->get_source_details( $source_id );
308
309
			// Proceed to charge, if the 3D secure source is chargeable.
310
			if ( 'chargeable' === $source_object->status ) {
311
				$charge_args = array(
312
					'amount'               => $source_object->amount,
313
					'currency'             => $source_object->currency,
314
					'customer'             => $customer_id,
315
					'source'               => $source_object->id,
316
					'description'          => html_entity_decode( $description, ENT_COMPAT, 'UTF-8' ),
317
					'statement_descriptor' => $source_object->statement_descriptor,
318
					'metadata'             => $this->prepare_metadata( $donation_id ),
319
				);
320
321
				// If preapproval enabled, only capture the charge
322
				// @see: https://stripe.com/docs/api#create_charge-capture.
323
				if ( give_stripe_is_preapproved_enabled() ) {
324
					$charge_args['capture'] = false;
325
				}
326
327
				try {
328
					$charge = $this->create_charge( $donation_id, $charge_args );
329
330
					if ( $charge ) {
331
						/**
332
						 * This action hook will help to perform additional steps when 3D secure payments are processed.
333
						 *
334
						 * @since 2.1
335
						 *
336
						 * @param int            $donation_id Donation ID.
337
						 * @param \Stripe\Charge $charge      Stripe Charge Object.
338
						 * @param string         $customer_id Stripe Customer ID.
339
						 */
340
						do_action( 'give_stripe_verify_3dsecure_payment', $donation_id, $charge, $customer_id );
341
342
						// Verify Payment.
343
						$this->verify_payment( $donation_id, $customer_id, $charge );
344
					}
345
				} catch ( \Stripe\Error\Base $e ) {
346
					$this->log_error( $e );
347
				} catch ( Exception $e ) {
348
					give_update_payment_status( $donation_id, 'failed' );
349
350
					give_record_gateway_error(
351
						__( 'Stripe Error', 'give' ),
352
						sprintf(
353
							/* translators: Exception Message Body */
354
							__( 'The Stripe Gateway returned an error while processing a donation. Details: %s', 'give' ),
355
							$e->getMessage()
356
						)
357
					);
358
359
					wp_safe_redirect( give_get_failed_transaction_uri() );
360
				} // End try().
361
			} else {
362
363
				give_update_payment_status( $donation_id, 'failed' );
364
				give_record_gateway_error( __( 'Donor Error', 'give' ), sprintf( __( 'Donor has cancelled the payment during authorization process.', 'give' ) ) );
365
				wp_safe_redirect( give_get_failed_transaction_uri() );
366
			} // End if().
367
368
			give_die();
369
		}
370
	}
371
}
372
return new Give_Stripe_Card();
373