Файловый менеджер - Редактировать - /home/harasnat/www/labour/wp-content/plugins/woocommerce-payments/includes/class-wc-payments-customer-service.php
Назад
<?php /** * Class WC_Payments_Customer * * @package WooCommerce\Payments */ use WCPay\Database_Cache; use WCPay\Exceptions\API_Exception; use WCPay\Logger; use WCPay\Constants\Payment_Method; defined( 'ABSPATH' ) || exit; /** * Class handling any customer functionality */ class WC_Payments_Customer_Service { /** * Deprecated Stripe customer ID option. * * This option was used to store the customer_id in a WC_User options before we decoupled live and test customers. */ const DEPRECATED_WCPAY_CUSTOMER_ID_OPTION = '_wcpay_customer_id'; /** * Live Stripe customer ID option. * * This option is used to store new live mode customers in a WC_User options. Customers stored in the deprecated * option are migrated to this one. */ const WCPAY_LIVE_CUSTOMER_ID_OPTION = '_wcpay_customer_id_live'; /** * Test Stripe customer ID option. * * This option is used to store new test mode customer IDs in a WC_User options. */ const WCPAY_TEST_CUSTOMER_ID_OPTION = '_wcpay_customer_id_test'; /** * Key used to store customer id for non logged in users in WooCommerce Session. */ const CUSTOMER_ID_SESSION_KEY = 'wcpay_customer_id'; /** * Client for making requests to the WooCommerce Payments API * * @var WC_Payments_API_Client */ private $payments_api_client; /** * WC_Payments_Account instance to get information about the account * * @var WC_Payments_Account */ private $account; /** * Database_Cache instance to get information about the account * * @var Database_Cache */ private $database_cache; /** * WC_Payments_Session_Service instance for working with session information * * @var WC_Payments_Session_Service */ private $session_service; /** * WC_Payments_Order_Service instance * * @var WC_Payments_Order_Service */ private $order_service; /** * Class constructor * * @param WC_Payments_API_Client $payments_api_client Payments API client. * @param WC_Payments_Account $account WC_Payments_Account instance. * @param Database_Cache $database_cache Database_Cache instance. * @param WC_Payments_Session_Service $session_service Session Service class instance. * @param WC_Payments_Order_Service $order_service Order Service class instance. */ public function __construct( WC_Payments_API_Client $payments_api_client, WC_Payments_Account $account, Database_Cache $database_cache, WC_Payments_Session_Service $session_service, WC_Payments_Order_Service $order_service ) { $this->payments_api_client = $payments_api_client; $this->account = $account; $this->database_cache = $database_cache; $this->session_service = $session_service; $this->order_service = $order_service; } /** * Initialize hooks */ public function init_hooks() { /* * Adds the WooCommerce Payments customer ID found in the user session * to the WordPress user as metadata. * * This is helpful in scenarios where the shopper begins the checkout flow * logged out (i.e. guest checkout) and a user account is created for them * during checkout. * * This occurs when a user account is necessary for checkout, e.g. when the shopper * purchases a subscription product. */ add_action( 'woocommerce_created_customer', [ $this, 'add_customer_id_to_user' ] ); } /** * Get WCPay customer ID for the given WordPress user ID * * @param int|null $user_id The user ID to look for a customer ID with. * * @return string|null WCPay customer ID or null if not found. */ public function get_customer_id_by_user_id( $user_id ) { // User ID might be 0 if fetched from a WP_User instance for a user who isn't logged in. if ( null === $user_id || 0 === $user_id ) { // Try to retrieve the customer id from the session if stored previously. $customer_id = WC()->session ? WC()->session->get( self::CUSTOMER_ID_SESSION_KEY ) : null; return is_string( $customer_id ) ? $customer_id : null; } $customer_id = get_user_option( $this->get_customer_id_option(), $user_id ); // If customer_id is false it could mean that it hasn't been migrated from the deprecated key. if ( false === $customer_id ) { $this->maybe_migrate_deprecated_customer( $user_id ); // Customer might've been migrated in maybe_migrate_deprecated_customer, so we need to fetch it again. $customer_id = get_user_option( $this->get_customer_id_option(), $user_id ); } return $customer_id ? $customer_id : null; } /** * Create a customer and associate it with a WordPress user. * * @param WP_User|null $user User to create a customer for. * @param array $customer_data Customer data. * * @return string The created customer's ID * * @throws API_Exception Error creating customer. */ public function create_customer_for_user( ?WP_User $user, array $customer_data = [] ): string { // Include the session ID for the user. $customer_data['session_id'] = $this->session_service->get_sift_session_id() ?? null; // Create a customer on the WCPay server. $customer_id = $this->payments_api_client->create_customer( $customer_data ); if ( $user instanceof WP_User && $user->ID > 0 ) { $this->update_user_customer_id( $user->ID, $customer_id ); } if ( isset( WC()->session ) ) { // Save the customer id in the session for non logged in users to reuse it in payments. WC()->session->set( self::CUSTOMER_ID_SESSION_KEY, $customer_id ); } return $customer_id; } /** * Manages customer details held on WCPay server for WordPress user associated with an order. * * @param int|null $user_id ID of the WP user to associate with the customer. * @param WC_Order $order Woo Order. * * @return string WooPayments customer ID. * @throws API_Exception Throws when server API request fails. */ public function get_or_create_customer_id_from_order( ?int $user_id, WC_Order $order ): string { // Determine the customer making the payment, create one if we don't have one already. $customer_id = $this->get_customer_id_by_user_id( $user_id ); $customer_data = self::map_customer_data( $order, new WC_Customer( $user_id ?? 0 ) ); $user = null === $user_id ? null : get_user_by( 'id', $user_id ); if ( null !== $customer_id ) { $this->update_customer_for_user( $customer_id, $user, $customer_data ); return $customer_id; } return $this->create_customer_for_user( $user, $customer_data ); } /** * Update the customer details held on the WCPay server associated with the given WordPress user. * * @param string $customer_id WCPay customer ID. * @param WP_User|null $user WordPress user. * @param array $customer_data Customer data. * * @return string The updated customer's ID. Can be different to the ID parameter if the customer was re-created. * * @throws API_Exception Error updating the customer. */ public function update_customer_for_user( string $customer_id, ?WP_User $user, array $customer_data ): string { try { // Update the customer on the WCPay server. $this->payments_api_client->update_customer( $customer_id, $customer_data ); // We successfully updated the existing customer, so return the passed in ID unchanged. return $customer_id; } catch ( API_Exception $e ) { // If we failed to find the customer we wanted to update, then create a new customer and associate it to the // current user instead. This might happen if the customer was deleted from the server, the linked WCPay // account was changed, or if users were imported from another site. if ( $e->get_error_code() === 'resource_missing' ) { // Create a new customer to associate with this user. We'll return the new customer ID. return $this->recreate_customer( $user, $customer_data ); } // For any other type of exception, just re-throw. throw $e; } } /** * Sets a payment method as default for a customer. * * @param string $customer_id The customer ID. * @param string $payment_method_id The payment method ID. */ public function set_default_payment_method_for_customer( $customer_id, $payment_method_id ) { $this->payments_api_client->update_customer( $customer_id, [ 'invoice_settings' => [ 'default_payment_method' => $payment_method_id, ], ] ); } /** * Gets all payment methods for a customer. * * @param string $customer_id The customer ID. * @param string $type Type of payment methods to fetch. * * @throws API_Exception We only handle 'resource_missing' code types and rethrow anything else. */ public function get_payment_methods_for_customer( $customer_id, $type = 'card' ) { if ( ! $customer_id ) { return []; } $cache_payment_methods = ! WC_Payments::is_network_saved_cards_enabled(); $cache_key = Database_Cache::PAYMENT_METHODS_KEY_PREFIX . $customer_id . '_' . $type; if ( $cache_payment_methods ) { $payment_methods = $this->database_cache->get( $cache_key ); if ( is_array( $payment_methods ) ) { return $payment_methods; } } try { $payment_methods = $this->payments_api_client->get_payment_methods( $customer_id, $type )['data']; if ( $cache_payment_methods ) { $this->database_cache->add( $cache_key, $payment_methods ); } return $payment_methods; } catch ( API_Exception $e ) { // If we failed to find the payment methods, we can simply return empty payment methods as this customer // will be recreated when the user successfully adds a payment method. if ( $e->get_error_code() === 'resource_missing' ) { return []; } // Rethrow for error codes we don't care about in this function. throw $e; } } /** * Updates a customer payment method. * * @param string $payment_method_id The payment method ID. * @param WC_Order $order Order to be used on the update. */ public function update_payment_method_with_billing_details_from_order( $payment_method_id, $order ) { $billing_details = $this->order_service->get_billing_data_from_order( $order ); if ( ! empty( $billing_details ) ) { $this->payments_api_client->update_payment_method( $payment_method_id, [ 'billing_details' => $billing_details, ] ); } } /** * Clear payment methods cache for a user. * * @param int $user_id WC user ID. */ public function clear_cached_payment_methods_for_user( $user_id ) { if ( WC_Payments::is_network_saved_cards_enabled() ) { return; // No need to do anything, payment methods will never be cached in this case. } $retrievable_payment_method_types = [ Payment_Method::CARD, Payment_Method::LINK, Payment_Method::SEPA ]; $customer_id = $this->get_customer_id_by_user_id( $user_id ); foreach ( $retrievable_payment_method_types as $type ) { $this->database_cache->delete( Database_Cache::PAYMENT_METHODS_KEY_PREFIX . $customer_id . '_' . $type ); } } /** * Given a WC_Order or WC_Customer, returns an array representing a Stripe customer object. * At least one parameter has to not be null. * * @param WC_Order $wc_order The Woo order to parse. * @param WC_Customer $wc_customer The Woo customer to parse. * * @return array Customer data. */ public static function map_customer_data( ?WC_Order $wc_order = null, ?WC_Customer $wc_customer = null ): array { if ( null === $wc_customer && null === $wc_order ) { return []; } // Where available, the order data takes precedence over the customer. $object_to_parse = $wc_order ?? $wc_customer; $name = $object_to_parse->get_billing_first_name() . ' ' . $object_to_parse->get_billing_last_name(); $description = ''; if ( null !== $wc_customer && ! empty( $wc_customer->get_username() ) ) { // We have a logged in user, so add their username to the customer description. // translators: %1$s Name, %2$s Username. $description = sprintf( __( 'Name: %1$s, Username: %2$s', 'woocommerce-payments' ), $name, $wc_customer->get_username() ); } else { // Current user is not logged in. // translators: %1$s Name. $description = sprintf( __( 'Name: %1$s, Guest', 'woocommerce-payments' ), $name ); } $data = [ 'name' => $name, 'description' => $description, 'email' => $object_to_parse->get_billing_email(), 'phone' => $object_to_parse->get_billing_phone(), 'address' => [ 'line1' => $object_to_parse->get_billing_address_1(), 'line2' => $object_to_parse->get_billing_address_2(), 'postal_code' => $object_to_parse->get_billing_postcode(), 'city' => $object_to_parse->get_billing_city(), 'state' => $object_to_parse->get_billing_state(), 'country' => $object_to_parse->get_billing_country(), ], ]; if ( ! empty( $object_to_parse->get_shipping_postcode() ) ) { $data['shipping'] = [ 'name' => $object_to_parse->get_shipping_first_name() . ' ' . $object_to_parse->get_shipping_last_name(), 'address' => [ 'line1' => $object_to_parse->get_shipping_address_1(), 'line2' => $object_to_parse->get_shipping_address_2(), 'postal_code' => $object_to_parse->get_shipping_postcode(), 'city' => $object_to_parse->get_shipping_city(), 'state' => $object_to_parse->get_shipping_state(), 'country' => $object_to_parse->get_shipping_country(), ], ]; } return $data; } /** * Delete all saved payment methods that are stored inside the database cache driver. * * @return void */ public function delete_cached_payment_methods() { $this->database_cache->delete_by_prefix( Database_Cache::PAYMENT_METHODS_KEY_PREFIX ); } /** * Recreates the customer for this user. * * @param WP_User|null $user User to recreate a customer for. * @param array $customer_data Customer data. * * @return string The newly created customer's ID * * @throws API_Exception Error creating customer. */ private function recreate_customer( ?WP_User $user, array $customer_data ): string { if ( $user instanceof WP_User && $user->ID > 0 ) { $result = delete_user_option( $user->ID, $this->get_customer_id_option() ); if ( ! $result ) { // Log the error, but continue since we'll be trying to update this option in create_customer. Logger::error( 'Failed to delete old customer ID for user ' . $user->ID ); } } return $this->create_customer_for_user( $user, $customer_data ); } /** * Returns the name of the customer option meta, taking test mode into account. * * @return string The customer ID option name. */ private function get_customer_id_option(): string { return WC_Payments::mode()->is_test() ? self::WCPAY_TEST_CUSTOMER_ID_OPTION : self::WCPAY_LIVE_CUSTOMER_ID_OPTION; } /** * Migrate any customer ID that might be in the DEPRECATED_WCPAY_CUSTOMER_ID_OPTION. * * @param int $user_id The user ID to look for a customer ID with. */ private function maybe_migrate_deprecated_customer( $user_id ) { $customer_id = get_user_option( self::DEPRECATED_WCPAY_CUSTOMER_ID_OPTION, $user_id ); if ( false !== $customer_id ) { // A customer was found in the deprecated key. Migrate it to the appropriate one and delete the old meta. // If an account is live mode, we optimistically assume that the customer is live mode, to avoid losing // live mode customer data. If the account is not live mode, it can only have test mode objects, so we // can safely migrate them to the test key. // If is_live cannot be determined, default it to true to avoid considering a live account as test. $account_is_live = null === $this->account->get_is_live() || $this->account->get_is_live(); $customer_option_id = $account_is_live ? self::WCPAY_LIVE_CUSTOMER_ID_OPTION : self::WCPAY_TEST_CUSTOMER_ID_OPTION; if ( update_user_option( $user_id, $customer_option_id, $customer_id ) ) { delete_user_option( $user_id, self::DEPRECATED_WCPAY_CUSTOMER_ID_OPTION ); } else { Logger::error( 'Failed to store new customer ID for user ' . $user_id . '; legacy customer was kept.' ); } } } /** * Get the WCPay customer ID associated with an order, or create one if none found. * * @param WC_Order $order WC Order object. * * @return string|null WCPay customer ID. * @throws API_Exception If there's an error creating customer. */ public function get_customer_id_for_order( $order ) { $customer_id = null; $user = $order->get_user(); if ( false !== $user ) { // Determine the customer making the payment, create one if we don't have one already. $customer_id = $this->get_customer_id_by_user_id( $user->ID ); if ( null === $customer_id ) { $customer_data = self::map_customer_data( $order, new WC_Customer( $user->ID ) ); $customer_id = $this->create_customer_for_user( $user, $customer_data ); } } return $customer_id; } /** * Updates the given user with the given WooCommerce Payments * customer ID. * * @param int $user_id The WordPress user ID. * @param string $customer_id The WooCommerce Payments customer ID. */ public function update_user_customer_id( int $user_id, string $customer_id ) { $global = WC_Payments::is_network_saved_cards_enabled(); $result = update_user_option( $user_id, $this->get_customer_id_option(), $customer_id, $global ); if ( ! $result ) { Logger::error( 'Failed to update customer ID for user ' . $user_id ); } } /** * Adds the WooCommerce Payments customer ID found in the user session * to the WordPress user as metadata. * * @param int $user_id The WordPress user ID. */ public function add_customer_id_to_user( $user_id ) { // Not processing a checkout, bail. if ( ! ( defined( 'WOOCOMMERCE_CHECKOUT' ) && WOOCOMMERCE_CHECKOUT ) && ! ( function_exists( 'wcs_is_checkout_blocks_api_request' ) && wcs_is_checkout_blocks_api_request( 'v1/checkout' ) ) ) { return; } // Retrieve the WooCommerce Payments customer ID from the user session. $customer_id = WC()->session ? WC()->session->get( self::CUSTOMER_ID_SESSION_KEY ) : null; if ( ! $customer_id ) { return; } $this->update_user_customer_id( $user_id, $customer_id ); } /** * Prepares customer data to be used on 'Pay for Order' or 'Add Payment Method' pages. * Customer data is retrieved from order when on Pay for Order. * Customer data is retrieved from customer when on 'Add Payment Method'. * * @return array|null An array with customer data or nothing. */ public function get_prepared_customer_data() { if ( ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended return null; } global $wp; $user_email = ''; $firstname = ''; $lastname = ''; $billing_country = ''; $address = null; if ( isset( $_GET['pay_for_order'] ) && 'true' === $_GET['pay_for_order'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $order_id = absint( $wp->query_vars['order-pay'] ); $order = wc_get_order( $order_id ); if ( is_a( $order, 'WC_Order' ) ) { $firstname = $order->get_billing_first_name(); $lastname = $order->get_billing_last_name(); $user_email = $order->get_billing_email(); $billing_country = $order->get_billing_country(); $address = [ 'city' => $order->get_billing_city(), 'country' => $order->get_billing_country(), 'line1' => $order->get_billing_address_1(), 'line2' => $order->get_billing_address_2(), 'postal_code' => $order->get_billing_postcode(), 'state' => $order->get_billing_state(), ]; } } if ( is_add_payment_method_page() ) { $user = wp_get_current_user(); if ( $user->ID ) { $firstname = $user->user_firstname; $lastname = $user->user_lastname; $user_email = get_user_meta( $user->ID, 'billing_email', true ); $user_email = ! empty( $user_email ) ? $user_email : $user->user_email; $billing_country = get_user_meta( $user->ID, 'billing_country', true ); } } return [ 'name' => $firstname . ' ' . $lastname, 'email' => $user_email, 'billing_country' => $billing_country, 'address' => $address, ]; } }
| ver. 1.4 |
Github
|
.
| PHP 8.1.33 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка