/**
  * Entry method for the Add Payment Method feature flow. Note this is *not*
  * stubbed in the WC_Payment_Gateway abstract class, but is called if the
  * gateway declares support for it.
  *
  * @since 4.0.0
  */
 public function add_payment_method()
 {
     assert($this->supports_add_payment_method());
     $order = $this->get_order_for_add_payment_method();
     try {
         $result = $this->do_add_payment_method_transaction($order);
     } catch (SV_WC_Plugin_Exception $e) {
         $result = array('message' => sprintf(__('Oops, adding your new payment method failed: %s', $this->text_domain), $e->getMessage()), 'success' => false);
     }
     SV_WC_Helper::wc_add_notice($result['message'], $result['success'] ? 'success' : 'error');
     // redirect to my account on success, or back to Add Payment Method screen on failure so user can try again
     wp_safe_redirect($result['success'] ? SV_WC_Plugin_Compatibility::wc_get_page_permalink('myaccount') : wc_get_endpoint_url('add-payment-method'));
     exit;
 }
 /**
  * Adds debug messages to the page as a WC message/error, and/or to the WC Error log
  *
  * @since 1.0.0
  * @param string $message message to add
  * @param string $type how to add the message, options are:
  *     'message' (styled as WC message), 'error' (styled as WC Error)
  */
 public function add_debug_message($message, $type = 'message')
 {
     // do nothing when debug mode is off or no message
     if ('off' == $this->debug_off() || !$message) {
         return;
     }
     // add log message to WC logger if log/both is enabled
     if ($this->debug_log()) {
         $this->get_plugin()->log($message, $this->get_id());
     }
     // avoid adding notices when performing refunds, these occur in the admin as an Ajax call, so checking the current filter
     // is the only reliably way to do so
     if (in_array('wp_ajax_woocommerce_refund_line_items', $GLOBALS['wp_current_filter'])) {
         return;
     }
     // add debug message to woocommerce->errors/messages if checkout or both is enabled, the admin/Ajax check ensures capture charge transactions aren't logged as notices to the front end
     if (($this->debug_checkout() || 'error' === $type && $this->is_test_environment()) && (!is_admin() || is_ajax())) {
         if ('message' === $type) {
             SV_WC_Helper::wc_add_notice(str_replace("\n", "<br/>", htmlspecialchars($message)), 'notice');
         } else {
             // defaults to error message
             SV_WC_Helper::wc_add_notice(str_replace("\n", "<br/>", htmlspecialchars($message)), 'error');
         }
     }
 }
 /**
  * Handle payment methods actions, e.g. deleting a payment method or setting
  * one as default
  *
  * @since 4.0.0
  */
 public function handle_payment_method_actions()
 {
     if (!$this->has_tokens) {
         return;
     }
     $token = isset($_GET['wc-' . $this->get_plugin()->get_id_dasherized() . '-token']) ? trim($_GET['wc-' . $this->get_plugin()->get_id_dasherized() . '-token']) : '';
     $action = isset($_GET['wc-' . $this->get_plugin()->get_id_dasherized() . '-action']) ? $_GET['wc-' . $this->get_plugin()->get_id_dasherized() . '-action'] : '';
     // process payment method actions
     if ($token && $action && !empty($_GET['_wpnonce']) && is_user_logged_in()) {
         // security check
         if (false === wp_verify_nonce($_GET['_wpnonce'], 'wc-' . $this->get_plugin()->get_id_dasherized() . '-token-action')) {
             SV_WC_Helper::wc_add_notice(_x('Oops, you took too long, please try again.', 'Supports my payment method feature', $this->get_plugin()->get_text_domain()), 'error');
             $this->redirect_to_my_account();
         }
         // current logged in user
         $user_id = get_current_user_id();
         $gateway = $this->get_plugin()->get_gateway_from_token($user_id, $token);
         // couldn't find an associated gateway for that token
         if (!is_object($gateway)) {
             SV_WC_Helper::wc_add_notice(_x('There was an error with your request, please try again.', 'Supports my payment method feature', $this->get_plugin()->get_text_domain()), 'error');
             $this->redirect_to_my_account();
         }
         switch ($action) {
             // handle deletion
             case 'delete':
                 if (!$gateway->remove_payment_token($user_id, $token)) {
                     SV_WC_Helper::wc_add_notice(_x('Error removing payment method', 'Supports my payment method feature', $this->get_plugin()->get_text_domain()), 'error');
                 } else {
                     SV_WC_Helper::wc_add_notice(_x('Payment method deleted.', 'Supports my payment method feature', $this->get_plugin()->get_text_domain()));
                 }
                 break;
                 // set default payment method
             // set default payment method
             case 'make-default':
                 $gateway->set_default_payment_token($user_id, $token);
                 SV_WC_Helper::wc_add_notice(_x('Default payment method updated.', 'Supports my payment method feature', $this->get_plugin()->get_text_domain()));
                 break;
                 // custom actions
             // custom actions
             default:
                 do_action('wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_action_' . sanitize_title($action), $this);
                 break;
         }
         $this->redirect_to_my_account();
     }
 }
 /**
  * Adds debug messages to the page as a WC message/error, and / or to the WC Error log
  *
  * @since 2.0
  * @param string $message to add
  * @param string $display how to display message, defaults to `message`, options are:
  *   + `message` - display with WC message style, no formatting
  *   + `request` - display with WC message style and <pre> formatting
  *   + `response` - display with WC message style and XML/<pre> formatting
  *   + `error` - display with WC error style, no formatting
  */
 protected function log($message, $display = 'message')
 {
     // do nothing when debug mode is off or blank message
     if ('off' == $this->debug_mode || !$message) {
         return;
     }
     // add message to checkout page
     if ('checkout' === $this->debug_mode || 'both' === $this->debug_mode) {
         switch ($display) {
             case 'message':
                 SV_WC_Helper::wc_add_notice($message);
                 break;
             case 'request':
                 SV_WC_Helper::wc_add_notice(__('API Request: ', WC_Amazon_FPS::TEXT_DOMAIN) . '<br/><pre>' . $message . '</pre>');
                 break;
             case 'response':
                 $dom = new DOMDocument();
                 $dom->loadXML($message);
                 $dom->formatOutput = true;
                 SV_WC_Helper::wc_add_notice(__('API Response: ', WC_Amazon_FPS::TEXT_DOMAIN) . '<br/><pre>' . htmlspecialchars($dom->saveXML()) . '</pre>');
                 break;
             case 'error':
                 SV_WC_Helper::wc_add_notice($message, 'error');
                 break;
         }
     }
     // add message to WC log
     if ('log' === $this->debug_mode || 'both' === $this->debug_mode) {
         $GLOBALS['wc_amazon_fps']->log($message);
     }
 }
 /**
  * Entry method for the Add Payment Method feature flow. Note this is *not*
  * stubbed in the WC_Payment_Gateway abstract class, but is called if the
  * gateway declares support for it.
  *
  * @since 4.0.0
  */
 public function add_payment_method()
 {
     assert($this->supports_add_payment_method());
     $order = $this->get_order_for_add_payment_method();
     try {
         $result = $this->do_add_payment_method_transaction($order);
     } catch (SV_WC_Plugin_Exception $e) {
         $result = array('message' => sprintf(esc_html__('Oops, adding your new payment method failed: %s', 'woocommerce-plugin-framework'), $e->getMessage()), 'success' => false);
     }
     SV_WC_Helper::wc_add_notice($result['message'], $result['success'] ? 'success' : 'error');
     // if successful, redirect to the newly added method
     if ($result['success']) {
         // if this is WooCommerce 2.5.5 or older, redirect to the My Account page
         if (SV_WC_Plugin_Compatibility::is_wc_version_lt_2_6()) {
             $redirect_url = wc_get_page_permalink('myaccount');
             // otherwise, redirect to the Payment Methods page (WC 2.6+)
         } else {
             $redirect_url = wc_get_account_endpoint_url('payment-methods');
         }
         // otherwise, back to the Add Payment Method page
     } else {
         $redirect_url = wc_get_endpoint_url('add-payment-method');
     }
     wp_safe_redirect($redirect_url);
     exit;
 }
 /**
  * Bypass credit card validation if Accept.js is enabled.
  *
  * @since 2.4.0
  * @param bool $is_valid whether the credit card fields are valid
  * @return bool
  */
 protected function validate_credit_card_fields($is_valid)
 {
     if (!$this->is_accept_js_enabled()) {
         return parent::validate_credit_card_fields($is_valid);
     }
     if (!SV_WC_Helper::get_post('wc-' . $this->get_id_dasherized() . '-payment-nonce')) {
         $this->add_debug_message('Accept.js Error: payment nonce is missing', 'error');
         $is_valid = false;
     }
     if (!SV_WC_Helper::get_post('wc-' . $this->get_id_dasherized() . '-payment-descriptor')) {
         $this->add_debug_message('Accept.js Error: payment descriptor is missing', 'error');
         $is_valid = false;
     }
     if (!$is_valid) {
         $params = $this->get_gateway_js_localized_script_params();
         SV_WC_Helper::wc_add_notice($params['general_error'], 'error');
     }
     return $is_valid;
 }
 /**
  * Handle payment methods actions, e.g. deleting a payment method or setting
  * one as default
  *
  * @since 4.0.0
  */
 public function handle_payment_method_actions()
 {
     if (!$this->has_tokens) {
         return;
     }
     $token = isset($_GET['wc-' . $this->get_plugin()->get_id_dasherized() . '-token']) ? trim($_GET['wc-' . $this->get_plugin()->get_id_dasherized() . '-token']) : '';
     $action = isset($_GET['wc-' . $this->get_plugin()->get_id_dasherized() . '-action']) ? $_GET['wc-' . $this->get_plugin()->get_id_dasherized() . '-action'] : '';
     // process payment method actions
     if ($token && $action && !empty($_GET['_wpnonce']) && is_user_logged_in()) {
         // security check
         if (false === wp_verify_nonce($_GET['_wpnonce'], 'wc-' . $this->get_plugin()->get_id_dasherized() . '-token-action')) {
             SV_WC_Helper::wc_add_notice(esc_html__('Oops, you took too long, please try again.', 'woocommerce-plugin-framework'), 'error');
             $this->redirect_to_my_account();
         }
         // current logged in user
         $user_id = get_current_user_id();
         $gateway = $this->get_plugin()->get_gateway_from_token($user_id, $token);
         // couldn't find an associated gateway for that token
         if (!is_object($gateway)) {
             SV_WC_Helper::wc_add_notice(esc_html__('There was an error with your request, please try again.', 'woocommerce-plugin-framework'), 'error');
             $this->redirect_to_my_account();
         }
         switch ($action) {
             // handle deletion
             case 'delete':
                 if (!$gateway->remove_payment_token($user_id, $token)) {
                     /* translators: Payment method as in a specific credit card, e-check or bank account */
                     SV_WC_Helper::wc_add_notice(esc_html__('Error removing payment method', 'woocommerce-plugin-framework'), 'error');
                 } else {
                     /* translators: Payment method as in a specific credit card, e-check or bank account */
                     SV_WC_Helper::wc_add_notice(esc_html__('Payment method deleted.', 'woocommerce-plugin-framework'));
                 }
                 break;
                 // set default payment method
             // set default payment method
             case 'make-default':
                 $gateway->set_default_payment_token($user_id, $token);
                 /* translators: Payment method as in a specific credit card, e-check or bank account */
                 SV_WC_Helper::wc_add_notice(esc_html__('Default payment method updated.', 'woocommerce-plugin-framework'));
                 break;
                 // custom actions
             // custom actions
             default:
                 /**
                  * My Payment Methods Custom Action.
                  *
                  * Fired when a custom action is requested for a payment method (e.g. other than delete/make default)
                  *
                  * @since 4.0.0
                  * @param \SV_WC_Payment_Gateway_My_Payment_Methods $this instance
                  */
                 do_action('wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_action_' . sanitize_title($action), $this);
                 break;
         }
         $this->redirect_to_my_account();
     }
 }
 /**
  * Handle any actions from the 'My Payment Methods' section on the
  * 'My Account' page
  *
  * @since 1.0.0
  */
 public function handle_my_payment_methods_actions()
 {
     assert($this->supports_tokenization());
     // pre-conditions
     if (!$this->is_available() || !$this->tokenization_enabled()) {
         return;
     }
     $token = isset($_GET['wc-' . $this->get_id_dasherized() . '-token']) ? trim($_GET['wc-' . $this->get_id_dasherized() . '-token']) : '';
     $action = isset($_GET['wc-' . $this->get_id_dasherized() . '-action']) ? $_GET['wc-' . $this->get_id_dasherized() . '-action'] : '';
     // process payment method actions
     if ($token && $action && !empty($_GET['_wpnonce']) && is_user_logged_in()) {
         // security check
         if (false === wp_verify_nonce($_GET['_wpnonce'], 'wc-' . $this->get_id_dasherized() . '-token-action')) {
             SV_WC_Helper::wc_add_notice(_x('There was an error with your request, please try again.', 'Supports direct payment method tokenization', $this->text_domain), 'error');
             wp_redirect(get_permalink(wc_get_page_id('myaccount')));
             exit;
         }
         // current logged in user
         $user_id = get_current_user_id();
         // handle deletion
         if ('delete' === $action) {
             if (!$this->remove_payment_token($user_id, $token)) {
                 SV_WC_Helper::wc_add_notice(_x('Error removing payment method', 'Supports direct payment method tokenization', $this->text_domain), 'error');
             } else {
                 SV_WC_Helper::wc_add_notice(_x('Payment method deleted.', 'Supports direct payment method tokenization', $this->text_domain));
             }
         }
         // handle default change
         if ('make-default' === $action) {
             $this->set_default_payment_token($user_id, $token);
         }
         // remove the query params
         wp_redirect(get_permalink(wc_get_page_id('myaccount')));
         exit;
     }
 }
