Server IP : 162.0.217.223 / Your IP : 216.73.216.150 Web Server : LiteSpeed System : Linux premium269.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64 User : mypckeys ( 1539) PHP Version : 8.1.33 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/mypckeys/www/wp-content/plugins/woo-stripe-payment/includes/ |
Upload File : |
<?php defined( 'ABSPATH' ) || exit(); /** * Processes the charge via webhooks for local payment methods like P24, EPS, etc. * * @param \Stripe\Source $source * @param WP_REST_Request $request * * @since 3.0.0 * @deprecated 3.3.73 * @package Stripe/Functions */ function wc_stripe_process_source_chargeable( $source, $request ) { if ( isset( $source->metadata['order_id'] ) ) { $order = wc_get_order( wc_stripe_filter_order_id( $source->metadata['order_id'], $source ) ); } else { // try finding order using source. $order = wc_stripe_get_order_from_source_id( $source->id ); } if ( ! $order ) { /** * If the order ID metadata is empty, it's possible the source became chargeable before * the plugin had a chance to update the order ID. Schedule a cron job to execute in 60 seconds * so the plugin can update the order ID and the charge can be processed. */ if ( empty( $source->metadata['order_id'] ) ) { if ( method_exists( WC(), 'queue' ) && ! doing_action( 'wc_stripe_retry_source_chargeable' ) ) { WC()->queue()->schedule_single( time() + MINUTE_IN_SECONDS, 'wc_stripe_retry_source_chargeable', array( $source->id ) ); } } else { wc_stripe_log_error( sprintf( 'Could not create a charge for source %s. No order ID was found in your WordPress database.', $source->id ) ); } return; } /** * * @var WC_Payment_Gateway_Stripe $payment_method */ $payment_method = WC()->payment_gateways()->payment_gateways()[ $order->get_payment_method() ]; // if the order has a transaction ID, then a charge has already been created. if ( $payment_method->has_order_lock( $order ) || ( $transaction_id = $order->get_transaction_id() ) ) { wc_stripe_log_info( sprintf( 'source.chargeable event received. Charge has already been created for order %s. Event exited.', $order->get_id() ) ); return; } $payment_method->set_order_lock( $order ); $payment_method->set_new_source_token( $source->id ); $result = $payment_method->payment_object->process_payment( $order ); if ( ! is_wp_error( $result ) && $result->complete_payment ) { $payment_method->payment_object->payment_complete( $order, $result->charge ); } } /** * When the charge has succeeded, the order should be completed. * * @param \Stripe\Charge $charge * @param WP_REST_Request $request * * @since 3.0.5 * @deprecated 3.3.73 * @package Stripe/Functions */ function wc_stripe_process_charge_succeeded( $charge, $request ) { // charges that belong to a payment intent can be skipped // because the payment_intent.succeeded event will be called. if ( $charge->payment_intent ) { return; } $order = wc_get_order( wc_stripe_filter_order_id( $charge->metadata['order_id'], $charge ) ); if ( ! $order ) { wc_stripe_log_error( sprintf( 'Could not complete payment for charge %s. No order ID %s was found in your WordPress database.', $charge->id, $charge->metadata['order_id'] ) ); return; } /** * * @var WC_Payment_Gateway_Stripe $payment_method */ $payment_method = WC()->payment_gateways()->payment_gateways()[ $order->get_payment_method() ]; /** * Make sure the payment method is asynchronous because synchronous payments are handled via the source.chargeable event which processes the payment. * This event is relevant for payment methods that receive a charge.succeeded event at some arbitrary amount of time * after the source is chargeable. */ if ( $payment_method instanceof WC_Payment_Gateway_Stripe && ! $payment_method->synchronous ) { // If the order's charge status is not equal to charge status from Stripe, then complete_payment. if ( $order->get_meta( WC_Stripe_Constants::CHARGE_STATUS ) != $charge->status ) { // want to prevent plugin from processing capture_charge since charge has already been captured. remove_action( 'woocommerce_order_status_completed', 'wc_stripe_order_status_completed' ); if ( stripe_wc()->advanced_settings->is_fee_enabled() ) { // retrieve the balance transaction $balance_transaction = WC_Stripe_Gateway::load()->mode( wc_stripe_order_mode( $order ) )->balanceTransactions->retrieve( $charge->balance_transaction ); if ( ! is_wp_error( $balance_transaction ) ) { $charge->balance_transaction = $balance_transaction; } } // call payment complete so shipping, emails, etc are triggered. $payment_method->payment_object->payment_complete( $order, $charge ); $order->add_order_note( __( 'Charge.succeeded webhook received. Payment has been completed.', 'woo-stripe-payment' ) ); } } } /** * * @param \Stripe\PaymentIntent $intent * @param WP_REST_Request $request * @param \Stripe\Event $event * * @since 3.1.0 * @package Stripe/Functions */ function wc_stripe_process_payment_intent_succeeded( $intent, $request, $event ) { $order = WC_Stripe_Utils::get_order_from_payment_intent( $intent ); if ( ! $order ) { wc_stripe_log_info( sprintf( 'Could not complete payment_intent.succeeded event for payment_intent %s. No order ID %s was found in your WordPress database. This typically happens when you have multiple webhooks setup for the same Stripe account. This order most likely originated from a different site.', $intent->id, isset( $intent->metadata->order_id ) ? $intent->metadata->order_id : '(No Order ID in metadata)' ) ); return; } /** * @var \WC_Payment_Gateway_Stripe $payment_method */ $payment_method = WC()->payment_gateways()->payment_gateways()[ $order->get_payment_method() ] ?? null; if ( $payment_method instanceof WC_Payment_Gateway_Stripe ) { if ( $payment_method->has_order_lock( $order ) || $order->get_date_paid() ) { wc_stripe_log_info( sprintf( 'payment_intent.succeeded event received. Intent has been completed for order %s. Event exited.', $order->get_id() ) ); return; } /** * We want to defer the processing of any credit card payments to prevent race conditions. The Stripe webhook can be * received while the checkout process is still running. */ if ( $payment_method->get_payment_method_type() === 'card' ) { WC()->queue()->schedule_single( time() + 2 * MINUTE_IN_SECONDS, 'wc_stripe_process_deferred_webhook', array( 'type' => $event->type, 'order_id' => $order->get_id(), 'payment_intent' => $intent->id ) ); } else { $payment_method->set_order_lock( $order ); $order->update_meta_data( WC_Stripe_Constants::PAYMENT_INTENT, WC_Stripe_Utils::sanitize_intent( $intent->toArray() ) ); $result = $payment_method->payment_object->process_payment( $order ); if ( ! is_wp_error( $result ) && $result->complete_payment ) { $payment_method->payment_object->payment_complete( $order, $result->charge ); $order->add_order_note( __( 'payment_intent.succeeded webhook received. Payment has been completed.', 'woo-stripe-payment' ) ); } } } } /** * * @param \Stripe\Charge $charge * @param WP_REST_Request $request * * @since 3.1.1 * @package Stripe/Functions */ function wc_stripe_process_charge_failed( $charge, $request ) { $order = wc_get_order( wc_stripe_filter_order_id( $charge->metadata['order_id'], $charge ) ); if ( $order ) { $payment_methods = WC()->payment_gateways()->payment_gateways(); if ( isset( $payment_methods[ $order->get_payment_method() ] ) ) { /** * * @var WC_Payment_Gateway_Stripe $payment_method */ $payment_method = $payment_methods[ $order->get_payment_method() ]; // only update order status if this is an asynchronous payment method, // and there is no completed date on the order. If there is a complete date it // means payment_complete was called on the order at some point if ( $payment_method instanceof WC_Payment_Gateway_Stripe && ! $payment_method->synchronous && ! $order->get_date_completed() ) { $order->update_status( apply_filters( 'wc_stripe_charge_failed_status', 'failed' ), $charge->failure_message ); } } } } /** * Function that processes the charge.refund webhook. If the refund is created in the Stripe dashboard, a * refund will be created in the WC system to keep WC and Stripe in sync. * * @param \Stripe\Charge $charge * * @since 3.2.15 */ function wc_stripe_process_create_refund( $charge ) { $mode = $charge->livemode ? 'live' : 'test'; $order = null; // get the order ID from the charge $order = WC_Stripe_Utils::get_order_from_charge( $charge ); try { if ( ! $order ) { throw new Exception( sprintf( 'Could not match order with charge %s.', $charge->id ) ); } if ( isset( $charge->metadata['cancellation_via'] ) && $charge->metadata['cancellation_via'] === 'woocommerce_admin' ) { // This refund webhook is the result of an authorized payment intent being cancelled. Don't create a refund object. return; } $response = WC_Stripe_Gateway::load( wc_stripe_order_mode( $order ) )->refunds->all( array( 'charge' => $charge->id ) ); $refunds = $response->data; usort( $refunds, function ( $a, $b ) { // sort so refund with most recent created timestamp is first return $a->created < $b->created ? 1 : - 1; } ); $refund = $refunds[0]; /** * @var \Stripe\Refund $refund */ // refund was not created via WC if ( ! isset( $refund->metadata['order_id'], $refund->metadata['created_via'] ) ) { $args = array( 'amount' => wc_stripe_remove_number_precision( $refund->amount, $order->get_currency() ), 'order_id' => $order->get_id(), 'reason' => $refund->reason, 'refund_payment' => false ); // if the order has been fully refunded, items should be re-stocked if ( $order->get_total() == ( $args['amount'] + $order->get_total_refunded() ) ) { $args['restock_items'] = true; $line_items = array(); foreach ( $order->get_items() as $item_id => $item ) { $line_items[ $item_id ] = array( 'qty' => $item->get_quantity() ); } $args['line_items'] = $line_items; } // create the refund $result = wc_create_refund( $args ); // Update the refund in Stripe with metadata if ( ! is_wp_error( $result ) ) { $client = WC_Stripe_Gateway::load( $mode ); $order->add_order_note( sprintf( __( 'Order refunded in Stripe. Amount: %s', 'woo-stripe-payment' ), $result->get_formatted_refund_amount() ) ); $client->refunds->update( $refund->id, array( 'metadata' => array( 'order_id' => $order->get_id(), 'created_via' => 'stripe_dashboard' ) ) ); if ( stripe_wc()->advanced_settings->is_fee_enabled() ) { // retrieve the charge but with expanded objects so fee and net can be calculated. $charge = $client->charges->retrieve( $charge->id, array( 'expand' => array( 'balance_transaction', 'refunds.data.balance_transaction' ) ) ); if ( ! is_wp_error( $charge ) ) { WC_Stripe_Utils::add_balance_transaction_to_order( $charge, $order, true ); } } } else { throw new Exception( $result->get_error_message() ); } } } catch ( Exception $e ) { wc_stripe_log_error( sprintf( 'Error processing refund webhook. Error: %s', $e->getMessage() ) ); } } /** * @param $source_id * * @throws \Stripe\Exception\ApiErrorException */ function wc_stripe_retry_source_chargeable( $source_id ) { $source = WC_Stripe_Gateway::load()->sources->retrieve( $source_id ); if ( ! is_wp_error( $source ) ) { wc_stripe_log_info( sprintf( 'Processing source.chargeable via scheduled action. Source ID %s', $source_id ) ); wc_stripe_process_source_chargeable( $source, null ); } } /** * @param Stripe\Dispute $dispute */ function wc_stripe_charge_dispute_created( $dispute ) { if ( stripe_wc()->advanced_settings->is_dispute_created_enabled() ) { $order = wc_stripe_get_order_from_transaction( $dispute->charge ); if ( ! $order ) { wc_stripe_log_info( sprintf( 'No order found for charge %s. Dispute %s', $dispute->charge, $dispute->id ) ); } else { $current_status = $order->get_status(); $message = sprintf( __( 'A dispute has been created for charge %1$s. Dispute status: %2$s.', 'woo-stripe-payment' ), $dispute->charge, strtoupper( $dispute->status ) ); $order->update_status( apply_filters( 'wc_stripe_dispute_created_order_status', stripe_wc()->advanced_settings->get_option( 'dispute_created_status', 'on-hold' ), $dispute, $order ), $message ); // update the dispute with metadata that can be used later WC_Stripe_Gateway::load( wc_stripe_order_mode( $order ) )->disputes->update( $dispute->id, array( 'metadata' => array( 'order_id' => $order->get_id(), 'prev_order_status' => $current_status ) ) ); // @todo send an email to the admin so they know a dispute was created } } } /** * @param Stripe\Dispute $dispute */ function wc_stripe_charge_dispute_closed( $dispute ) { if ( stripe_wc()->advanced_settings->is_dispute_closed_enabled() ) { if ( isset( $dispute->metadata['order_id'] ) ) { $order = wc_get_order( absint( $dispute->metadata['order_id'] ) ); } else { $order = wc_stripe_get_order_from_transaction( $dispute->charge ); } if ( ! $order ) { return wc_stripe_log_info( sprintf( 'No order found for charge %s. Dispute %s', $dispute->charge, $dispute->id ) ); } $message = sprintf( __( 'Dispute %1$s has been closed. Result: %2$s.', 'woo-stripe-payment' ), $dispute->id, $dispute->status ); switch ( $dispute->status ) { case 'won': //set the order's status back to what it was before the dispute if ( ! empty( $dispute->metadata['prev_order_status'] ) ) { $status = $dispute->metadata['prev_order_status']; } else { $status = $order->needs_processing() ? 'processing' : 'completed'; } $order->update_status( $status, $message ); break; case 'lost': $order->update_status( apply_filters( 'wc_stripe_dispute_closed_order_status', 'failed', $dispute, $order ), $message ); } } } /** * @param Stripe\Review $review */ function wc_stripe_review_opened( $review ) { if ( stripe_wc()->advanced_settings->is_review_opened_enabled() ) { if ( isset( $review->charge ) ) { $order = wc_stripe_get_order_from_transaction( $review->charge ); } else { // In some cases, Stripe does not provide the charge ID in the Review object. $pi = $review->payment_intent; if ( $pi ) { $payment_intent = WC_Stripe_Gateway::load()->mode( $review )->paymentIntents->retrieve( $pi ); if ( ! is_wp_error( $payment_intent ) && isset( $payment_intent->metadata['order_id'] ) ) { $order = wc_get_order( $payment_intent->metadata['order_id'] ); } } } if ( $order ) { $status = $order->get_status(); $order->update_meta_data( WC_Stripe_Constants::PREV_STATUS, $status ); $message = sprintf( __( 'A review has been opened for charge %1$s. Reason: %2$s.', 'woo-stripe-payment' ), $review->charge, strtoupper( $review->reason ) ); $order->update_status( apply_filters( 'wc_stripe_review_opened_order_status', 'on-hold', $review, $order ), $message ); } } } /** * @param Stripe\Review $review */ function wc_stripe_review_closed( $review ) { if ( stripe_wc()->advanced_settings->is_review_closed_enabled() ) { if ( isset( $review->charge ) ) { $order = wc_stripe_get_order_from_transaction( $review->charge ); } else { // In some cases, Stripe does not provide the charge ID in the Review object. $pi = $review->payment_intent; if ( $pi ) { $payment_intent = WC_Stripe_Gateway::load()->mode( $review )->paymentIntents->retrieve( $pi ); if ( ! is_wp_error( $payment_intent ) && isset( $payment_intent->metadata['order_id'] ) ) { $order = wc_get_order( $payment_intent->metadata['order_id'] ); } } } if ( $order ) { $status = $order->get_meta( WC_Stripe_Constants::PREV_STATUS ); if ( ! $status ) { $status = $order->needs_processing() ? 'processing' : 'completed'; } $order->delete_meta_data( WC_Stripe_Constants::PREV_STATUS ); $message = sprintf( __( 'A review has been closed for charge %1$s. Reason: %2$s.', 'woo-stripe-payment' ), $review->charge, strtoupper( $review->reason ) ); $order->update_status( $status, $message ); } } } /** * @param \Stripe\PaymentIntent $payment_intent */ function wc_stripe_process_requires_action( $payment_intent ) { if ( isset( $payment_intent->metadata['gateway_id'], $payment_intent->metadata['order_id'] ) ) { if ( in_array( $payment_intent->metadata['gateway_id'], array( 'stripe_oxxo', 'stripe_boleto', 'stripe_konbini' ), true ) ) { $order = WC_Stripe_Utils::get_order_from_payment_intent( $payment_intent ); if ( ! $order ) { return; } /** * * @var WC_Payment_Gateway_Stripe $payment_method */ $payment_method = WC()->payment_gateways()->payment_gateways()[ $payment_intent->metadata['gateway_id'] ]; if ( $payment_method ) { $payment_method->process_voucher_order_status( $order ); wc_stripe_log_info( sprintf( 'Order status processed for Voucher payment. Order ID %s. Payment Intent %s', $order->get_id(), $payment_intent->id ) ); } } } } /** * @param Stripe\Charge $charge */ function wc_stripe_process_charge_pending( $charge ) { if ( isset( $charge->metadata['gateway_id'], $charge->metadata['order_id'] ) ) { $payment_methods = WC()->payment_gateways()->payment_gateways(); $payment_method = $charge->metadata['gateway_id']; $payment_method = isset( $payment_methods[ $payment_method ] ) ? $payment_methods[ $payment_method ] : null; if ( $payment_method && $payment_method instanceof \WC_Payment_Gateway_Stripe && ! $payment_method->synchronous ) { $order = wc_get_order( wc_stripe_filter_order_id( $charge->metadata['order_id'], $charge ) ); if ( $order ) { // temporary check to prevent race conditions caused by status update also occurring in // class-wc-stripe-payment-intent.php line 89 at the same time as the webhook being received for ach payments if ( $payment_method->id !== 'stripe_ach' && ! $payment_method->has_order_lock( $order ) ) { $payment_method->set_order_lock( $order ); $payment_method->payment_object->payment_complete( $order, $charge ); $payment_method->release_order_lock( $order ); } } } } }