PayWithAmazonEDD_Amazon_Payments

The Easy Digital Downloads PayWithAmazon EDD Amazon Payments class.

Defined (1)

The class is defined in the following location(s).

/includes/gateways/amazon-payments.php  
  1. final class EDD_Amazon_Payments { 
  2.  
  3. private static $instance; 
  4. public $gateway_id = 'amazon'; 
  5. public $client = null; 
  6. public $redirect_uri = null; 
  7. public $checkout_uri = null; 
  8. public $signin_redirect = null; 
  9. public $reference_id = null; 
  10. public $doing_ipn = false; 
  11. public $is_setup = null; 
  12.  
  13. /** 
  14. * Get things going 
  15. * @access private 
  16. * @since 2.4 
  17. * @return void 
  18. */ 
  19. private function __construct() { 
  20.  
  21. if ( version_compare( phpversion(), 5.3, '<' ) ) { 
  22. // The Amazon Login & Pay libraries require PHP 5.3 
  23. return; 
  24.  
  25. $this->reference_id = ! empty( $_REQUEST['amazon_reference_id'] ) ? sanitize_text_field( $_REQUEST['amazon_reference_id'] ) : ''; 
  26.  
  27. // Run this separate so we can ditch as early as possible 
  28. $this->register(); 
  29.  
  30. if ( ! edd_is_gateway_active( $this->gateway_id ) ) { 
  31. return; 
  32.  
  33. $this->config(); 
  34. $this->includes(); 
  35. $this->setup_client(); 
  36. $this->filters(); 
  37. $this->actions(); 
  38.  
  39.  
  40. /** 
  41. * Retrieve current instance 
  42. * @access private 
  43. * @since 2.4 
  44. * @return EDD_Amazon_Payments instance 
  45. */ 
  46. public static function getInstance() { 
  47.  
  48. if ( ! isset( self::$instance ) && ! ( self::$instance instanceof EDD_Amazon_Payments ) ) { 
  49. self::$instance = new EDD_Amazon_Payments; 
  50.  
  51. return self::$instance; 
  52.  
  53.  
  54. /** 
  55. * Register the payment gateway 
  56. * @access private 
  57. * @since 2.4 
  58. * @return void 
  59. */ 
  60. private function register() { 
  61.  
  62. add_filter( 'edd_payment_gateways', array( $this, 'register_gateway' ), 1, 1 ); 
  63.  
  64.  
  65. /** 
  66. * Setup constant configuration for file paths 
  67. * @access private 
  68. * @since 2.4 
  69. * @return void 
  70. */ 
  71. private function config() { 
  72.  
  73. if ( ! defined( 'EDD_AMAZON_CLASS_DIR' ) ) { 
  74. $path = trailingslashit( plugin_dir_path( EDD_PLUGIN_FILE ) ) . 'includes/gateways/libs/amazon'; 
  75. define( 'EDD_AMAZON_CLASS_DIR', trailingslashit( $path ) ); 
  76.  
  77.  
  78. /** 
  79. * Method to check if all the required settings have been filled out, allowing us to not output information without it. 
  80. * @since 2.7 
  81. * @return bool 
  82. */ 
  83. public function is_setup() { 
  84. if ( null !== $this->is_setup ) { 
  85. return $this->is_setup; 
  86.  
  87. $required_items = array( 'merchant_id', 'client_id', 'access_key', 'secret_key' ); 
  88.  
  89. $current_values = array( 
  90. 'merchant_id' => edd_get_option( 'amazon_seller_id', '' ),  
  91. 'client_id' => edd_get_option( 'amazon_client_id', '' ),  
  92. 'access_key' => edd_get_option( 'amazon_mws_access_key', '' ),  
  93. 'secret_key' => edd_get_option( 'amazon_mws_secret_key', '' ),  
  94. ); 
  95.  
  96. $this->is_setup = true; 
  97.  
  98. foreach ( $required_items as $key ) { 
  99. if ( empty( $current_values[ $key ] ) ) { 
  100. $this->is_setup = false; 
  101. break; 
  102.  
  103. return $this->is_setup; 
  104.  
  105. /** 
  106. * Load additional files 
  107. * @access private 
  108. * @since 2.4 
  109. * @return void 
  110. */ 
  111. private function includes() { 
  112.  
  113. // Include the Amazon Library 
  114. require_once EDD_AMAZON_CLASS_DIR . 'Client.php'; // Requires the other files itself 
  115. require_once EDD_AMAZON_CLASS_DIR . 'IpnHandler.php'; 
  116.  
  117.  
  118. /** 
  119. * Add filters 
  120. * @since 2.4 
  121. * @return void 
  122. */ 
  123. private function filters() { 
  124.  
  125. add_filter( 'edd_accepted_payment_icons', array( $this, 'register_payment_icon' ), 10, 1 ); 
  126. add_filter( 'edd_show_gateways', array( $this, 'maybe_hide_gateway_select' ) ); 
  127.  
  128. if ( is_admin() ) { 
  129. add_filter( 'edd_settings_sections_gateways', array( $this, 'register_gateway_section' ), 1, 1 ); 
  130. add_filter( 'edd_settings_gateways', array( $this, 'register_gateway_settings' ), 1, 1 ); 
  131. add_filter( 'edd_payment_details_transaction_id-' . $this->gateway_id, array( $this, 'link_transaction_id' ), 10, 2 ); 
  132.  
  133.  
  134. /** 
  135. * Add actions 
  136. * @access private 
  137. * @since 2.4 
  138. * @return void 
  139. */ 
  140. private function actions() { 
  141.  
  142. add_action( 'wp_enqueue_scripts', array( $this, 'print_client' ), 10 ); 
  143. add_action( 'wp_enqueue_scripts', array( $this, 'load_scripts' ), 11 ); 
  144. add_action( 'init', array( $this, 'check_config' ), 1 ); 
  145. add_action( 'init', array( $this, 'capture_oauth' ), 9 ); 
  146. add_action( 'init', array( $this, 'signin_redirect' ) ); 
  147. add_action( 'edd_purchase_form_before_register_login', array( $this, 'login_form' ) ); 
  148. add_action( 'edd_checkout_error_check', array( $this, 'checkout_errors' ), 10, 2 ); 
  149. add_action( 'edd_gateway_amazon', array( $this, 'process_purchase' ) ); 
  150. add_action( 'wp_ajax_edd_amazon_get_address', array( $this, 'ajax_get_address' ) ); 
  151. add_action( 'wp_ajax_nopriv_edd_amazon_get_address', array( $this, 'ajax_get_address' ) ); 
  152. add_action( 'edd_pre_process_purchase', array( $this, 'disable_address_requirement' ), 99999 ); 
  153. add_action( 'init', array( $this, 'process_ipn' ) ); 
  154. add_action( 'edd_update_payment_status', array( $this, 'process_refund' ), 200, 3 ); 
  155.  
  156. if ( empty( $this->reference_id ) ) { 
  157. return; 
  158.  
  159. add_action( 'edd_amazon_cc_form', array( $this, 'wallet_form' ) ); 
  160.  
  161.  
  162. /** 
  163. * Show an error message on checkout if Amazon is enabled but not setup. 
  164. * @since 2.7 
  165. */ 
  166. public function check_config() { 
  167. $is_enabled = edd_is_gateway_active( $this->gateway_id ); 
  168. if ( ! $is_enabled || false === $this->is_setup() ) { 
  169. edd_set_error( 'amazon_gateway_not_configured', __( 'There is an error with the Amazon Payments configuration.', 'easy-digital-downloads' ) ); 
  170.  
  171. /** 
  172. * Retrieve the client object 
  173. * @access private 
  174. * @since 2.4 
  175. * @return PayWithAmazon\Client 
  176. */ 
  177. private function get_client() { 
  178.  
  179. if ( ! $this->is_setup() ) { 
  180. return false; 
  181.  
  182. if ( ! is_null( $this->client ) ) { 
  183. return $this->client; 
  184.  
  185. $this->setup_client(); 
  186.  
  187. return $this->client; 
  188.  
  189. /** 
  190. * Setup the client object 
  191. * @access private 
  192. * @since 2.4 
  193. * @return void 
  194. */ 
  195. private function setup_client() { 
  196.  
  197. if ( ! $this->is_setup() ) { 
  198. return; 
  199.  
  200. $region = edd_get_shop_country(); 
  201.  
  202. if( 'GB' === $region ) { 
  203. $region = 'UK'; 
  204.  
  205. $config = array( 
  206. 'merchant_id' => edd_get_option( 'amazon_seller_id', '' ),  
  207. 'client_id' => edd_get_option( 'amazon_client_id', '' ),  
  208. 'access_key' => edd_get_option( 'amazon_mws_access_key', '' ),  
  209. 'secret_key' => edd_get_option( 'amazon_mws_secret_key', '' ),  
  210. 'region' => $region,  
  211. 'sandbox' => edd_is_test_mode(),  
  212. ); 
  213.  
  214. $config = apply_filters( 'edd_amazon_client_config', $config ); 
  215.  
  216. $this->client = new Client( $config ); 
  217.  
  218.  
  219. /** 
  220. * Register the gateway 
  221. * @access public 
  222. * @since 2.4 
  223. * @param $gateways array 
  224. * @return array 
  225. */ 
  226. public function register_gateway( $gateways ) { 
  227.  
  228. $default_amazon_info = array( 
  229. $this->gateway_id => array( 
  230. 'admin_label' => __( 'Amazon', 'easy-digital-downloads' ),  
  231. 'checkout_label' => __( 'Amazon', 'easy-digital-downloads' ),  
  232. 'supports' => array(),  
  233. ),  
  234. ); 
  235.  
  236. $default_amazon_info = apply_filters( 'edd_register_amazon_gateway', $default_amazon_info ); 
  237. $gateways = array_merge( $gateways, $default_amazon_info ); 
  238.  
  239. return $gateways; 
  240.  
  241.  
  242. /** 
  243. * Register the payment icon 
  244. * @access public 
  245. * @since 2.4 
  246. * @param array $payment_icons Array of payment icons 
  247. * @return array The array of icons with Amazon Added 
  248. */ 
  249. public function register_payment_icon( $payment_icons ) { 
  250. $payment_icons['amazon'] = 'Amazon'; 
  251.  
  252. return $payment_icons; 
  253.  
  254. /** 
  255. * Hides payment gateway select options after return from Amazon 
  256. * @access public 
  257. * @since 2.7.6 
  258. * @param bool $show Should gateway select be shown 
  259. * @return bool 
  260. */ 
  261. public function maybe_hide_gateway_select( $show ) { 
  262.  
  263. if( ! empty( $_REQUEST['payment-mode'] ) && 'amazon' == $_REQUEST['payment-mode'] && ! empty( $_REQUEST['amazon_reference_id'] ) && ! empty( $_REQUEST['state'] ) && 'authorized' == $_REQUEST['state'] ) { 
  264.  
  265. $show = false; 
  266.  
  267. return $show; 
  268.  
  269. /** 
  270. * Register the payment gateways setting section 
  271. * @since 2.5 
  272. * @param array $gateway_sections Array of sections for the gateways tab 
  273. * @return array Added Amazon Payments into sub-sections 
  274. */ 
  275. public function register_gateway_section( $gateway_sections ) { 
  276. $gateway_sections['amazon'] = __( 'Amazon Payments', 'easy-digital-downloads' ); 
  277.  
  278. return $gateway_sections; 
  279.  
  280. /** 
  281. * Register the gateway settings 
  282. * @access public 
  283. * @since 2.4 
  284. * @param $gateway_settings array 
  285. * @return array 
  286. */ 
  287. public function register_gateway_settings( $gateway_settings ) { 
  288.  
  289. $default_amazon_settings = array( 
  290. 'amazon' => array( 
  291. 'id' => 'amazon',  
  292. 'name' => '<strong>' . __( 'Amazon Payments Settings', 'easy-digital-downloads' ) . '</strong>',  
  293. 'type' => 'header',  
  294. ),  
  295. 'amazon_register' => array( 
  296. 'id' => 'amazon_register',  
  297. 'name' => __( 'Register with Amazon', 'easy-digital-downloads' ),  
  298. 'desc' => '<p><a href="' . $this->get_registration_url() . '" class="button" target="_blank">' . 
  299. __( 'Connect Easy Digital Downloads to Amazon', 'easy-digital-downloads' ) . 
  300. '</a></p>' . 
  301. '<p class="description">' . 
  302. __( 'Once registration is complete, enter your API credentials below.', 'easy-digital-downloads' ) . 
  303. '</p>',  
  304. 'type' => 'descriptive_text',  
  305. ),  
  306. 'amazon_seller_id' => array( 
  307. 'id' => 'amazon_seller_id',  
  308. 'name' => __( 'Seller ID', 'easy-digital-downloads' ),  
  309. 'desc' => __( 'Found in the Integration settings. Also called a Merchant ID', 'easy-digital-downloads' ),  
  310. 'type' => 'text',  
  311. 'size' => 'regular',  
  312. ),  
  313. 'amazon_mws_access_key' => array( 
  314. 'id' => 'amazon_mws_access_key',  
  315. 'name' => __( 'MWS Access Key', 'easy-digital-downloads' ),  
  316. 'desc' => __( 'Found on Seller Central in the MWS Keys section', 'easy-digital-downloads' ),  
  317. 'type' => 'text',  
  318. 'size' => 'regular',  
  319. ),  
  320. 'amazon_mws_secret_key' => array( 
  321. 'id' => 'amazon_mws_secret_key',  
  322. 'name' => __( 'MWS Secret Key', 'easy-digital-downloads' ),  
  323. 'desc' => __( 'Found on Seller Central in the MWS Keys section', 'easy-digital-downloads' ),  
  324. 'type' => 'text',  
  325. 'size' => 'regular',  
  326. ),  
  327. 'amazon_client_id' => array( 
  328. 'id' => 'amazon_client_id',  
  329. 'name' => __( 'Client ID', 'easy-digital-downloads' ),  
  330. 'desc' => __( 'The Amazon Client ID. Should look like `amzn1.application-oa2...`', 'easy-digital-downloads' ),  
  331. 'type' => 'text',  
  332. 'size' => 'regular',  
  333. ),  
  334. 'amazon_mws_callback_url' => array( 
  335. 'id' => 'amazon_callback_url',  
  336. 'name' => __( 'Amazon MWS Callback URL', 'easy-digital-downloads' ),  
  337. 'desc' => __( 'The Return URL to provide in your MWS Application. Enter this under your Login and Pay → Web Settings', 'easy-digital-downloads' ),  
  338. 'type' => 'text',  
  339. 'size' => 'large',  
  340. 'std' => $this->get_amazon_authenticate_redirect(),  
  341. 'faux' => true,  
  342. ),  
  343. 'amazon_mws_ipn_url' => array( 
  344. 'id' => 'amazon_ipn_url',  
  345. 'name' => __( 'Amazon Merchant IPN URL', 'easy-digital-downloads' ),  
  346. 'desc' => sprintf( __( 'The IPN URL to provide in your MWS account. Enter this under your <a href="%s">Integration Settings</a>', 'easy-digital-downloads' ), 'https://sellercentral.amazon.com/gp/pyop/seller/account/settings/user-settings-edit.html' ),  
  347. 'type' => 'text',  
  348. 'size' => 'large',  
  349. 'std' => $this->get_amazon_ipn_url(),  
  350. 'faux' => true,  
  351. ),  
  352. ); 
  353.  
  354. $default_amazon_settings = apply_filters( 'edd_default_amazon_settings', $default_amazon_settings ); 
  355. $gateway_settings['amazon'] = $default_amazon_settings; 
  356.  
  357. return $gateway_settings; 
  358.  
  359.  
  360. /** 
  361. * Load javascript files and localized variables 
  362. * @access public 
  363. * @since 2.4 
  364. * @return void 
  365. */ 
  366. public function load_scripts() { 
  367.  
  368. if ( ! $this->is_setup() ) { 
  369. return; 
  370.  
  371. if ( ! edd_is_checkout() ) { 
  372. return; 
  373.  
  374. $test_mode = edd_is_test_mode(); 
  375. $seller_id = edd_get_option( 'amazon_seller_id', '' ); 
  376. $client_id = edd_get_option( 'amazon_client_id', '' ); 
  377.  
  378. $default_amazon_scope = array( 
  379. 'profile',  
  380. 'postal_code',  
  381. 'payments:widget',  
  382. ); 
  383.  
  384. if ( edd_use_taxes() ) { 
  385. $default_amazon_scope[] = 'payments:shipping_address'; 
  386.  
  387. $default_amazon_button_settings = array( 
  388. 'type' => 'PwA',  
  389. 'color' => 'Gold',  
  390. 'size' => 'medium',  
  391. 'scope' => implode( ' ', $default_amazon_scope ),  
  392. 'popup' => true,  
  393. ); 
  394.  
  395. $amazon_button_settings = apply_filters( 'edd_amazon_button_settings', $default_amazon_button_settings ); 
  396. $base_url = ''; 
  397. $sandbox = $test_mode ? 'sandbox/' : ''; 
  398.  
  399. switch ( edd_get_shop_country() ) { 
  400. case 'GB': 
  401. $base_url = 'https://static-eu.payments-amazon.com/OffAmazonPayments/uk/' . $sandbox . 'lpa/'; 
  402. break; 
  403. case 'DE': 
  404. $base_url = 'https://static-eu.payments-amazon.com/OffAmazonPayments/de/' . $sandbox. 'lpa/'; 
  405. break; 
  406. default: 
  407. $base_url = 'https://static-na.payments-amazon.com/OffAmazonPayments/us/' . $sandbox; 
  408. break; 
  409.  
  410. if ( ! empty( $base_url ) ) { 
  411.  
  412. $url = $base_url . 'js/Widgets.js?sellerId=' . $seller_id; 
  413.  
  414. wp_enqueue_script( 'edd-amazon-widgets', $url, array( 'jquery' ), null, false ); 
  415. wp_localize_script( 'edd-amazon-widgets', 'edd_amazon', apply_filters( 'edd_amazon_checkout_vars', array( 
  416. 'sellerId' => $seller_id,  
  417. 'clientId' => $client_id,  
  418. 'referenceID' => $this->reference_id,  
  419. 'buttonType' => $amazon_button_settings['type'],  
  420. 'buttonColor' => $amazon_button_settings['color'],  
  421. 'buttonSize' => $amazon_button_settings['size'],  
  422. 'scope' => $amazon_button_settings['scope'],  
  423. 'popup' => $amazon_button_settings['popup'],  
  424. 'checkoutUri' => $this->get_amazon_checkout_uri(),  
  425. 'redirectUri' => $this->get_amazon_authenticate_redirect(),  
  426. 'signinUri' => $this->get_amazon_signin_redirect(),  
  427. ) ) ); 
  428.  
  429.  
  430.  
  431. /** 
  432. * Print client ID in header 
  433. * @access public 
  434. * @since 2.4 
  435. * @return void 
  436. */ 
  437. public function print_client() { 
  438.  
  439. if ( ! $this->is_setup() ) { 
  440. return false; 
  441.  
  442. if ( ! edd_is_checkout() ) { 
  443. return; 
  444. ?> 
  445. <script> 
  446. window.onAmazonLoginReady = function() { 
  447. amazon.Login.setClientId(<?php echo json_encode( edd_get_option( 'amazon_client_id', '' ) ); ?>); 
  448. }; 
  449. </script> 
  450. <?php 
  451.  
  452.  
  453. /** 
  454. * Capture authentication after returning from Amazon 
  455. * @access public 
  456. * @since 2.4 
  457. * @return void 
  458. */ 
  459. public function capture_oauth() { 
  460.  
  461. if ( ! isset( $_GET['edd-listener'] ) || $_GET['edd-listener'] !== 'amazon' ) { 
  462. return; 
  463.  
  464. if ( ! isset( $_GET['state'] ) || $_GET['state'] !== 'return_auth' ) { 
  465. return; 
  466.  
  467. if( empty( $_GET['access_token'] ) || false === strpos( $_GET['access_token'], 'Atza' ) ) { 
  468. return; 
  469.  
  470. try { 
  471.  
  472. $profile = $this->client->getUserInfo( $_GET['access_token'] ); 
  473.  
  474. EDD()->session->set( 'amazon_access_token', $_GET['access_token'] ); 
  475. EDD()->session->set( 'amazon_profile', $profile ); 
  476.  
  477. } catch( Exception $e ) { 
  478.  
  479. wp_die( print_r( $e, true ) ); 
  480.  
  481.  
  482.  
  483. /** 
  484. * Set customer details after authentication 
  485. * @access public 
  486. * @since 2.4 
  487. * @return void 
  488. */ 
  489. public function signin_redirect() { 
  490.  
  491. if ( ! isset( $_GET['edd-listener'] ) || $_GET['edd-listener'] !== 'amazon' ) { 
  492. return; 
  493.  
  494. if ( ! isset( $_GET['state'] ) || $_GET['state'] !== 'signed-in' ) { 
  495. return; 
  496.  
  497. $profile = EDD()->session->get( 'amazon_profile' ); 
  498. $reference = $_GET['amazon_reference_id']; 
  499.  
  500. if( ! is_user_logged_in() ) { 
  501.  
  502. $user = get_user_by( 'email', $profile['email'] ); 
  503.  
  504. if( $user ) { 
  505.  
  506. edd_log_user_in( $user->ID, $user->user_login, '' ); 
  507.  
  508. $customer = array( 
  509. 'first_name' => $user->first_name,  
  510. 'last_name' => $user->last_name,  
  511. 'email' => $user->user_email 
  512. ); 
  513.  
  514. } else { 
  515.  
  516. $names = explode( ' ', $profile['name'], 2 ); 
  517.  
  518. $customer = array( 
  519. 'first_name' => $names[0],  
  520. 'last_name' => isset( $names[1] ) ? $names[1] : '',  
  521. 'email' => $profile['email'] 
  522. ); 
  523.  
  524. if( 'none' !== edd_get_option( 'show_register_form' ) ) { 
  525.  
  526. // Create a customer account if registration is not disabled 
  527.  
  528. $args = array( 
  529. 'user_email' => $profile['email'],  
  530. 'user_login' => $profile['email'],  
  531. 'display_name' => $profile['name'],  
  532. 'first_name' => $customer['first_name'],  
  533. 'last_name' => $customer['last_name'],  
  534. 'user_pass' => wp_generate_password( 20 ),  
  535. ); 
  536.  
  537. $user_id = wp_insert_user( $args ); 
  538.  
  539. edd_log_user_in( $user_id, $args['user_login'], $args['user_pass'] ); 
  540.  
  541.  
  542.  
  543. EDD()->session->set( 'customer', $customer ); 
  544.  
  545.  
  546.  
  547. wp_redirect( edd_get_checkout_uri( array( 'payment-mode' => 'amazon', 'state' => 'authorized', 'amazon_reference_id' => $reference ) ) ); exit; 
  548.  
  549.  
  550.  
  551. /** 
  552. * Display the log in button 
  553. * @access public 
  554. * @since 2.4 
  555. * @return void 
  556. */ 
  557. public function login_form() { 
  558.  
  559. if ( ! $this->is_setup() ) { 
  560. return false; 
  561.  
  562. if ( empty( $this->reference_id ) && 'amazon' == edd_get_chosen_gateway() ) : 
  563.  
  564. remove_all_actions( 'edd_purchase_form_after_cc_form' ); 
  565. remove_all_actions( 'edd_purchase_form_after_user_info' ); 
  566. remove_all_actions( 'edd_purchase_form_register_fields' ); 
  567. remove_all_actions( 'edd_purchase_form_login_fields' ); 
  568. remove_all_actions( 'edd_register_fields_before' ); 
  569. remove_all_actions( 'edd_cc_form' ); 
  570. remove_all_actions( 'edd_checkout_form_top' ); 
  571.  
  572. ob_start(); ?> 
  573. <fieldset id="edd-amazon-login-fields" class="edd-amazon-fields"> 
  574.  
  575. <div id="edd-amazon-pay-button"></div> 
  576. <script type="text/javascript"> 
  577. var authRequest; 
  578. OffAmazonPayments.Button('edd-amazon-pay-button', edd_amazon.sellerId, { 
  579. type: edd_amazon.buttonType,  
  580. color: edd_amazon.buttonColor,  
  581. size: edd_amazon.buttonSize,  
  582.  
  583. authorization: function() { 
  584.  
  585. loginOptions = { 
  586. scope: edd_amazon.scope,  
  587. popup: edd_amazon.popup 
  588. }; 
  589.  
  590. authRequest = amazon.Login.authorize( loginOptions, edd_amazon.redirectUri ); 
  591.  
  592. },  
  593. onSignIn: function( orderReference ) { 
  594. amazonOrderReferenceId = orderReference.getAmazonOrderReferenceId(); 
  595. window.location = edd_amazon.signinUri + '&amazon_reference_id=' + amazonOrderReferenceId; 
  596. }, onError: function(error) { 
  597. jQuery('#edd_purchase_submit').prepend( '<div class="edd_errors"><p class="edd_error" id="edd_error_"' + error.getErrorCode() + '>' + error.getErrorMessage() + '</p></div>' ); 
  598. }); 
  599. </script> 
  600.  
  601. </fieldset> 
  602.  
  603. <?php 
  604.  
  605. echo ob_get_clean(); 
  606.  
  607. endif; 
  608.  
  609. /** 
  610. * Display the wallet and address forms 
  611. * @access public 
  612. * @since 2.4 
  613. * @return void 
  614. */ 
  615. public function wallet_form() { 
  616.  
  617. if ( ! $this->is_setup() ) { 
  618. return false; 
  619.  
  620. $profile = EDD()->session->get( 'amazon_profile' ); 
  621. remove_action( 'edd_purchase_form_after_cc_form', 'edd_checkout_tax_fields', 999 ); 
  622. ob_start(); ?> 
  623. <fieldset id="edd_cc_fields" class="edd-amazon-fields"> 
  624. <p class="edd-amazon-profile-wrapper"> 
  625. <?php _e( 'Currently logged into Amazon as', 'easy-digital-downloads' ); ?>: <span class="edd-amazon-profile-name"><?php echo $profile['name']; ?></span> 
  626. <span class="edd-amazon-logout">(<a id="Logout"><?php _e( 'Logout', 'easy-digital-downloads' ); ?></a>)</span> 
  627. </p> 
  628. <?php if( edd_use_taxes() ) : ?> 
  629. <div id="edd-amazon-address-box"></div> 
  630. <?php endif; ?> 
  631. <div id="edd-amazon-wallet-box"></div> 
  632. <script> 
  633. var edd_global_vars; 
  634. if( '1' == edd_global_vars.taxes_enabled ) { 
  635. new OffAmazonPayments.Widgets.AddressBook({ 
  636. sellerId: edd_amazon.sellerId,  
  637. amazonOrderReferenceId: edd_amazon.referenceID,  
  638. onOrderReferenceCreate: function(orderReference) { 
  639. orderReference.getAmazonOrderReferenceId(); 
  640. },  
  641. onAddressSelect: function(orderReference) { 
  642. jQuery.ajax({ 
  643. type: "POST",  
  644. data: { 
  645. action : 'edd_amazon_get_address',  
  646. reference_id : edd_amazon.referenceID 
  647. },  
  648. dataType: "json",  
  649. url: edd_global_vars.ajaxurl,  
  650. xhrFields: { 
  651. withCredentials: true 
  652. },  
  653. success: function (response) { 
  654. jQuery('#card_city').val( response.City ); 
  655. jQuery('#card_address').val( response.AddressLine1 ); 
  656. jQuery('#card_address_2').val( response.AddressLine2 ); 
  657. jQuery('#card_zip').val( response.PostalCode ); 
  658. jQuery('#billing_country').val( response.CountryCode ); 
  659. jQuery('#card_state').val( response.StateOrRegion ).trigger( 'change' ); 
  660. }).fail(function (response) { 
  661. if ( window.console && window.console.log ) { 
  662. console.log( response ); 
  663. }).done(function (response) { 
  664.  
  665. }); 
  666. },  
  667. design: { 
  668. designMode: 'responsive' 
  669. },  
  670. onError: function(error) { 
  671. jQuery('#edd-amazon-address-box').hide(); 
  672. jQuery('#edd_purchase_submit').prepend( '<div class="edd_errors"><p class="edd_error" id="edd_error_"' + error.getErrorCode() + '>' + error.getErrorMessage() + '</p></div>' ); 
  673. }).bind("edd-amazon-address-box"); 
  674.  
  675. new OffAmazonPayments.Widgets.Wallet({ 
  676. sellerId: edd_amazon.sellerId,  
  677. amazonOrderReferenceId: edd_amazon.referenceID,  
  678. design: { 
  679. designMode: 'responsive' 
  680. },  
  681. onPaymentSelect: function(orderReference) { 
  682. // Display your custom complete purchase button 
  683. },  
  684. onError: function(error) { 
  685. jQuery('#edd_purchase_submit').prepend( '<div class="edd_errors"><p class="edd_error" id="edd_error_"' + error.getErrorCode() + '>' + error.getErrorMessage() + '</p></div>' ); 
  686. }).bind("edd-amazon-wallet-box"); 
  687.  
  688. } else { 
  689.  
  690. new OffAmazonPayments.Widgets.Wallet({ 
  691. sellerId: edd_amazon.sellerId,  
  692. design: { 
  693. designMode: 'responsive' 
  694. },  
  695. onOrderReferenceCreate: function(orderReference) { 
  696. jQuery( '#edd_amazon_reference_id' ).val( orderReference.getAmazonOrderReferenceId() ); 
  697. },  
  698. onPaymentSelect: function(orderReference) { 
  699. // Display your custom complete purchase button 
  700. },  
  701. onError: function(error) { 
  702. jQuery('#edd_purchase_submit').prepend( '<div class="edd_errors"><p class="edd_error" id="edd_error_"' + error.getErrorCode() + '>' + error.getErrorMessage() + '</p></div>' ); 
  703. }).bind("edd-amazon-wallet-box"); 
  704.  
  705. </script> 
  706.  
  707. <div id="edd_cc_address"> 
  708. <input type="hidden" name="edd_amazon_reference_id" id="edd_amazon_reference_id" value="<?php echo esc_attr( $this->reference_id ); ?>"/> 
  709. <input type="hidden" name="card_city" class="card_city" id="card_city" value=""/> 
  710. <input type="hidden" name="card_address" class="card_address" id="card_address" value=""/> 
  711. <input type="hidden" name="card_address_2" class="card_address_2" id="card_address_2" value=""/> 
  712. <input type="hidden" name="card_zip" class="card_zip" id="card_zip" value=""/> 
  713. <input type="hidden" name="card_state" class="card_state" id="card_state" value=""/> 
  714. <input type="hidden" name="billing_country" class="billing_country" id="billing_country" value=""/> 
  715. </div> 
  716.  
  717. </fieldset> 
  718.  
  719. <?php 
  720. $form = ob_get_clean(); 
  721. echo $form; 
  722.  
  723.  
  724. /** 
  725. * Retrieve the billing address via ajax 
  726. * @access public 
  727. * @since 2.4 
  728. * @return void 
  729. */ 
  730. public function ajax_get_address() { 
  731.  
  732. if ( ! $this->is_setup() ) { 
  733. return false; 
  734.  
  735. if( empty( $_POST['reference_id'] ) ) { 
  736. die( '-2' ); 
  737.  
  738. $request = $this->client->getOrderReferenceDetails( array( 
  739. 'merchant_id' => edd_get_option( 'amazon_seller_id', '' ),  
  740. 'amazon_order_reference_id' => $_POST['reference_id'],  
  741. 'address_consent_token' => EDD()->session->get( 'amazon_access_token' ) 
  742. ) ); 
  743.  
  744.  
  745. $address = array(); 
  746. $data = new ResponseParser( $request->response ); 
  747. $data = $data->toArray(); 
  748.  
  749. if( isset( $data['GetOrderReferenceDetailsResult']['OrderReferenceDetails']['Destination']['PhysicalDestination'] ) ) { 
  750.  
  751. $address = $data['GetOrderReferenceDetailsResult']['OrderReferenceDetails']['Destination']['PhysicalDestination']; 
  752. $address = wp_parse_args( $address, array( 'City', 'CountryCode', 'StateOrRegion', 'PostalCode', 'AddressLine1', 'AddressLine2' ) ); 
  753.  
  754.  
  755. echo json_encode( $address ); exit; 
  756.  
  757.  
  758. /** 
  759. * Check for errors during checkout 
  760. * @access public 
  761. * @since 2.4 
  762. * @param $valid_data Customer / product data from checkout 
  763. * @param $post_data $_POST 
  764. * @return void 
  765. */ 
  766. public function checkout_errors( $valid_data, $post_data ) { 
  767.  
  768. // should validate that we have a reference ID here, perhaps even fire the API call here 
  769. if( empty( $post_data['edd_amazon_reference_id'] ) ) { 
  770. edd_set_error( 'missing_reference_id', __( 'Missing Reference ID, please try again', 'easy-digital-downloads' ) ); 
  771.  
  772. /** 
  773. * Process the purchase and create the charge in Amazon 
  774. * @access public 
  775. * @since 2.4 
  776. * @param $purchase_data array Cart details 
  777. * @return void 
  778. */ 
  779. public function process_purchase( $purchase_data ) { 
  780.  
  781. if( empty( $purchase_data['post_data']['edd_amazon_reference_id'] ) ) { 
  782. edd_set_error( 'missing_reference_id', __( 'Missing Reference ID, please try again', 'easy-digital-downloads' ) ); 
  783.  
  784. $errors = edd_get_errors(); 
  785. if ( $errors ) { 
  786.  
  787. edd_send_back_to_checkout( '?payment-mode=amazon' ); 
  788.  
  789.  
  790. $args = apply_filters( 'edd_amazon_charge_args', array( 
  791. 'merchant_id' => edd_get_option( 'amazon_seller_id', '' ),  
  792. 'amazon_reference_id' => $purchase_data['post_data']['edd_amazon_reference_id'],  
  793. 'authorization_reference_id' => $purchase_data['purchase_key'],  
  794. 'charge_amount' => $purchase_data['price'],  
  795. 'currency_code' => edd_get_currency(),  
  796. 'charge_note' => html_entity_decode( edd_get_purchase_summary( $purchase_data, false ) ),  
  797. 'charge_order_id' => $purchase_data['purchase_key'],  
  798. 'store_name' => remove_accents( wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ) ),  
  799. 'transaction_timeout' => 0 
  800. ), $purchase_data ); 
  801.  
  802. $args['platform_id'] = 'A3JST9YM1SX7LB'; 
  803.  
  804. $charge = $this->client->charge( $args ); 
  805.  
  806. if( 200 == $charge->response['Status'] ) { 
  807.  
  808. $charge = new ResponseParser( $charge->response ); 
  809. $charge = $charge->toArray(); 
  810.  
  811. $status = $charge['AuthorizeResult']['AuthorizationDetails']['AuthorizationStatus']['State']; 
  812.  
  813. if( 'Declined' === $status ) { 
  814.  
  815. $reason = $charge['AuthorizeResult']['AuthorizationDetails']['AuthorizationStatus']['ReasonCode']; 
  816. edd_set_error( 'payment_declined', sprintf( __( 'Your payment could not be authorized, please try a different payment method. Reason: %s', 'easy-digital-downloads' ), $reason ) ); 
  817. edd_send_back_to_checkout( '?payment-mode=amazon&amazon_reference_id=' . $purchase_data['post_data']['edd_amazon_reference_id'] ); 
  818.  
  819. // Setup payment data to be recorded 
  820. $payment_data = array( 
  821. 'price' => $purchase_data['price'],  
  822. 'date' => $purchase_data['date'],  
  823. 'user_email' => $purchase_data['user_email'],  
  824. 'purchase_key' => $purchase_data['purchase_key'],  
  825. 'currency' => edd_get_currency(),  
  826. 'downloads' => $purchase_data['downloads'],  
  827. 'user_info' => $purchase_data['user_info'],  
  828. 'cart_details' => $purchase_data['cart_details'],  
  829. 'gateway' => $this->gateway_id,  
  830. 'status' => 'pending',  
  831. ); 
  832.  
  833. $payment_id = edd_insert_payment( $payment_data ); 
  834.  
  835. $authorization_id = $charge['AuthorizeResult']['AuthorizationDetails']['AmazonAuthorizationId']; 
  836. $capture_id = str_replace( '-A', '-C', $authorization_id ); 
  837. $reference_id = sanitize_text_field( $_POST['edd_amazon_reference_id'] ); 
  838.  
  839. // Confirm the capture was completed 
  840. $capture = $this->client->getCaptureDetails( array( 
  841. 'merchant_id' => edd_get_option( 'amazon_seller_id', '' ),  
  842. 'amazon_capture_id' => $capture_id 
  843. ) ); 
  844.  
  845. $capture = new ResponseParser( $capture->response ); 
  846. $capture = $capture->toArray(); 
  847.  
  848. edd_update_payment_meta( $payment_id, '_edd_amazon_authorization_id', $authorization_id ); 
  849. edd_update_payment_meta( $payment_id, '_edd_amazon_capture_id', $capture_id ); 
  850.  
  851. edd_set_payment_transaction_id( $payment_id, $reference_id ); 
  852.  
  853. edd_update_payment_status( $payment_id, 'publish' ); 
  854.  
  855. // Empty the shopping cart 
  856. edd_empty_cart(); 
  857. edd_send_to_success_page(); 
  858.  
  859. } else { 
  860.  
  861. // Set an error 
  862. edd_set_error( 'amazon_error', sprintf( __( 'There was an issue processing your payment. Amazon error: %s', 'easy-digital-downloads' ), print_r( $charge, true ) ) ); 
  863. edd_send_back_to_checkout( '?payment-mode=amazon&amazon_reference_id=' . $purchase_data['post_data']['edd_amazon_reference_id'] ); 
  864.  
  865.  
  866.  
  867.  
  868. /** 
  869. * Retrieve the checkout URL for Amazon after authentication is complete 
  870. * @access public 
  871. * @since 2.4 
  872. * @return string 
  873. */ 
  874. private function get_amazon_checkout_uri() { 
  875.  
  876. if ( is_null( $this->checkout_uri ) ) { 
  877. $this->checkout_uri = esc_url_raw( add_query_arg( array( 'payment-mode' => 'amazon' ), edd_get_checkout_uri() ) ); 
  878.  
  879. return $this->checkout_uri; 
  880.  
  881.  
  882. /** 
  883. * Retrieve the return URL for Amazon after authentication on Amazon is complete 
  884. * @access public 
  885. * @since 2.4 
  886. * @return string 
  887. */ 
  888. private function get_amazon_authenticate_redirect() { 
  889.  
  890. if ( is_null( $this->redirect_uri ) ) { 
  891. $this->redirect_uri = esc_url_raw( add_query_arg( array( 'edd-listener' => 'amazon', 'state' => 'return_auth' ), edd_get_checkout_uri() ) ); 
  892.  
  893. return $this->redirect_uri; 
  894.  
  895.  
  896. /** 
  897. * Retrieve the URL to send customers too once sign-in is complete 
  898. * @access public 
  899. * @since 2.4 
  900. * @return string 
  901. */ 
  902. private function get_amazon_signin_redirect() { 
  903.  
  904. if ( is_null( $this->signin_redirect ) ) { 
  905. $this->signin_redirect = esc_url_raw( add_query_arg( array( 'edd-listener' => 'amazon', 'state' => 'signed-in' ), home_url() ) ); 
  906.  
  907. return $this->signin_redirect; 
  908.  
  909.  
  910. /** 
  911. * Retrieve the IPN URL for Amazon 
  912. * @access public 
  913. * @since 2.4 
  914. * @return string 
  915. */ 
  916. private function get_amazon_ipn_url() { 
  917.  
  918. return esc_url_raw( add_query_arg( array( 'edd-listener' => 'amazon' ), home_url( 'index.php' ) ) ); 
  919.  
  920.  
  921. /** 
  922. * Removes the requirement for entering the billing address 
  923. * Address is pulled directly from Amazon 
  924. * @access public 
  925. * @since 2.4 
  926. * @return void 
  927. */ 
  928. public function disable_address_requirement() { 
  929.  
  930. if( ! empty( $_POST['edd-gateway'] ) && $this->gateway_id == $_REQUEST['edd-gateway'] ) { 
  931. add_filter( 'edd_require_billing_address', '__return_false', 9999 ); 
  932.  
  933.  
  934. /** 
  935. * Given a transaction ID, generate a link to the Amazon transaction ID details 
  936. * @since 2.4 
  937. * @param string $transaction_id The Transaction ID 
  938. * @param int $payment_id The payment ID for this transaction 
  939. * @return string A link to the PayPal transaction details 
  940. */ 
  941. public function link_transaction_id( $transaction_id, $payment_id ) { 
  942.  
  943. $base_url = 'https://sellercentral.amazon.com/hz/me/pmd/payment-details?orderReferenceId='; 
  944. $transaction_url = '<a href="' . esc_url( $base_url . $transaction_id ) . '" target="_blank">' . $transaction_id . '</a>'; 
  945.  
  946. return apply_filters( 'edd_' . $this->gateway_id . '_link_payment_details_transaction_id', $transaction_url ); 
  947.  
  948.  
  949. /** 
  950. * Process IPN messages from Amazon 
  951. * @access public 
  952. * @since 2.4 
  953. * @return void 
  954. */ 
  955. public function process_ipn() { 
  956.  
  957. if ( ! isset( $_GET['edd-listener'] ) || $_GET['edd-listener'] !== 'amazon' ) { 
  958. return; 
  959.  
  960. if ( isset( $_GET['state'] ) ) { 
  961. return; 
  962.  
  963. // Get the IPN headers and Message body 
  964. $headers = getallheaders(); 
  965. $body = file_get_contents( 'php://input' ); 
  966.  
  967. $this->doing_ipn = true; 
  968.  
  969. try { 
  970.  
  971. $ipn = new IpnHandler( $headers, $body ); 
  972. $data = $ipn->toArray(); 
  973. $seller_id = $data['SellerId']; 
  974.  
  975. if( $seller_id != edd_get_option( 'amazon_seller_id', '' ) ) { 
  976. wp_die( __( 'Invalid Amazon seller ID', 'easy-digital-downloads' ), __( 'IPN Error', 'easy-digital-downloads' ), array( 'response' => 401 ) ); 
  977.  
  978. switch( $data['NotificationType'] ) { 
  979.  
  980. case 'OrderReferenceNotification' : 
  981.  
  982. break; 
  983.  
  984. case 'PaymentAuthorize' : 
  985.  
  986. break; 
  987.  
  988. case 'PaymentCapture' : 
  989.  
  990. $key = $data['CaptureDetails']['CaptureReferenceId']; 
  991. $status = $data['CaptureDetails']['CaptureStatus']['State']; 
  992.  
  993. if( 'Declined' === $status ) { 
  994.  
  995. $payment_id = edd_get_purchase_id_by_key( $key ); 
  996.  
  997. edd_update_payment_status( $payment_id, 'failed' ); 
  998.  
  999. edd_insert_payment_note( $payment_id, __( 'Capture declined in Amazon', 'easy-digital-downloads' ) ); 
  1000.  
  1001.  
  1002. break; 
  1003.  
  1004.  
  1005. case 'PaymentRefund' : 
  1006.  
  1007. $trans_id = substr( $data['RefundDetails']['AmazonRefundId'], 0, 19 ); 
  1008. $status = $data['RefundDetails']['RefundStatus']['State']; 
  1009.  
  1010. if( 'Completed' === $status ) { 
  1011.  
  1012. $payment_id = edd_get_purchase_id_by_transaction_id( $trans_id ); 
  1013.  
  1014. edd_update_payment_status( $payment_id, 'refunded' ); 
  1015.  
  1016. edd_insert_payment_note( $payment_id, sprintf( __( 'Refund completed in Amazon. Refund ID: %s', 'easy-digital-downloads' ), $data['RefundDetails']['AmazonRefundId'] ) ); 
  1017.  
  1018.  
  1019. break; 
  1020.  
  1021.  
  1022.  
  1023.  
  1024. } catch( Exception $e ) { 
  1025.  
  1026. wp_die( $e->getErrorMessage(), __( 'IPN Error', 'easy-digital-downloads' ), array( 'response' => 401 ) ); 
  1027.  
  1028.  
  1029.  
  1030. /** 
  1031. * Detect a refund action from EDD 
  1032. * @access public 
  1033. * @since 2.4 
  1034. * @param $payment_id int The ID number of the payment being refunded 
  1035. * @param $new_status string The new status assigned to the payment 
  1036. * @param $old_status string The previous status of the payment 
  1037. * @return void 
  1038. */ 
  1039. public function process_refund( $payment_id, $new_status, $old_status ) { 
  1040.  
  1041. if( 'publish' != $old_status && 'revoked' != $old_status ) { 
  1042. return; 
  1043.  
  1044. if( 'refunded' != $new_status ) { 
  1045. return; 
  1046.  
  1047. if( $this->doing_ipn ) { 
  1048. return; 
  1049.  
  1050. if( 'amazon' !== edd_get_payment_gateway( $payment_id ) ) { 
  1051. return; 
  1052.  
  1053. $this->refund( $payment_id ); 
  1054.  
  1055.  
  1056. /** 
  1057. * Refund a charge in Amazon 
  1058. * @access public 
  1059. * @since 2.4 
  1060. * @param $payment_id int The ID number of the payment being refunded 
  1061. * @return string 
  1062. */ 
  1063. private function refund( $payment_id = 0 ) { 
  1064.  
  1065. $refund = $this->client->refund( array( 
  1066. 'merchant_id' => edd_get_option( 'amazon_seller_id', '' ),  
  1067. 'amazon_capture_id' => edd_get_payment_meta( $payment_id, '_edd_amazon_capture_id', true ),  
  1068. 'refund_reference_id' => md5( edd_get_payment_key( $payment_id ) . '-refund' ),  
  1069. 'refund_amount' => edd_get_payment_amount( $payment_id ),  
  1070. 'currency_code' => edd_get_payment_currency_code( $payment_id ),  
  1071. ) ); 
  1072.  
  1073. if( 200 == $refund->response['Status'] ) { 
  1074.  
  1075. $refund = new ResponseParser( $refund->response ); 
  1076. $refund = $refund->toArray(); 
  1077.  
  1078. $reference_id = $refund['RefundResult']['RefundDetails']['RefundReferenceId']; 
  1079. $status = $refund['RefundResult']['RefundDetails']['RefundStatus']['State']; 
  1080.  
  1081. switch( $status ) { 
  1082.  
  1083. case 'Declined' : 
  1084.  
  1085. $code = $refund['RefundResult']['RefundDetails']['RefundStatus']['ReasonCode']; 
  1086. $note = __( 'Refund declined in Amazon. Refund ID: %s', 'easy-digital-downloads' ); 
  1087.  
  1088. break; 
  1089.  
  1090. case 'Completed' : 
  1091.  
  1092. $refund_id = $refund['RefundResult']['RefundDetails']['AmazonRefundId']; 
  1093. $note = sprintf( __( 'Refund completed in Amazon. Refund ID: %s', 'easy-digital-downloads' ), $refund_id ); 
  1094.  
  1095. break; 
  1096.  
  1097. case 'Pending' : 
  1098.  
  1099. $note = sprintf( __( 'Refund initiated in Amazon. Reference ID: %s', 'easy-digital-downloads' ), $reference_id ); 
  1100.  
  1101. break; 
  1102.  
  1103. edd_insert_payment_note( $payment_id, $note ); 
  1104.  
  1105. } else { 
  1106.  
  1107. edd_insert_payment_note( $payment_id, __( 'Refund request failed in Amazon.', 'easy-digital-downloads' ) ); 
  1108.  
  1109.  
  1110.  
  1111. /** 
  1112. * Retrieve the URL for connecting Amazon account to EDD 
  1113. * @access public 
  1114. * @since 2.4 
  1115. * @return string 
  1116. */ 
  1117. private function get_registration_url() { 
  1118.  
  1119. switch ( edd_get_shop_country() ) { 
  1120. case 'GB': 
  1121. $base_url = 'https://payments.amazon.co.uk/preregistration/lpa'; 
  1122. break; 
  1123. case 'DE': 
  1124. $base_url = 'https://payments.amazon.de/preregistration/lpa'; 
  1125. break; 
  1126. default: 
  1127. $base_url = 'https://sellercentral.amazon.com/hz/me/sp/signup'; 
  1128. break; 
  1129.  
  1130. $query_args = array( 
  1131. 'solutionProviderId' => 'A3JST9YM1SX7LB',  
  1132. 'marketplaceId' => 'AGWSWK15IEJJ7',  
  1133. 'solutionProviderToken' => 'AAAAAQAAAAEAAAAQnngerc8vYweGDt8byl2smgAAAHBgMm923quugHaGmPi%2B3sqo93TSL1aKwU85v71Zh7EXVK8De%2FuahjCFHft3cxN3rwAF4Iwg03sDW0jnkLULmFk7M1Fr69IV2XF477m0kU1EM0Z%2FbQssHdLai%2Fzoce1jZVmw8So3F2jhiDyfTHUK2AYP',  
  1134. 'solutionProviderOptions' => 'lwa%3Bmws-acc%3B',  
  1135. ); 
  1136.  
  1137. return add_query_arg( $query_args, $base_url ); 
  1138.