/**
  * Initialize a payment token where $token is a 24 digit globally unique id
  * provided by QBMS with a predetermined structure used to infer
  * certain information about the payment method. The WalletEntryID is
  * structured as follows:
  *
  * + 1 digit wallet entry type (1 - Credit Card, 2 - Check)
  * + 2 digit brand type (01 - Visa, 02 - MasterCard, 03 - Amex, 04 - Discover, 05 - DinersClub, 06 - JCB, 00 - Check)
  * + 17 digit random number
  * + Last 4 digits of the credit card or check account number.
  *
  * @since 1.0
  * @param string $token the QBMS Wallet entry ID value
  * @param array $data associated data
  */
 public function __construct($token, $data)
 {
     $data['type'] = $this->get_type_from_token($token);
     $data['last_four'] = $this->get_last_four_from_token($token);
     if ('credit_card' == $data['type']) {
         $data['card_type'] = $this->get_card_type_from_token($token);
     }
     parent::__construct($token, $data);
 }
 /**
  * Add any Authorize.net AIM specific transaction information as
  * class members of WC_Order instance.  Added members can include:
  *
  * auth_net_aim_merchant_defined_fields - custom fields added to the transaction in format array( name => value )
  *
  * @since 3.0
  * @see WC_Gateway_Authorize_Net_AIM::get_order()
  * @param int $order_id order ID being processed
  * @return WC_Order object with payment and transaction information attached
  */
 protected function get_order($order_id)
 {
     // add common order members
     $order = parent::get_order($order_id);
     // custom merchant-defined transaction fields
     $order->auth_net_aim_merchant_defined_fields = apply_filters('wc_authorize_net_aim_merchant_defined_fields', array(), $order, $this);
     // set card type
     if ($this->is_credit_card_gateway()) {
         $order->payment->card_type = SV_WC_Payment_Gateway_Payment_Token::type_from_account_number($order->payment->account_number);
     }
     return $order;
 }
 /**
  * Construct the token
  *
  * @since 2.0.0
  * @param string $payment_profile_id payment profile (token) ID
  * @param array $data accepts order, billing_hash, and payment_hash elements
  */
 public function __construct($payment_profile_id, $data)
 {
     $this->set_customer_profile_id($data['customer_profile_id']);
     // add payment-specific info to token from $order->payment if set
     if (isset($data['order']) && $data['order'] instanceof WC_Order) {
         $data = array_merge($data, $this->parse_data_from_order($data['order']));
     }
     // TODO: it's tough to understand when & how class members are set here vs. those in the $data array -- look to refactor this @MR
     if (empty($data['billing_hash'])) {
         $data['billing_hash'] = $this->calculate_billing_hash($data);
     } else {
         $this->set_billing_hash($data['billing_hash']);
     }
     if (empty($data['payment_hash'])) {
         $data['payment_hash'] = $this->calculate_payment_hash($data);
     } else {
         $this->set_payment_hash($data['payment_hash']);
     }
     // no need to save these with the token
     unset($data['order']);
     unset($data['billing']);
     parent::__construct($payment_profile_id, $data);
 }
 /**
  * Add a payment method and token as user meta.
  *
  * @since 1.0.0
  * @param int $user_id user identifier
  * @param SV_WC_Payment_Gateway_Payment_Token $token the token
  * @param string $environment_id optional environment id, defaults to plugin current environment
  * @return bool|int false if token not added, user meta ID if added
  */
 public function add_payment_token($user_id, $token, $environment_id = null)
 {
     assert($this->supports_tokenization());
     // default to current environment
     if (is_null($environment_id)) {
         $environment_id = $this->get_environment();
     }
     // get existing tokens
     $tokens = $this->get_payment_tokens($user_id, array('environment_id' => $environment_id));
     // if this token is set as active, mark all others as false
     if ($token->is_default()) {
         foreach (array_keys($tokens) as $key) {
             $tokens[$key]->set_default(false);
         }
     }
     // add the new token
     $tokens[$token->get_token()] = $token;
     // persist the updated tokens
     return $this->update_payment_tokens($user_id, $tokens, $environment_id);
 }
 /**
  * Get the payment method title for a given token, e.g:
  *
  * <Amex logo> American Express ending in 6666
  *
  * @since 4.0.0
  * @param SV_WC_Payment_Gateway_Payment_Token $token token
  * @return string payment method title
  */
 protected function get_payment_method_title($token)
 {
     $image_url = $token->get_image_url();
     $last_four = $token->get_last_four();
     $type = $token->get_type_full();
     if ($image_url) {
         // format like "<Amex logo image> American Express"
         $title = sprintf('<img src="%1$s" alt="%2$s" title="%2$s" width="40" height="25" />%3$s', esc_url($image_url), esc_attr__($type, $this->get_plugin()->get_text_domain()), esc_html__($type, $this->get_plugin()->get_text_domain()));
     } else {
         // missing payment method image, format like "American Express"
         $title = esc_html__($type, $this->get_plugin()->get_text_domain());
     }
     // add "ending in XXXX" if available
     if ($last_four) {
         $title .= '&nbsp;' . sprintf(__('ending in %s', $this->get_plugin()->get_text_domain()), $last_four);
     }
     // add "(default)" if token is set as default
     if ($token->is_default()) {
         $title .= ' ' . __('(default)', $this->get_plugin()->get_text_domain());
     }
     return apply_filters('wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_table_method_title', $title, $token, $this);
 }
 /**
  * Get the title for a saved payment method, like
  *
  * <Amex logo> American Express ending in 6666 (expires 10/20)
  *
  * @since 4.0.0
  * @param SV_WC_Payment_Gateway_Payment_Token $token payment token
  * @return string saved payment method title
  */
 protected function get_saved_payment_method_title($token)
 {
     $image_url = $token->get_image_url();
     $last_four = $token->get_last_four();
     $type = $token->get_type_full();
     if ($image_url) {
         // format like "<Amex logo image> American Express"
         $title = sprintf('<img src="%1$s" alt="%2$s" title="%2$s" width="30" height="20" style="width: 30px; height: 20px;" />%3$s', esc_url($image_url), esc_attr__($type, 'woocommerce-plugin-framework'), esc_html__($type, 'woocommerce-plugin-framework'));
     } else {
         // missing payment method image, format like "American Express"
         $title = esc_html__($type, 'woocommerce-plugin-framework');
     }
     // add "ending in XXXX" if available
     if ($last_four) {
         /* translators: Placeholders: %s - last four digits of card/account */
         $title .= '&nbsp;' . sprintf(esc_html__('ending in %s', 'woocommerce-plugin-framework'), $last_four);
     }
     // add "(expires MM/YY)" if available
     if ($token->get_exp_month() && $token->get_exp_year()) {
         /* translators: Placeholders: %s - expiry date */
         $title .= ' ' . sprintf(esc_html__('(expires %s)', 'woocommerce-plugin-framework'), $token->get_exp_date());
     }
     /**
      * Payment Gateway Payment Form Payment Method Title.
      *
      * Filters the text/HTML rendered for a saved payment method, like "Amex ending in 6666".
      *
      * @since 4.0.0
      * @param string $title
      * @param \SV_WC_Payment_Gateway_Payment_Token $token
      * @param \SV_WC_Payment_Gateway_Payment_Form $this payment form instance
      */
     return apply_filters('wc_' . $this->get_gateway()->get_id() . '_payment_form_payment_method_title', $title, $token, $this);
 }
 /**
  * Adds an order note, along with anything else required after an approved
  * credit card transaction
  *
  * @since 2.2.0
  * @param WC_Order $order the order
  * @param SV_WC_Payment_Gateway_API_Payment_Notification_Credit_Card_Response transaction response
  */
 protected function do_credit_card_transaction_approved($order, $response)
 {
     $last_four = substr($response->get_account_number(), -4);
     $transaction_type = '';
     if ($response->is_authorization()) {
         $transaction_type = 'Authorization';
     } elseif ($response->is_charge()) {
         $transaction_type = 'Charge';
     }
     // credit card order note
     $message = sprintf(__('%s %s %s Approved: %s ending in %s (expires %s)', $this->text_domain), $this->get_method_title(), $this->is_test_environment() ? 'Test' : '', $transaction_type, $response->get_card_type() ? SV_WC_Payment_Gateway_Payment_Token::type_to_name($response->get_card_type()) : 'card', $last_four, $response->get_exp_month() . '/' . substr($response->get_exp_year(), -2));
     // adds the transaction id (if any) to the order note
     if ($response->get_transaction_id()) {
         $message .= ' ' . sprintf(__('(Transaction ID %s)', $this->text_domain), $response->get_transaction_id());
     }
     $order->add_order_note($message);
 }
        /**
         * Conditionally adds the payment token fields to the Admin User Edit
         * screen, if tokenization is enabled on the gateway, and the gateway
         * API does not support payment token retrieval (meaning the tokens
         * are stored only locally)
         *
         * @see SV_WC_Payment_Gateway_Admin_User_Edit_Handler::save_user_profile_tokenization_fields()
         * @param SV_WC_Payment_Gateway $gateway the gateway instance
         * @param WP_User $user user object for the current edit page
         */
        protected function maybe_add_user_profile_tokenization_fields($gateway, $user)
        {
            // ensure that it supports tokenization, but doesn't have a "get tokens" request, meaning that the tokens are stored and accessed locally
            if ($gateway->tokenization_enabled() && !$gateway->get_api()->supports_get_tokenized_payment_methods()) {
                $environments = $gateway->get_environments();
                foreach ($environments as $environment_id => $environment_name) {
                    // get any payment tokens
                    $payment_tokens = $gateway->get_payment_tokens($user->ID, null, $environment_id);
                    ?>

				<table class="form-table">
					<tr>
						<th style="padding-bottom:0px;"><?php 
                    echo count($environments) > 1 ? sprintf(__('%s Payment Tokens', $this->text_domain), $environment_name) : __('Payment Tokens', $this->text_domain);
                    ?>
</th>
						<td style="padding-bottom:0px;">
							<?php 
                    if (empty($payment_tokens)) {
                        echo "<p>" . __('This customer has no saved payment tokens', $this->text_domain) . "</p>";
                    } else {
                        ?>
								<ul style="margin:0;">
									<?php 
                        foreach ($payment_tokens as $token) {
                            ?>
											<li>
												<?php 
                            echo $token->get_token();
                            ?>
 (<?php 
                            printf('%s ending in %s expiring %s', $token->get_type_full(), $token->get_last_four(), $token->get_exp_month() . '/' . $token->get_exp_year());
                            echo $token->is_default() ? ' <strong>' . __('Default card', $this->text_domain) . '</strong>' : '';
                            ?>
)
												<a href="#" class="js-sv-wc-payment-token-delete" data-payment_token="<?php 
                            echo $token->get_token();
                            ?>
"><?php 
                            _e('Delete', $this->text_domain);
                            ?>
</a>
											</li>
										<?php 
                        }
                        ?>
								</ul>
								<input type="hidden" class="js-sv-wc-payment-tokens-deleted" name="wc_<?php 
                        echo $gateway->get_id();
                        ?>
_payment_tokens_deleted_<?php 
                        echo $environment_id;
                        ?>
" value="" />
							<?php 
                    }
                    ?>
						</td>
					</tr>
					<tr>
						<th style="padding-top:0px;"><?php 
                    _e('Add a Payment Token', $this->text_domain);
                    ?>
</th>
						<td style="padding-top:0px;">
							<input type="text" name="wc_<?php 
                    echo $gateway->get_id();
                    ?>
_payment_token_<?php 
                    echo $environment_id;
                    ?>
" placeholder="<?php 
                    esc_attr_e('Token', $this->text_domain);
                    ?>
" style="width:145px;" />
							<?php 
                    if ($gateway->supports(SV_WC_Payment_Gateway::FEATURE_CARD_TYPES)) {
                        ?>
								<select name="wc_<?php 
                        echo $gateway->get_id();
                        ?>
_payment_token_type_<?php 
                        echo $environment_id;
                        ?>
">
									<option value=""><?php 
                        _e("Card Type", $this->text_domain);
                        ?>
</option>
									<?php 
                        foreach ($gateway->get_card_types() as $card_type) {
                            $card_type = strtolower($card_type);
                            ?>
										<option value="<?php 
                            echo $card_type;
                            ?>
"><?php 
                            echo SV_WC_Payment_Gateway_Payment_Token::type_to_name($card_type);
                            ?>
</option>
										<?php 
                        }
                        ?>
								</select>
							<?php 
                    }
                    ?>
							<input type="text" name="wc_<?php 
                    echo $gateway->get_id();
                    ?>
_payment_token_last_four_<?php 
                    echo $environment_id;
                    ?>
" placeholder="<?php 
                    printf(esc_attr__('Last Four', $this->text_domain), substr(date('Y') + 1, -2));
                    ?>
" style="width:75px;" />
							<input type="text" name="wc_<?php 
                    echo $gateway->get_id();
                    ?>
_payment_token_exp_date_<?php 
                    echo $environment_id;
                    ?>
" placeholder="<?php 
                    printf(esc_attr__('Expiry Date (01/%s)', $this->text_domain), date('Y') + 1);
                    ?>
" style="width:155px;" />
							<br/>
							<span class="description"><?php 
                    echo apply_filters('wc_payment_gateway_' . $gateway->get_id() . '_user_profile_add_token_description', '', $gateway, $user);
                    ?>
</span>
						</td>
					</tr>
				</table>
				<?php 
                }
                $this->maybe_add_user_profile_tokenization_fields_js();
            }
        }
 /**
  * Add a subscriptions header to the My Payment Methods table.
  *
  * @since 4.3.0
  * @param array $method the table row data
  * @param \SV_WC_Payment_Gateway_Payment_Token $token the payment token
  * @param \SV_WC_Payment_Gateway_My_Payment_Methods the my payment methods instance
  * @return array
  */
 public function add_my_payment_methods_table_body_row_data($method, $token, $handler)
 {
     // If the subscription data has already been added or this method is for a different gateway, bail
     if (isset($method['subscriptions']) || str_replace('_', '-', $token->get_type()) !== $this->get_gateway()->get_payment_type()) {
         return $method;
     }
     $subscription_ids = array();
     // Build a link for each subscription
     foreach ($this->get_payment_token_subscriptions(get_current_user_id(), $token) as $subscription) {
         $subscription_ids[] = sprintf('<a href="%1$s">%2$s</a>', esc_url($subscription->get_view_order_url()), esc_attr(sprintf(_x('#%s', 'hash before order number', 'woocommerce-plugin-framework'), $subscription->get_order_number())));
     }
     if (!empty($subscription_ids)) {
         $method['subscriptions'] = implode(', ', $subscription_ids);
     }
     return $method;
 }
 /**
  * Get the payment method title for a given token, e.g:
  *
  * <Amex logo> American Express ending in 6666
  *
  * @since 4.0.0
  * @param SV_WC_Payment_Gateway_Payment_Token $token token
  * @return string payment method title
  */
 protected function get_payment_method_title($token)
 {
     $image_url = $token->get_image_url();
     $last_four = $token->get_last_four();
     $type = $token->get_type_full();
     if ($image_url) {
         // format like "<Amex logo image> American Express"
         $title = sprintf('<img src="%1$s" alt="%2$s" title="%2$s" width="40" height="25" />%3$s', esc_url($image_url), esc_attr__($type, 'woocommerce-plugin-framework'), esc_html__($type, 'woocommerce-plugin-framework'));
     } else {
         // missing payment method image, format like "American Express"
         $title = esc_html__($type, 'woocommerce-plugin-framework');
     }
     // add "ending in XXXX" if available
     if ($last_four) {
         /* translators: %s - last four digits of a card/account */
         $title .= '&nbsp;' . sprintf(esc_html__('ending in %s', 'woocommerce-plugin-framework'), $last_four);
     }
     // add "(default)" if token is set as default
     if ($token->is_default()) {
         $title .= ' ' . esc_html__('(default)', 'woocommerce-plugin-framework');
     }
     /**
      * My Payment Methods Table Method Title Filter.
      *
      * Allow actors to modify the table method title.
      *
      * @since 4.0.0
      * @param string $title payment method title
      * @param \SV_WC_Payment_Gateway_Payment_Token $token token object
      * @param \SV_WC_Payment_Gateway_My_Payment_Methods $this instance
      */
     return apply_filters('wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_table_method_title', $title, $token, $this);
 }
 /**
  * Get the order note message when a customer saves their payment method
  * to their account
  *
  * @since 4.1.2
  * @param \SV_WC_Payment_Gateway_Payment_Token $token the payment token being saved
  * @return string
  */
 protected function get_order_note($token)
 {
     $gateway = $this->get_gateway();
     $message = '';
     // order note based on gateway type
     if ($gateway->is_credit_card_gateway()) {
         /* translators: Placeholders: %1$s - payment gateway title (such as Authorize.net, Braintree, etc), %2$s - payment method name (mastercard, bank account, etc), %3$s - last four digits of the card/account, %4$s - card/account expiry date */
         $message = sprintf(__('%1$s Payment Method Saved: %2$s ending in %3$s (expires %4$s)', 'woocommerce-plugin-framework'), $gateway->get_method_title(), $token->get_type_full(), $token->get_last_four(), $token->get_exp_date());
     } elseif ($gateway->is_echeck_gateway()) {
         // account type (checking/savings) may or may not be available, which is fine
         /* translators: Placeholders: %1$s - payment gateway title (such as CyberSouce, NETbilling, etc), %2$s - account type (checking/savings - may or may not be available), %3$s - last four digits of the account */
         $message = sprintf(__('%1$s eCheck Payment Method Saved: %2$s account ending in %3$s', 'woocommerce-plugin-framework'), $gateway->get_method_title(), $token->get_account_type(), $token->get_last_four());
     }
     return $message;
 }
 /**
  * Add a payment method and token as user meta.
  *
  * @since 1.0
  * @param int $user_id user identifier
  * @param SV_WC_Payment_Gateway_Payment_Token $token the token
  * @return bool|int false if token not added, user meta ID if added
  * @throws SV_WC_Payment_Gateway_Feature_Unsupported_Exception if payment method tokenization is not supported
  */
 public function add_payment_token($user_id, $token)
 {
     if (!$this->supports_tokenization()) {
         throw new SV_WC_Payment_Gateway_Feature_Unsupported_Exception('Payment tokenization not supported by gateway');
     }
     // get existing tokens
     $tokens = $this->get_payment_tokens($user_id);
     // if this token is set as active, mark all others as false
     if ($token->is_default()) {
         foreach (array_keys($tokens) as $key) {
             $tokens[$key]->set_default(false);
         }
     }
     // add the new token
     $tokens[$token->get_token()] = $token;
     // persist the updated tokens
     return $this->update_payment_tokens($user_id, $tokens);
 }