/**
     * Process automatic subscription payment
     * 
     * @access public
     * @param bool $payment_successful
     * @param array $order
     * @param array $subscription
     * @return bool
     */
    public function process_payment($payment_successful, $order, $subscription)
    {
        $customer_id = get_user_meta($subscription->user_id, '_subscriptio_stripe_customer_id', true);
        $default_card = get_user_meta($subscription->user_id, '_subscriptio_stripe_customer_default_card', true);

        if (empty($customer_id) || empty($default_card)) {
            return false;
        }

        // Load payment gateway object to access its methods
        $gateway = new Subscriptio_Stripe_Gateway();

        // Send request
        $response = $gateway->charge(array(
            'amount'        => $order->order_total * apply_filters('subscriptio_stripe_decimals_in_currency', 100, $order),
            'currency'      => strtolower($order->get_order_currency()),
            'description'   => apply_filters('subscriptio_stripe_payment_description', esc_html(get_bloginfo('name')) . ' - ' . __('Order', 'subscriptio-stripe') . ' ' . $order->get_order_number() . ' (' . __('Subscription', 'subscriptio-stripe') . ' ' . $subscription->get_subscription_number() . ')', $order),
            'metadata'      => array(
                'order_id'          => $order->id,
                'subscription_id'   => $subscription->id,
                'email'             => $order->billing_email,
            ),
            'statement_description' => substr(sprintf(__('Subscr %s', 'subscriptio-stripe'), $subscription->get_subscription_number()), 0, 15),
            'customer'      => $customer_id,
            'card'          => $default_card,
        ));

        // Received error?
        if (is_string($response)) {
            $order->add_order_note(__('Automatic subscription payment failed (Stripe).', 'subscriptio-stripe') . ' ' . $response);
            return false;
        }

        // Save charge id
        update_post_meta($order->id, '_subscriptio_stripe_charge_id', $response->id);

        // Save capture status
        update_post_meta($order->id, '_subscriptio_stripe_charge_captured', ($response->captured ? 'yes' : 'no'));

        // Charge captured?
        if ($response->captured) {
            $order->add_order_note(sprintf(__('Stripe charge %s captured.', 'subscriptio-stripe'), $response->id));
            $order->payment_complete();
        }

        // Only authorized
        else {
            $order->add_order_note(sprintf(__('Stripe charge %s authorized and will be charged as soon as you start processing this order. Authorization will expire in 7 days.', 'subscriptio-stripe'), $response->id));
            $order->update_status('on-hold');
            $order->reduce_order_stock();
        }

        return true;
    }
    /**
     * Delete card
     * 
     * @access public
     * @return void
     */
    public function delete_card()
    {
        global $woocommerce;

        // Not our request?
        if ($_SERVER['REQUEST_METHOD'] !== 'GET' || !isset($_GET['subscriptio_stripe_delete_card'])) {
            return;
        }

        // User not logged in?
        if (!is_user_logged_in()) {
            return;
        }

        $user_id = get_current_user_id();

        // Load cards
        $cards = get_user_meta($user_id, '_subscriptio_stripe_customer_cards', true);

        if (empty($cards)) {
            return;
        }

        $cards = maybe_unserialize($cards);

        // No such card?
        if (!isset($cards[$_GET['subscriptio_stripe_delete_card']])) {
            return;
        }

        // Load customer id
        $customer_id = get_user_meta($user_id, '_subscriptio_stripe_customer_id', true);

        if (empty($customer_id)) {
            return;
        }

        // Load payment gateway object to access its methods
        $gateway = new Subscriptio_Stripe_Gateway();

        // Send request to delete this card
        $response = $gateway->send_request('cards', 'delete', array(
            'id'            => $customer_id,
            'secondary_id'  => $_GET['subscriptio_stripe_delete_card'],
        ));

        // Delete card from user's card list
        unset($cards[$_GET['subscriptio_stripe_delete_card']]);

        // Last card deleted?
        if (empty($cards)) {
            delete_user_meta($user_id, '_subscriptio_stripe_customer_cards');
            delete_user_meta($user_id, '_subscriptio_stripe_customer_default_card');
        }
        else {
            update_user_meta($user_id, '_subscriptio_stripe_customer_cards', $cards);

            // Default card deleted?
            $default_card = get_user_meta($user_id, '_subscriptio_stripe_customer_default_card', true);

            if (!empty($default_card) && $default_card == $_GET['subscriptio_stripe_delete_card']) {
                $new_default = array_keys($cards);
                $new_default = array_shift($new_default);
                update_user_meta($user_id, '_subscriptio_stripe_customer_default_card', $new_default);
            }
        }

        // Show success message
        $woocommerce->add_message(__('Credit card deleted successfully.', 'subscriptio-stripe'));
        wp_safe_redirect(get_permalink(woocommerce_get_page_id('myaccount')));
        exit;
    }
    /**
     * Refund payment
     * 
     * @access public
     * @param int $order_id
     * @return void
     */
    public function refund($order_id)
    {
        $order = new WC_Order($order_id);

        if (!$order) {
            return;
        }

        // Paid via Stripe?
        if ($order->payment_method == 'subscriptio_stripe') {

            // Get charge id
            $charge_id = get_post_meta($order_id, '_subscriptio_stripe_charge_id', true);

            if (empty($charge_id)) {
                return;
            }

            // Load payment gateway object to access its methods
            $gateway = new Subscriptio_Stripe_Gateway();

            // Send request to capture payment
            $response = $gateway->send_request('charges', 'refund', array(
                'id'        => $charge_id,
                'amount'    => $order->order_total * apply_filters('subscriptio_stripe_decimals_in_currency', 100, $order),
            ));

            // Request failed?
            if (!is_object($response)) {
                $order->add_order_note(__('Stripe refund failed.', 'subscriptio-stripe') . ' ' . $response);
                return;
            }

            // Received error from Stripe?
            if (!empty($response->error)) {
                $order->add_order_note(__('Stripe refund failed.', 'subscriptio-stripe') . ' ' . $response->error->message);
                return;
            }

            // Request was successful
            $order->add_order_note(sprintf(__('Stripe charge %s refunded.', 'subscriptio-stripe'), $response->id));
            delete_post_meta($order->id, '_subscriptio_stripe_charge_id');
            delete_post_meta($order->id, '_subscriptio_stripe_charge_captured');
        }
    }