Файловый менеджер - Редактировать - /home/harasnat/www/labour/wp-content/plugins/woocommerce-payments/src/Internal/Service/Level3Service.php
Назад
<?php /** * Class Level3Service * * @package WooCommerce\Payments */ namespace WCPay\Internal\Service; use WC_Order_Item; use WC_Order_Item_Product; use WC_Order_Item_Fee; use WC_Payments_Account; use WC_Payments_Utils; use WCPay\Exceptions\Order_Not_Found_Exception; use WCPay\Internal\Proxy\LegacyProxy; /** * Service for generating Level 3 data from orders. */ class Level3Service { /** * Order service. * * @var OrderService */ private $order_service; /** * WC_Payments_Account instance to get information about the account * * @var WC_Payments_Account */ private $account; /** * Legacy proxy. * * @var LegacyProxy */ private $legacy_proxy; /** * Service constructor. * * @param OrderService $order_service Order service. * @param WC_Payments_Account $account WooPayments account. * @param LegacyProxy $legacy_proxy Legacy proxy. */ public function __construct( OrderService $order_service, WC_Payments_Account $account, LegacyProxy $legacy_proxy ) { $this->order_service = $order_service; $this->account = $account; $this->legacy_proxy = $legacy_proxy; } /** * Create the level 3 data array to send to Stripe when making a purchase. * * @param int $order_id The order that is being paid for. * @return array The level 3 data to send to the API. * @throws Order_Not_Found_Exception */ public function get_data_from_order( int $order_id ): array { $order = $this->order_service->_deprecated_get_order( $order_id ); $merchant_country = $this->account->get_account_country(); // We do not need to send level3 data if merchant account country is non-US. if ( 'US' !== $merchant_country ) { return []; } // Get the order items. Don't need their keys, only their values. // Order item IDs are used as keys in the original order items array. $order_items = array_values( $order->get_items( [ 'line_item', 'fee' ] ) ); $currency = $order->get_currency(); $items_to_send = []; foreach ( $order_items as $item ) { $items_to_send = array_merge( $items_to_send, $this->process_item( $item, $currency ) ); } $level3_data = [ 'merchant_reference' => (string) $order->get_id(), // An alphanumeric string of up to characters in length. This unique value is assigned by the merchant to identify the order. Also known as an “Order ID”. 'customer_reference' => (string) $order->get_id(), 'shipping_amount' => $this->prepare_amount( (float) $order->get_shipping_total() + (float) $order->get_shipping_tax(), $currency ), // The shipping cost, in cents, as a non-negative integer. 'line_items' => $items_to_send, ]; // The customer’s U.S. shipping ZIP code. $shipping_address_zip = $order->get_shipping_postcode(); if ( WC_Payments_Utils::is_valid_us_zip_code( $shipping_address_zip ) ) { $level3_data['shipping_address_zip'] = $shipping_address_zip; } // The merchant’s U.S. shipping ZIP code. $store_postcode = $this->legacy_proxy->call_function( 'get_option', 'woocommerce_store_postcode' ); if ( WC_Payments_Utils::is_valid_us_zip_code( $store_postcode ) ) { $level3_data['shipping_from_zip'] = $store_postcode; } /** * Filters the Level 3 data based on order. * * Example usage: Enables updating the discount based on the products in the order, * if any of the products are gift cards. * * @since 8.0.0 * * @param array $level3_data Precalculated Level 3 data based on order. * @param WC_Order $order The order object. */ $level3_data = apply_filters( 'wcpay_payment_request_level3_data', $level3_data, $order ); if ( count( $level3_data['line_items'] ) > 200 ) { // If more than 200 items are present, bundle the last ones in a single item. $items_to_send = array_merge( array_slice( $level3_data['line_items'], 0, 199 ), [ $this->bundle_level3_data_from_items( array_slice( $level3_data['line_items'], 199 ) ) ] ); $level3_data['line_items'] = $items_to_send; } return $level3_data; } /** * Processes a single order item. * Based on the queried items, this class should only receive * `WC_Order_Item_Product` or `WC_Order_Item_Fee` line items. * * @param WC_Order_Item_Product|WC_Order_Item_Fee $item Item to process. * @param string $currency Currency to use. * @return \stdClass[] */ private function process_item( WC_Order_Item $item, string $currency ): array { // Check to see if it is a WC_Order_Item_Product or a WC_Order_Item_Fee. if ( $item instanceof WC_Order_Item_Product ) { $subtotal = $item->get_subtotal(); $product_id = $item->get_variation_id() ? $item->get_variation_id() : $item->get_product_id(); $product_code = substr( $product_id, 0, 12 ); } else { $subtotal = $item->get_total(); $product_code = substr( sanitize_title( $item->get_name() ), 0, 12 ); } $description = substr( $item->get_name(), 0, 26 ); $quantity = ceil( $item->get_quantity() ); $tax_amount = $this->prepare_amount( $item->get_total_tax(), $currency ); if ( $subtotal >= 0 ) { $unit_cost = $this->prepare_amount( $subtotal / $quantity, $currency ); $discount_amount = $this->prepare_amount( $subtotal - $item->get_total(), $currency ); } else { // It's possible to create products with negative price - represent it as free one with discount. $discount_amount = abs( $this->prepare_amount( $subtotal / $quantity, $currency ) ); $unit_cost = 0; } // Tax also shouldn't be negative so represent it as a discount. if ( $tax_amount < 0 ) { $discount_amount += abs( $tax_amount ); $tax_amount = 0; } $line_item = (object) [ 'product_code' => (string) $product_code, // Up to 12 characters that uniquely identify the product. 'product_description' => $description, // Up to 26 characters long describing the product. 'unit_cost' => $unit_cost, // Cost of the product, in cents, as a non-negative integer. 'quantity' => $quantity, // The number of items of this type sold, as a non-negative integer. 'tax_amount' => $tax_amount, // The amount of tax this item had added to it, in cents, as a non-negative integer. 'discount_amount' => $discount_amount, // The amount an item was discounted—if there was a sale,for example, as a non-negative integer. ]; $line_items = [ $line_item ]; /** * In edge cases, rounding after division might lead to a slight inconsistency. * * For example: 10/3 with 2 decimal places = 3.33, but 3.33*3 = 9.99. */ if ( $subtotal > 0 ) { $prepared_subtotal = $this->prepare_amount( $subtotal, $currency ); $difference = $prepared_subtotal - ( $unit_cost * $quantity ); if ( $difference > 0 ) { $line_items[] = (object) [ 'product_code' => 'rounding-fix', 'product_description' => __( 'Rounding fix', 'woocommerce-payments' ), 'unit_cost' => $difference, 'quantity' => 1, 'tax_amount' => 0, 'discount_amount' => 0, ]; } } return $line_items; } /** * Returns a bundle of products passed as an argument. Useful when working with Stripe's level 3 data * * @param array $items The Stripe's level 3 array of items. * * @return \stdClass A bundle of the products passed. */ private function bundle_level3_data_from_items( array $items ) { // Total cost is the sum of each product cost * quantity. $items_count = count( $items ); $total_cost = array_sum( array_map( function ( $cost, $qty ) { return $cost * $qty; }, array_column( $items, 'unit_cost' ), array_column( $items, 'quantity' ) ) ); return (object) [ 'product_code' => (string) substr( uniqid(), 0, 26 ), 'product_description' => "{$items_count} more items", 'unit_cost' => $total_cost, 'quantity' => 1, 'tax_amount' => array_sum( array_column( $items, 'tax_amount' ) ), 'discount_amount' => array_sum( array_column( $items, 'discount_amount' ) ), ]; } /** * Returns an API-ready amount based on a currency. * * @param float $amount The base amount. * @param string $currency The currency for the amount. * * @return int The amount in cents. */ private function prepare_amount( float $amount, string $currency ): int { return WC_Payments_Utils::prepare_amount( $amount, $currency ); } }
| ver. 1.4 |
Github
|
.
| PHP 8.1.33 | Генерация страницы: 0.02 |
proxy
|
phpinfo
|
Настройка