/classes/wc-gateway-paypal-pro-payflow-angelleye.php

  1. <?php 
  2.  
  3. /** 
  4. * WC_Gateway_PayPal_Pro_PayFlow class. 
  5. * 
  6. * @extends WC_Payment_Gateway 
  7. */ 
  8. class WC_Gateway_PayPal_Pro_PayFlow_AngellEYE extends WC_Payment_Gateway_CC { 
  9.  
  10. /** 
  11. * __construct function. 
  12. * 
  13. * @access public 
  14. * @return void 
  15. */ 
  16. public $customer_id; 
  17. function __construct() { 
  18. $this->id = 'paypal_pro_payflow'; 
  19. $this->method_title = __( 'PayPal Payments Pro 2.0 (PayFlow)', 'paypal-for-woocommerce' ); 
  20. $this->method_description = __( 'PayPal Payments Pro allows you to accept credit cards directly on your site without any redirection through PayPal. You host the checkout form on your own web server, so you will need an SSL certificate to ensure your customer data is protected.', 'paypal-for-woocommerce' ); 
  21. $this->has_fields = true; 
  22.  
  23. $this->allowed_currencies = apply_filters('woocommerce_paypal_pro_allowed_currencies', array('USD', 'EUR', 'GBP', 'CAD', 'JPY', 'AUD', 'NZD')); 
  24.  
  25.  
  26. // Load the form fields 
  27. $this->init_form_fields(); 
  28.  
  29. // Load the settings. 
  30. $this->init_settings(); 
  31.  
  32. // Get setting values 
  33. $this->title = $this->get_option('title'); 
  34. $this->description = $this->get_option('description'); 
  35. $this->enabled = $this->get_option('enabled'); 
  36. $this->testmode = 'yes' === $this->get_option('testmode', 'no'); 
  37. if( $this->testmode == false ) { 
  38. $this->testmode = AngellEYE_Utility::angelleye_paypal_for_woocommerce_is_set_sandbox_product(); 
  39. $this->invoice_id_prefix = $this->get_option('invoice_id_prefix', ''); 
  40. $this->debug = 'yes' === $this->get_option('debug', 'no'); 
  41. $this->error_email_notify = 'yes' === $this->get_option('error_email_notify', 'no'); 
  42. $this->error_display_type = $this->get_option('error_display_type', 'no'); 
  43. $this->send_items = 'yes' === $this->get_option('send_items', 'yes'); 
  44. $this->payment_action = $this->get_option('payment_action', 'Sale'); 
  45.  
  46. //fix ssl for image icon 
  47. $this->icon = $this->get_option('card_icon', plugins_url('/assets/images/payflow-cards.png', plugin_basename(dirname(__FILE__)))); 
  48. if (is_ssl()) { 
  49. $this->icon = preg_replace("/^http:/i", "https:", $this->icon); 
  50. $this->icon = apply_filters('woocommerce_paypal_pro_payflow_icon', $this->icon); 
  51. $this->paypal_partner = $this->get_option('paypal_partner', 'PayPal'); 
  52. $this->paypal_vendor = $this->get_option('paypal_vendor'); 
  53. $this->paypal_user = $this->get_option('paypal_user', $this->paypal_vendor); 
  54. $this->paypal_password = $this->get_option('paypal_password'); 
  55. if ($this->testmode == true) { 
  56. $this->paypal_vendor = $this->get_option('sandbox_paypal_vendor'); 
  57. $this->paypal_partner = $this->get_option('sandbox_paypal_partner', 'PayPal'); 
  58. $this->paypal_password = $this->get_option('sandbox_paypal_password'); 
  59. $this->paypal_user = $this->get_option('sandbox_paypal_user', $this->paypal_vendor); 
  60.  
  61. $this->supports = array( 
  62. 'products',  
  63. 'refunds' 
  64. ); 
  65.  
  66. $this->enable_tokenized_payments = $this->get_option('enable_tokenized_payments', 'no'); 
  67. if($this->enable_tokenized_payments == 'yes') { 
  68. $this->supports = array( 
  69. 'subscriptions',  
  70. 'products',  
  71. 'refunds',  
  72. 'subscription_cancellation',  
  73. 'subscription_reactivation',  
  74. 'subscription_suspension',  
  75. 'subscription_amount_changes',  
  76. 'subscription_payment_method_change', // Subs 1.n compatibility. 
  77. 'subscription_payment_method_change_customer',  
  78. 'subscription_payment_method_change_admin',  
  79. 'subscription_date_changes',  
  80. 'multiple_subscriptions',  
  81. 'add_payment_method',  
  82. 'tokenization' 
  83. ); 
  84.  
  85. $this->softdescriptor = $this->get_option('softdescriptor', ''); 
  86. $this->avs_cvv2_result_admin_email = 'yes' === $this->get_option('avs_cvv2_result_admin_email', 'no');  
  87. $this->Force_tls_one_point_two = get_option('Force_tls_one_point_two', 'no'); 
  88. $this->enable_cardholder_first_last_name = 'yes' === $this->get_option('enable_cardholder_first_last_name', 'no'); 
  89. $this->is_encrypt = $this->get_option('is_encrypt', 'no'); 
  90. $this->credit_card_month_field = $this->get_option('credit_card_month_field', 'names'); 
  91. $this->credit_card_year_field = $this->get_option('credit_card_year_field', 'four_digit'); 
  92. $this->fraud_management_filters = $this->get_option('fraud_management_filters', 'place_order_on_hold_for_further_review'); 
  93.  
  94. /** 2.0.0 */ 
  95. add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options')); 
  96.  
  97.  
  98. add_filter( 'woocommerce_credit_card_form_fields', array($this, 'angelleye_paypal_pro_payflow_credit_card_form_fields'), 10, 2); 
  99. add_filter('woocommerce_settings_api_sanitized_fields_' . $this->id, array($this, 'angelleye_paypal_pro_payflow_encrypt_gateway_api'), 10, 1); 
  100. if ($this->enable_cardholder_first_last_name) { 
  101. add_action('woocommerce_credit_card_form_start', array($this, 'angelleye_woocommerce_credit_card_form_start'), 10, 1); 
  102. if( $this->avs_cvv2_result_admin_email ) { 
  103. add_action( 'woocommerce_email_before_order_table', array( $this, 'angelleye_paypal_pro_payflow_email_instructions' ), 10, 3 ); 
  104.  
  105. $this->enable_automated_account_creation_for_guest_checkouts = 'yes' === $this->get_option('enable_automated_account_creation_for_guest_checkouts', 'no'); 
  106. $this->enable_guest_checkout = get_option('woocommerce_enable_guest_checkout') == 'yes' ? true : false; 
  107. if ($this->supports('tokenization') && is_checkout() && $this->enable_guest_checkout && !is_user_logged_in() && $this->enable_automated_account_creation_for_guest_checkouts) { 
  108. $this->enable_automated_account_creation_for_guest_checkouts = true; 
  109. add_action('woocommerce_after_checkout_validation', array($this, 'enable_automated_account_creation_for_guest_checkouts'), 10, 1); 
  110. } else { 
  111. $this->enable_automated_account_creation_for_guest_checkouts = false; 
  112.  
  113. $this->customer_id; 
  114. if (class_exists('WC_Gateway_Calculation_AngellEYE')) { 
  115. $this->calculation_angelleye = new WC_Gateway_Calculation_AngellEYE(); 
  116. } else { 
  117. require_once( PAYPAL_FOR_WOOCOMMERCE_PLUGIN_DIR . '/classes/wc-gateway-calculations-angelleye.php' ); 
  118. $this->calculation_angelleye = new WC_Gateway_Calculation_AngellEYE(); 
  119.  
  120.  
  121.  
  122. public function add_log($message) { 
  123. if ($this->debug) { 
  124. if (!isset($this->log)) { 
  125. $this->log = new WC_Logger(); 
  126. $this->log->add('paypal_payflow', $message); 
  127.  
  128. /** 
  129. * Initialise Gateway Settings Form Fields 
  130. */ 
  131. function init_form_fields() { 
  132.  
  133. $this->form_fields = array( 
  134. 'enabled' => array( 
  135. 'title' => __('Enable/Disable', 'paypal-for-woocommerce'),  
  136. 'label' => __('Enable PayPal Pro Payflow Edition', 'paypal-for-woocommerce'),  
  137. 'type' => 'checkbox',  
  138. 'description' => '',  
  139. 'default' => 'no' 
  140. ),  
  141. 'title' => array( 
  142. 'title' => __('Title', 'paypal-for-woocommerce'),  
  143. 'type' => 'text',  
  144. 'description' => __('This controls the title which the user sees during checkout.', 'paypal-for-woocommerce'),  
  145. 'default' => __('Credit card', 'paypal-for-woocommerce') 
  146. ),  
  147. 'description' => array( 
  148. 'title' => __('Description', 'paypal-for-woocommerce'),  
  149. 'type' => 'textarea',  
  150. 'description' => __('This controls the description which the user sees during checkout.', 'paypal-for-woocommerce'),  
  151. 'default' => __('Pay with your credit card.', 'paypal-for-woocommerce') 
  152. ),  
  153. 'testmode' => array( 
  154. 'title' => __('Test Mode', 'paypal-for-woocommerce'),  
  155. 'label' => __('Enable PayPal Sandbox/Test Mode', 'paypal-for-woocommerce'),  
  156. 'type' => 'checkbox',  
  157. 'description' => __('Place the payment gateway in development mode.', 'paypal-for-woocommerce'),  
  158. 'default' => 'no' 
  159. ),  
  160. 'invoice_id_prefix' => array( 
  161. 'title' => __('Invoice ID Prefix', 'paypal-for-woocommerce'),  
  162. 'type' => 'text',  
  163. 'description' => __('Add a prefix to the invoice ID sent to PayPal. This can resolve duplicate invoice problems when working with multiple websites on the same PayPal account.', 'paypal-for-woocommerce'),  
  164. ),  
  165. 'card_icon' => array( 
  166. 'title' => __('Card Icon', 'paypal-for-woocommerce'),  
  167. 'type' => 'text',  
  168. 'default' => plugins_url('/assets/images/payflow-cards.png', plugin_basename(dirname(__FILE__))),  
  169. 'class' => 'button_upload' 
  170. ),  
  171. 'debug' => array( 
  172. 'title' => __('Debug Log', 'paypal-for-woocommerce'),  
  173. 'type' => 'checkbox',  
  174. 'label' => __('Enable logging', 'paypal-for-woocommerce'),  
  175. 'default' => 'no',  
  176. 'description' => sprintf(__('Log PayPal events inside <code>%s</code>', 'paypal-for-woocommerce'), wc_get_log_file_path('paypal_payflow')),  
  177. ),  
  178. 'error_email_notify' => array( 
  179. 'title' => __('Error Email Notifications', 'paypal-for-woocommerce'),  
  180. 'type' => 'checkbox',  
  181. 'label' => __('Enable admin email notifications for errors.', 'paypal-for-woocommerce'),  
  182. 'default' => 'yes',  
  183. 'description' => __('This will send a detailed error email to the WordPress site administrator if a PayPal API error occurs.', 'paypal-for-woocommerce') 
  184. ),  
  185. 'error_display_type' => array( 
  186. 'title' => __('Error Display Type', 'paypal-for-woocommerce'),  
  187. 'type' => 'select',  
  188. 'label' => __('Display detailed or generic errors', 'paypal-for-woocommerce'),  
  189. 'class' => 'error_display_type_option',  
  190. 'options' => array( 
  191. 'detailed' => 'Detailed',  
  192. 'generic' => 'Generic' 
  193. ),  
  194. 'description' => __( 'Detailed displays actual errors returned from PayPal. Generic displays general errors that do not reveal details  
  195. and helps to prevent fraudulant activity on your site.' , 'paypal-for-woocommerce' ) 
  196. ),  
  197. 'sandbox_paypal_vendor' => array( 
  198. 'title' => __('Sandbox PayPal Vendor', 'paypal-for-woocommerce'),  
  199. 'type' => 'text',  
  200. 'description' => __('Your merchant login ID that you created when you registered for the account.', 'paypal-for-woocommerce'),  
  201. 'default' => '' 
  202. ),  
  203. 'sandbox_paypal_password' => array( 
  204. 'title' => __('Sandbox PayPal Password', 'paypal-for-woocommerce'),  
  205. 'type' => 'password',  
  206. 'description' => __('The password that you defined while registering for the account.', 'paypal-for-woocommerce'),  
  207. 'default' => '' 
  208. ),  
  209. 'sandbox_paypal_user' => array( 
  210. 'title' => __('Sandbox PayPal User', 'paypal-for-woocommerce'),  
  211. 'type' => 'text',  
  212. 'description' => __( 'If you set up one or more additional users on the account, this value is the ID 
  213. of the user authorized to process transactions. Otherwise, leave this field blank.', 'paypal-for-woocommerce' ),  
  214. 'default' => '' 
  215. ),  
  216.  
  217. 'sandbox_paypal_partner' => array( 
  218. 'title' => __( 'Sandbox PayPal Partner', 'paypal-for-woocommerce' ),  
  219. 'type' => 'text',  
  220. 'description' => __('The ID provided to you by the authorized PayPal Reseller who registered you for the Payflow SDK. If you purchased your account directly from PayPal, use PayPal or leave blank.', 'paypal-for-woocommerce'),  
  221. 'default' => 'PayPal' 
  222. ),  
  223. 'paypal_vendor' => array( 
  224. 'title' => __('Live PayPal Vendor', 'paypal-for-woocommerce'),  
  225. 'type' => 'text',  
  226. 'description' => __('Your merchant login ID that you created when you registered for the account.', 'paypal-for-woocommerce'),  
  227. 'default' => '' 
  228. ),  
  229. 'paypal_password' => array( 
  230. 'title' => __('Live PayPal Password', 'paypal-for-woocommerce'),  
  231. 'type' => 'password',  
  232. 'description' => __('The password that you defined while registering for the account.', 'paypal-for-woocommerce'),  
  233. 'default' => '' 
  234. ),  
  235. 'sandbox_paypal_user' => array( 
  236. 'title' => __('Sandbox PayPal User', 'paypal-for-woocommerce'),  
  237. 'type' => 'text',  
  238. 'description' => __('If you set up one or more additional users on the account, this value is the ID of the user authorized to process transactions. Otherwise, leave this field blank.', 'paypal-for-woocommerce'),  
  239. 'default' => '' 
  240. ),  
  241. 'sandbox_paypal_partner' => array( 
  242. 'title' => __('Sandbox PayPal Partner', 'paypal-for-woocommerce'),  
  243. 'type' => 'text',  
  244. 'description' => __('The ID provided to you by the authorized PayPal Reseller who registered you for the Payflow SDK. If you purchased your account directly from PayPal, use PayPal or leave blank.', 'paypal-for-woocommerce'),  
  245. ),  
  246. 'paypal_user' => array( 
  247. 'title' => __('Live PayPal User', 'paypal-for-woocommerce'),  
  248. 'type' => 'text',  
  249. 'description' => __( 'If you set up one or more additional users on the account, this value is the ID 
  250. of the user authorized to process transactions. Otherwise, leave this field blank.', 'paypal-for-woocommerce' ),  
  251. 'default' => '' 
  252. ),  
  253. 'paypal_partner' => array( 
  254. 'title' => __('Live PayPal Partner', 'paypal-for-woocommerce'),  
  255. 'type' => 'text',  
  256. 'description' => __( 'The ID provided to you by the authorized PayPal Reseller who registered you 
  257. for the Payflow SDK. If you purchased your account directly from PayPal, use PayPal or leave blank.', 'paypal-for-woocommerce' ),  
  258. 'default' => 'PayPal' 
  259. ),  
  260. 'send_items' => array( 
  261. 'title' => __('Send Item Details', 'paypal-for-woocommerce'),  
  262. 'label' => __('Send line item details to PayPal', 'paypal-for-woocommerce'),  
  263. 'type' => 'checkbox',  
  264. 'description' => __('Include all line item details in the payment request to PayPal so that they can be seen from the PayPal transaction details page.', 'paypal-for-woocommerce'),  
  265. 'default' => 'yes' 
  266. ),  
  267. 'payment_action' => array( 
  268. 'title' => __('Payment Action', 'paypal-for-woocommerce'),  
  269. 'label' => __('Whether to process as a Sale or Authorization.', 'paypal-for-woocommerce'),  
  270. 'description' => __('Sale will capture the funds immediately when the order is placed. Authorization will authorize the payment but will not capture the funds. You would need to capture funds through your PayPal account when you are ready to deliver.'),  
  271. 'type' => 'select',  
  272. 'options' => array( 
  273. 'Sale' => 'Sale',  
  274. 'Authorization' => 'Authorization',  
  275. ),  
  276. 'default' => 'Sale' 
  277. ),  
  278. 'softdescriptor' => array( 
  279. 'title' => __('Credit Card Statement Name', 'paypal-for-woocommerce'),  
  280. 'type' => 'text',  
  281. 'description' => __('The value entered here will be displayed on the buyer\'s credit card statement.', 'paypal-for-woocommerce'),  
  282. 'default' => '',  
  283. 'desc_tip' => true,  
  284. ),  
  285. 'fraud_management_filters' => array( 
  286. 'title' => __('Fraud Management Filters ', 'paypal-for-woocommerce'),  
  287. 'label' => '',  
  288. 'description' => __('Choose how you would like to handle orders when Fraud Management Filters are flagged.', 'paypal-for-woocommerce'),  
  289. 'type' => 'select',  
  290. 'class' => '',  
  291. 'options' => array( 
  292. 'ignore_warnings_and_proceed_as_usual' => __('Ignore warnings and proceed as usual.', 'paypal-for-woocommerce'),  
  293. 'place_order_on_hold_for_further_review' => __('Place order On Hold for further review.', 'paypal-for-woocommerce'),  
  294. ),  
  295. 'default' => 'place_order_on_hold_for_further_review',  
  296. 'desc_tip' => true,  
  297. ),  
  298. 'credit_card_month_field' => array( 
  299. 'title' => __('Credit Card Month Format', 'paypal-for-woocommerce'),  
  300. 'label' => __('Credit Card Month Display Format.', 'paypal-for-woocommerce'),  
  301. 'description' => __('Choose whether you wish to display Name format or Number format of Month field in the credit card form.'),  
  302. 'type' => 'select',  
  303. 'css' => 'max-width:200px;',  
  304. 'class' => 'wc-enhanced-select',  
  305. 'options' => array( 
  306. 'numbers' => 'Numbers',  
  307. 'names' => 'Names',  
  308. ),  
  309. 'default' => 'names' 
  310. ),  
  311. 'credit_card_year_field' => array( 
  312. 'title' => __('Credit Card Year Format', 'paypal-for-woocommerce'),  
  313. 'label' => __('Credit Card Year Display Format.', 'paypal-for-woocommerce'),  
  314. 'description' => __('Choose whether you wish to display two digit format or four digit of Year field in the credit card form.'),  
  315. 'type' => 'select',  
  316. 'css' => 'max-width:200px;',  
  317. 'class' => 'wc-enhanced-select',  
  318. 'options' => array( 
  319. 'two_digit' => 'Show Two Digit Years',  
  320. 'four_digit' => 'Show Four Digit Years',  
  321. ),  
  322. 'default' => 'four_digit' 
  323. ),  
  324. 'avs_cvv2_result_admin_email' => array( 
  325. 'title' => __('AVS / CVV2 Results in Admin Order Email', 'paypal-for-woocommerce'),  
  326. 'label' => __('Adds the AVS / CVV2 results to the admin order email notification', 'paypal-for-woocommerce'),  
  327. 'type' => 'checkbox',  
  328. 'description' => __('Display Address Verification Result (AVS) and Card Security Code Result (CVV2) Results in Admin Order Email.', 'paypal-for-woocommerce'),  
  329. 'default' => 'no',  
  330. 'desc_tip' => true,  
  331. ),  
  332. 'credit_card_month_field' => array( 
  333. 'title' => __('Choose Credit Card Month Field', 'paypal-for-woocommerce'),  
  334. 'label' => __('Choose Credit Card Month Field Format.', 'paypal-for-woocommerce'),  
  335. 'description' => __('Choose whether you wish to display Name format or Number format of Month field in the credit card form.'),  
  336. 'type' => 'select',  
  337. 'css' => 'max-width:200px;',  
  338. 'class' => 'wc-enhanced-select',  
  339. 'options' => array( 
  340. 'numbers' => 'Numbers',  
  341. 'names' => 'Names',  
  342. ),  
  343. 'default' => 'names' 
  344. ),  
  345. 'credit_card_year_field' => array( 
  346. 'title' => __('Choose Credit Card Year Field', 'paypal-for-woocommerce'),  
  347. 'label' => __('Choose Credit Card Year Field Format.', 'paypal-for-woocommerce'),  
  348. 'description' => __('Choose whether you wish to display Show Two digit format or Four digit of Year field in the credit card form.'),  
  349. 'type' => 'select',  
  350. 'css' => 'max-width:200px;',  
  351. 'class' => 'wc-enhanced-select',  
  352. 'options' => array( 
  353. 'two_digit' => 'Show Two Digit Years',  
  354. 'four_digit' => 'Show Four Digit Years',  
  355. ),  
  356. 'default' => 'four_digit' 
  357. ),  
  358. 'enable_tokenized_payments' => array( 
  359. 'title' => __('Enable Tokenized Payments', 'paypal-for-woocommerce'),  
  360. 'label' => __('Enable Tokenized Payments', 'paypal-for-woocommerce'),  
  361. 'type' => 'checkbox',  
  362. 'description' => __('Allow buyers to securely save payment details to their account for quick checkout / auto-ship orders in the future.', 'paypal-for-woocommerce'),  
  363. 'default' => 'no',  
  364. 'class' => 'enable_tokenized_payments' 
  365. ),  
  366. 'enable_cardholder_first_last_name' => array( 
  367. 'title' => __('Enable Cardholder Name', 'paypal-for-woocommerce'),  
  368. 'label' => __('Adds fields for "card holder name" to checkout in addition to the "billing name" fields.', 'paypal-for-woocommerce'),  
  369. 'type' => 'checkbox',  
  370. 'description' => __('Display card holder first and last name in credit card form.', 'paypal-for-woocommerce'),  
  371. 'default' => 'no' 
  372. ),  
  373. 'is_encrypt' => array( 
  374. 'title' => __('', 'paypal-for-woocommerce'),  
  375. 'label' => __('', 'paypal-for-woocommerce'),  
  376. 'type' => 'hidden',  
  377. 'default' => 'yes',  
  378. 'class' => '' 
  379. ); 
  380. $this->form_fields = apply_filters('angelleye_fc_form_fields', $this->form_fields); 
  381.  
  382. /** 
  383. * Check if this gateway is enabled and available in the user's country 
  384. * 
  385. * This method no is used anywhere??? put above but need a fix below 
  386. */ 
  387. public function is_available() { 
  388.  
  389. if ( $this->enabled == "yes" ) { 
  390. if (!is_ssl() && !$this->testmode) { 
  391. return false; 
  392. // Currency check 
  393. if ( ! in_array( get_woocommerce_currency(), $this->allowed_currencies ) ) { 
  394. return false; 
  395.  
  396. // Required fields check 
  397. if ( ! $this->paypal_vendor || ! $this->paypal_password ) { 
  398. return false; 
  399.  
  400. return true; 
  401.  
  402. return false; 
  403.  
  404. /** 
  405. * Process the payment 
  406. */ 
  407. function process_payment($order_id) { 
  408. $order = new WC_Order($order_id); 
  409. $card_number = isset($_POST['paypal_pro_payflow-card-number']) ? wc_clean($_POST['paypal_pro_payflow-card-number']) : ''; 
  410. $card_cvc = isset($_POST['paypal_pro_payflow-card-cvc']) ? wc_clean($_POST['paypal_pro_payflow-card-cvc']) : ''; 
  411. $card_exp_year = isset($_POST['paypal_pro_payflow_card_expiration_year']) ? wc_clean($_POST['paypal_pro_payflow_card_expiration_year']) : ''; 
  412. $card_exp_month = isset($_POST['paypal_pro_payflow_card_expiration_month']) ? wc_clean($_POST['paypal_pro_payflow_card_expiration_month']) : ''; 
  413. $card_number = str_replace(array(' ', '-'), '', $card_number); 
  414. $card_type = AngellEYE_Utility::card_type_from_account_number($card_number); 
  415. if ($card_type == 'amex' && (get_woocommerce_currency() != 'USD' && get_woocommerce_currency() != 'AUD')) { 
  416. throw new Exception(__('Your processor is unable to process the Card Type in the currency requested. Please try another card type', 'paypal-for-woocommerce')); 
  417. if (strlen($card_exp_year) == 4) { 
  418. $card_exp_year = $card_exp_year - 2000; 
  419.  
  420. $card_exp_month = (int) $card_exp_month; 
  421. if ($card_exp_month < 10) { 
  422. $card_exp_month = '0' . $card_exp_month; 
  423. // Do payment with paypal 
  424. return $this->do_payment($order, $card_number, $card_exp_month . $card_exp_year, $card_cvc); 
  425.  
  426.  
  427.  
  428.  
  429. /** 
  430. * do_payment 
  431. * 
  432. * Process the PayFlow transaction with PayPal. 
  433. * 
  434. * @access public 
  435. * @param mixed $order 
  436. * @param mixed $card_number 
  437. * @param mixed $card_exp 
  438. * @param mixed $card_csc 
  439. * @param string $centinelPAResStatus (default: '') 
  440. * @param string $centinelEnrolled (default: '') 
  441. * @param string $centinelCavv (default: '') 
  442. * @param string $centinelEciFlag (default: '') 
  443. * @param string $centinelXid (default: '') 
  444. * @return void 
  445. */ 
  446. function do_payment($order, $card_number, $card_exp, $card_csc) { 
  447.  
  448. $order_id = version_compare( WC_VERSION, '3.0', '<' ) ? $order->id : $order->get_id(); 
  449.  
  450. if (!class_exists('Angelleye_PayPal')) { 
  451. require_once('lib/angelleye/paypal-php-library/includes/paypal.class.php'); 
  452. if(!class_exists('Angelleye_PayPal_PayFlow' )) { 
  453. require_once('lib/angelleye/paypal-php-library/includes/paypal.payflow.class.php');  
  454.  
  455. /** 
  456. * Create PayPal_PayFlow object. 
  457. */ 
  458. $PayPalConfig = array( 
  459. 'Sandbox' => $this->testmode,  
  460. 'APIUsername' => $this->paypal_user,  
  461. 'APIPassword' => trim($this->paypal_password),  
  462. 'APIVendor' => $this->paypal_vendor,  
  463. 'APIPartner' => $this->paypal_partner,  
  464. 'Force_tls_one_point_two' => $this->Force_tls_one_point_two 
  465. ); 
  466. $PayPal = new Angelleye_PayPal_PayFlow($PayPalConfig); 
  467.  
  468. try { 
  469.  
  470. $billing_address_1 = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_address_1 : $order->get_billing_address_1(); 
  471. $billing_address_2 = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_address_2 : $order->get_billing_address_2(); 
  472. $billtostreet = $billing_address_1 . ' ' . $billing_address_2; 
  473. $billing_city = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_city : $order->get_billing_city(); 
  474. $billing_postcode = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_postcode : $order->get_billing_postcode(); 
  475. $billing_country = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_country : $order->get_billing_country(); 
  476. $billing_state = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_state : $order->get_billing_state(); 
  477. $billing_email = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_email : $order->get_billing_email(); 
  478.  
  479. if(!empty($_POST['paypal_pro_payflow-card-cardholder-first'])) { 
  480. $firstname = wc_clean($_POST['paypal_pro_payflow-card-cardholder-first']); 
  481. } else { 
  482. $firstname = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_first_name : $order->get_billing_first_name(); 
  483. }  
  484.  
  485. if(!empty($_POST['paypal_pro_payflow-card-cardholder-last'])) { 
  486. $lastname = wc_clean($_POST['paypal_pro_payflow-card-cardholder-last']); 
  487. } else { 
  488. $lastname = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_last_name : $order->get_billing_last_name(); 
  489.  
  490. $PayPalRequestData = array( 
  491. 'tender'=>'C', // Required. The method of payment. Values are: A = ACH, C = Credit Card, D = Pinless Debit, K = Telecheck, P = PayPal 
  492. 'trxtype' => ($this->payment_action == 'Authorization' || $order->get_total() == 0 ) ? 'A' : 'S', // Required. Indicates the type of transaction to perform. Values are: A = Authorization, B = Balance Inquiry, C = Credit, D = Delayed Capture, F = Voice Authorization, I = Inquiry, L = Data Upload, N = Duplicate Transaction, S = Sale, V = Void 
  493. 'acct'=>$card_number, // Required for credit card transaction. Credit card or purchase card number. 
  494. 'expdate'=>$card_exp, // Required for credit card transaction. Expiration date of the credit card. Format: MMYY 
  495. 'amt'=> AngellEYE_Gateway_Paypal::number_format($order->get_total()), // Required. Amount of the transaction. Must have 2 decimal places.  
  496. 'currency'=>version_compare(WC_VERSION, '3.0', '<') ? $order->get_order_currency() : $order->get_currency(), //  
  497. 'dutyamt' => '', // 
  498. 'freightamt' => '', // 
  499. 'taxamt' => '', // 
  500. 'taxexempt' => '', // 
  501. 'custom' => apply_filters( 'ae_pppf_custom_parameter', json_encode( array( 'order_id' => version_compare(WC_VERSION, '3.0', '<') ? $order->id : $order->get_id(), 'order_key' => version_compare( WC_VERSION, '3.0', '<' ) ? $order->order_key : $order->get_order_key() ) ) , $order ), // Free-form field for your own use.  
  502. 'comment1'=> apply_filters( 'ae_pppf_comment1_parameter', '' , $order ), // Merchant-defined value for reporting and auditing purposes. 128 char max 
  503. 'comment2' => apply_filters('ae_pppf_comment2_parameter', '', $order), // Merchant-defined value for reporting and auditing purposes. 128 char max 
  504. 'cvv2' => $card_csc, // A code printed on the back of the card (or front for Amex) 
  505. 'recurring' => '', // Identifies the transaction as recurring. One of the following values: Y = transaction is recurring, N = transaction is not recurring. 
  506. 'swipe' => '', // Required for card-present transactions. Used to pass either Track 1 or Track 2, but not both. 
  507. 'orderid' => $this->invoice_id_prefix . preg_replace("/[^a-zA-Z0-9]/", "", $order->get_order_number()), // Checks for duplicate order. If you pass orderid in a request and pass it again in the future the response returns DUPLICATE=2 along with the orderid 
  508. 'orderdesc' => 'Order ' . $order->get_order_number() . ' on ' . get_bloginfo('name'), // 
  509. 'billtoemail'=>$billing_email, // Account holder's email address. 
  510. 'billtophonenum' => '', // Account holder's phone number. 
  511. 'billtofirstname' => $firstname, // Account holder's first name. 
  512. 'billtomiddlename' => '', // Account holder's middle name. 
  513. 'billtolastname' => $lastname, // Account holder's last name. 
  514. 'billtostreet'=> $billtostreet, // The cardholder's street address (number and street name). 150 char max 
  515. 'billtocity'=>$billing_city, // Bill to city. 45 char max 
  516. 'billtostate'=>$billing_state, // Bill to state.  
  517. 'billtozip'=>$billing_postcode, // Account holder's 5 to 9 digit postal code. 9 char max. No dashes, spaces, or non-numeric characters 
  518. 'billtocountry'=>$billing_country, // Bill to Country. 3 letter country code. 
  519. 'origid' => '', // Required by some transaction types. ID of the original transaction referenced. The PNREF parameter returns this ID, and it appears as the Transaction ID in PayPal Manager reports. 
  520. 'custref' => '', // 
  521. 'custcode' => '', // 
  522. 'custip' => $this->get_user_ip(), // 
  523. 'invnum'=> $this->invoice_id_prefix . preg_replace("/[^a-zA-Z0-9]/", "", str_replace("#", "", $order->get_order_number())), // 
  524. 'ponum' => '', // 
  525. 'starttime' => '', // For inquiry transaction when using CUSTREF to specify the transaction. 
  526. 'endtime' => '', // For inquiry transaction when using CUSTREF to specify the transaction. 
  527. 'securetoken' => '', // Required if using secure tokens. A value the Payflow server created upon your request for storing transaction data. 32 char 
  528. 'partialauth' => '', // Required for partial authorizations. Set to Y to submit a partial auth. 
  529. 'authcode'=>'', // Rrequired for voice authorizations. Returned only for approved voice authorization transactions. AUTHCODE is the approval code received over the phone from the processing network. 6 char max 
  530. 'merchdescr' => $this->softdescriptor 
  531. ); 
  532.  
  533. /** 
  534. * Shipping info 
  535. */ 
  536. $shipping_address_1 = version_compare( WC_VERSION, '3.0', '<' ) ? $order->shipping_address_1 : $order->get_shipping_address_1(); 
  537. if($shipping_address_1) 
  538.  
  539.  
  540. $shipping_address_2 = version_compare( WC_VERSION, '3.0', '<' ) ? $order->shipping_address_2 : $order->get_shipping_address_2(); 
  541. $PayPalRequestData['SHIPTOFIRSTNAME'] = version_compare( WC_VERSION, '3.0', '<' ) ? $order->shipping_first_name : $order->get_shipping_first_name(); 
  542. $PayPalRequestData['SHIPTOLASTNAME'] = version_compare( WC_VERSION, '3.0', '<' ) ? $order->shipping_last_name : $order->get_shipping_last_name(); 
  543. $PayPalRequestData['SHIPTOSTREET'] = $shipping_address_1 . ' ' . $shipping_address_2; 
  544. $PayPalRequestData['SHIPTOCITY'] = version_compare( WC_VERSION, '3.0', '<' ) ? $order->shipping_city : $order->get_shipping_city(); 
  545. $PayPalRequestData['SHIPTOSTATE'] = version_compare( WC_VERSION, '3.0', '<' ) ? $order->shipping_state : $order->get_shipping_state(); 
  546. $PayPalRequestData['SHIPTOCOUNTRY'] = version_compare( WC_VERSION, '3.0', '<' ) ? $order->shipping_country : $order->get_shipping_country(); 
  547. $PayPalRequestData['SHIPTOZIP'] = version_compare( WC_VERSION, '3.0', '<' ) ? $order->shipping_postcode : $order->get_shipping_postcode(); 
  548.  
  549. $PaymentData = AngellEYE_Gateway_Paypal::calculate($order, $this->send_items); 
  550. $OrderItems = array(); 
  551. if ($this->send_items) { 
  552. $item_loop = 0; 
  553. foreach ($PaymentData['order_items'] as $_item) { 
  554. $Item['L_NUMBER' . $item_loop] = $_item['number']; 
  555. $Item['L_NAME' . $item_loop] = $_item['name']; 
  556. $Item['L_COST' . $item_loop] = $_item['amt']; 
  557. $Item['L_QTY' . $item_loop] = $_item['qty']; 
  558. if ($_item['number']) { 
  559. $Item['L_SKU' . $item_loop] = $_item['number']; 
  560. $OrderItems = array_merge($OrderItems, $Item); 
  561. $item_loop++; 
  562.  
  563. /** 
  564. * Shipping/tax/item amount 
  565. */ 
  566. $PayPalRequestData['taxamt'] = $PaymentData['taxamt']; 
  567. $PayPalRequestData['freightamt'] = $PaymentData['shippingamt']; 
  568. $PayPalRequestData['ITEMAMT'] = $PaymentData['itemamt']; 
  569.  
  570. if ($this->send_items) { 
  571. $PayPalRequestData = array_merge($PayPalRequestData, $OrderItems); 
  572.  
  573.  
  574. $log = $PayPalRequestData; 
  575. if(!empty($_POST['wc-paypal_pro_payflow-payment-token']) && $_POST['wc-paypal_pro_payflow-payment-token'] != 'new') { 
  576. $token_id = wc_clean( $_POST['wc-paypal_pro_payflow-payment-token'] ); 
  577. $token = WC_Payment_Tokens::get( $token_id ); 
  578. $PayPalRequestData['origid'] = $token->get_token(); 
  579. $PayPalRequestData['expdate'] = ''; 
  580. } else { 
  581. $log['acct'] = '****'; 
  582. $log['cvv2'] = '****'; 
  583. if (!empty($order->subscription_renewal)) { 
  584. $PayPalRequestData['origid'] = get_post_meta($order_id, '_payment_tokens', true); 
  585. $this->add_log('PayFlow Request: '.print_r( $log, true ) ); 
  586. $PayPalResult = $PayPal->ProcessTransaction(apply_filters('angelleye_woocommerce_paypal_pro_payflow_process_transaction_request_args', $PayPalRequestData)); 
  587.  
  588. /** 
  589. * cURL Error Handling #146 
  590. * @since 1.1.8 
  591. */ 
  592.  
  593. AngellEYE_Gateway_Paypal::angelleye_paypal_for_woocommerce_curl_error_handler($PayPalResult, $methos_name = 'do_payment', $gateway = 'PayPal Payments Pro 2.0 (PayFlow)', $this->error_email_notify); 
  594.  
  595.  
  596. $this->add_log('PayFlow Endpoint: ' . $PayPal->APIEndPoint); 
  597. $this->add_log('PayFlow Response: ' . print_r($PayPalResult, true)); 
  598.  
  599.  
  600. /** 
  601. * Error check 
  602. */ 
  603. if (empty($PayPalResult['RAWRESPONSE'])) { 
  604. $fc_empty_response = apply_filters( 'ae_pppf_paypal_response_empty_message', __('Empty PayPal response.', 'paypal-for-woocommerce'), $PayPalResult ); 
  605. throw new Exception( $fc_empty_response ); 
  606.  
  607. /** 
  608. * Check for errors or fraud filter warnings and proceed accordingly. 
  609. */ 
  610. if (isset($PayPalResult['RESULT']) && ($PayPalResult['RESULT'] == 0 || $PayPalResult['RESULT'] == 126)) { 
  611. // Add order note 
  612. if ($PayPalResult['RESULT'] == 126) { 
  613. $order->add_order_note( $PayPalResult['RESPMSG']); 
  614. $order->add_order_note( $PayPalResult['PREFPSMSG']); 
  615. $order->add_order_note( "The payment was flagged by a fraud filter, please check your PayPal Manager account to review and accept or deny the payment."); 
  616. else 
  617.  
  618. if (isset($PayPalResult['PPREF']) && !empty($PayPalResult['PPREF'])) { 
  619.  
  620. add_post_meta($order_id, 'PPREF', $PayPalResult['PPREF']); 
  621. $order->add_order_note(sprintf(__('PayPal Pro payment completed (PNREF: %s) (PPREF: %s)', 'paypal-for-woocommerce'), $PayPalResult['PNREF'], $PayPalResult['PPREF'])); 
  622. } else { 
  623. $order->add_order_note(sprintf(__('PayPal Pro payment completed (PNREF: %s)', 'paypal-for-woocommerce'), $PayPalResult['PNREF'])); 
  624. /** Checkout Note */ 
  625. if (isset($_POST) && !empty($_POST['order_comments'])) { 
  626. // Update post 37 
  627. $checkout_note = array( 
  628. 'ID' => $order_id,  
  629. 'post_excerpt' => $_POST['order_comments'],  
  630. ); 
  631. wp_update_post($checkout_note); 
  632.  
  633. /** 
  634. * Add order notes for AVS result 
  635. */ 
  636. $avs_address_response_code = isset($PayPalResult['AVSADDR']) ? $PayPalResult['AVSADDR'] : ''; 
  637. $avs_zip_response_code = isset($PayPalResult['AVSZIP']) ? $PayPalResult['AVSZIP'] : ''; 
  638.  
  639. $avs_response_order_note = __('Address Verification Result', 'paypal-for-woocommerce'); 
  640. $avs_response_order_note .= "\n"; 
  641. $avs_response_order_note .= sprintf(__('Address Match: %s', 'paypal-for-woocommerce'), $avs_address_response_code); 
  642. $avs_response_order_note .= "\n"; 
  643. $avs_response_order_note .= sprintf(__('Postal Match: %s', 'paypal-for-woocommerce'), $avs_zip_response_code); 
  644.  
  645. $old_wc = version_compare(WC_VERSION, '3.0', '<'); 
  646. if ($old_wc) { 
  647. update_post_meta($order_id, '_AVSADDR', $avs_address_response_code); 
  648. update_post_meta($order_id, '_AVSZIP', $avs_zip_response_code); 
  649. } else { 
  650. update_post_meta($order->get_id(), '_AVSADDR', $avs_address_response_code); 
  651. update_post_meta($order->get_id(), '_AVSZIP', $avs_zip_response_code); 
  652. $order->add_order_note($avs_response_order_note); 
  653.  
  654. /** 
  655. * Add order notes for CVV2 result 
  656. */ 
  657. $cvv2_response_code = isset($PayPalResult['CVV2MATCH']) ? $PayPalResult['CVV2MATCH'] : ''; 
  658. $cvv2_response_order_note = __('Card Security Code Result', 'paypal-for-woocommerce'); 
  659. $cvv2_response_order_note .= "\n"; 
  660. $cvv2_response_order_note .= sprintf(__('CVV2 Match: %s', 'paypal-for-woocommerce'), $cvv2_response_code); 
  661.  
  662. if ($old_wc) { 
  663. update_post_meta($order_id, '_CVV2MATCH', $cvv2_response_code); 
  664. } else { 
  665. update_post_meta($order->get_id(), '_CVV2MATCH', $cvv2_response_code); 
  666.  
  667. $order->add_order_note($cvv2_response_order_note); 
  668.  
  669. // Payment complete 
  670. //$order->add_order_note("PayPal Result".print_r($PayPalResult, true)); 
  671. do_action('before_save_payment_token', $order_id);  
  672. if(!empty($_POST['wc-paypal_pro_payflow-payment-token']) && $_POST['wc-paypal_pro_payflow-payment-token'] == 'new') { 
  673. if(!empty($_POST['wc-paypal_pro_payflow-new-payment-method']) && $_POST['wc-paypal_pro_payflow-new-payment-method'] == true) { 
  674. $customer_id = $order->get_user_id(); 
  675. $TRANSACTIONID = $PayPalResult['PNREF']; 
  676. $this->are_reference_transactions_enabled($TRANSACTIONID); 
  677. $token = new WC_Payment_Token_CC(); 
  678. $token->set_user_id($customer_id); 
  679. $token->set_token($TRANSACTIONID); 
  680. $token->set_gateway_id($this->id); 
  681. $token->set_card_type(AngellEYE_Utility::card_type_from_account_number($PayPalRequestData['acct'])); 
  682. $token->set_last4(substr($PayPalRequestData['acct'], -4)); 
  683. $token->set_expiry_month( substr( $PayPalRequestData['expdate'], 0, 2 ) ); 
  684. $expiry_year = substr( $PayPalRequestData['expdate'], 2, 3 ); 
  685. if ( strlen( $expiry_year ) == 2 ) { 
  686. $expiry_year = $expiry_year + 2000; 
  687. $token->set_expiry_year( $expiry_year ); 
  688. $save_result = $token->save(); 
  689. if ($save_result) { 
  690. $order->add_payment_token($token); 
  691. if($this->fraud_management_filters == 'place_order_on_hold_for_further_review' && $PayPalResult['RESULT'] == 126) { 
  692. $order->update_status('on-hold', $PayPalResult['RESPMSG']); 
  693. } else { 
  694. $order->payment_complete($PayPalResult['PNREF']); 
  695.  
  696.  
  697. // Remove cart 
  698. WC()->cart->empty_cart(); 
  699.  
  700. // Return thank you page redirect 
  701. return array( 
  702. 'result' => 'success',  
  703. 'redirect' => $this->get_return_url($order) 
  704. ); 
  705. else 
  706. $order->update_status('failed', __('PayPal Pro payment failed. Payment was rejected due to an error: ', 'paypal-for-woocommerce') . '(' . $PayPalResult['RESULT'] . ') ' . '"' . $PayPalResult['RESPMSG'] . '"'); 
  707.  
  708. // Generate error message based on Error Display Type setting 
  709. if($this->error_display_type == 'detailed') 
  710. $fc_error_display_type = __('Payment error:', 'paypal-for-woocommerce') . ' ' . $PayPalResult['RESULT'] . '-' . $PayPalResult['RESPMSG']; 
  711. else 
  712. $fc_error_display_type = __('Payment error:', 'paypal-for-woocommerce') . ' There was a problem processing your payment. Please try another method.'; 
  713. $fc_error_display_type = apply_filters('ae_pppf_error_user_display_message', $fc_error_display_type, $PayPalResult['RESULT'], $PayPalResult['RESPMSG'], $PayPalResult); 
  714. wc_add_notice($fc_error_display_type, "error"); 
  715.  
  716. // Notice admin if has any issue from PayPal 
  717. if($this->error_email_notify) 
  718. $admin_email = get_option("admin_email"); 
  719. $message = __("PayFlow API call failed.", "paypal-for-woocommerce") . "\n\n"; 
  720. $message .= __('Error Code: ', 'paypal-for-woocommerce') . $PayPalResult['RESULT'] . "\n"; 
  721. $message .= __('Detailed Error Message: ', 'paypal-for-woocommerce') . $PayPalResult['RESPMSG']; 
  722. $message .= isset($PayPalResult['PREFPSMSG']) && $PayPalResult['PREFPSMSG'] != '' ? ' - ' . $PayPalResult['PREFPSMSG'] . "\n" : "\n"; 
  723. $message .= __('User IP: ', 'paypal-for-woocommerce') . $this->get_user_ip() . "\n"; 
  724. $message .= __( 'Order ID: ' ).$order_id ."\n"; 
  725. $message .= __( 'Customer Name: ' ).$firstname.' '.$lastname."\n"; 
  726. $message .= __( 'Customer Email: ' ).$billing_email."\n"; 
  727. $message = apply_filters('ae_pppf_error_email_message', $message); 
  728. $subject = apply_filters('ae_pppf_error_email_subject', "PayPal Pro Error Notification"); 
  729. wp_mail($admin_email, $subject, $message); 
  730.  
  731. return; 
  732.  
  733. } catch (Exception $e) { 
  734. if ($order->has_status(array('pending', 'failed'))) { 
  735. $this->send_failed_order_email($order_id); 
  736. $fc_connect_error = apply_filters('angelleye_fc_connect_error', $e->getMessage(), $e); 
  737. wc_add_notice($fc_connect_error, "error"); 
  738. return;  
  739.  
  740.  
  741. public function payment_fields() { 
  742. do_action('angelleye_before_fc_payment_fields', $this); 
  743. if ($this->description) { 
  744. echo '<p>' . wp_kses_post($this->description); 
  745. if($this->testmode == true) 
  746. echo '<p>'; 
  747. _e('NOTICE: SANDBOX (TEST) MODE ENABLED.', 'paypal-for-woocommerce'); 
  748. echo '<br />'; 
  749. _e('For testing purposes you can use the card number 4111111111111111 with any CVC and a valid expiration date.', 'paypal-for-woocommerce'); 
  750. echo '</p>'; 
  751. parent::payment_fields(); 
  752. do_action('payment_fields_saved_payment_methods', $this); 
  753.  
  754. public function paypal_for_woocommerce_paypal_pro_payflow_credit_card_form_expiration_date_selectbox() { 
  755. $form_html = ""; 
  756. $form_html .= '<p class="form-row form-row-first">'; 
  757. $form_html .= '<label for="cc-expire-month">' . __("Expiration Date", 'paypal-for-woocommerce') . '<span class="required">*</span></label>'; 
  758. $form_html .= '<select name="paypal_pro_payflow_card_expiration_month" id="cc-expire-month" class="woocommerce-select woocommerce-cc-month mr5">'; 
  759. $form_html .= '<option value="">' . __('Month', 'paypal-for-woocommerce') . '</option>'; 
  760. $months = array(); 
  761. for ($i = 1; $i <= 12; $i++) : 
  762. $timestamp = mktime(0, 0, 0, $i, 1); 
  763. $months[date('n', $timestamp)] = date_i18n(_x('F', 'Month Names', 'paypal-for-woocommerce'), $timestamp); 
  764. endfor; 
  765. foreach ($months as $num => $name) { 
  766. if($this->credit_card_month_field == 'names') { 
  767. $form_html .= '<option value=' . $num . '>' . $name . '</option>'; 
  768. } else { 
  769. $month_value = ($num < 10) ? '0'.$num : $num; 
  770. $form_html .= '<option value=' . $num . '>' . $month_value . '</option>'; 
  771. $form_html .= '</select>'; 
  772. $form_html .= '<select name="paypal_pro_payflow_card_expiration_year" id="cc-expire-year" class="woocommerce-select woocommerce-cc-year ml5">'; 
  773. $form_html .= '<option value="">' . __('Year', 'paypal-for-woocommerce') . '</option>'; 
  774. for ($i = date('y'); $i <= date('y') + 15; $i++) { 
  775. if($this->credit_card_year_field == 'four_digit') { 
  776. $form_html .= '<option value=' . $i . '>20' . $i . '</option>'; 
  777. } else { 
  778. $form_html .= '<option value=' . $i . '>' . $i . '</option>'; 
  779. $form_html .= '</select>'; 
  780. $form_html .= '</p>'; 
  781. return $form_html; 
  782.  
  783.  
  784. /** 
  785. * Get user's IP address 
  786. */ 
  787. function get_user_ip() { 
  788. return !empty($_SERVER['HTTP_X_FORWARD_FOR']) ? $_SERVER['HTTP_X_FORWARD_FOR'] : $_SERVER['REMOTE_ADDR']; 
  789.  
  790. /** 
  791. * clear_centinel_session function. 
  792. * 
  793. * @access public 
  794. * @return void 
  795. */ 
  796. function clear_centinel_session() { 
  797. unset($_SESSION['Message']); 
  798. foreach ($_SESSION as $key => $value) { 
  799. if (preg_match("/^Centinel_.*/", $key) > 0) { 
  800. unset($_SESSION[$key]); 
  801.  
  802. /** 
  803. * Process a refund if supported 
  804. * @param int $order_id 
  805. * @param float $amount 
  806. * @param string $reason 
  807. * @return bool|wp_error True or false based on success, or a WP_Error object 
  808. */ 
  809. public function process_refund($order_id, $amount = null, $reason = '') { 
  810.  
  811. do_action('angelleye_before_fc_refund', $order_id, $amount, $reason); 
  812.  
  813. $order = wc_get_order($order_id); 
  814. $this->add_log('Begin Refund'); 
  815. $this->add_log('Order ID: ' . print_r($order_id, true)); 
  816. $this->add_log('Transaction ID: ' . print_r($order->get_transaction_id(), true)); 
  817. if (!$order || !$order->get_transaction_id() || !$this->paypal_user || !$this->paypal_password || !$this->paypal_vendor) { 
  818. return false; 
  819.  
  820. /** 
  821. * Check if the PayPal_PayFlow class has already been established. 
  822. */ 
  823. if (!class_exists('Angelleye_PayPal')) { 
  824. require_once('lib/angelleye/paypal-php-library/includes/paypal.class.php'); 
  825. if (!class_exists('Angelleye_PayPal_PayFlow')) { 
  826. require_once('lib/angelleye/paypal-php-library/includes/paypal.payflow.class.php'); 
  827.  
  828. /** 
  829. * Create PayPal_PayFlow object. 
  830. */ 
  831. $PayPalConfig = array( 
  832. 'Sandbox' => $this->testmode,  
  833. 'APIUsername' => $this->paypal_user,  
  834. 'APIPassword' => trim($this->paypal_password),  
  835. 'APIVendor' => $this->paypal_vendor,  
  836. 'APIPartner' => $this->paypal_partner,  
  837. 'Force_tls_one_point_two' => $this->Force_tls_one_point_two 
  838. ); 
  839. $PayPal = new Angelleye_PayPal_PayFlow($PayPalConfig); 
  840. $PayPalRequestData = array( 
  841. 'TENDER' => 'C', // C = credit card, P = PayPal 
  842. 'TRXTYPE' => 'C', // S=Sale, A= Auth, C=Credit, D=Delayed Capture, V=Void 
  843. 'ORIGID' => $order->get_transaction_id(),  
  844. 'AMT' => $amount,  
  845. 'CURRENCY' => version_compare(WC_VERSION, '3.0', '<') ? $order->get_order_currency() : $order->get_currency() 
  846. ); 
  847.  
  848. $PayPalResult = $PayPal->ProcessTransaction($PayPalRequestData); 
  849.  
  850. $PayPalRequest = isset($PayPalResult['RAWREQUEST']) ? $PayPalResult['RAWREQUEST'] : ''; 
  851. $PayPalResponse = isset($PayPalResult['RAWRESPONSE']) ? $PayPalResult['RAWRESPONSE'] : ''; 
  852.  
  853. $this->add_log('Refund Request: ' . print_r($PayPalRequestData, true)); 
  854. $this->add_log('Refund Response: ' . print_r($PayPal->NVPToArray($PayPal->MaskAPIResult($PayPalResponse)), true)); 
  855.  
  856. /** 
  857. * cURL Error Handling #146 
  858. * @since 1.1.8 
  859. */ 
  860.  
  861. AngellEYE_Gateway_Paypal::angelleye_paypal_for_woocommerce_curl_error_handler($PayPalResult, $methos_name = 'Refund Request', $gateway = 'PayPal Payments Pro 2.0 (PayFlow)', $this->error_email_notify); 
  862.  
  863. add_action('angelleye_after_refund', $PayPalResult, $order, $amount, $reason); 
  864. if (isset($PayPalResult['RESULT']) && ($PayPalResult['RESULT'] == 0 || $PayPalResult['RESULT'] == 126)) { 
  865.  
  866. $order->add_order_note('Refund Transaction ID:' . $PayPalResult['PNREF']); 
  867.  
  868. $max_remaining_refund = wc_format_decimal($order->get_total() - $order->get_total_refunded()); 
  869. if (!$max_remaining_refund > 0) { 
  870. $order->update_status('refunded'); 
  871.  
  872. if (ob_get_length()) ob_end_clean(); 
  873. return true; 
  874. }else { 
  875. $fc_refund_error = apply_filters('ae_pppf_refund_error_message', $PayPalResult['RESPMSG'], $PayPalResult); 
  876. return new WP_Error('paypal-error', $fc_refund_error); 
  877. return false; 
  878.  
  879. /** 
  880. * Validate the payment form 
  881. * PayFlow - Empty Card Data Validation Problem #220 
  882. * @since 1.1.7.6 
  883. */ 
  884. public function validate_fields() { 
  885.  
  886. if (isset($_POST['wc-paypal_pro_payflow-payment-token']) && 'new' !== $_POST['wc-paypal_pro_payflow-payment-token']) { 
  887. $token_id = wc_clean($_POST['wc-paypal_pro_payflow-payment-token']); 
  888. $token = WC_Payment_Tokens::get($token_id); 
  889. if ($token->get_user_id() !== get_current_user_id()) { 
  890. throw new Exception(__('Error processing checkout. Please try again.', 'paypal-for-woocommerce')); 
  891. } else { 
  892. return true; 
  893. $card_number = isset($_POST['paypal_pro_payflow-card-number']) ? wc_clean($_POST['paypal_pro_payflow-card-number']) : ''; 
  894. $card_cvc = isset($_POST['paypal_pro_payflow-card-cvc']) ? wc_clean($_POST['paypal_pro_payflow-card-cvc']) : ''; 
  895. $card_exp_year = isset($_POST['paypal_pro_payflow_card_expiration_year']) ? wc_clean($_POST['paypal_pro_payflow_card_expiration_year']) : ''; 
  896. $card_exp_month = isset($_POST['paypal_pro_payflow_card_expiration_month']) ? wc_clean($_POST['paypal_pro_payflow_card_expiration_month']) : ''; 
  897.  
  898.  
  899. // Format values 
  900. $card_number = str_replace(array(' ', '-'), '', $card_number); 
  901.  
  902. if (strlen($card_exp_year) == 4) { 
  903. $card_exp_year = $card_exp_year - 2000; 
  904.  
  905. do_action('before_angelleye_pro_payflow_checkout_validate_fields', $card_number, $card_cvc, $card_exp_month, $card_exp_year); 
  906.  
  907. // Check card security code 
  908.  
  909. if (!ctype_digit($card_cvc)) { 
  910. wc_add_notice(__('Card security code is invalid (only digits are allowed)', 'paypal-for-woocommerce'), "error"); 
  911. return false; 
  912.  
  913. // Check card expiration data 
  914.  
  915. if (!ctype_digit($card_exp_month) || !ctype_digit($card_exp_year) || $card_exp_month > 12 || $card_exp_month < 1 || $card_exp_year < date('y') || $card_exp_year > date('y') + 20) { 
  916. wc_add_notice(__('Card expiration date is invalid', 'paypal-for-woocommerce'), "error"); 
  917. return false; 
  918.  
  919. // Check card number 
  920.  
  921. if (empty($card_number) || !ctype_digit($card_number)) { 
  922. wc_add_notice(__('Card number is invalid', 'paypal-for-woocommerce'), "error"); 
  923. return false; 
  924.  
  925. do_action('after_angelleye_pro_payflow_checkout_validate_fields', $card_number, $card_cvc, $card_exp_month, $card_exp_year); 
  926.  
  927. return true; 
  928.  
  929. public function field_name($name) { 
  930. return ' name="' . esc_attr($this->id . '-' . $name) . '" '; 
  931.  
  932. public function angelleye_paypal_pro_payflow_credit_card_form_fields($default_fields, $current_gateway_id) { 
  933. if ($current_gateway_id == $this->id) { 
  934. $fields = array( 
  935. 'card-number-field' => '<p class="form-row form-row-wide"> 
  936. <label for="' . esc_attr($this->id) . '-card-number">' . __('Card number', 'woocommerce') . ' <span class="required">*</span></label> 
  937. <input id="' . esc_attr($this->id) . '-card-number" class="input-text wc-credit-card-form-card-number" inputmode="numeric" autocomplete="cc-number" autocorrect="no" autocapitalize="no" spellcheck="no" type="tel" placeholder="•••• •••• •••• ••••" ' . $this->field_name('card-number') . ' /> 
  938. </p>',  
  939. 'card-expiry-field' => $this->paypal_for_woocommerce_paypal_pro_payflow_credit_card_form_expiration_date_selectbox(),  
  940. '<p class="form-row form-row-last"> 
  941. <label for="' . esc_attr($this->id) . '-card-cvc">' . __('Card Security Code', 'woocommerce') . ' <span class="required">*</span></label> 
  942. <input id="' . esc_attr($this->id) . '-card-cvc" class="input-text wc-credit-card-form-card-cvc" inputmode="numeric" autocomplete="off" autocorrect="no" autocapitalize="no" spellcheck="no" type="tel" maxlength="4" placeholder="' . esc_attr__('CVC', 'woocommerce') . '" ' . $this->field_name('card-cvc') . ' style="width:100px" /> 
  943. </p>' 
  944. ); 
  945. return $fields; 
  946. } else { 
  947. return $default_fields; 
  948.  
  949. public function angelleye_woocommerce_credit_card_form_start($current_id) { 
  950. if ($this->enable_cardholder_first_last_name && $current_id == $this->id) { 
  951. $fields['card-cardholder-first'] = '<p class="form-row form-row-first"> 
  952. <label for="' . esc_attr($this->id) . '-card-cvc">' . __('Cardholder First Name', 'paypal-for-woocommerce') . '</label> 
  953. <input id="' . esc_attr($this->id) . '-card-cvc" class="input-text wc-credit-card-form-cardholder" type="text" autocomplete="off" placeholder="' . esc_attr__('First Name', 'paypal-for-woocommerce') . '" name="' . $current_id . '-card-cardholder-first' . '" /> 
  954. </p>'; 
  955. $fields['card-cardholder-last'] = '<p class="form-row form-row-last"> 
  956. <label for="' . esc_attr($this->id) . '-card-startdate">' . __('Cardholder Last Name', 'paypal-for-woocommerce') . '</label> 
  957. <input id="' . esc_attr($this->id) . '-card-startdate" class="input-text wc-credit-card-form-cardholder" type="text" autocomplete="off" placeholder="' . __('Last Name', 'paypal-for-woocommerce') . '" name="' . $current_id . '-card-cardholder-last' . '" /> 
  958. </p>'; 
  959.  
  960. foreach ($fields as $field) { 
  961. echo $field; 
  962. public function get_posted_card() { 
  963. try { 
  964. $card_number = isset($_POST['paypal_pro_payflow-card-number']) ? wc_clean($_POST['paypal_pro_payflow-card-number']) : ''; 
  965. $card_cvc = isset($_POST['paypal_pro_payflow-card-cvc']) ? wc_clean($_POST['paypal_pro_payflow-card-cvc']) : ''; 
  966. $card_exp_year = isset($_POST['paypal_pro_payflow_card_expiration_year']) ? wc_clean($_POST['paypal_pro_payflow_card_expiration_year']) : ''; 
  967. $card_exp_month = isset($_POST['paypal_pro_payflow_card_expiration_month']) ? wc_clean($_POST['paypal_pro_payflow_card_expiration_month']) : ''; 
  968. $card_number = str_replace(array(' ', '-'), '', $card_number); 
  969. $card_type = AngellEYE_Utility::card_type_from_account_number($card_number); 
  970. if ($card_type == 'amex' && (get_woocommerce_currency() != 'USD' && get_woocommerce_currency() != 'AUD')) { 
  971. throw new Exception(__('Your processor is unable to process the Card Type in the currency requested. Please try another card type', 'paypal-for-woocommerce')); 
  972. if (strlen($card_exp_year) == 4) { 
  973. $card_exp_year = $card_exp_year - 2000; 
  974. $card_exp_month = (int) $card_exp_month; 
  975. if ($card_exp_month < 10) { 
  976. $card_exp_month = '0' . $card_exp_month; 
  977. return (object) array( 
  978. 'number' => $card_number,  
  979. 'type' => '',  
  980. 'cvc' => $card_cvc,  
  981. 'exp_month' => $card_exp_month,  
  982. 'exp_year' => $card_exp_year,  
  983. 'start_month' => '',  
  984. 'start_year' => '' 
  985. ); 
  986. } catch (Exception $ex) { 
  987.  
  988.  
  989.  
  990. public function add_payment_method() { 
  991. $customer_id = get_current_user_id(); 
  992. if (!class_exists('Angelleye_PayPal')) { 
  993. require_once('lib/angelleye/paypal-php-library/includes/paypal.class.php'); 
  994. if (!class_exists('Angelleye_PayPal_PayFlow')) { 
  995. require_once('lib/angelleye/paypal-php-library/includes/paypal.payflow.class.php'); 
  996. $PayPalConfig = array( 
  997. 'Sandbox' => $this->testmode,  
  998. 'APIUsername' => $this->paypal_user,  
  999. 'APIPassword' => trim($this->paypal_password),  
  1000. 'APIVendor' => $this->paypal_vendor,  
  1001. 'APIPartner' => $this->paypal_partner,  
  1002. 'Force_tls_one_point_two' => $this->Force_tls_one_point_two 
  1003. ); 
  1004. $PayPal = new Angelleye_PayPal_PayFlow($PayPalConfig); 
  1005. $this->validate_fields(); 
  1006. $card = $this->get_posted_card(); 
  1007.  
  1008. $billtofirstname = (get_user_meta($customer_id, 'billing_first_name', true)) ? get_user_meta($customer_id, 'billing_first_name', true) : get_user_meta($customer_id, 'shipping_first_name', true); 
  1009. $billtolastname = (get_user_meta($customer_id, 'billing_last_name', true)) ? get_user_meta($customer_id, 'billing_last_name', true) : get_user_meta($customer_id, 'shipping_last_name', true); 
  1010. $billtostate = (get_user_meta($customer_id, 'billing_state', true)) ? get_user_meta($customer_id, 'billing_state', true) : get_user_meta($customer_id, 'shipping_state', true); 
  1011. $billtocountry = (get_user_meta($customer_id, 'billing_country', true)) ? get_user_meta($customer_id, 'billing_country', true) : get_user_meta($customer_id, 'shipping_country', true); 
  1012. $billtozip = (get_user_meta($customer_id, 'billing_postcode', true)) ? get_user_meta($customer_id, 'billing_postcode', true) : get_user_meta($customer_id, 'shipping_postcode', true); 
  1013.  
  1014. $PayPalRequestData = array( 
  1015. 'tender' => 'C',  
  1016. 'trxtype' => 'A',  
  1017. 'acct' => $card->number,  
  1018. 'expdate' => $card->exp_month . $card->exp_year,  
  1019. 'amt' => '0.00',  
  1020. 'currency' => get_woocommerce_currency(),  
  1021. 'cvv2' => $card->cvc,  
  1022. 'orderid' => '',  
  1023. 'orderdesc' => '',  
  1024. 'billtoemail' => '',  
  1025. 'billtophonenum' => '',  
  1026. 'billtofirstname' => $billtofirstname,  
  1027. 'billtomiddlename' => '',  
  1028. 'billtolastname' => $billtolastname,  
  1029. 'billtostreet' => '',  
  1030. 'billtocity' => '',  
  1031. 'billtostate' => $billtostate,  
  1032. 'billtozip' => $billtozip,  
  1033. 'billtocountry' => $billtocountry,  
  1034. 'origid' => '',  
  1035. 'custref' => '',  
  1036. 'custcode' => '',  
  1037. 'custip' => $this->get_user_ip(),  
  1038. 'invnum' => '',  
  1039. 'ponum' => '',  
  1040. 'starttime' => '',  
  1041. 'endtime' => '',  
  1042. 'securetoken' => '',  
  1043. 'partialauth' => '',  
  1044. 'authcode' => '' 
  1045. ); 
  1046. $PayPalResult = $PayPal->ProcessTransaction(apply_filters('angelleye_woocommerce_paypal_express_set_express_checkout_request_args', $PayPalRequestData)); 
  1047. if (isset($PayPalResult['RESULT']) && ($PayPalResult['RESULT'] == 0 || $PayPalResult['RESULT'] == 126)) { 
  1048. if ($PayPalResult['RESULT'] == 126) { 
  1049. wc_add_notice(__('The payment was flagged by a fraud filter, please check your PayPal Manager account to review and accept or deny the payment.', 'woocommerce'), 'error'); 
  1050. wp_redirect(wc_get_account_endpoint_url('payment-methods')); 
  1051. exit(); 
  1052. } else { 
  1053. $customer_id = get_current_user_id(); 
  1054. $TRANSACTIONID = $PayPalResult['PNREF']; 
  1055. $this->are_reference_transactions_enabled($TRANSACTIONID); 
  1056. $token = new WC_Payment_Token_CC(); 
  1057. $token->set_user_id($customer_id); 
  1058. $token->set_token($TRANSACTIONID); 
  1059. $token->set_gateway_id($this->id); 
  1060. $token->set_card_type(AngellEYE_Utility::card_type_from_account_number($PayPalRequestData['acct'])); 
  1061. $token->set_last4(substr($PayPalRequestData['acct'], -4)); 
  1062. $token->set_expiry_month( substr( $PayPalRequestData['expdate'], 0, 2 ) ); 
  1063. $expiry_year = substr( $PayPalRequestData['expdate'], 2, 3 ); 
  1064. if ( strlen( $expiry_year ) == 2 ) { 
  1065. $expiry_year = $expiry_year + 2000; 
  1066. $token->set_expiry_year( $expiry_year ); 
  1067. $save_result = $token->save(); 
  1068. if ($save_result) { 
  1069. return array( 
  1070. 'result' => 'success',  
  1071. 'redirect' => wc_get_account_endpoint_url('payment-methods') 
  1072. ); 
  1073. } else { 
  1074. wc_add_notice(__($PayPalResult['RESPMSG'], 'woocommerce'), 'error'); 
  1075. wp_redirect(wc_get_account_endpoint_url('payment-methods')); 
  1076. exit(); 
  1077. public function process_subscription_payment($order, $amount) { 
  1078. $order_id = version_compare( WC_VERSION, '3.0', '<' ) ? $order->id : $order->get_id(); 
  1079. if (!class_exists('Angelleye_PayPal')) { 
  1080. require_once('lib/angelleye/paypal-php-library/includes/paypal.class.php'); 
  1081. if (!class_exists('Angelleye_PayPal_PayFlow')) { 
  1082. require_once('lib/angelleye/paypal-php-library/includes/paypal.payflow.class.php'); 
  1083. $PayPalConfig = array( 
  1084. 'Sandbox' => $this->testmode,  
  1085. 'APIUsername' => $this->paypal_user,  
  1086. 'APIPassword' => trim($this->paypal_password),  
  1087. 'APIVendor' => $this->paypal_vendor,  
  1088. 'APIPartner' => $this->paypal_partner,  
  1089. 'Force_tls_one_point_two' => $this->Force_tls_one_point_two 
  1090. ); 
  1091. $PayPal = new Angelleye_PayPal_PayFlow($PayPalConfig); 
  1092. try { 
  1093.  
  1094. if(!empty($_POST['paypal_pro_payflow-card-cardholder-first'])) { 
  1095. $firstname = wc_clean($_POST['paypal_pro_payflow-card-cardholder-first']); 
  1096. } else { 
  1097. $firstname = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_first_name : $order->get_billing_first_name(); 
  1098. }  
  1099.  
  1100. if(!empty($_POST['paypal_pro_payflow-card-cardholder-last'])) { 
  1101. $lastname = wc_clean($_POST['paypal_pro_payflow-card-cardholder-last']); 
  1102. } else { 
  1103. $lastname = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_last_name : $order->get_billing_last_name(); 
  1104.  
  1105. $billing_address_1 = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_address_1 : $order->get_billing_address_1(); 
  1106. $billing_address_2 = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_address_2 : $order->get_billing_address_2(); 
  1107. $billing_city = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_city : $order->get_billing_city(); 
  1108. $billing_postcode = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_postcode : $order->get_billing_postcode(); 
  1109. $billing_country = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_country : $order->get_billing_country(); 
  1110. $billing_state = version_compare( WC_VERSION, '3.0', '<' ) ? $order->billing_state : $order->get_billing_state(); 
  1111. $billing_email = version_compare( WC_VERSION, '3.0', '<' ) ? $billing_email : $order->get_billing_email(); 
  1112.  
  1113. $customer_note = $order->customer_note ? substr(preg_replace("/[^A-Za-z0-9 ]/", "", $order->customer_note), 0, 256) : ''; 
  1114. $PayPalRequestData = array( 
  1115. 'tender' => 'C', // Required. The method of payment. Values are: A = ACH, C = Credit Card, D = Pinless Debit, K = Telecheck, P = PayPal 
  1116. 'trxtype' => ($this->payment_action == 'Authorization' || $order->get_total() == 0 ) ? 'A' : 'S', // Required. Indicates the type of transaction to perform. Values are: A = Authorization, B = Balance Inquiry, C = Credit, D = Delayed Capture, F = Voice Authorization, I = Inquiry, L = Data Upload, N = Duplicate Transaction, S = Sale, V = Void 
  1117. 'amt' => AngellEYE_Gateway_Paypal::number_format($order->get_total()), // Required. Amount of the transaction. Must have 2 decimal places. 
  1118. 'currency' => get_woocommerce_currency(), // 
  1119. 'comment1' => apply_filters('ae_pppf_custom_parameter', $customer_note, $order), // Merchant-defined value for reporting and auditing purposes. 128 char max 
  1120. 'comment2' => apply_filters('ae_pppf_comment2_parameter', '', $order), // Merchant-defined value for reporting and auditing purposes. 128 char max 
  1121. 'recurring' => '', // Identifies the transaction as recurring. One of the following values: Y = transaction is recurring, N = transaction is not recurring. 
  1122. 'swipe' => '', // Required for card-present transactions. Used to pass either Track 1 or Track 2, but not both. 
  1123. 'orderid' => $this->invoice_id_prefix . preg_replace("/[^a-zA-Z0-9]/", "", $order->get_order_number()), // Checks for duplicate order. If you pass orderid in a request and pass it again in the future the response returns DUPLICATE=2 along with the orderid 
  1124. 'orderdesc' => 'Order ' . $order->get_order_number() . ' on ' . get_bloginfo('name'), // 
  1125. 'billtoemail' => $billing_email, // Account holder's email address. 
  1126. 'billtophonenum' => '', // Account holder's phone number. 
  1127. 'billtostreet' => $billing_address_1 . ' ' . $billing_address_2, // The cardholder's street address (number and street name). 150 char max 
  1128. 'billtocity' => $billing_city, // Bill to city. 45 char max 
  1129. 'billtostate' => $billing_state, // Bill to state. 
  1130. 'billtozip' => $billing_postcode, // Account holder's 5 to 9 digit postal code. 9 char max. No dashes, spaces, or non-numeric characters 
  1131. 'billtocountry' => $billing_country, // Bill to Country. 3 letter country code. 
  1132. 'origid' => '', // Required by some transaction types. ID of the original transaction referenced. The PNREF parameter returns this ID, and it appears as the Transaction ID in PayPal Manager reports. 
  1133. 'custref' => '', // 
  1134. 'custcode' => '', // 
  1135. 'custip' => $this->get_user_ip(), // 
  1136. 'invnum' => $this->invoice_id_prefix . str_replace("#", "", $order->get_order_number()), // 
  1137. 'ponum' => '', // 
  1138. 'starttime' => '', // For inquiry transaction when using CUSTREF to specify the transaction. 
  1139. 'endtime' => '', // For inquiry transaction when using CUSTREF to specify the transaction. 
  1140. 'securetoken' => '', // Required if using secure tokens. A value the Payflow server created upon your request for storing transaction data. 32 char 
  1141. 'partialauth' => '', // Required for partial authorizations. Set to Y to submit a partial auth. 
  1142. 'authcode' => '' // Rrequired for voice authorizations. Returned only for approved voice authorization transactions. AUTHCODE is the approval code received over the phone from the processing network. 6 char max 
  1143. ); 
  1144. /** 
  1145. * Shipping info 
  1146. */ 
  1147.  
  1148. $shipping_first_name = version_compare( WC_VERSION, '3.0', '<' ) ? $order->shipping_first_name : $order->get_shipping_first_name(); 
  1149. $shipping_last_name = version_compare( WC_VERSION, '3.0', '<' ) ? $order->shipping_last_name : $order->get_shipping_last_name(); 
  1150. $shipping_address_1 = version_compare( WC_VERSION, '3.0', '<' ) ? $order->shipping_address_1 : $order->get_shipping_address_1(); 
  1151. $shipping_address_2 = version_compare( WC_VERSION, '3.0', '<' ) ? $order->shipping_address_2 : $order->get_shipping_address_2(); 
  1152. $shipping_city = version_compare( WC_VERSION, '3.0', '<' ) ? $order->shipping_city : $order->get_shipping_city(); 
  1153. $shipping_postcode = version_compare( WC_VERSION, '3.0', '<' ) ? $order->shipping_postcode : $order->get_shipping_postcode(); 
  1154. $shipping_country = version_compare( WC_VERSION, '3.0', '<' ) ? $order->shipping_country : $order->get_shipping_country(); 
  1155. $shipping_state = version_compare( WC_VERSION, '3.0', '<' ) ? $order->shipping_state : $order->get_shipping_state(); 
  1156.  
  1157. if ($shipping_address_1) { 
  1158. $PayPalRequestData['SHIPTOFIRSTNAME'] = $shipping_first_name; 
  1159. $PayPalRequestData['SHIPTOLASTNAME'] = $shipping_last_name; 
  1160. $PayPalRequestData['SHIPTOSTREET'] = $shipping_address_1 . ' ' . $shipping_address_2; 
  1161. $PayPalRequestData['SHIPTOCITY'] = $shipping_city; 
  1162. $PayPalRequestData['SHIPTOSTATE'] = $shipping_state; 
  1163. $PayPalRequestData['SHIPTOCOUNTRY'] = $shipping_country; 
  1164. $PayPalRequestData['SHIPTOZIP'] = $shipping_postcode; 
  1165. $PaymentData = $this->calculation_angelleye->order_calculation($order_id); 
  1166. $OrderItems = array(); 
  1167. if ($this->send_items) { 
  1168. $item_loop = 0; 
  1169. foreach ($PaymentData['order_items'] as $_item) { 
  1170. $Item['L_NUMBER' . $item_loop] = $_item['number']; 
  1171. $Item['L_NAME' . $item_loop] = $_item['name']; 
  1172. $Item['L_COST' . $item_loop] = $_item['amt']; 
  1173. $Item['L_QTY' . $item_loop] = $_item['qty']; 
  1174. if ($_item['number']) { 
  1175. $Item['L_SKU' . $item_loop] = $_item['number']; 
  1176. $OrderItems = array_merge($OrderItems, $Item); 
  1177. $item_loop++; 
  1178. /** 
  1179. * Shipping/tax/item amount 
  1180. */ 
  1181. $PayPalRequestData['taxamt'] = $PaymentData['taxamt']; 
  1182. $PayPalRequestData['freightamt'] = $PaymentData['shippingamt']; 
  1183. $PayPalRequestData['ITEMAMT'] = $PaymentData['itemamt']; 
  1184. if ($this->send_items) { 
  1185. $PayPalRequestData = array_merge($PayPalRequestData, $OrderItems); 
  1186. if (!empty($order->subscription_renewal)) { 
  1187. $PayPalRequestData['origid'] = get_post_meta($order_id, '_payment_tokens_id', true); 
  1188. $PayPalResult = $PayPal->ProcessTransaction($PayPalRequestData); 
  1189.  
  1190. $this->add_log('PayFlow Endpoint: ' . $PayPal->APIEndPoint); 
  1191. $this->add_log('PayFlow Response: ' . print_r($PayPalResult, true)); 
  1192.  
  1193. if (empty($PayPalResult['RAWRESPONSE'])) { 
  1194. $fc_empty_response = apply_filters('ae_pppf_paypal_response_empty_message', __('Empty PayPal response.', 'paypal-for-woocommerce'), $PayPalResult); 
  1195. throw new Exception($fc_empty_response); 
  1196. if (isset($PayPalResult['RESULT']) && ($PayPalResult['RESULT'] == 0 || $PayPalResult['RESULT'] == 126)) { 
  1197. if ($PayPalResult['RESULT'] == 126) { 
  1198. $order->add_order_note($PayPalResult['RESPMSG']); 
  1199. $order->add_order_note($PayPalResult['PREFPSMSG']); 
  1200. $order->add_order_note("The payment was flagged by a fraud filter, please check your PayPal Manager account to review and accept or deny the payment."); 
  1201. } else { 
  1202. if (isset($PayPalResult['PPREF']) && !empty($PayPalResult['PPREF'])) { 
  1203. add_post_meta($order_id, 'PPREF', $PayPalResult['PPREF']); 
  1204. $order->add_order_note(sprintf(__('PayPal Pro payment completed (PNREF: %s) (PPREF: %s)', 'paypal-for-woocommerce'), $PayPalResult['PNREF'], $PayPalResult['PPREF'])); 
  1205. } else { 
  1206. $order->add_order_note(sprintf(__('PayPal Pro payment completed (PNREF: %s)', 'paypal-for-woocommerce'), $PayPalResult['PNREF'])); 
  1207. /** Checkout Note */ 
  1208. if (isset($_POST) && !empty($_POST['order_comments'])) { 
  1209. $checkout_note = array( 
  1210. 'ID' => $order_id,  
  1211. 'post_excerpt' => $_POST['order_comments'],  
  1212. ); 
  1213. wp_update_post($checkout_note); 
  1214. /** 
  1215. * Add order notes for AVS result 
  1216. */ 
  1217. $avs_address_response_code = isset($PayPalResult['AVSADDR']) ? $PayPalResult['AVSADDR'] : ''; 
  1218. $avs_zip_response_code = isset($PayPalResult['AVSZIP']) ? $PayPalResult['AVSZIP'] : ''; 
  1219. $avs_response_order_note = __('Address Verification Result', 'paypal-for-woocommerce'); 
  1220. $avs_response_order_note .= "\n"; 
  1221. $avs_response_order_note .= sprintf(__('Address Match: %s', 'paypal-for-woocommerce'), $avs_address_response_code); 
  1222. $avs_response_order_note .= "\n"; 
  1223. $avs_response_order_note .= sprintf(__('Postal Match: %s', 'paypal-for-woocommerce'), $avs_zip_response_code); 
  1224. $order->add_order_note($avs_response_order_note); 
  1225. /** 
  1226. * Add order notes for CVV2 result 
  1227. */ 
  1228. $cvv2_response_code = isset($PayPalResult['CVV2MATCH']) ? $PayPalResult['CVV2MATCH'] : ''; 
  1229. $cvv2_response_order_note = __('Card Security Code Result', 'paypal-for-woocommerce'); 
  1230. $cvv2_response_order_note .= "\n"; 
  1231. $cvv2_response_order_note .= sprintf(__('CVV2 Match: %s', 'paypal-for-woocommerce'), $cvv2_response_code); 
  1232. $order->add_order_note($cvv2_response_order_note); 
  1233. $order->payment_complete($PayPalResult['PNREF']); 
  1234. $this->save_payment_token($order, $PayPalResult['PNREF']); 
  1235. $this->are_reference_transactions_enabled($PayPalResult['PNREF']); 
  1236. if (!empty($order->subscription_renewal)) { 
  1237. return true; 
  1238. } else { 
  1239. $order->update_status('failed', __('PayPal Pro payment failed. Payment was rejected due to an error: ', 'paypal-for-woocommerce') . '(' . $PayPalResult['RESULT'] . ') ' . '"' . $PayPalResult['RESPMSG'] . '"'); 
  1240. if ($this->error_email_notify) { 
  1241. $admin_email = get_option("admin_email"); 
  1242. $message = __("PayFlow API call failed.", "paypal-for-woocommerce") . "\n\n"; 
  1243. $message .= __('Error Code: ', 'paypal-for-woocommerce') . $PayPalResult['RESULT'] . "\n"; 
  1244. $message .= __('Detailed Error Message: ', 'paypal-for-woocommerce') . $PayPalResult['RESPMSG']; 
  1245. $message .= isset($PayPalResult['PREFPSMSG']) && $PayPalResult['PREFPSMSG'] != '' ? ' - ' . $PayPalResult['PREFPSMSG'] . "\n" : "\n"; 
  1246. $message .= __('User IP: ', 'paypal-for-woocommerce') . $this->get_user_ip() . "\n"; 
  1247. $message .= __('Order ID: ') . $order_id . "\n"; 
  1248. $message .= __('Customer Name: ') . $firstname . ' ' . $lastname . "\n"; 
  1249. $message .= __('Customer Email: ') . $billing_email . "\n"; 
  1250. $message = apply_filters('ae_pppf_error_email_message', $message); 
  1251. $subject = apply_filters('ae_pppf_error_email_subject', "PayPal Pro Error Notification"); 
  1252. wp_mail($admin_email, $subject, $message); 
  1253. return; 
  1254. } catch (Exception $e) { 
  1255. if ($order->has_status(array('pending', 'failed'))) { 
  1256. $this->send_failed_order_email($order_id); 
  1257. return; 
  1258.  
  1259. public function are_reference_transactions_enabled($token_id) { 
  1260. if ($this->supports('tokenization') && class_exists('WC_Subscriptions_Order')) { 
  1261. $are_reference_transactions_enabled = get_option('are_reference_transactions_enabled', 'no'); 
  1262. if ($are_reference_transactions_enabled == 'no') { 
  1263. $customer_id = get_current_user_id(); 
  1264. if (!class_exists('Angelleye_PayPal')) { 
  1265. require_once('lib/angelleye/paypal-php-library/includes/paypal.class.php'); 
  1266. if (!class_exists('Angelleye_PayPal_PayFlow')) { 
  1267. require_once('lib/angelleye/paypal-php-library/includes/paypal.payflow.class.php'); 
  1268. $PayPalConfig = array( 
  1269. 'Sandbox' => $this->testmode,  
  1270. 'APIUsername' => $this->paypal_user,  
  1271. 'APIPassword' => trim($this->paypal_password),  
  1272. 'APIVendor' => $this->paypal_vendor,  
  1273. 'APIPartner' => $this->paypal_partner,  
  1274. 'Force_tls_one_point_two' => $this->Force_tls_one_point_two 
  1275. ); 
  1276. $PayPal = new Angelleye_PayPal_PayFlow($PayPalConfig); 
  1277. $this->validate_fields(); 
  1278. $card = $this->get_posted_card(); 
  1279. $billtofirstname = (get_user_meta($customer_id, 'billing_first_name', true)) ? get_user_meta($customer_id, 'billing_first_name', true) : get_user_meta($customer_id, 'shipping_first_name', true); 
  1280. $billtolastname = (get_user_meta($customer_id, 'billing_last_name', true)) ? get_user_meta($customer_id, 'billing_last_name', true) : get_user_meta($customer_id, 'shipping_last_name', true); 
  1281. $billtostate = (get_user_meta($customer_id, 'billing_state', true)) ? get_user_meta($customer_id, 'billing_state', true) : get_user_meta($customer_id, 'shipping_state', true); 
  1282. $billtocountry = (get_user_meta($customer_id, 'billing_country', true)) ? get_user_meta($customer_id, 'billing_country', true) : get_user_meta($customer_id, 'shipping_country', true); 
  1283. $billtozip = (get_user_meta($customer_id, 'billing_postcode', true)) ? get_user_meta($customer_id, 'billing_postcode', true) : get_user_meta($customer_id, 'shipping_postcode', true); 
  1284. $PayPalRequestData = array( 
  1285. 'tender' => 'C',  
  1286. 'trxtype' => 'A',  
  1287. 'acct' => '',  
  1288. 'expdate' => '',  
  1289. 'amt' => '0.00',  
  1290. 'currency' => get_woocommerce_currency(),  
  1291. 'cvv2' => '',  
  1292. 'orderid' => '',  
  1293. 'orderdesc' => '',  
  1294. 'billtoemail' => '',  
  1295. 'billtophonenum' => '',  
  1296. 'billtofirstname' => $billtofirstname,  
  1297. 'billtomiddlename' => '',  
  1298. 'billtolastname' => $billtolastname,  
  1299. 'billtostreet' => '',  
  1300. 'billtocity' => '',  
  1301. 'billtostate' => $billtostate,  
  1302. 'billtozip' => $billtozip,  
  1303. 'billtocountry' => $billtocountry,  
  1304. 'origid' => $token_id,  
  1305. 'custref' => '',  
  1306. 'custcode' => '',  
  1307. 'custip' => $this->get_user_ip(),  
  1308. 'invnum' => '',  
  1309. 'ponum' => '',  
  1310. 'starttime' => '',  
  1311. 'endtime' => '',  
  1312. 'securetoken' => '',  
  1313. 'partialauth' => '',  
  1314. 'authcode' => '' 
  1315. ); 
  1316. $PayPalResult = $PayPal->ProcessTransaction($PayPalRequestData); 
  1317. if (isset($PayPalResult['RESULT']) && ($PayPalResult['RESULT'] == 117)) { 
  1318. $admin_email = get_option("admin_email"); 
  1319. $message = __("PayPal Reference Transactions are not enabled on your account, some subscription management features are not enabled", "paypal-for-woocommerce") . "\n\n"; 
  1320. $message .= __("PayFlow API call failed.", "paypal-for-woocommerce") . "\n\n"; 
  1321. $message .= __('Error Code: ', 'paypal-for-woocommerce') . $PayPalResult['RESULT'] . "\n"; 
  1322. $message .= __('Detailed Error Message: ', 'paypal-for-woocommerce') . $PayPalResult['RESPMSG']; 
  1323. $message .= isset($PayPalResult['PREFPSMSG']) && $PayPalResult['PREFPSMSG'] != '' ? ' - ' . $PayPalResult['PREFPSMSG'] . "\n" : "\n"; 
  1324. $message .= __('User IP: ', 'paypal-for-woocommerce') . $this->get_user_ip() . "\n"; 
  1325. $message = apply_filters('ae_pppf_error_email_message', $message); 
  1326. $subject = apply_filters('ae_pppf_error_email_subject', "PayPal Payments Pro (PayFlow) Error Notification"); 
  1327. wp_mail($admin_email, $subject, $message); 
  1328. return false; 
  1329. } else { 
  1330. update_option('are_reference_transactions_enabled', 'yes'); 
  1331. public function send_failed_order_email($order_id) { 
  1332. $emails = WC()->mailer()->get_emails(); 
  1333. if (!empty($emails) && !empty($order_id)) { 
  1334. $emails['WC_Email_Failed_Order']->trigger($order_id); 
  1335.  
  1336. public function save_payment_token($order, $payment_tokens_id) { 
  1337. // Store source in the order 
  1338. if (!empty($payment_tokens_id)) { 
  1339. update_post_meta($order->id, '_payment_tokens_id', $payment_tokens_id); 
  1340. return $settings; 
  1341.  
  1342.  
  1343. public function angelleye_paypal_pro_payflow_encrypt_gateway_api($settings) { 
  1344. if( !empty($settings['sandbox_paypal_partner'])) { 
  1345. $paypal_partner = $settings['sandbox_paypal_partner']; 
  1346. } else { 
  1347. $paypal_partner = $settings['paypal_partner']; 
  1348. if(strlen($paypal_partner) > 28 ) { 
  1349. return $settings; 
  1350.  
  1351. if( !empty($settings['is_encrypt']) ) { 
  1352. $gateway_settings_keys = array('sandbox_paypal_vendor', 'sandbox_paypal_password', 'sandbox_paypal_user', 'sandbox_paypal_partner', 'paypal_vendor', 'paypal_password', 'paypal_user', 'paypal_partner'); 
  1353. foreach ($gateway_settings_keys as $gateway_settings_key => $gateway_settings_value) { 
  1354. if( !empty( $settings[$gateway_settings_value]) ) { 
  1355. $settings[$gateway_settings_value] = AngellEYE_Utility::crypting($settings[$gateway_settings_value], $action = 'e'); 
  1356. return $settings; 
  1357.  
  1358. public function angelleye_paypal_pro_payflow_email_instructions($order, $sent_to_admin, $plain_text = false) { 
  1359. $payment_method = version_compare( WC_VERSION, '3.0', '<' ) ? $order->payment_method : $order->get_payment_method(); 
  1360. if ( $sent_to_admin && 'paypal_pro_payflow' === $payment_method ) { 
  1361. // Store source in the order 
  1362. if (!class_exists('Angelleye_PayPal')) { 
  1363. require_once('lib/angelleye/paypal-php-library/includes/paypal.class.php'); 
  1364. if (!class_exists('Angelleye_PayPal_PayFlow')) { 
  1365. require_once('lib/angelleye/paypal-php-library/includes/paypal.payflow.class.php'); 
  1366. $PayPalConfig = array( 
  1367. 'Sandbox' => $this->testmode,  
  1368. 'APIUsername' => $this->paypal_user,  
  1369. 'APIPassword' => trim($this->paypal_password),  
  1370. 'APIVendor' => $this->paypal_vendor,  
  1371. 'APIPartner' => $this->paypal_partner,  
  1372. 'Force_tls_one_point_two' => $this->Force_tls_one_point_two 
  1373. ); 
  1374. $PayPal = new Angelleye_PayPal_PayFlow($PayPalConfig); 
  1375. $old_wc = version_compare( WC_VERSION, '3.0', '<' ); 
  1376. $order_id = version_compare( WC_VERSION, '3.0', '<' ) ? $order->id : $order->get_id(); 
  1377. $cvvmatch = $old_wc ? get_post_meta( $order->id, '_CVV2MATCH', true ) : get_post_meta($order->get_id(), '_CVV2MATCH', true); 
  1378. if ( ! empty( $cvvmatch ) ) { 
  1379. $cvv2_response_message = $PayPal->GetCVV2CodeMessage($cvvmatch); 
  1380. echo '<h2 class="wc-cvv2-details-heading">' . __( 'Card Security Code Details', 'paypal-for-woocommerce' ) . '</h2>' . PHP_EOL; 
  1381. echo '<ul class="wc-cvv2-details order_details cvv2_details">' . PHP_EOL; 
  1382. $cvv_details_fields = apply_filters( 'angelleye_cvv2_details_fields', array( 
  1383. 'cvv2_response_code'=> array( 
  1384. 'label' => __( 'Card Security Code', 'paypal-for-woocommerce' ),  
  1385. 'value' => $cvvmatch 
  1386. ),  
  1387. 'cvv2_response_message' => array( 
  1388. 'label' => __( 'Card Security Message', 'paypal-for-woocommerce' ),  
  1389. 'value' => $cvv2_response_message 
  1390. ), $order_id ); 
  1391. foreach ( $cvv_details_fields as $field_key => $field ) { 
  1392. if ( ! empty( $field['value'] ) ) { 
  1393. echo '<li class="' . esc_attr( $field_key ) . '">' . esc_attr( $field['label'] ) . ': <strong>' . wptexturize( $field['value'] ) . '</strong></li>' . PHP_EOL; 
  1394. echo '</ul>'; 
  1395.  
  1396. $avscode = $old_wc ? get_post_meta( $order->id, '_AVSADDR', true ) : get_post_meta($order->get_id(), '_AVSADDR', true); 
  1397. if ( ! empty( $avscode ) ) { 
  1398. $avs_response_message = $PayPal->GetAVSCodeMessage($avscode); 
  1399. echo '<h2 class="wc-avs-details-heading">' . __( 'Address Verification Details', 'paypal-for-woocommerce' ) . '</h2>' . PHP_EOL; 
  1400. echo '<ul class="wc-avs-details order_details avs_details">' . PHP_EOL; 
  1401. $avs_details_fields = apply_filters( 'angelleye_avs_details_fields', array( 
  1402. 'avs_response_code'=> array( 
  1403. 'label' => __( 'AVS Response Code', 'paypal-for-woocommerce' ),  
  1404. 'value' => $avscode 
  1405. ),  
  1406. 'avs_response_message' => array( 
  1407. 'label' => __( 'AVS Response Message', 'paypal-for-woocommerce' ),  
  1408. 'value' => $avs_response_message 
  1409. ), $order_id ); 
  1410. foreach ( $avs_details_fields as $field_key => $field ) { 
  1411. if ( ! empty( $field['value'] ) ) { 
  1412. echo '<li class="' . esc_attr( $field_key ) . '">' . esc_attr( $field['label'] ) . ': <strong>' . wptexturize( $field['value'] ) . '</strong></li>' . PHP_EOL; 
  1413. echo '</ul>'; 
  1414.  
.