public function __construct() { $this->id = 'paypalbraintree_paypal'; parent::__construct(); $this->icon = plugins_url('../assets/images/payments/PP_logo_h_100x26.png', __FILE__); $this->checkout_template = 'checkout/paypal-braintree-pay-with-paypal.php'; $this->title = $this->get_option('title_paypal'); $this->description = $this->get_option('description_paypal'); }
/** * WC_Gateway_Paypal_Braintree_Pay_With_Card constructor. */ public function __construct() { $this->id = 'paypalbraintree_cards'; parent::__construct(); /** * Filter the accepted credit card icons for Paypal Powered by Braintree. * * @param string $card_icons_url disployed on the checkout page. */ $this->icon = apply_filters('wc_gateway_paypal_braintree_card_icons_image_url', plugins_url('../assets/images/payments/payment-method-cards.png', __FILE__)); $this->checkout_template = 'checkout/paypal-braintree-pay-with-card.php'; $this->title = $this->get_option('title_cards'); $this->description = $this->get_option('description_cards'); }
/** * process_payment * * Completes the initial payment on the subscription order * * Although PayPal Braintree supports subscription products (they call them plans), * they don't support the wide variety of intervals we do, nor multiple subscription * products in a single order. * * So, this extension does all the subscription work itself, storing a customer * in the vault on the first payment, and using those stored credentials for * renewal orders * * @param int $order_id * @return mixed */ public function process_payment($order_id) { // If the order contains no subscriptions, just let the parent process it if (!$this->order_contains_subscription($order_id)) { return parent::process_payment($order_id); } $order = new WC_Order($order_id); $this->log(__FUNCTION__, "Info: Beginning processing of payment for (subscription) order {$order_id} for the amount of {$order->order_total}"); $this->log(__FUNCTION__, "Info: Merchant ID = {$this->merchant_id}"); $paypal_braintree_nonce = self::get_posted_variable('paypalbraintree_nonce'); if (empty($paypal_braintree_nonce)) { $this->log(__FUNCTION__, 'Error: The paypal_braintree_nonce was unexpectedly empty'); wc_add_notice(__('Error: PayPal Powered by Braintree did not supply a payment nonce. Please try again later or use another means of payment.', 'woocommerce-gateway-paypal-braintree'), 'error'); return false; } $user_id = $order->get_user_id(); if (!is_user_logged_in()) { $this->log(__FUNCTION__, 'Error: No user logged in / being created for the initial subscription payment'); wc_add_notice(__('Error: You must login or create an account before you can purchase a subscription.', 'woocommerce-gateway-paypal-braintree'), 'error'); return false; } // Create the gateway instance up front require_once dirname(__FILE__) . '/../braintree_sdk/lib/Braintree.php'; $gateway = new Braintree_Gateway(array('accessToken' => $this->merchant_access_token)); // Check their user meta for a stored braintree customer id $braintree_customer_id = get_user_meta($user_id, '_wc_paypal_braintree_customer_id', true); if (empty($braintree_customer_id)) { $this->log(__FUNCTION__, 'Info: Did not find braintree customer id on user meta. Need to create customer'); // Create a new customer id, passing the nonce so we can add the card to the vault // ref https://developers.braintreepayments.com/reference/request/customer/create/php $customer_args = array('firstName' => $order->billing_first_name, 'lastName' => $order->billing_last_name, 'company' => $order->billing_company, 'phone' => $order->billing_phone, 'email' => $order->billing_email, 'paymentMethodNonce' => $paypal_braintree_nonce); try { $result = $gateway->customer()->create($customer_args); } catch (Exception $e) { $this->log(__FUNCTION__, 'Error: Unable to create customer. Reason: ' . $e->getMessage()); wc_add_notice(__('Error: PayPal Powered by Braintree was unable to create a customer record for you. Please try again later or use another means of payment.', 'woocommerce-gateway-paypal-braintree'), 'error'); return false; } if (!$result->success) { $this->log(__FUNCTION__, "Error: Unable to create customer: {$result->message}"); wc_add_notice(__('Error: PayPal Powered by Braintree was unable to create a customer record for you. Please try again later or use another means of payment.', 'woocommerce-gateway-paypal-braintree'), 'error'); return false; } $braintree_customer_id = $result->customer->id; update_user_meta($user_id, '_wc_paypal_braintree_customer_id', $braintree_customer_id); $this->log(__FUNCTION__, "Info: Created customer successfully - braintree customer id = {$braintree_customer_id}"); $payment_methods = $result->customer->paymentMethods; $payment_method_token = ''; foreach ((array) $payment_methods as $payment_method) { if ($payment_method->default) { $payment_method_token = $payment_method->token; } } $authentication = array('paymentMethodToken' => $payment_method_token); } else { // We found the braintree customer id in the customer's meta $this->log(__FUNCTION__, "Info: Found a braintree customer id in the users meta - customer id = {$braintree_customer_id}"); $authentication = array('paymentMethodNonce' => $paypal_braintree_nonce); } $sale_args = $this->generate_sales_args($order, $braintree_customer_id); $sale_args = array_merge($sale_args, $authentication); $transaction_id = ''; // Process trial periods and possible coupon discounts. if (isset($sale_args['amount']) && 0.0 === doubleval($sale_args['amount'])) { $user_id = $order->get_user_id(); $this->log(__FUNCTION__, "Zero payment amount for trial or coupon. Order ID: {$order_id}, User ID: {$user_id}"); $customer = $gateway->customer()->find($braintree_customer_id); $payment_method_token = ''; foreach ((array) $customer->paymentMethods as $payment_method) { if ($payment_method->default) { $payment_method_token = $payment_method->token; } } } else { // charges more than zero should be sent away // We have a customer id now, so let's do the sale and store the payment method in the vault. $result = $gateway->transaction()->sale($sale_args); if (!$result->success) { $notice = sprintf(__('Error: PayPal Powered by Braintree was unable to complete the transaction. Please try again later or use another means of payment. Reason: %s', 'woocommerce-gateway-paypal-braintree'), $error_message); wc_add_notice($notice, 'error'); $this->log(__FUNCTION__, "Error: Unable to complete transaction. Reason: {$result->message}"); return false; } $transaction_id = $result->transaction->id; $this->log(__FUNCTION__, "Info: Successfully processed initial payment, transaction id = {$transaction_id}"); $credit_card_meta = $result->transaction->creditCard; $payment_method_token = $credit_card_meta['token']; if (empty($payment_method_token)) { $this->log(__FUNCTION__, 'Info: Customer used the paypal subflow'); $paypal_meta = $result->transaction->paypal; $payment_method_token = $paypal_meta['token']; } else { $this->log(__FUNCTION__, 'Info: Customer used the credit card subflow'); } $braintree_customer_id = $result->transaction->customer['id']; } if (empty($payment_method_token)) { $this->log(__FUNCTION__, 'Warning: Initial payment succeeded, but no token was provided by the gateway for recurring payments.'); } // Save the customer ID in each subscription for this order for later use during renewal if (empty($braintree_customer_id)) { $this->log(__FUNCTION__, 'Warning: Initial payment succeeded, but no braintree customer ID was provided by the gateway for recurring payments.'); } else { $this->log(__FUNCTION__, "Info: Saving to subscription(s) recurring payment braintree customer ID {$braintree_customer_id}"); } // Note: A single order may contain multiple subscriptions // Save the token in each subscription for this order for later use during renewal foreach (wcs_get_subscriptions_for_order($order->id) as $subscription) { update_post_meta($subscription->id, '_wc_paypal_braintree_payment_method_token', $payment_method_token); update_post_meta($subscription->id, '_wc_paypal_braintree_customer_id', $braintree_customer_id); } $order->payment_complete($transaction_id); $this->log(__FUNCTION__, "Info: Completed processing of payment for order {$order_id}"); return array('result' => 'success', 'redirect' => $this->get_return_url($order)); }