$settings['access_key'], 'secret_key' => $settings['secret_key'], 'partner_tag' => $settings['partner_tag'], 'marketplace' => $settings['marketplace'] ?? AFFIAMSH_FALLBACK_MARKETPLACE, 'region' => $settings['region'] ?? 'eu-west-1', 'using_fallback' => false ]; } else { // Usa le credenziali di fallback $marketplaces = affiamsh_get_amazon_marketplaces(); $marketplace = AFFIAMSH_FALLBACK_MARKETPLACE; return [ 'access_key' => AFFIAMSH_FALLBACK_ACCESS_KEY, 'secret_key' => AFFIAMSH_FALLBACK_SECRET_KEY, 'partner_tag' => AFFIAMSH_FALLBACK_PARTNER_TAG, 'marketplace' => $marketplace, 'region' => $marketplaces[$marketplace] ?? 'eu-west-1', 'using_fallback' => true ]; } } // Enqueue plugin styles add_action('wp_enqueue_scripts', function () { wp_enqueue_style( 'affiamsh-amazon-products-style', plugins_url('amazon-products.css', __FILE__), [], AFFIAMSH_VER ); }); // Add the settings menu add_action('admin_menu', function () { add_menu_page( 'Affiliate Amazon Shortcode Settings', 'Affiliate Amazon Shortcode', 'manage_options', 'affiamsh-amazon-api-settings', 'affiamsh_amazon_api_settings_page', 'dashicons-cart' ); }); // Get Amazon marketplaces function affiamsh_get_amazon_marketplaces() { return [ 'www.amazon.it' => 'eu-west-1', 'www.amazon.com' => 'us-east-1', 'www.amazon.co.uk' => 'eu-west-1', 'www.amazon.de' => 'eu-central-1', 'www.amazon.fr' => 'eu-west-1', 'www.amazon.es' => 'eu-west-1', 'www.amazon.ca' => 'ca-central-1', 'www.amazon.co.jp' => 'ap-northeast-1', 'www.amazon.in' => 'ap-south-1', ]; } // Get image sizes function affiamsh_get_image_sizes() { return [ 'Medium' => 'Images.Primary.Medium', 'Large' => 'Images.Primary.Large', ]; } // Settings Page function affiamsh_amazon_api_settings_page() { if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['affiamsh_api_settings_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['affiamsh_api_settings_nonce'])), 'affiamsh_save_settings')) { $marketplace = isset($_POST['marketplace']) ? sanitize_text_field(wp_unslash($_POST['marketplace'])) : ''; $marketplaces = affiamsh_get_amazon_marketplaces(); $image_sizes = affiamsh_get_image_sizes(); $settings = [ 'access_key' => isset($_POST['access_key']) ? sanitize_text_field(wp_unslash($_POST['access_key'])) : '', 'secret_key' => isset($_POST['secret_key']) ? sanitize_text_field(wp_unslash($_POST['secret_key'])) : '', 'partner_tag' => isset($_POST['partner_tag']) ? sanitize_text_field(wp_unslash($_POST['partner_tag'])) : '', 'region' => $marketplaces[$marketplace] ?? 'us-east-1', 'marketplace' => $marketplace, 'num_products' => isset($_POST['num_products']) ? absint(wp_unslash($_POST['num_products'])) : 3, 'num_columns' => isset($_POST['num_columns']) ? absint(wp_unslash($_POST['num_columns'])) : 3, 'image_size' => isset($_POST['image_size']) ? sanitize_text_field(wp_unslash($_POST['image_size'])) : 'Medium', 'font_size' => isset($_POST['font_size']) ? affiamsh_validate_font_size(sanitize_text_field(wp_unslash($_POST['font_size']))) : '16px', ]; update_option('affiamsh_plugin_settings', $settings); echo '

Settings saved successfully.

'; } $settings = get_option('affiamsh_plugin_settings', []); $credentials = affiamsh_get_credentials(); $marketplaces = affiamsh_get_amazon_marketplaces(); $image_sizes = affiamsh_get_image_sizes(); ?>

Amazon API Settings

ℹ️ Demo Mode Active

You're using default credentials for testing. Products will be displayed with a demo affiliate ID.

To use your own affiliate ID and earn commissions, enter your Amazon API credentials below.

Access Key

Leave empty to use demo credentials (you won't earn commissions)

Secret Key

Leave empty to use demo credentials (you won't earn commissions)

Partner Tag

Your Amazon Affiliate ID. Leave empty to use demo mode (you won't earn commissions)

Marketplace
Number of Products
Number of Columns
Image Size
Font Size

Enter font size, e.g., 14px, 16px, 18px

Shortcode Format

Add this shortcode in your post/page [affiamsh_amazon keyword="Your Keyword"]

Go Premium

Unlock additional features with the Premium version of this plugin. Learn more.

'smartphone'], $atts, 'affiamsh_amazon'); $settings = get_option('affiamsh_plugin_settings', []); // Ottieni le credenziali (con fallback se necessario) $credentials = affiamsh_get_credentials(); // Construct the payload $image_sizes = affiamsh_get_image_sizes(); $image_size_key = $settings['image_size'] ?? 'Medium'; $image_size = $image_sizes[$image_size_key] ?? 'Images.Primary.Medium'; $payload = "{" . " \"Keywords\": \"" . esc_js($atts['keyword']) . "\"," . " \"Resources\": [" . " \"$image_size\"," . " \"ItemInfo.ContentInfo\"," . " \"ItemInfo.Title\"," . " \"Offers.Listings.Price\"" . " ]," . " \"SearchIndex\": \"All\"," . " \"PartnerTag\": \"" . esc_js($credentials['partner_tag']) . "\"," . " \"PartnerType\": \"Associates\"," . " \"Marketplace\": \"" . esc_js($credentials['marketplace']) . "\"," . " \"ItemCount\": " . absint($settings['num_products'] ?? 3) . "}"; $host = str_replace('www.', 'webservices.', $credentials['marketplace']); $uriPath = "/paapi5/searchitems"; $url = 'https://' . $host . $uriPath; // Sign the request using AwsV4 $awsv4 = new Affiamsh_AwsV4($credentials['access_key'], $credentials['secret_key']); $awsv4->setRegionName($credentials['region']); $awsv4->setServiceName("ProductAdvertisingAPI"); $awsv4->setPath($uriPath); $awsv4->setPayload($payload); $awsv4->setRequestMethod("POST"); $awsv4->addHeader('content-encoding', 'amz-1.0'); $awsv4->addHeader('content-type', 'application/json; charset=utf-8'); $awsv4->addHeader('host', $host); $awsv4->addHeader('x-amz-target', 'com.amazon.paapi5.v1.ProductAdvertisingAPIv1.SearchItems'); $headers = $awsv4->getHeaders(); // Perform the API request $response = wp_remote_post($url, [ 'headers' => $headers, 'body' => $payload, 'timeout' => 20, 'method' => 'POST', ]); if (is_wp_error($response)) { return '

Error: ' . esc_html($response->get_error_message()) . '

'; } $http_code = wp_remote_retrieve_response_code($response); if ($http_code !== 200) { $error_body = wp_remote_retrieve_body($response); return '

Error: Invalid response from Amazon server. HTTP Code: ' . esc_html($http_code) . '

' . '
' . esc_html($error_body) . '
'; } $body = wp_remote_retrieve_body($response); $data = json_decode($body, true); if (empty($data)) { return '

Error: Unable to parse the Amazon server response.

'; } if (empty($data['SearchResult']['Items'])) { return '

No products found.

'; } // Generate HTML $num_products = $settings['num_products'] ?? 3; $num_columns = $settings['num_columns'] ?? 3; $font_size = esc_attr($settings['font_size'] ?? '16px'); // Get PRO options $pro_opts = get_option('affiamsh_pro_display_options', [ 'template' => 'card', 'theme' => 'slate', 'text_color' => '', 'title_color' => '', 'price_color' => '' ]); $template = isset($pro_opts['template']) && !empty($pro_opts['template']) ? $pro_opts['template'] : 'card'; $theme = isset($pro_opts['theme']) && !empty($pro_opts['theme']) ? $pro_opts['theme'] : 'slate'; $is_pro = affiamsh_is_pro(); // Build classes $container_classes = 'affiamsh-amazon-products template-' . esc_attr($template); $container_classes .= ' affiamsh-theme-' . esc_attr($theme); // Build inline styles con CSS variables $inline_styles = "display: grid; grid-template-columns: repeat(" . esc_attr($num_columns) . ", 1fr); gap: 20px;margin-bottom:20px;"; // Add custom color overrides SOLO se theme è CUSTOM e PRO è attivo if ($is_pro && $theme === 'custom') { if (!empty($pro_opts['text_color'])) { $inline_styles .= " --affiamsh-text: " . esc_attr($pro_opts['text_color']) . " !important;"; } if (!empty($pro_opts['title_color'])) { $inline_styles .= " --affiamsh-title: " . esc_attr($pro_opts['title_color']) . " !important;"; } if (!empty($pro_opts['price_color'])) { $inline_styles .= " --affiamsh-price: " . esc_attr($pro_opts['price_color']) . " !important;"; } if (!empty($pro_opts['box_bg'])) { $inline_styles .= " --affiamsh-bg: " . esc_attr($pro_opts['box_bg']) . " !important;"; } if (!empty($pro_opts['ticket_bg'])) { $inline_styles .= " --affiamsh-discount-bg: " . esc_attr($pro_opts['ticket_bg']) . " !important;"; } if (!empty($pro_opts['discount_fg'])) { $inline_styles .= " --affiamsh-discount-fg: " . esc_attr($pro_opts['discount_fg']) . " !important;"; } if (!empty($pro_opts['box_bg_hover'])) { $inline_styles .= " --affiamsh-bg-hover: " . esc_attr($pro_opts['box_bg_hover']) . " !important;"; } } $html = '
'; foreach ($data['SearchResult']['Items'] as $index => $item) { if ($index >= $num_products) break; $title = esc_html($item['ItemInfo']['Title']['DisplayValue'] ?? 'Title not available'); $short_title = (strlen($title) > 50) ? substr($title, 0, 50) . '...' : $title; $image = esc_url($item['Images']['Primary'][$image_size_key]['URL'] ?? ''); $link = esc_url($item['DetailPageURL'] ?? '#'); $price = $item['Offers']['Listings'][0]['Price']['DisplayAmount'] ?? 'Price not available'; $percentage = $item['Offers']['Listings'][0]['Price']['Savings']['Percentage'] ?? null; $html .= '
'; $html .= ''; $html .= '' . $title . ''; $html .= '
' . $short_title . '
'; $html .= '
'; $price_class = 'affiamsh-amazon-product-price'; if ($percentage) { $html .= '

' . '-' . esc_html($percentage) . '% ' . '' . esc_html($price) . '' . '

'; } else { $html .= '

' . esc_html($price) . '

'; } $html .= '
'; } $html .= '
'; return $html; } add_shortcode('affiamsh_amazon', 'affiamsh_amazon_handler'); /** * Classe AwsV4 */ class Affiamsh_AwsV4 { private $accessKey = null; private $secretKey = null; private $path = null; private $regionName = null; private $serviceName = null; private $httpMethodName = null; private $queryParametes = array(); private $awsHeaders = array(); private $payload = ""; private $HMACAlgorithm = "AWS4-HMAC-SHA256"; private $aws4Request = "aws4_request"; private $strSignedHeader = null; private $xAmzDate = null; private $currentDate = null; public function __construct($accessKey, $secretKey) { $this->accessKey = $accessKey; $this->secretKey = $secretKey; $this->xAmzDate = $this->getTimeStamp(); $this->currentDate = $this->getDate(); } function setPath($path) { $this->path = $path; } function setServiceName($serviceName) { $this->serviceName = $serviceName; } function setRegionName($regionName) { $this->regionName = $regionName; } function setPayload($payload) { $this->payload = $payload; } function setRequestMethod($method) { $this->httpMethodName = $method; } function addHeader($headerName, $headerValue) { $this->awsHeaders[$headerName] = $headerValue; } private function prepareCanonicalRequest() { $canonicalURL = ""; $canonicalURL .= $this->httpMethodName . "\n"; $canonicalURL .= $this->path . "\n" . "\n"; $signedHeaders = ''; foreach ($this->awsHeaders as $key => $value) { $signedHeaders .= $key . ";"; $canonicalURL .= $key . ":" . $value . "\n"; } $canonicalURL .= "\n"; $this->strSignedHeader = substr($signedHeaders, 0, -1); $canonicalURL .= $this->strSignedHeader . "\n"; $canonicalURL .= $this->generateHex($this->payload); return $canonicalURL; } private function prepareStringToSign($canonicalURL) { $stringToSign = ''; $stringToSign .= $this->HMACAlgorithm . "\n"; $stringToSign .= $this->xAmzDate . "\n"; $stringToSign .= $this->currentDate . "/" . $this->regionName . "/" . $this->serviceName . "/" . $this->aws4Request . "\n"; $stringToSign .= $this->generateHex($canonicalURL); return $stringToSign; } private function calculateSignature($stringToSign) { $signatureKey = $this->getSignatureKey($this->secretKey, $this->currentDate, $this->regionName, $this->serviceName); $signature = hash_hmac("sha256", $stringToSign, $signatureKey, true); $strHexSignature = strtolower(bin2hex($signature)); return $strHexSignature; } public function getHeaders() { $this->awsHeaders['x-amz-date'] = $this->xAmzDate; ksort($this->awsHeaders); $canonicalURL = $this->prepareCanonicalRequest(); $stringToSign = $this->prepareStringToSign($canonicalURL); $signature = $this->calculateSignature($stringToSign); if ($signature) { $this->awsHeaders['Authorization'] = $this->buildAuthorizationString($signature); return $this->awsHeaders; } } private function buildAuthorizationString($strSignature) { return $this->HMACAlgorithm . " " . "Credential=" . $this->accessKey . "/" . $this->getDate() . "/" . $this->regionName . "/" . $this->serviceName . "/" . $this->aws4Request . "," . "SignedHeaders=" . $this->strSignedHeader . "," . "Signature=" . $strSignature; } private function generateHex($data) { return strtolower(bin2hex(hash("sha256", $data, true))); } private function getSignatureKey($key, $date, $regionName, $serviceName) { $kSecret = "AWS4" . $key; $kDate = hash_hmac("sha256", $date, $kSecret, true); $kRegion = hash_hmac("sha256", $regionName, $kDate, true); $kService = hash_hmac("sha256", $serviceName, $kRegion, true); $kSigning = hash_hmac("sha256", $this->aws4Request, $kService, true); return $kSigning; } private function getTimeStamp() { return gmdate("Ymd\THis\Z"); } private function getDate() { return gmdate("Ymd"); } } // === PRO Licensing & Display Options === if (!defined('AFFIAMSH_PRO_KEY_PLAIN')) { define('AFFIAMSH_PRO_KEY_PLAIN', 'AMSH1899271'); } if (!function_exists('affiamsh_is_pro')) { function affiamsh_is_pro(): bool { return (bool) get_option('affiamsh_is_pro', false); } } add_action('admin_menu', function () { add_submenu_page( 'affiamsh-amazon-api-settings', __('Activate PRO', 'affiliate-amazon-shortcode'), __('Activate PRO', 'affiliate-amazon-shortcode'), 'manage_options', 'affiamsh-activate-pro', 'affiamsh_pro_activation_page' ); add_submenu_page( 'affiamsh-amazon-api-settings', __('Display (PRO)', 'affiliate-amazon-shortcode'), __('Display (PRO)', 'affiliate-amazon-shortcode'), 'manage_options', 'affiamsh-pro-display', 'affiamsh_pro_display_settings_page' ); }); add_action('admin_init', function () { if (!isset($_POST['affiamsh_activate_pro'])) { return; } if (!current_user_can('manage_options')) { return; } check_admin_referer('affiamsh_activate_pro'); $key = isset($_POST['affiamsh_license_key']) ? sanitize_text_field( wp_unslash($_POST['affiamsh_license_key']) ) : ''; if (hash_equals(AFFIAMSH_PRO_KEY_PLAIN, $key)) { update_option('affiamsh_is_pro', 1); update_option('affiamsh_license_key', $key); add_settings_error('affiamsh_pro', 'pro_ok', __('PRO version successful activated.', 'affiliate-amazon-shortcode'), 'updated'); } else { update_option('affiamsh_is_pro', 0); add_settings_error('affiamsh_pro', 'pro_ko', __('License Code Invalid.', 'affiliate-amazon-shortcode'), 'error'); } }); add_action('admin_init', function () { register_setting('affiamsh_pro_display_group', 'affiamsh_pro_display_options', function ($value) { $out = [ 'template' => 'card', 'theme' => 'slate', 'text_color' => '', 'title_color' => '', 'price_color' => '', 'box_bg' => '', 'ticket_bg' => '', 'discount_fg' => '', 'box_bg_hover' => '', ]; if (is_array($value)) { $tpl = isset($value['template']) ? sanitize_text_field($value['template']) : 'card'; $out['template'] = in_array($tpl, ['card','list'], true) ? $tpl : 'card'; $allowed_themes = ['slate','blue','emerald','amber','rose','violet','indigo','teal','zinc','custom']; $th = isset($value['theme']) ? sanitize_text_field($value['theme']) : 'slate'; if (!in_array($th, $allowed_themes, true)) { $th = 'slate'; } if (!affiamsh_is_pro()) { $th = 'slate'; } $out['theme'] = $th; if ($th === 'custom') { foreach (['text_color','title_color','price_color','box_bg','ticket_bg','discount_fg','box_bg_hover'] as $k) { $c = isset($value[$k]) ? sanitize_text_field($value[$k]) : ''; if ($c && preg_match('/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/', $c)) { $out[$k] = $c; } } } else { $out['text_color'] = ''; $out['title_color'] = ''; $out['price_color'] = ''; $out['box_bg'] = ''; $out['ticket_bg'] = ''; $out['discount_fg'] = ''; $out['box_bg_hover'] = ''; } } return $out; }); }); function affiamsh_pro_activation_page() { ?>

✅

'card', 'theme' => 'slate', 'text_color' => '', 'title_color' => '', 'price_color' => '', 'box_bg' => '', 'ticket_bg' => '', 'discount_fg' => '', 'box_bg_hover' => '', ]); $theme = isset($opts['theme']) ? $opts['theme'] : 'slate'; $is_pro = affiamsh_is_pro(); $show_colors = ($theme === 'custom'); ?>