예제 #9
0
 /**
  * Add the XML response to the woocommerce message object
  *
  * @param SimpleXMLElement $response response from Realex server
  * @param string $title debug message title to display
  * @param string $type optional message type, one of 'message' or 'error', defaults to 'message'
  * @param boolean $set_message optional whether to set the supplied
  *        message so that it appears on the next page load (ie, a
  *        message you want displayed on the 'thank you' page
  *
  * @return void
  */
 public function response_debug_message($response, $title, $type = 'message', $set_message = false)
 {
     if (get_class($response) == 'SimpleXMLElement') {
         $dom = dom_import_simplexml($response)->ownerDocument;
         $dom->formatOutput = true;
         $raw_message = $dom->saveXML();
         $message = htmlspecialchars(preg_replace("/\n+/", "\n", $raw_message));
     } elseif (is_object($response)) {
         $raw_message = $message = print_r($response, true);
     }
     $debug_message = "<pre><strong>" . $title . "</strong>\n" . $message . "</pre>";
     if ($type == 'message') {
         SV_WC_Helper::wc_add_notice($debug_message);
     } else {
         SV_WC_Helper::wc_add_notice($debug_message, 'error');
     }
 }
예제 #10
0
    /**
     * Process a RealMPI transaction
     *
     * @param Realex_API $realex_client realex api client
     * @param WC_Order $order the order
     */
    private function authorize_3dsecure($realex_client, $order)
    {
        $response = $this->threeds_verifyenrolled_request($realex_client, $order);
        if (!$response) {
            SV_WC_Helper::wc_add_notice(__('Connection error', 'woocommerce-gateway-realex'), 'error');
            return;
        }
        if (!$realex_client->verify_transaction_signature($response)) {
            // response was not properly signed by realex
            SV_WC_Helper::wc_add_notice(__('Error - invalid transaction signature, check your Realex settings.', 'woocommerce-gateway-realex'), 'error');
            // if debug mode load the response into the messages object
            if ($this->wc_gateway_realex->is_debug_mode()) {
                $this->wc_gateway_realex->response_debug_message($response, "Response: 3ds-verifyenrolled", 'error');
            }
            return;
        }
        if ($response->result == '00' || $response->result == '110' && $response->enrolled == 'N' && (string) $response->url) {
            // Success: redirect cardholder to authentication URL
            //  or, card holder not enrolled but an attempt server is available.  There seems to be no test case
            //  for this case, but this check is based on my reading of the RealMPI Remote Developers Guide 7.8 "Response Codes for 3ds-verifyenrolled"
            if ($this->wc_gateway_realex->is_debug_mode()) {
                $this->wc_gateway_realex->response_debug_message($response, "Response: 3ds-verifyenrolled", true);
            }
            $account_number = $this->wc_gateway_realex->get_post('realex_accountNumber');
            $card_type = $this->wc_gateway_realex->get_post('realex_cardType');
            $expiration_month = $this->wc_gateway_realex->get_post('realex_expirationMonth');
            $expiration_year = $this->wc_gateway_realex->get_post('realex_expirationYear');
            $issueno = $this->wc_gateway_realex->get_post('realex_issueNumber');
            $cvnumber = $this->wc_gateway_realex->get_post('realex_cvNumber');
            $realex_vault_new = $this->wc_gateway_realex->get_post('realex_vault_new');
            ?>
			<html>
				<head>
					<title>3DSecure Payment Authorisation</title>
				</head>
				<body>
					<form name="frmLaunchACS" id="3ds_submit_form" method="POST" action="<?php 
            echo $response->url;
            ?>
">
						<input type="hidden" name="PaReq" value="<?php 
            echo $response->pareq;
            ?>
">
						<input type="hidden" name="TermUrl" value="<?php 
            echo $this->acs_term_url;
            ?>
">
						<input type="hidden" name="MD" value="<?php 
            echo $this->encrypt_merchant_data(array('order_id' => $order->id, 'realex_accountNumber' => $account_number, 'realex_cardType' => $card_type, 'realex_expirationMonth' => $expiration_month, 'realex_expirationYear' => $expiration_year, 'realex_issueNumber' => $issueno, 'realex_cvNumber' => $cvnumber, 'realex_vault_new' => $realex_vault_new));
            ?>
">
						<noscript>
							<div class="woocommerce_message"><?php 
            _e('Processing your Payer Authentication Transaction', 'woocommerce-gateway-realex');
            ?>
 - <?php 
            _e('Please click Submit to continue the processing of your transaction.', 'woocommerce-gateway-realex');
            ?>
  <input type="submit" class="button" id="3ds_submit" value="Submit" /></div>
						</noscript>
					</form>
					<script>
						document.frmLaunchACS.submit();
					</script>
				</body>
			</html>
			<?php 
            exit;
            // If all goes well, we should receive an asynchronous request
            //  back from the authentication server, which will be handled
            //  by the handle_acs_response() method
        } elseif ($response->result == '110') {
            // cardholder not enrolled
            if ($this->wc_gateway_realex->is_debug_mode()) {
                $this->wc_gateway_realex->response_debug_message($response, "Response: 3ds-verifyenrolled", true);
            }
            if ($response->enrolled == 'N' && !(string) $response->url) {
                // Not Enrolled: cardholder is not enrolled, liability shifted, send a normal auth message (ECI: Visa: 6, MC/SWITCH: 1)
                $this->threedsecure = $this->get_eci_merchant_3dsecure($this->wc_gateway_realex->get_post('realex_cardType'));
                return $this->wc_gateway_realex->authorize($realex_client, $order, null, false);
            } elseif ($response->enrolled == 'U') {
                // enrolled status could not be verified, no liability shift, send a normal auth message (ECI: Visa: 7, MC/SWITCH: 0)
                $order_note = __('3DSecure enrollment status could not be verified, no shift in chargeback liability.', 'woocommerce-gateway-realex');
                if ($this->liability_shift()) {
                    // liability shift required, order fail
                    $this->wc_gateway_realex->order_failed($order, $order_note);
                    SV_WC_Helper::wc_add_notice(__('The transaction has been declined, please wait and try again or try an alternative payment method.  Your order has been recorded, please contact us if you wish to provide payment over the phone.', 'woocommerce-gateway-realex'), 'error');
                } else {
                    // charge without liability shift allowed
                    $order->add_order_note($order_note);
                    $this->threedsecure = $this->get_eci_non_3dsecure($this->wc_gateway_realex->get_post('realex_cardType'));
                    return $this->wc_gateway_realex->authorize($realex_client, $order, null, false);
                }
            } else {
                // don't know whether this can happen because the implementation docs don't describe it, so we'll be conservative
                $order_note = sprintf(__('3DSecure unknown enrollment status: (%d %s).', 'woocommerce-gateway-realex'), $response->result, $response->enrolled);
                $this->wc_gateway_realex->order_failed($order, $order_note);
                SV_WC_Helper::wc_add_notice(__('The transaction has been declined, please wait and try again or try an alternative payment method.  Your order has been recorded, please contact us if you wish to provide payment over the phone.', 'woocommerce-gateway-realex'), 'error');
            }
        } else {
            // 220: Message Timeout: card scheme directory server unavailable, no liability shift, send a normal auth message (ECI: Visa: 7, MC/SWITCH: 0) (no known test case)
            // 521: Card number is not a Switch Card.  3DSecure Transactions are not supported for Solo Cards.  no liability shift, send a normal auth message (ECI: Visa: 7, MC/SWITCH: 0) (no known test case)
            // 520: Invalid response from enrollment server, no liability shift. send a normal auth message (ECI: Visa: 7, MC/SWITCH: 0)
            // 503: No entry for Merchant ID
            if ($this->wc_gateway_realex->is_debug_mode()) {
                $this->wc_gateway_realex->response_debug_message($response, "Response: 3ds-verifyenrolled");
            }
            // create the appropriate order note
            if ($response->result == '220') {
                $order_note = __('3DSecure card scheme directory server unavailable, no shift in chargeback liability (220).', 'woocommerce-gateway-realex');
            } elseif ($response->result == '521') {
                $order_note = __('3DSecure are not supported for Solo Cards, no shift in chargeback liability (521).', 'woocommerce-gateway-realex');
            } elseif ($response->result == '520') {
                $order_note = __('Invalid response from 3DSecure Enrollment Server, no shift in chargeback liability (520).', 'woocommerce-gateway-realex');
            } elseif ($response->result == '503') {
                $order_note = sprintf(__('3DSecure verify enrollment error, ensure RealMPI is enabled for your account/currency: (%s - %s).', 'woocommerce-gateway-realex'), $response->result, $response->message);
            } else {
                $order_note = sprintf(__('Realex Verify Enrollment unknown error (Result: %s - "%s").', 'woocommerce-gateway-realex'), $response->result, $response->message);
            }
            if ($this->liability_shift()) {
                // liability shift required, order fail
                $this->wc_gateway_realex->order_failed($order, $order_note);
                SV_WC_Helper::wc_add_notice(__('The transaction has been declined, please wait and try again or try an alternative payment method.  Your order has been recorded, please contact us if you wish to provide payment over the phone.', 'woocommerce-gateway-realex'), 'error');
            } else {
                // charge without liability shift allowed
                $order->add_order_note($order_note);
                $this->threedsecure = $this->get_eci_non_3dsecure($this->wc_gateway_realex->get_post('realex_cardType'));
                return $this->wc_gateway_realex->authorize($realex_client, $order, null, false);
            }
        }
    }