/**
  * Get the order from the PayPal 'Custom' variable.
  *
  * @param  string $raw_custom JSON Data passed back by PayPal
  * @return bool|WC_Order      Order object or false
  */
 protected function get_paypal_order($raw_custom)
 {
     // We have the data in the correct format, so get the order.
     if (($custom = json_decode($raw_custom)) && is_object($custom)) {
         $order_id = $custom->order_id;
         $order_key = $custom->order_key;
     } else {
         wc_gateway_ppec_log(sprintf('%s: %s', __FUNCTION__, 'Error: Order ID and key were not found in "custom".'));
         return false;
     }
     if (!($order = wc_get_order($order_id))) {
         // We have an invalid $order_id, probably because invoice_prefix has changed.
         $order_id = wc_get_order_id_by_order_key($order_key);
         $order = wc_get_order($order_id);
     }
     if (!$order || $order->order_key !== $order_key) {
         wc_gateway_ppec_log(sprintf('%s: %s', __FUNCTION__, 'Error: Order Keys do not match.'));
         return false;
     }
     return $order;
 }
 /**
  * Maybe received credentials after successfully returned from IPS flow.
  *
  * @return mixed
  */
 public function maybe_received_credentials()
 {
     if (!is_admin() || !is_user_logged_in()) {
         return false;
     }
     // Require the nonce.
     if (empty($_GET['wc_ppec_ips_admin_nonce']) || empty($_GET['env'])) {
         return false;
     }
     $env = in_array($_GET['env'], array('live', 'sandbox')) ? $_GET['env'] : 'live';
     // Verify the nonce.
     if (!wp_verify_nonce($_GET['wc_ppec_ips_admin_nonce'], 'wc_ppec_ips')) {
         wp_die(__('Invalid connection request', 'woocommerce-gateway-paypal-express-checkout'));
     }
     wc_gateway_ppec_log(sprintf('%s: returned back from IPS flow with parameters: %s', __METHOD__, print_r($_GET, true)));
     // Check if error.
     if (!empty($_GET['error'])) {
         $error_message = !empty($_GET['error_message']) ? $_GET['error_message'] : '';
         wc_gateway_ppec_log(sprintf('%s: returned back from IPS flow with error: %s', __METHOD__, $error_message));
         $this->_redirect_with_messages(__('Sorry, Easy Setup encountered an error.  Please try again.', 'woocommerce-gateway-paypal-express-checkout'));
     }
     // Make sure credentials present in query string.
     foreach (array('api_style', 'api_username', 'api_password', 'signature') as $param) {
         if (empty($_GET[$param])) {
             wc_gateway_ppec_log(sprintf('%s: returned back from IPS flow but missing parameter %s', __METHOD__, $param));
             $this->_redirect_with_messages(__('Sorry, Easy Setup encountered an error.  Please try again.', 'woocommerce-gateway-paypal-express-checkout'));
         }
     }
     $creds = new WC_Gateway_PPEC_Client_Credential_Signature($_GET['api_username'], $_GET['api_password'], $_GET['signature']);
     $error_msgs = array();
     try {
         $payer_id = wc_gateway_ppec()->client->test_api_credentials($creds, $env);
         if (!$payer_id) {
             $this->_redirect_with_messages(__('Easy Setup was able to obtain your API credentials, but was unable to verify that they work correctly.  Please make sure your PayPal account is set up properly and try Easy Setup again.', 'woocommerce-gateway-paypal-express-checkout'));
         }
     } catch (PayPal_API_Exception $ex) {
         $error_msgs[] = array('warning' => __('Easy Setup was able to obtain your API credentials, but an error occurred while trying to verify that they work correctly.  Please try Easy Setup again.', 'woocommerce-gateway-paypal-express-checkout'));
     }
     $error_msgs[] = array('success' => __('Success!  Your PayPal account has been set up successfully.', 'woocommerce-gateway-paypal-express-checkout'));
     if (!empty($error_msgs)) {
         wc_gateway_ppec_log(sprintf('%s: returned back from IPS flow: %s', __METHOD__, print_r($error_msgs, true)));
     }
     // Save credentials to settings API
     $settings_array = (array) get_option('woocommerce_ppec_paypal_settings', array());
     if ('live' === $env) {
         $settings_array['environment'] = 'live';
         $settings_array['api_username'] = $creds->get_username();
         $settings_array['api_password'] = $creds->get_password();
         $settings_array['api_signature'] = is_callable(array($creds, 'get_signature')) ? $creds->get_signature() : '';
         $settings_array['api_certificate'] = is_callable(array($creds, 'get_certificate')) ? $creds->get_certificate() : '';
         $settings_array['api_subject'] = $creds->get_subject();
     } else {
         $settings_array['environment'] = 'sandbox';
         $settings_array['sandbox_api_username'] = $creds->get_username();
         $settings_array['sandbox_api_password'] = $creds->get_password();
         $settings_array['sandbox_api_signature'] = is_callable(array($creds, 'get_signature')) ? $creds->get_signature() : '';
         $settings_array['sandbox_api_certificate'] = is_callable(array($creds, 'get_certificate')) ? $creds->get_certificate() : '';
         $settings_array['sandbox_api_subject'] = $creds->get_subject();
     }
     update_option('woocommerce_ppec_paypal_settings', $settings_array);
     $this->_redirect_with_messages($error_msgs);
 }
 /**
  * Make a remote request to PayPal API.
  *
  * @see https://developer.paypal.com/docs/classic/api/NVPAPIOverview/#creating-an-nvp-request
  *
  * @param  array $params NVP request parameters
  * @return array         NVP response
  */
 protected function _request(array $params)
 {
     try {
         wc_gateway_ppec_log(sprintf('%s: trying to make a request to PayPal with params: %s', __METHOD__, print_r($params, true)));
         // Make sure $_credential and $_environment have been configured.
         if (!$this->_credential) {
             throw new Exception(__('Missing credential', 'woocommerce-gateway-paypal-express-checkout'), self::INVALID_CREDENTIAL_ERROR);
         }
         if (!is_a($this->_credential, 'WC_Gateway_PPEC_Client_Credential')) {
             throw new Exception(__('Invalid credential object', 'woocommerce-gateway-paypal-express-checkout'), self::INVALID_CREDENTIAL_ERROR);
         }
         if (!in_array($this->_environment, array('live', 'sandbox'))) {
             throw new Exception(__('Invalid environment', 'woocommerce-gateway-paypal-express-checkout'), self::INVALID_ENVIRONMENT_ERROR);
         }
         // First, add in the necessary credential parameters.
         $body = array_merge($params, $this->_credential->get_request_params());
         $args = array('method' => 'POST', 'body' => $body, 'user-agent' => __CLASS__, 'httpversion' => '1.1', 'timeout' => 30);
         // For cURL transport.
         add_action('http_api_curl', array($this->_credential, 'configure_curl'), 10, 3);
         wc_gateway_ppec_log(sprintf('%s: remote request to %s with args: %s', __METHOD__, $this->get_endpoint(), print_r($args, true)));
         $resp = wp_safe_remote_post($this->get_endpoint(), $args);
         wc_gateway_ppec_log(sprintf('%s: response from remote request to %s: %s', __METHOD__, $this->get_endpoint(), print_r($resp, true)));
         if (is_wp_error($resp)) {
             throw new Exception(sprintf(__('An error occurred while trying to connect to PayPal: %s', 'woocommerce-gateway-paypal-express-checkout'), $resp->get_error_message()), self::REQUEST_ERROR);
         }
         parse_str(wp_remote_retrieve_body($resp), $result);
         if (!array_key_exists('ACK', $result)) {
             throw new Exception(__('Malformed response received from PayPal', 'woocommerce-gateway-paypal-express-checkout'), self::REQUEST_ERROR);
         }
         wc_gateway_ppec_log(sprintf('%s: acknowleged response body: %s', __METHOD__, print_r($result, true)));
         remove_action('http_api_curl', array($this->_credential, 'configure_curl'), 10);
         // Let the caller deals with the response.
         return $result;
     } catch (Exception $e) {
         remove_action('http_api_curl', array($this->_credential, 'configure_curl'), 10);
         // TODO: Maybe returns WP_Error ?
         $error = array('ACK' => 'Failure', 'L_ERRORCODE0' => $e->getCode(), 'L_SHORTMESSAGE0' => 'Error in ' . __METHOD__, 'L_LONGMESSAGE0' => $e->getMessage(), 'L_SEVERITYCODE0' => 'Error');
         wc_gateway_ppec_log(sprintf('%s: exception is thrown while trying to make a request to PayPal: %s', __METHOD__, $e->getMessage()));
         wc_gateway_ppec_log(sprintf('%s: returns error: %s', __METHOD__, print_r($error, true)));
         return $error;
     }
 }
 /**
  * Handle a completed payment.
  *
  * @param WC_Order $order Order object
  * @param array $posted_data Posted data
  */
 protected function payment_status_completed($order, $posted_data)
 {
     if ($order->has_status(array('processing', 'completed'))) {
         wc_gateway_ppec_log('Aborting, Order #' . $order->id . ' is already complete.');
         exit;
     }
     $this->validate_transaction_type($posted_data['txn_type']);
     $this->validate_currency($order, $posted_data['mc_currency']);
     $this->validate_amount($order, $posted_data['mc_gross']);
     $this->save_paypal_meta_data($order, $posted_data);
     if ('completed' === $posted_data['payment_status']) {
         $this->payment_complete($order, !empty($posted_data['txn_id']) ? wc_clean($posted_data['txn_id']) : '', __('IPN payment completed', 'woocommerce-gateway-paypal-express-checkout'));
         if (!empty($posted_data['mc_fee'])) {
             // Log paypal transaction fee.
             update_post_meta($order->id, 'PayPal Transaction Fee', wc_clean($posted_data['mc_fee']));
         }
     } else {
         if ('authorization' === $posted_data['pending_reason']) {
             $this->payment_on_hold($order, __('Payment authorized. Change payment status to processing or complete to capture funds.', 'woocommerce-gateway-paypal-express-checkout'));
         } else {
             $this->payment_on_hold($order, sprintf(__('Payment pending (%s).', 'woocommerce-gateway-paypal-express-checkout'), $posted_data['pending_reason']));
         }
     }
 }