Es. #333333

Es. #111111

Es. #b12704

Es. #ffffff

E.g. #f8fafc

Es. #fff1f2

Es. #be123c

'.esc_html__('Settings','affiliate-amazon-shortcode').''; $links[] = ''.esc_html__('Activate PRO','affiliate-amazon-shortcode').''; $links[] = ''.esc_html__('Purchase PRO','affiliate-amazon-shortcode').''; return $links; }); add_action('admin_post_affiamsh_reset_pro', function () { if (!current_user_can('manage_options')) { wp_die( esc_html__( 'Forbidden', 'affiliate-amazon-shortcode' ) ); } check_admin_referer('affiamsh_reset_pro'); delete_option('affiamsh_is_pro'); add_settings_error('affiamsh_pro', 'pro_reset', __('PRO disabled. You are in FREE version.', 'affiliate-amazon-shortcode'), 'updated'); wp_redirect( admin_url('admin.php?page=affiamsh-activate-pro') ); exit; }); add_action('wp_enqueue_scripts', function () { wp_register_script('affiamsh-frontend', '', [], AFFIAMSH_VER, true); wp_enqueue_script('affiamsh-frontend'); $opts = get_option('affiamsh_pro_display_options', []); $data = [ 'isPro' => affiamsh_is_pro() ? 1 : 0, 'template' => isset($opts['template']) ? $opts['template'] : 'default', 'theme' => isset($opts['theme']) ? $opts['theme'] : 'slate', ]; $js = '(function(d,w){try{var CFG=' . wp_json_encode($data) . ';' . 'function injectWatermark(){' . 'if(CFG.isPro){return;}' . 'var wrappers=d.querySelectorAll(".affiamsh-amazon-products");' . 'wrappers.forEach(function(w){' . 'if(w.querySelector(".affiamsh-watermark"))return;' . 'var wm=d.createElement("span");' . 'wm.className="affiamsh-watermark";' . 'wm.setAttribute("aria-hidden","true");' . 'wm.textContent="Made with Affiliate Amazon Shortcode Plugin";' . 'w.appendChild(wm);' . 'try{' . 'var cs=w.ownerDocument.defaultView.getComputedStyle(w);' . 'if(!cs||cs.position==="static"){w.style.position="relative";}' . '}catch(e){if(!w.style.position){w.style.position="relative";}}' . '});' . '}' . 'injectWatermark();' . 'w.addEventListener("load",injectWatermark);' . '}catch(e){}})(document,window);'; wp_add_inline_script('affiamsh-frontend', $js); }, 40); ?>