Edit File by line

Deprecated: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in /home/sportsfever/public_html/filemanger/function.php on line 93

Warning: Undefined array key "page_file_edit_line" in /home/sportsfever/public_html/filemanger/edit_text_line.php on line 32
/home/sportsfe.../httpdocs/clone/wp-conte.../plugins/wpforms-.../src/Integrat.../Stripe/Api
File: PaymentIntents.php
* Finalize single payment after 3D Secure authorization is finished successfully.
[500] Fix | Delete
*
[501] Fix | Delete
* @since 1.8.2
[502] Fix | Delete
*
[503] Fix | Delete
* @throws ApiErrorException If the request fails.
[504] Fix | Delete
*/
[505] Fix | Delete
protected function finalize_single() {
[506] Fix | Delete
[507] Fix | Delete
// Saving payment info is important for a future form entry meta update.
[508] Fix | Delete
$this->intent = $this->retrieve_payment_intent( $this->payment_intent_id, [ 'expand' => [ 'customer' ] ] );
[509] Fix | Delete
[510] Fix | Delete
if ( $this->intent->status !== 'succeeded' ) {
[511] Fix | Delete
[512] Fix | Delete
// This error is unlikely to happen because the same check is done on a frontend.
[513] Fix | Delete
$this->error = esc_html__( 'Stripe payment was not confirmed. Please check your Stripe dashboard.', 'wpforms-lite' );
[514] Fix | Delete
[515] Fix | Delete
return;
[516] Fix | Delete
}
[517] Fix | Delete
[518] Fix | Delete
// Saving customer and subscription info is important for a future form meta update.
[519] Fix | Delete
$this->customer = $this->intent->customer;
[520] Fix | Delete
}
[521] Fix | Delete
[522] Fix | Delete
/**
[523] Fix | Delete
* Process subscription.
[524] Fix | Delete
*
[525] Fix | Delete
* @since 1.8.2
[526] Fix | Delete
*
[527] Fix | Delete
* @param array $args Subscription arguments.
[528] Fix | Delete
*
[529] Fix | Delete
* @throws ApiErrorException If the request fails.
[530] Fix | Delete
*/
[531] Fix | Delete
public function process_subscription( $args ) {
[532] Fix | Delete
[533] Fix | Delete
if ( $this->payment_method_id ) {
[534] Fix | Delete
[535] Fix | Delete
// Normal flow.
[536] Fix | Delete
$this->charge_subscription( $args );
[537] Fix | Delete
[538] Fix | Delete
} elseif ( $this->payment_intent_id ) {
[539] Fix | Delete
[540] Fix | Delete
// 3D Secure flow.
[541] Fix | Delete
$this->finalize_subscription();
[542] Fix | Delete
}
[543] Fix | Delete
}
[544] Fix | Delete
[545] Fix | Delete
/**
[546] Fix | Delete
* Request a subscription charge to be made by Stripe.
[547] Fix | Delete
*
[548] Fix | Delete
* @since 1.8.2
[549] Fix | Delete
*
[550] Fix | Delete
* @param array $args Subscription payment arguments.
[551] Fix | Delete
*/
[552] Fix | Delete
protected function charge_subscription( $args ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
[553] Fix | Delete
[554] Fix | Delete
if ( empty( $this->payment_method_id ) ) {
[555] Fix | Delete
$this->error = esc_html__( 'Stripe subscription stopped, missing PaymentMethod id.', 'wpforms-lite' );
[556] Fix | Delete
[557] Fix | Delete
return;
[558] Fix | Delete
}
[559] Fix | Delete
[560] Fix | Delete
$sub_args = [
[561] Fix | Delete
'items' => [
[562] Fix | Delete
[
[563] Fix | Delete
'plan' => $this->get_plan_id( $args ),
[564] Fix | Delete
],
[565] Fix | Delete
],
[566] Fix | Delete
'metadata' => [
[567] Fix | Delete
'form_name' => $args['form_title'],
[568] Fix | Delete
'form_id' => $args['form_id'],
[569] Fix | Delete
],
[570] Fix | Delete
'expand' => [ 'latest_invoice.payment_intent' ],
[571] Fix | Delete
];
[572] Fix | Delete
[573] Fix | Delete
if ( isset( $args['application_fee_percent'] ) ) {
[574] Fix | Delete
$sub_args['application_fee_percent'] = $args['application_fee_percent'];
[575] Fix | Delete
}
[576] Fix | Delete
[577] Fix | Delete
try {
[578] Fix | Delete
$this->set_customer( $args['email'], $args['customer_name'] ?? '', $args['customer_address'] ?? [] );
[579] Fix | Delete
$sub_args['customer'] = $this->get_customer( 'id' );
[580] Fix | Delete
[581] Fix | Delete
if ( Helpers::is_payment_element_enabled() ) {
[582] Fix | Delete
[583] Fix | Delete
$sub_args['payment_behavior'] = 'default_incomplete';
[584] Fix | Delete
$sub_args['off_session'] = true;
[585] Fix | Delete
$sub_args['payment_settings'] = [
[586] Fix | Delete
'save_default_payment_method' => 'on_subscription',
[587] Fix | Delete
];
[588] Fix | Delete
[589] Fix | Delete
if ( Helpers::is_link_supported() ) {
[590] Fix | Delete
$sub_args['payment_settings']['payment_method_types'] = [ 'card', 'link' ];
[591] Fix | Delete
}
[592] Fix | Delete
} else {
[593] Fix | Delete
[594] Fix | Delete
$new_payment_method = $this->attach_customer_to_payment();
[595] Fix | Delete
[596] Fix | Delete
if ( is_null( $new_payment_method ) ) {
[597] Fix | Delete
return;
[598] Fix | Delete
}
[599] Fix | Delete
[600] Fix | Delete
// Check whether a default PaymentMethod needs to be explicitly set.
[601] Fix | Delete
$selected_payment_method_id = $this->select_subscription_default_payment_method( $new_payment_method );
[602] Fix | Delete
[603] Fix | Delete
if ( $selected_payment_method_id ) {
[604] Fix | Delete
// Explicitly set a PaymentMethod for this Subscription because default Customer's PaymentMethod cannot be used.
[605] Fix | Delete
$sub_args['default_payment_method'] = $selected_payment_method_id;
[606] Fix | Delete
}
[607] Fix | Delete
}
[608] Fix | Delete
[609] Fix | Delete
// Create the subscription.
[610] Fix | Delete
$this->subscription = Subscription::create( $sub_args, Helpers::get_auth_opts() );
[611] Fix | Delete
[612] Fix | Delete
$this->intent = $this->subscription->latest_invoice->payment_intent;
[613] Fix | Delete
[614] Fix | Delete
if ( ! $this->intent || ! in_array( $this->intent->status, [ 'succeeded', 'requires_action', 'requires_confirmation', 'requires_payment_method' ], true ) ) {
[615] Fix | Delete
$this->error = esc_html__( 'Stripe subscription stopped. invalid PaymentIntent status.', 'wpforms-lite' );
[616] Fix | Delete
[617] Fix | Delete
return;
[618] Fix | Delete
}
[619] Fix | Delete
[620] Fix | Delete
if ( $this->intent->status === 'succeeded' ) {
[621] Fix | Delete
return;
[622] Fix | Delete
}
[623] Fix | Delete
[624] Fix | Delete
$this->set_bypass_captcha_3dsecure_token();
[625] Fix | Delete
[626] Fix | Delete
if ( in_array( $this->intent->status , [ 'requires_confirmation', 'requires_payment_method' ], true ) ) {
[627] Fix | Delete
$this->request_confirm_payment_ajax( $this->intent );
[628] Fix | Delete
}
[629] Fix | Delete
[630] Fix | Delete
$this->request_3dsecure_ajax( $this->intent );
[631] Fix | Delete
} catch ( Exception $e ) {
[632] Fix | Delete
[633] Fix | Delete
$this->handle_exception( $e );
[634] Fix | Delete
}
[635] Fix | Delete
}
[636] Fix | Delete
[637] Fix | Delete
/**
[638] Fix | Delete
* Finalize a subscription after 3D Secure authorization is finished successfully.
[639] Fix | Delete
*
[640] Fix | Delete
* @since 1.8.2
[641] Fix | Delete
*
[642] Fix | Delete
* @throws ApiErrorException If the request fails.
[643] Fix | Delete
*/
[644] Fix | Delete
protected function finalize_subscription() {
[645] Fix | Delete
[646] Fix | Delete
// Saving payment info is important for a future form entry meta update.
[647] Fix | Delete
$this->intent = $this->retrieve_payment_intent( $this->payment_intent_id, [ 'expand' => [ 'invoice.subscription', 'customer' ] ] );
[648] Fix | Delete
[649] Fix | Delete
if ( $this->intent->status !== 'succeeded' ) {
[650] Fix | Delete
[651] Fix | Delete
// This error is unlikely to happen because the same check is done on a frontend.
[652] Fix | Delete
$this->error = esc_html__( 'Stripe subscription was not confirmed. Please check your Stripe dashboard.', 'wpforms-lite' );
[653] Fix | Delete
[654] Fix | Delete
return;
[655] Fix | Delete
}
[656] Fix | Delete
[657] Fix | Delete
// Saving customer and subscription info is important for a future form meta update.
[658] Fix | Delete
$this->customer = $this->intent->customer;
[659] Fix | Delete
$this->subscription = $this->intent->invoice->subscription;
[660] Fix | Delete
}
[661] Fix | Delete
[662] Fix | Delete
/**
[663] Fix | Delete
* Attach customer to payment method.
[664] Fix | Delete
*
[665] Fix | Delete
* @since 1.8.2
[666] Fix | Delete
*
[667] Fix | Delete
* @return PaymentMethod|null
[668] Fix | Delete
*/
[669] Fix | Delete
private function attach_customer_to_payment() {
[670] Fix | Delete
[671] Fix | Delete
try {
[672] Fix | Delete
[673] Fix | Delete
$payment_method = PaymentMethod::retrieve(
[674] Fix | Delete
$this->payment_method_id,
[675] Fix | Delete
Helpers::get_auth_opts()
[676] Fix | Delete
);
[677] Fix | Delete
[678] Fix | Delete
// Attaching a PaymentMethod to a Customer validates CVC and throws an exception if PaymentMethod is invalid.
[679] Fix | Delete
$payment_method->attach( [ 'customer' => $this->get_customer( 'id' ) ] );
[680] Fix | Delete
[681] Fix | Delete
return $payment_method;
[682] Fix | Delete
} catch ( Exception $e ) {
[683] Fix | Delete
[684] Fix | Delete
$this->handle_exception( $e );
[685] Fix | Delete
}
[686] Fix | Delete
[687] Fix | Delete
return null;
[688] Fix | Delete
}
[689] Fix | Delete
[690] Fix | Delete
/**
[691] Fix | Delete
* Get saved Stripe PaymentIntent object or its key.
[692] Fix | Delete
*
[693] Fix | Delete
* @since 1.8.2
[694] Fix | Delete
*
[695] Fix | Delete
* @param string $key Name of the key to retrieve.
[696] Fix | Delete
*
[697] Fix | Delete
* @return mixed
[698] Fix | Delete
*/
[699] Fix | Delete
public function get_payment( $key = '' ) {
[700] Fix | Delete
[701] Fix | Delete
return $this->get_var( 'intent', $key );
[702] Fix | Delete
}
[703] Fix | Delete
[704] Fix | Delete
/**
[705] Fix | Delete
* Get details from a saved Charge object.
[706] Fix | Delete
*
[707] Fix | Delete
* @since 1.8.2
[708] Fix | Delete
*
[709] Fix | Delete
* @param string|array $keys Key or an array of keys to retrieve.
[710] Fix | Delete
*
[711] Fix | Delete
* @return array
[712] Fix | Delete
*/
[713] Fix | Delete
public function get_charge_details( $keys ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
[714] Fix | Delete
[715] Fix | Delete
$charge = isset( $this->intent->charges->data[0] ) ? $this->intent->charges->data[0] : null;
[716] Fix | Delete
[717] Fix | Delete
if ( empty( $charge ) || empty( $keys ) ) {
[718] Fix | Delete
return [];
[719] Fix | Delete
}
[720] Fix | Delete
[721] Fix | Delete
if ( is_string( $keys ) ) {
[722] Fix | Delete
$keys = [ $keys ];
[723] Fix | Delete
}
[724] Fix | Delete
[725] Fix | Delete
$result = [];
[726] Fix | Delete
[727] Fix | Delete
foreach ( $keys as $key ) {
[728] Fix | Delete
if ( isset( $charge->payment_method_details->card, $charge->payment_method_details->card->{$key} ) ) {
[729] Fix | Delete
$result[ $key ] = sanitize_text_field( $charge->payment_method_details->card->{$key} );
[730] Fix | Delete
[731] Fix | Delete
continue;
[732] Fix | Delete
}
[733] Fix | Delete
[734] Fix | Delete
if ( isset( $charge->payment_method_details->{$key} ) ) {
[735] Fix | Delete
$result[ $key ] = sanitize_text_field( $charge->payment_method_details->{$key} );
[736] Fix | Delete
[737] Fix | Delete
continue;
[738] Fix | Delete
}
[739] Fix | Delete
[740] Fix | Delete
if ( isset( $charge->billing_details->{$key} ) ) {
[741] Fix | Delete
$result[ $key ] = sanitize_text_field( $charge->billing_details->{$key} );
[742] Fix | Delete
}
[743] Fix | Delete
}
[744] Fix | Delete
[745] Fix | Delete
return $result;
[746] Fix | Delete
}
[747] Fix | Delete
[748] Fix | Delete
/**
[749] Fix | Delete
* Request a frontend 3D Secure authorization from a user.
[750] Fix | Delete
*
[751] Fix | Delete
* @since 1.8.2
[752] Fix | Delete
*
[753] Fix | Delete
* @param PaymentIntent $intent PaymentIntent to authorize.
[754] Fix | Delete
*/
[755] Fix | Delete
protected function request_3dsecure_ajax( $intent ) {
[756] Fix | Delete
[757] Fix | Delete
if ( ! isset( $intent->status, $intent->next_action->type ) ) {
[758] Fix | Delete
return;
[759] Fix | Delete
}
[760] Fix | Delete
[761] Fix | Delete
if ( $intent->status !== 'requires_action' || $intent->next_action->type !== 'use_stripe_sdk' ) {
[762] Fix | Delete
return;
[763] Fix | Delete
}
[764] Fix | Delete
[765] Fix | Delete
wp_send_json_success(
[766] Fix | Delete
[
[767] Fix | Delete
'action_required' => true,
[768] Fix | Delete
'payment_intent_client_secret' => $intent->client_secret,
[769] Fix | Delete
]
[770] Fix | Delete
);
[771] Fix | Delete
}
[772] Fix | Delete
[773] Fix | Delete
/**
[774] Fix | Delete
* Request a frontend payment confirmation from a user.
[775] Fix | Delete
*
[776] Fix | Delete
* @since 1.8.2
[777] Fix | Delete
*
[778] Fix | Delete
* @param PaymentIntent $intent PaymentIntent to authorize.
[779] Fix | Delete
*/
[780] Fix | Delete
protected function request_confirm_payment_ajax( $intent ) {
[781] Fix | Delete
[782] Fix | Delete
wp_send_json_success(
[783] Fix | Delete
[
[784] Fix | Delete
'action_required' => true,
[785] Fix | Delete
'payment_intent_client_secret' => $intent->client_secret,
[786] Fix | Delete
]
[787] Fix | Delete
);
[788] Fix | Delete
}
[789] Fix | Delete
[790] Fix | Delete
/**
[791] Fix | Delete
* Select 'default_payment_method' for Subscription if it needs to be explicitly set
[792] Fix | Delete
* and cleanup remote PaymentMethods in the process.
[793] Fix | Delete
*
[794] Fix | Delete
* @since 1.8.2
[795] Fix | Delete
*
[796] Fix | Delete
* @param PaymentMethod $new_payment_method PaymentMethod object.
[797] Fix | Delete
*
[798] Fix | Delete
* @return string
[799] Fix | Delete
*
[800] Fix | Delete
* @throws Exception In case of Stripe API error.
[801] Fix | Delete
*/
[802] Fix | Delete
protected function select_subscription_default_payment_method( $new_payment_method ) {
[803] Fix | Delete
[804] Fix | Delete
// Stripe does not set the first PaymentMethod attached to a Customer as Customer's 'default_payment_method'.
[805] Fix | Delete
// Setting it manually if Customer's 'default_payment_method' is empty.
[806] Fix | Delete
if ( isset( $new_payment_method->id ) && empty( $this->customer->invoice_settings->default_payment_method ) ) {
[807] Fix | Delete
$this->update_remote_customer_default_payment_method( $new_payment_method->id );
[808] Fix | Delete
// In this case Subscription's 'default_payment_method' doesn't have to be explicitly set and defaults to Customer's 'default_payment_method'.
[809] Fix | Delete
return '';
[810] Fix | Delete
}
[811] Fix | Delete
[812] Fix | Delete
// Return early if not a credit card is used for a payment ( e.g. Link ).
[813] Fix | Delete
if ( ! isset( $new_payment_method->card->fingerprint ) ) {
[814] Fix | Delete
return '';
[815] Fix | Delete
}
[816] Fix | Delete
[817] Fix | Delete
$default_payment_method = PaymentMethod::retrieve(
[818] Fix | Delete
$this->customer->invoice_settings->default_payment_method,
[819] Fix | Delete
Helpers::get_auth_opts()
[820] Fix | Delete
);
[821] Fix | Delete
[822] Fix | Delete
// Update Customer's 'default_payment_method' with a new PaymentMethod if it has the same fingerprint.
[823] Fix | Delete
if ( isset( $new_payment_method->card->fingerprint, $default_payment_method->card->fingerprint ) && $new_payment_method->card->fingerprint === $default_payment_method->card->fingerprint ) {
[824] Fix | Delete
$this->update_remote_customer_default_payment_method( $new_payment_method->id );
[825] Fix | Delete
$default_payment_method->detach();
[826] Fix | Delete
// In this case Subscription's 'default_payment_method' doesn't have to be explicitly set and defaults to Customer's 'default_payment_method'.
[827] Fix | Delete
return '';
[828] Fix | Delete
}
[829] Fix | Delete
[830] Fix | Delete
// In case Customer's 'default_payment_method' is set and its fingerprint doesn't match with a new PaymentMethod, several things need to be done:
[831] Fix | Delete
// - Scan all active subscriptions for 'default_payment_method' with a same fingerprint as a new PaymentMethod.
[832] Fix | Delete
// - Change all matching subscriptions 'default_payment_method' to a new PaymentMethod.
[833] Fix | Delete
// - Delete all PaymentMethods previously set as 'default_payment_method' for matching subscriptions.
[834] Fix | Delete
$this->detach_remote_subscriptions_duplicated_payment_methods( $new_payment_method );
[835] Fix | Delete
[836] Fix | Delete
// In this case Subscription's 'default_payment_method' has to be explicitly set
[837] Fix | Delete
// because Customer's 'default_payment_method' contains a different PaymentMethod and cannot be defaulted to.
[838] Fix | Delete
return $new_payment_method->id;
[839] Fix | Delete
}
[840] Fix | Delete
[841] Fix | Delete
/**
[842] Fix | Delete
* Update 'default_payment_method' for a Customer stored on a Stripe side.
[843] Fix | Delete
*
[844] Fix | Delete
* @since 1.8.2
[845] Fix | Delete
*
[846] Fix | Delete
* @param string $payment_method_id PaymentMethod id.
[847] Fix | Delete
*
[848] Fix | Delete
* @throws Exception If a Customer fails to update.
[849] Fix | Delete
*/
[850] Fix | Delete
protected function update_remote_customer_default_payment_method( $payment_method_id ) {
[851] Fix | Delete
[852] Fix | Delete
Customer::update(
[853] Fix | Delete
$this->get_customer( 'id' ),
[854] Fix | Delete
[
[855] Fix | Delete
'invoice_settings' => [
[856] Fix | Delete
'default_payment_method' => $payment_method_id,
[857] Fix | Delete
],
[858] Fix | Delete
],
[859] Fix | Delete
Helpers::get_auth_opts()
[860] Fix | Delete
);
[861] Fix | Delete
}
[862] Fix | Delete
[863] Fix | Delete
/**
[864] Fix | Delete
* Detach all active Subscriptions PaymentMethods having the same fingerprint as a given PaymentMethod.
[865] Fix | Delete
*
[866] Fix | Delete
* @since 1.8.2
[867] Fix | Delete
*
[868] Fix | Delete
* @param PaymentMethod $new_payment_method PaymentMethod object.
[869] Fix | Delete
*
[870] Fix | Delete
* @throws Exception In case of Stripe API error.
[871] Fix | Delete
*/
[872] Fix | Delete
protected function detach_remote_subscriptions_duplicated_payment_methods( $new_payment_method ) {
[873] Fix | Delete
[874] Fix | Delete
$subscriptions = Subscription::all(
[875] Fix | Delete
[
[876] Fix | Delete
'customer' => $this->get_customer( 'id' ),
[877] Fix | Delete
'status' => 'active',
[878] Fix | Delete
'limit' => 100, // Maximum limit allowed by Stripe (https://stripe.com/docs/api/subscriptions/list#list_subscriptions-limit).
[879] Fix | Delete
'expand' => [ 'data.default_payment_method' ],
[880] Fix | Delete
],
[881] Fix | Delete
Helpers::get_auth_opts()
[882] Fix | Delete
);
[883] Fix | Delete
[884] Fix | Delete
$detach_methods = [];
[885] Fix | Delete
[886] Fix | Delete
foreach ( $subscriptions as $subscription ) {
[887] Fix | Delete
[888] Fix | Delete
if ( empty( $subscription->default_payment_method ) ) {
[889] Fix | Delete
continue;
[890] Fix | Delete
}
[891] Fix | Delete
[892] Fix | Delete
if ( $new_payment_method->card->fingerprint === $subscription->default_payment_method->card->fingerprint ) {
[893] Fix | Delete
[894] Fix | Delete
Subscription::update(
[895] Fix | Delete
$subscription->id,
[896] Fix | Delete
[ 'default_payment_method' => $new_payment_method->id ],
[897] Fix | Delete
Helpers::get_auth_opts()
[898] Fix | Delete
);
[899] Fix | Delete
$detach_methods[ $subscription->default_payment_method->id ] = $subscription->default_payment_method;
[900] Fix | Delete
}
[901] Fix | Delete
}
[902] Fix | Delete
[903] Fix | Delete
foreach ( $detach_methods as $detach_method ) {
[904] Fix | Delete
$detach_method->detach();
[905] Fix | Delete
}
[906] Fix | Delete
}
[907] Fix | Delete
[908] Fix | Delete
/**
[909] Fix | Delete
* Set an encrypted token as a PaymentIntent metadata item.
[910] Fix | Delete
*
[911] Fix | Delete
* @since 1.8.2
[912] Fix | Delete
*
[913] Fix | Delete
* @throws ApiErrorException In case payment intent save wasn't successful.
[914] Fix | Delete
*/
[915] Fix | Delete
private function set_bypass_captcha_3dsecure_token() {
[916] Fix | Delete
[917] Fix | Delete
$form_data = wpforms()->get( 'process' )->form_data;
[918] Fix | Delete
[919] Fix | Delete
// Set token only if captcha is enabled for the form.
[920] Fix | Delete
if ( empty( $form_data['settings']['recaptcha'] ) ) {
[921] Fix | Delete
return;
[922] Fix | Delete
}
[923] Fix | Delete
[924] Fix | Delete
$this->intent->metadata['captcha_3dsecure_token'] = Crypto::encrypt( $this->intent->id );
[925] Fix | Delete
[926] Fix | Delete
$this->intent->update( $this->intent->id, $this->intent->serializeParameters(), Helpers::get_auth_opts() );
[927] Fix | Delete
}
[928] Fix | Delete
[929] Fix | Delete
/**
[930] Fix | Delete
* Bypass CAPTCHA check on successful 3dSecure check.
[931] Fix | Delete
*
[932] Fix | Delete
* @since 1.8.2
[933] Fix | Delete
*
[934] Fix | Delete
* @param bool $is_bypassed True if CAPTCHA is bypassed.
[935] Fix | Delete
* @param array $entry Form entry data.
[936] Fix | Delete
* @param array $form_data Form data and settings.
[937] Fix | Delete
*
[938] Fix | Delete
* @return bool
[939] Fix | Delete
*
[940] Fix | Delete
* @throws ApiErrorException In case payment intent save wasn't successful.
[941] Fix | Delete
*/
[942] Fix | Delete
public function bypass_captcha_on_3dsecure_submit( $is_bypassed, $entry, $form_data ) {
[943] Fix | Delete
[944] Fix | Delete
// Firstly, run checks that may prevent bypassing:
[945] Fix | Delete
// 1) Sanity check to prevent possible tinkering with captcha on non-payment forms.
[946] Fix | Delete
// 2) Both reCAPTCHA and hCaptcha are enabled by the same setting.
[947] Fix | Delete
if (
[948] Fix | Delete
! Helpers::is_payments_enabled( $form_data ) ||
[949] Fix | Delete
empty( $form_data['settings']['recaptcha'] ) ||
[950] Fix | Delete
empty( $entry['payment_intent_id'] )
[951] Fix | Delete
) {
[952] Fix | Delete
return $is_bypassed;
[953] Fix | Delete
}
[954] Fix | Delete
[955] Fix | Delete
// This is executed before payment processing kicks in and fills `$this->intent`.
[956] Fix | Delete
// PaymentIntent intent has to be retrieved from Stripe instead of getting it from `$this->intent`.
[957] Fix | Delete
$intent = $this->retrieve_payment_intent( $entry['payment_intent_id'] );
[958] Fix | Delete
[959] Fix | Delete
if ( empty( $intent->status ) || $intent->status !== 'succeeded' ) {
[960] Fix | Delete
return $is_bypassed;
[961] Fix | Delete
}
[962] Fix | Delete
[963] Fix | Delete
$token = ! empty( $intent->metadata['captcha_3dsecure_token'] ) ? $intent->metadata['captcha_3dsecure_token'] : '';
[964] Fix | Delete
[965] Fix | Delete
if ( Crypto::decrypt( $token ) !== $intent->id ) {
[966] Fix | Delete
return $is_bypassed;
[967] Fix | Delete
}
[968] Fix | Delete
[969] Fix | Delete
// Cleanup the token to prevent its repeated usage and declutter the metadata.
[970] Fix | Delete
$intent->metadata['captcha_3dsecure_token'] = null;
[971] Fix | Delete
[972] Fix | Delete
$intent->update( $intent->id, $intent->serializeParameters(), Helpers::get_auth_opts() );
[973] Fix | Delete
[974] Fix | Delete
return true;
[975] Fix | Delete
}
[976] Fix | Delete
[977] Fix | Delete
/**
[978] Fix | Delete
* Retrieve Mandate object from Stripe.
[979] Fix | Delete
*
[980] Fix | Delete
* @since 1.8.7
[981] Fix | Delete
*
[982] Fix | Delete
* @param string $id Mandate id.
[983] Fix | Delete
* @param array $args Additional arguments.
[984] Fix | Delete
*
[985] Fix | Delete
* @throws ApiErrorException If the request fails.
[986] Fix | Delete
*
[987] Fix | Delete
* @return Mandate|null
[988] Fix | Delete
*/
[989] Fix | Delete
public function retrieve_mandate( string $id, array $args = [] ) {
[990] Fix | Delete
[991] Fix | Delete
try {
[992] Fix | Delete
[993] Fix | Delete
$defaults = [ 'id' => $id ];
[994] Fix | Delete
[995] Fix | Delete
if ( isset( $args['mode'] ) ) {
[996] Fix | Delete
$auth_opts = [ 'api_key' => Helpers::get_stripe_key( 'secret', $args['mode'] ) ];
[997] Fix | Delete
[998] Fix | Delete
unset( $args['mode'] );
[999] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function