File manager - Edit - /home/verseaumee/blueversion/wp-content/plugins/coinbase-commerce/trunk/class-wc-gateway-coinbase.php
Back
<?php // phpcs:disable /** * Coinbase Commerce Payment Gateway. * * Provides a Coinbase Commerce Payment Gateway. * * @class WC_Gateway_Coinbase * @extends WC_Payment_Gateway * @since 1.0.0 * @package WooCommerce/Classes/Payment */ if ( ! defined( 'ABSPATH' ) ) { exit; } /** * WC_Gateway_Coinbase Class. */ class WC_Gateway_Coinbase extends WC_Payment_Gateway { /** * Log_enabled - whether or not logging is enabled * * @var bool Whether or not logging is enabled */ public static $log_enabled = false; /** * WC_Logger Logger instance * * @var WC_Logger Logger instance * */ public static $log = false; /** * Constructor for the gateway. */ public function __construct() { $this->id = 'coinbase'; $this->has_fields = false; $this->order_button_text = __( 'Proceed to Coinbase', 'coinbase' ); $this->method_title = __( 'Coinbase', 'coinbase' ); $this->method_description = '<p>' . // translators: Introduction text at top of Coinbase Commerce settings page. __( 'A payment gateway that sends your customers to Coinbase Commerce to pay with cryptocurrency.', 'coinbase' ) . '</p><p>' . sprintf( // translators: Introduction text at top of Coinbase Commerce settings page. Includes external URL. __( 'If you do not currently have a Coinbase Commerce account, you can set one up here: %s', 'coinbase' ), '<a target="_blank" href="https://commerce.coinbase.com/">https://commerce.coinbase.com/</a>' ); // Timeout after 3 days. Default to 3 days as pending Bitcoin txns // are usually forgotten after 2-3 days. $this->timeout = ( new WC_DateTime() )->sub( new DateInterval( 'P3D' ) ); // Load the settings. $this->init_form_fields(); $this->init_settings(); // Define user set variables. $this->title = $this->get_option( 'title' ); $this->description = $this->get_option( 'description' ); $this->debug = 'yes' === $this->get_option( 'debug', 'no' ); self::$log_enabled = $this->debug; add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); add_filter( 'woocommerce_order_data_store_cpt_get_orders_query', array( $this, '_custom_query_var' ), 10, 2 ); add_action( 'woocommerce_api_wc_gateway_coinbase', array( $this, 'handle_webhook' ) ); } /** * Logging method. * * @param string $message Log message. * @param string $level Optional. Default 'info'. * emergency|alert|critical|error|warning|notice|info|debug */ public static function log( $message, $level = 'info' ) { if ( self::$log_enabled ) { if ( empty( self::$log ) ) { self::$log = wc_get_logger(); } self::$log->log( $level, $message, array( 'source' => 'coinbase' ) ); } } /** * Get gateway icon. * * @return string */ public function get_icon() { if ( $this->get_option( 'show_icons' ) === 'no' ) { return ''; } $image_path = plugin_dir_path( __FILE__ ) . 'assets/images'; $icon_html = ''; $methods = get_option( 'coinbase_payment_methods', array( 'bitcoin', 'bitcoincash', 'dai', 'ethereum', 'litecoin', 'dogecoin', 'usdc', 'usdt', 'ape', 'shib' ) ); // Load icon for each available payment method. foreach ( $methods as $m ) { $path = realpath( $image_path . '/' . $m . '.png' ); if ( $path && dirname( $path ) === $image_path && is_file( $path ) ) { $url = WC_HTTPS::force_https_url( plugins_url( '/assets/images/' . $m . '.png', __FILE__ ) ); $icon_html .= '<img width="26" src="' . esc_attr( $url ) . '" alt="' . esc_attr__( $m, 'coinbase' ) . '" />'; } } /** DOCBLOCK - Makes linter happy. * * @since today */ return apply_filters( 'woocommerce_gateway_icon', $icon_html, $this->id ); } /** * Initialise Gateway Settings Form Fields. */ public function init_form_fields() { $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable/Disable', 'woocommerce' ), 'type' => 'checkbox', 'label' => __( 'Enable Coinbase Commerce Payment', 'coinbase' ), 'default' => 'yes', ), 'title' => array( 'title' => __( 'Title', 'woocommerce' ), 'type' => 'text', 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ), 'default' => __( 'Ethereum and other cryptocurrencies', 'coinbase' ), 'desc_tip' => true, ), 'description' => array( 'title' => __( 'Description', 'woocommerce' ), 'type' => 'text', 'desc_tip' => true, 'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce' ), 'default' => __( 'Pay with Ethereum or other cryptocurrencies.', 'coinbase' ), ), 'api_key' => array( 'title' => __( 'API Key', 'coinbase' ), 'type' => 'text', 'default' => '', 'description' => sprintf( // translators: Description field for API on settings page. Includes external link. __( 'You can manage your API keys within the Coinbase Commerce Settings page, available here: %s', 'coinbase' ), esc_url( 'https://commerce.coinbase.com/dashboard/settings' ) ), ), 'webhook_secret' => array( 'title' => __( 'Webhook Shared Secret', 'coinbase' ), 'type' => 'text', 'description' => // translators: Instructions for setting up 'webhook shared secrets' on settings page. __( 'Using webhooks allows Coinbase Commerce to send payment confirmation messages to the website. To fill this out:', 'coinbase' ) . '<br /><br />' . // translators: Step 1 of the instructions for 'webhook shared secrets' on settings page. __( '1. In your Coinbase Commerce settings page, scroll to the \'Webhook subscriptions\' section', 'coinbase' ) . '<br />' . // translators: Step 2 of the instructions for 'webhook shared secrets' on settings page. Includes webhook URL. sprintf( __( '2. Click \'Add an endpoint\' and paste the following URL: %s', 'coinbase' ), add_query_arg( 'wc-api', 'WC_Gateway_Coinbase', home_url( '/', 'https' ) ) ) . '<br />' . // translators: Step 3 of the instructions for 'webhook shared secrets' on settings page. __( '3. Make sure to select "Send me all events", to receive all payment updates.', 'coinbase' ) . '<br />' . // translators: Step 4 of the instructions for 'webhook shared secrets' on settings page. __( '4. Click "Show shared secret" and paste into the box above.', 'coinbase' ), ), 'show_icons' => array( 'title' => __( 'Show icons', 'coinbase' ), 'type' => 'checkbox', 'label' => __( 'Display currency icons on checkout page.', 'coinbase' ), 'default' => 'yes', ), 'debug' => array( 'title' => __( 'Debug log', 'woocommerce' ), 'type' => 'checkbox', 'label' => __( 'Enable logging', 'woocommerce' ), 'default' => 'no', // translators: Description for 'Debug log' section of settings page. 'description' => sprintf( __( 'Log Coinbase API events inside %s', 'coinbase' ), '<code>' . WC_Log_Handler_File::get_log_file_path( 'coinbase' ) . '</code>' ), ), ); } /** * Process the payment and return the result. * * @param int $order_id * @return array */ public function process_payment( $order_id ) { $order = wc_get_order( $order_id ); // Create description for charge based on order's products. Ex: 1 x Product1, 2 x Product2 try { $order_items = array_map( function( $item ) { return $item['quantity'] . ' x ' . $item['name']; }, $order->get_items() ); $description = mb_substr( implode( ', ', $order_items ), 0, 200 ); } catch ( Exception $e ) { $description = null; } $this->init_api(); // Create a new charge. $metadata = array( 'order_id' => strval($order->get_id()), 'order_key' => $order->get_order_key(), 'source' => 'woocommerce' ); $result = Coinbase_API_Handler::create_charge( $order->get_total(), get_woocommerce_currency(), $metadata, $this->get_return_url( $order ), null, $description, $this->get_cancel_url( $order ) ); if ( ! $result[0] ) { return array( 'result' => 'fail' ); } $charge = $result[1]['data']; $order->update_meta_data( '_coinbase_charge_id', $charge['id'] ); $order->save(); return array( 'result' => 'success', 'redirect' => $charge['hosted_url'], ); } /** * Get the cancel url. * * @param WC_Order $order Order object. * @return string */ public function get_cancel_url( $order ) { $return_url = $order->get_cancel_order_url(); if ( is_ssl() || get_option( 'woocommerce_force_ssl_checkout' ) == 'yes' ) { $return_url = str_replace( 'http:', 'https:', $return_url ); } /** DOCBLOCK - Makes linter happy. * * @since today */ return apply_filters( 'woocommerce_get_cancel_url', $return_url, $order ); } /** * Check payment statuses on orders and update order statuses. */ public function check_orders() { $this->init_api(); // Check the status of non-archived Coinbase orders. $orders = wc_get_orders( array( 'coinbase_archived' => false, 'status' => array( 'wc-pending' ), 'meta_query' => array( array( 'key' => '_coinbase_archived', 'compare' => 'NOT EXISTS', ), array( 'key' => '_coinbase_charge_id', 'compare' => 'EXISTS', ) ) ) ); foreach ( $orders as $order ) { $charge_id = $order->get_meta( '_coinbase_charge_id' ); usleep( 300000 ); // Ensure we don't hit the rate limit. $result = Coinbase_API_Handler::send_request( 'charges/' . $charge_id ); if ( ! $result[0] ) { self::log( 'Failed to fetch order updates for: ' . $order->get_id() ); continue; } $timeline = $result[1]['data']['timeline']; self::log( 'Timeline: ' . print_r( $timeline, true ) ); $this->_update_order_status( $order, $timeline ); } } /** * Handle requests sent to webhook. */ public function handle_webhook() { $payload = file_get_contents( 'php://input' ); if ( ! empty( $payload ) && $this->validate_webhook( $payload ) ) { $data = json_decode( $payload, true ); $event_data = $data['event']['data']; self::log( 'Webhook received event: ' . print_r( $data, true ) ); if ( ! isset( $event_data['metadata']['order_id'] ) ) { // Probably a charge not created by us. exit; } $order_id = $event_data['metadata']['order_id']; $this->_update_order_status( wc_get_order( $order_id ), $event_data['timeline'] ); exit; // 200 response for acknowledgement. } wp_die( 'Coinbase Webhook Request Failure', 'Coinbase Webhook', array( 'response' => 500 ) ); } /** * Check Coinbase webhook request is valid. * * @param string $payload */ public function validate_webhook( $payload ) { self::log( 'Checking Webhook response is valid' ); if ( ! isset( $_SERVER['HTTP_X_CC_WEBHOOK_SIGNATURE'] ) ) { return false; } $sig = $_SERVER['HTTP_X_CC_WEBHOOK_SIGNATURE']; $secret = $this->get_option( 'webhook_secret' ); $sig2 = hash_hmac( 'sha256', $payload, $secret ); if ( $sig === $sig2 ) { return true; } return false; } /** * Init the API class and set the API key etc. */ protected function init_api() { include_once dirname( __FILE__ ) . '/includes/class-coinbase-api-handler.php'; Coinbase_API_Handler::$log = get_class( $this ) . '::log'; Coinbase_API_Handler::$api_key = $this->get_option( 'api_key' ); } /** * Update the status of an order from a given timeline. * * @param WC_Order $order * @param array $timeline */ public function _update_order_status( $order, $timeline ) { $prev_status = $order->get_meta( '_coinbase_status' ); $last_update = end( $timeline ); $status = $last_update['status']; if ( $status !== $prev_status ) { $order->update_meta_data( '_coinbase_status', $status ); if ( 'EXPIRED' === $status && 'pending' == $order->get_status() ) { $order->update_status( 'cancelled', __( 'Coinbase payment expired.', 'coinbase' ) ); } elseif ( 'CANCELED' === $status ) { $order->update_status( 'cancelled', __( 'Coinbase payment cancelled.', 'coinbase' ) ); } elseif ( 'PENDING' === $status ) { $order->update_status( 'blockchainpending', __( 'Coinbase payment detected, but awaiting blockchain confirmation.', 'coinbase' ) ); } elseif ( 'COMPLETED' === $status ) { $order->update_status( 'processing', __( 'Coinbase payment was successfully processed.', 'coinbase' ) ); $order->payment_complete(); } } // Archive if in a resolved state and idle more than timeout. if ( in_array( $status, array( 'EXPIRED', 'COMPLETED' ), true ) && $order->get_date_modified() < $this->timeout ) { self::log( 'Archiving order: ' . $order->get_order_number() ); $order->update_meta_data( '_coinbase_archived', true ); } } /** * Handle a custom 'coinbase_archived' query var to get orders * payed through Coinbase with the '_coinbase_archived' meta. * * @param array $query - Args for WP_Query. * @param array $query_vars - Query vars from WC_Order_Query. * @return array modified $query */ public function _custom_query_var( $query, $query_vars ) { if ( array_key_exists( 'coinbase_archived', $query_vars ) ) { $query['meta_query'][] = array( 'key' => '_coinbase_archived', 'compare' => $query_vars['coinbase_archived'] ? 'EXISTS' : 'NOT EXISTS', ); // Limit only to orders payed through Coinbase. $query['meta_query'][] = array( 'key' => '_coinbase_charge_id', 'compare' => 'EXISTS', ); } return $query; } }
| ver. 1.4 |
Github
|
.
| PHP 8.5.7 | Generation time: 0 |
proxy
|
phpinfo
|
Settings