PluginProbe
Lasso Lite – Affiliate Link Manager & Product Displays / 116
Lasso Lite – Affiliate Link Manager & Product Displays v116
158 157 155 156 154 153 152 151 150 149 148 trunk 0.9.9 104 105 106 107 108 109 110 111 112 113 114 115 All 57 releases
← All changes | classes/class-amazon-api.php +49 -574 158116 View file →
@@ -6,9 +6,8 @@
6 6 */
7 7
8 8 namespace LassoLite\Classes;
9 9
10 -use LassoLite\Admin\Constant;
11 10 use LassoLite\Classes\Affiliate_Link;
12 11 use LassoLite\Classes\Cache_Per_Process;
13 12 use LassoLite\Classes\Helper;
14 13 use LassoLite\Classes\Setting;
@@ -14,10 +13,8 @@
14 13 use LassoLite\Classes\Setting;
15 14
16 15 use LassoLite\Libs\Amazon_Api_V5\AwsV5;
17 16
18 -use LassoLite\Models\Amazon_Products;
19 -
20 17 /**
21 18 * Config
22 19 */
23 20 class Amazon_Api {
@@ -400,9 +397,9 @@
400 397 * Check whether a url is amazon link or not
401 398 *
402 399 * @param string $url Url.
403 400 */
404 - public static function is_amazon_shortened_url( $url ) {
401 + public static function is_amazon_shortented_url( $url ) {
405 402 $is_amazon_url = self::is_amazon_url( $url );
406 403 $is_shortented_url = strpos( $url, 'amzn.to' ) || strpos( $url, 'amzn.com' );
407 404
408 405 return $is_amazon_url && $is_shortented_url;
@@ -457,38 +454,18 @@
457 454 * @param string $product_id Amazon product id.
458 455 * @param bool $store_product Store product into DB or not. Default to false.
459 456 * @param bool|string $updated_at Set date time or not. Default to false.
460 457 * @param string $amz_link Amazon link. Default to empty.
461 - * @param bool $url_version_param Is add version param to request api url to ignore cache. Default to false.
462 - * @param bool $force_bls Force fetch product from BLS or not. Default to false.
463 - * @param bool $refresh_image Bypass cache and fetch fresh product image/metadata. Default to false.
464 458 * @return mixed
465 459 */
466 - public function fetch_product_info( $product_id, $store_product = false, $updated_at = false, $amz_link = '', $url_version_param = false, $force_bls = false, $refresh_image = false ) {
460 + public function fetch_product_info( $product_id, $store_product = false, $updated_at = false, $amz_link = '' ) {
467 461 $lasso_db = new Lasso_DB();
468 462
469 463 $lasso_settings = Setting::get_settings();
470 464 $is_amazon_configured = $lasso_settings['amazon_access_key_id'] && $lasso_settings['amazon_secret_key'] && $lasso_settings['amazon_tracking_id'];
471 -
472 - if (
473 - self::is_amazon_creators_verified( $lasso_settings )
474 - && $this->is_same_domain( $amz_link )
475 - ) {
476 - $creators_result = $this->fetch_product_info_from_creators_api(
477 - $product_id,
478 - $store_product,
479 - $updated_at,
480 - $amz_link,
481 - $lasso_settings
482 - );
483 - if ( null !== $creators_result ) {
484 - return $creators_result;
485 - }
486 - }
487 -
488 - $result = ! $force_bls && $is_amazon_configured && $this->is_same_domain( $amz_link ) ? $this->get_product_by_id_v5( $product_id ) : false;
465 + $result = $is_amazon_configured && $this->is_same_domain( $amz_link ) ? $this->get_product_by_id_v5( $product_id ) : false;
489 466 // phpcs:ignore
490 - if ( is_object( $result ) && isset( $result->Errors[0] ) && (
467 + if ( isset( $result->Errors[0] ) && (
491 468 "The ItemId $product_id provided in the request is invalid." === $result->Errors[0]->Message // phpcs:ignore
492 469 || "The value [$product_id] provided in the request for ItemIds is invalid." === $result->Errors[0]->Message // phpcs:ignore
493 470 )
494 471 ) {
@@ -498,9 +475,9 @@
498 475 'full_item' => array(),
499 476 'status' => 'failed',
500 477 'error_code' => 'NotFound',
501 478 );
502 - } elseif ( is_object( $result ) && isset( $result->ItemsResult->Items[0] ) ) { // phpcs:ignore
479 + } elseif ( isset( $result->ItemsResult->Items[0] ) ) { // phpcs:ignore
503 480 $item = $result->ItemsResult->Items[0]; // phpcs:ignore
504 481
505 482 $product = $this->extract_search_result_v5( $item, true );
506 483 $product_url = $amz_link ? $amz_link : $product['url'];
@@ -515,10 +492,23 @@
515 492 $product = $variation_product;
516 493 }
517 494 }
518 495
519 - $product = $this->enrich_fetched_amazon_product( $product, $store_product, $updated_at, $amz_link );
496 + // ? Get Lasso ID
497 + $query = '
498 + SELECT post_id
499 + FROM ' . $lasso_db->postmeta . "
500 + WHERE meta_key = 'amazon_product_id' AND meta_value = '" . $product['product_id'] . "'
501 + ";
502 + $lasso_id = $lasso_db->get_var( $query );
503 + $product['lasso_id'] = ( isset( $lasso_id ) ) ? $lasso_id : 0;
520 504
505 + if ( $store_product ) {
506 + $amazon_tracking_id = Setting::get_setting( 'amazon_tracking_id', '' );
507 + $product['default_url'] = '' === $amazon_tracking_id ? $amz_link : $product['default_url'];
508 + $this->update_amazon_product_in_db( $product, $updated_at );
509 + }
510 +
521 511 return array(
522 512 'product' => $product,
523 513 'api' => 'yes',
524 514 'full_item' => $item,
@@ -524,152 +514,20 @@
524 514 'full_item' => $item,
525 515 'status' => 'success',
526 516 'error_code' => '',
527 517 );
528 - } elseif ( '' !== $lasso_settings['license_serial'] || $force_bls ) {
529 - list( $product, $status ) = $this->fetch_product_from_bls( $product_id, $store_product, $updated_at, $amz_link, $url_version_param, $force_bls, $refresh_image );
530 -
531 - return array(
532 - 'product' => $product,
533 - 'api' => 'no',
534 - 'full_item' => array(),
535 - 'status' => 200 === $status ? 'success' : 'fail',
536 - 'error_code' => 404 === $status ? 'NotFound' : '',
537 - );
538 - }
539 -
540 - return array(
541 - 'product' => array(),
542 - 'api' => 'no',
543 - 'full_item' => array(),
544 - 'status' => 'failed',
545 - 'error_code' => 'NotFound',
546 - );
547 - }
548 -
549 - /**
550 - * Fetch amazon product from BLS (Lambda)
551 - *
552 - * @param string $product_id Amazon product id.
553 - * @param bool $store_product Store product into DB or not. Default to false.
554 - * @param bool|string $updated_at Set date time or not. Default to false.
555 - * @param string $amz_link Amazon link. Default to empty.
556 - * @param bool $url_version_param Is add version param to request api url to ignore cache. Default to false.
557 - * @param bool $force_bls Force fetch product from BLS or not. Default to false.
558 - * @param bool $refresh_image Bypass cache and fetch fresh product image/metadata. Default to false.
559 - */
560 - public function fetch_product_from_bls( $product_id, $store_product = false, $updated_at = false, $amz_link = '', $url_version_param = false, $force_bls = false, $refresh_image = false ) {
561 - $url = strpos( $amz_link, 'amazon.' ) !== false ? $amz_link : $this->get_amazon_link_by_product_id( $product_id, $amz_link );
562 - $m_link = self::get_amazon_product_url( $url );
563 - $url = self::get_amazon_product_url( $url, false );
564 -
565 - $amazon_product = array(
566 - 'title' => '',
567 - 'image' => '',
568 - 'url' => $m_link,
569 - 'price' => '',
570 - 'currency' => '',
571 - 'savings_amount' => 0,
572 - 'savings_percent' => 0,
573 - 'savings_basis' => 0,
574 - );
575 -
576 - try {
577 - $res = Helper::get_url_status_code_by_broken_link_service( $url, true, false, $url_version_param, $force_bls, $refresh_image );
578 - } catch ( \Throwable $e ) {
579 - $res = array(
580 - 'status_code' => 500,
581 - 'response' => null,
582 - );
583 - }
584 -
585 - $bls_response = ( isset( $res['response'] ) && is_object( $res['response'] ) ) ? $res['response'] : null;
586 - $bls_status = ( null !== $bls_response && isset( $bls_response->status ) ) ? intval( $bls_response->status ) : 0;
587 -
588 - if ( 200 === $res['status_code'] && 200 === $bls_status ) {
589 - $img_url = $bls_response->imgUrl ?? '';
590 - $img_url = '' !== $img_url ? $img_url : '';
591 - $product_name = $bls_response->productName ?? '';
592 - $product_name = '' === $product_name ? ( $bls_response->pageTitle ?? '' ) : $product_name;
593 - $quantity = $bls_response->quantity ?? 200;
594 - $price = $bls_response->price ?? '';
595 - $product_id = self::get_product_id_by_url( $url );
596 -
597 - $temp_url = $bls_response->finalUrl ?? $url;
598 - $url = '' !== $temp_url ? $temp_url : $url;
599 - $m_link = self::get_amazon_product_url( $amz_link ? $amz_link : $url );
600 -
601 - if ( strpos( $product_name, 'Amazon.com:' ) === 0 ) {
602 - $product_name = str_replace( 'Amazon.com:', '', $product_name );
603 - $product_name = trim( $product_name );
604 - }
605 -
606 - if ( $product_id && $store_product ) {
607 - $store_data = array(
608 - 'product_id' => $product_id,
609 - 'title' => $product_name,
610 - 'price' => $price,
611 - 'default_url' => $url,
612 - 'url' => $m_link,
613 - 'image' => trim( $img_url ),
614 - 'quantity' => intval( $quantity ), // Manual checks won't show out of stock for now. TODO: Add BLS to out of stock checks.
615 - 'is_manual' => 1,
616 - );
617 -
618 - // ? Set additional data for amazon product
619 - if ( isset( $bls_response->additionalData ) && ! empty( $bls_response->additionalData ) ) {
620 - $basis_price = $bls_response->additionalData->basis_price ?? '';
621 - $basis_price = Helper::get_price_value_from_price_text( $basis_price );
622 - $savings_amount = $bls_response->additionalData->saving_amount ?? '';
623 - $savings_amount = Helper::get_price_value_from_price_text( $savings_amount );
624 -
625 - $store_data['currency'] = $bls_response->additionalData->currency_name ?? '';
626 - $store_data['savings_basis'] = $basis_price;
627 - $store_data['savings_amount'] = $savings_amount;
628 - $store_data['savings_percent'] = $bls_response->additionalData->saving_amount_percent ?? '';
629 -
630 - $amazon_product['currency'] = $store_data['currency'];
631 - $amazon_product['savings_basis'] = $store_data['savings_basis'];
632 - $amazon_product['savings_amount'] = $store_data['savings_amount'];
633 - $amazon_product['savings_percent'] = $store_data['savings_percent'];
634 - }
635 -
636 - $this->update_amazon_product_in_db( $store_data, $updated_at, true ); // allow_partial: BLS may omit imgUrl.
637 - }
638 -
639 - $amazon_product['title'] = $product_name;
640 - $amazon_product['image'] = $img_url;
641 - $amazon_product['url'] = $m_link;
642 - $amazon_product['price'] = $price;
643 - $amazon_product['quantity'] = $quantity;
644 - $amazon_product['status_code'] = $bls_status;
645 - }
646 - if ( 404 === $res['status_code'] || ( 200 === $res['status_code'] && 404 === $bls_status ) ) {
647 - $amz_model = new Amazon_Products();
648 - $last_updated = gmdate( 'Y-m-d H:i:s', time() );
649 - $amz_model->update_amazon_field( $product_id, 'last_updated', $last_updated );
650 - $amz_model->update_amazon_field( $product_id, 'out_of_stock', 0 );
651 - }
652 -
653 - if ( $bls_status ) {
654 - $status = $bls_status;
655 - } elseif ( 200 === intval( $res['status_code'] ?? 0 ) ) {
656 - $status = 500;
657 518 } else {
658 - $status = intval( $res['status_code'] ?? 500 );
519 + return array();
659 520 }
660 -
661 - return array( $amazon_product, intval( $status ) );
662 521 }
663 522
664 523 /**
665 524 * Insert or Update Amazon Product Data
666 525 *
667 - * @param array $product Amazon product.
668 - * @param bool|string $updated_at Set update date time. Default to false.
669 - * @param bool $allow_partial When true, allow empty image (BLS may omit imgUrl). Default false.
526 + * @param array $product Amazon product.
527 + * @param bool|string $updated_at Set update date time. Default to false.
670 528 */
671 - public function update_amazon_product_in_db( $product, $updated_at = false, $allow_partial = false ) {
529 + public function update_amazon_product_in_db( $product, $updated_at = false ) {
672 530 global $wpdb;
673 531
674 532 $lasso_db = new Lasso_DB();
675 533
@@ -691,11 +549,9 @@
691 549 $is_manual = $product['is_manual'] ?? 0;
692 550 $quantity = intval( $product['quantity'] ?? 200 );
693 551 $out_of_stock = 0 === $quantity ? 1 : 0;
694 552
695 - $image_required = ! $allow_partial;
696 - if ( '' === $amazon_id || '' === $default_product_name
697 - || ( $image_required && '' === $default_image )
553 + if ( '' === $amazon_id || '' === $default_product_name || '' === $default_image
698 554 || ( '' !== $default_image && Helper::validate_url( $default_image ) === false && strpos( $default_image, 'data:image' ) !== 0 )
699 555 ) {
700 556 return false;
701 557 }
@@ -1024,44 +880,8 @@
1024 880 return isset( $matches[1] ) && ! empty( $matches[1] ) ? $matches[1] : false;
1025 881 }
1026 882
1027 883 /**
1028 - * Keep URL arguments for Amazon URL
1029 - *
1030 - * @param string $product_url Amazon product url.
1031 - *
1032 - * @return array $results
1033 - */
1034 - private static function keep_args( $product_url ) {
1035 - // ? amazon link but it is not product url
1036 - if ( ! self::is_amazon_url( $product_url ) || self::is_amazon_shortened_url( $product_url ) ) {
1037 - return array();
1038 - }
1039 -
1040 - $results = array();
1041 - $url_params = array(
1042 - 'maas',
1043 - 'ref_',
1044 - 's',
1045 - 'aa_campaignid',
1046 - 'aa_creativeid',
1047 - 'aa_adgroupid',
1048 - 'campaignId',
1049 - 'linkCode',
1050 - 'linkId',
1051 - );
1052 -
1053 - foreach ( $url_params as $param_name ) {
1054 - $param_value = Helper::get_argument_from_url( $product_url, $param_name );
1055 - if ( $param_value ) {
1056 - $results[] = $param_name . '=' . $param_value;
1057 - }
1058 - }
1059 -
1060 - return $results;
1061 - }
1062 -
1063 - /**
1064 884 * Get amazon tracking id by url
1065 885 * This function will be deprecated in the future. Please use Helper::get_argument_from_url() instead
1066 886 *
1067 887 * @param string $link Amazon link.
@@ -1075,18 +895,8 @@
1075 895 return $matches[2] ?? '';
1076 896 }
1077 897
1078 898 /**
1079 - * Clean Amazon URL that contains maas parameter
1080 - *
1081 - * @param string $product_url Amazon product URL.
1082 - * @return string
1083 - */
1084 - public static function clean_maas_url( $product_url ) {
1085 - return $product_url;
1086 - }
1087 -
1088 - /**
1089 899 * Make product url to shorten url if this setting is enabled
1090 900 *
1091 901 * @param string $product_url Amazon product url.
1092 902 * @param bool $monetize Monetize link or not. Default to true.
@@ -1094,67 +904,62 @@
1094 904 * @param string $custom_tracking_id Allow to use custom tracking id.
1095 905 */
1096 906 public static function get_amazon_product_url( $product_url, $monetize = true, $check_lasso_post = true, $custom_tracking_id = '' ) {
1097 907 // ? amazon link but it is not product url
1098 - if ( ! self::is_amazon_url( $product_url ) || self::is_amazon_shortened_url( $product_url ) ) {
908 + if ( ! self::is_amazon_url( $product_url ) || self::is_amazon_shortented_url( $product_url ) ) {
1099 909 return $product_url;
1100 910 }
1101 911
1102 - // If MAAS param exists and the original tag is exactly "maas", leave the URL untouched
1103 - $__maas_arg = Helper::get_argument_from_url( $product_url, 'maas' );
1104 - $__orig_tag = Helper::get_argument_from_url( $product_url, 'tag' );
1105 - if ( $__maas_arg && strtolower( $__orig_tag ) === 'maas' ) {
1106 - return $product_url;
1107 - }
912 + $product_id = self::get_product_id_by_url( $product_url );
1108 913
1109 - $product_id = self::get_product_id_by_url( $product_url );
914 + $tag = Helper::get_argument_from_url( $product_url, 'tag' );
915 + $maas = Helper::get_argument_from_url( $product_url, 'maas' );
916 + $ref_ = Helper::get_argument_from_url( $product_url, 'ref_' );
917 + $s_args = Helper::get_argument_from_url( $product_url, 's' );
1110 918
919 + $maas_args = $maas ? 'maas=' . $maas : '';
920 + $ref__args = $ref_ ? 'ref_=' . $ref_ : '';
921 + $s_args = $s_args ? 's=' . $s_args : '';
922 +
1111 923 // ? remove all url queries, just keep needed args
1112 924 $url_without_params = explode( '?', $product_url )[0];
1113 925 if ( $product_id && ! $monetize ) {
1114 - $keep_args = self::keep_args( $product_url );
1115 - $args = Helper::build_url_parameter_string( $keep_args );
926 + $args = Helper::build_url_parameter_string( array( $maas_args, $ref__args, $s_args ) );
1116 927
1117 - $product_url = $args ? $url_without_params . '?' . $args : $url_without_params;
1118 - $product_url = self::clean_maas_url( $product_url );
928 + return $args ? $url_without_params . '?' . $args : $url_without_params;
929 + }
1119 930
1120 - return $product_url;
931 + $lasso_settings = Setting::get_settings();
932 + $amazon_multiple_tracking_id = $lasso_settings['amazon_multiple_tracking_id'] ?? true;
933 + $amazon_tracking_id_whitelist = $lasso_settings['amazon_tracking_id_whitelist'] ?? array();
934 + $amazon_tracking_id = trim( $lasso_settings['amazon_tracking_id'] ?? '' );
935 +
936 + if ( ! $amazon_multiple_tracking_id ) {
937 + $amazon_tracking_id_whitelist = array();
1121 938 }
1122 939
1123 - $lasso_settings = Setting::get_settings();
1124 - $amazon_tracking_id = trim( $lasso_settings['amazon_tracking_id'] ?? '' );
1125 - $amazon_add_tracking_id_to_attribution = $lasso_settings['amazon_add_tracking_id_to_attribution'] ?? true;
1126 -
1127 940 $lasso_db = new Lasso_DB();
1128 941 $amz_cache_key = self::OBJECT_KEY . '_' . self::FUNCTION_NAME_GET_LASSO_ID_BY_PRODUCT_ID_AND_TYPE . '_' . $product_id . '_' . self::PRODUCT_TYPE;
1129 942 $lasso_id = Cache_Per_Process::get_instance()->get_cache( $amz_cache_key, null );
1130 943 if ( null === $lasso_id ) {
1131 - $lasso_id = $lasso_db->get_lasso_id_by_product_id_and_type( $product_id, self::PRODUCT_TYPE );
944 + $lasso_id = $lasso_db->get_lasso_id_by_product_id_and_type( $product_id );
1132 945 Cache_Per_Process::get_instance()->set_cache( $amz_cache_key, $lasso_id );
1133 946 }
1134 947
1135 948 if ( $check_lasso_post && ! $lasso_id ) {
1136 - $product_url = self::clean_maas_url( $product_url );
1137 949 return $product_url;
1138 950 }
1139 951
1140 - $tag = Helper::get_argument_from_url( $product_url, 'tag' );
1141 952 $tag = $custom_tracking_id ? $custom_tracking_id : $tag;
1142 953 $tag = $tag ? $tag : '';
1143 - $tag = ! empty( $tag ) ? $tag : $amazon_tracking_id;
954 + $tag = ! empty( $amazon_tracking_id ) && ! in_array( $tag, $amazon_tracking_id_whitelist, true )
955 + ? $amazon_tracking_id : $tag;
1144 956
1145 957 // ? Return the remove all url queries for product url
1146 958 if ( $product_id ) {
1147 - $tag_args = $tag ? 'tag=' . $tag : '';
1148 - $keep_args = self::keep_args( $product_url );
1149 - $maas = Helper::get_argument_from_url( $product_url, 'maas' );
1150 - $add_tag_to_url = ( $maas && $amazon_add_tracking_id_to_attribution ) || ! $maas;
959 + $tag_args = $tag ? 'tag=' . $tag : '';
960 + $args = Helper::build_url_parameter_string( array( $tag_args, $maas_args, $ref__args, $s_args ) );
1151 961
1152 - if ( $add_tag_to_url ) {
1153 - array_unshift( $keep_args, $tag_args );
1154 - }
1155 -
1156 - $args = Helper::build_url_parameter_string( $keep_args );
1157 962 $product_url = $args ? $url_without_params . '?' . $args : $url_without_params;
1158 963 } else {
1159 964 $product_url = str_replace( '&', '&', $product_url );
1160 965 $parse = wp_parse_url( $product_url );
@@ -1176,10 +981,8 @@
1176 981 $product_url = trim( $product_url );
1177 982 $product_url = trim( $product_url, '?' );
1178 983 }
1179 984
1180 - $product_url = self::clean_maas_url( $product_url );
1181 -
1182 985 return $product_url;
1183 986 }
1184 987
1185 988 /**
@@ -1470,334 +1273,6 @@
1470 1273
1471 1274 $json_response = $this->query_amazon_v5( $parameters );
1472 1275
1473 1276 return $json_response;
1474 - }
1475 -
1476 - /**
1477 - * Build discount pricing html.
1478 - *
1479 - * @param string $latest_price Latest price.
1480 - * @param mixed $basis_price Basis price value.
1481 - * @param string $currency Currency ISO.
1482 - */
1483 - public static function build_discount_pricing_html( $latest_price, $basis_price, $currency ) {
1484 - $result = '';
1485 -
1486 - try {
1487 - $latest_price_value = Helper::get_price_value_from_price_text( $latest_price );
1488 - $basis_price_value = Helper::get_price_value_from_price_text( $basis_price );
1489 -
1490 - if ( $basis_price_value && ( round( $latest_price_value, 2 ) < round( $basis_price_value, 2 ) ) ) {
1491 - $currency_symbol = Helper::get_currency_symbol_from_iso_code( $currency );
1492 - $currency_position = preg_match( '/[€]|R\$|TL|kr|zł/', $latest_price ) ? 'end' : 'begin';
1493 - $basis_price_format = preg_match( '/[€]|R\$|TL|kr|zł/', $latest_price ) ? number_format( $basis_price_value, 2, ',', '.' ) : number_format( $basis_price_value, 2, '.', ',' );
1494 - $format_price = 'begin' === $currency_position ? $currency_symbol . $basis_price_format : $basis_price_format . ' ' . $currency_symbol;
1495 -
1496 - $result = "<strike>$format_price</strike>";
1497 - }
1498 - } catch ( \Exception $e ) {
1499 - $result = '';
1500 - }
1501 -
1502 - return $result;
1503 - }
1504 -
1505 - /**
1506 - * Check amazon setting is configured or not
1507 - *
1508 - * @return boolean
1509 - */
1510 - public static function is_amazon_setting_configured() {
1511 - $lasso_settings = Setting::get_settings();
1512 - $is_amazon_configured = $lasso_settings['amazon_access_key_id'] && $lasso_settings['amazon_secret_key'] && $lasso_settings['amazon_tracking_id'];
1513 -
1514 - return $is_amazon_configured || self::is_amazon_creators_verified( $lasso_settings );
1515 - }
1516 -
1517 - /**
1518 - * Whether Amazon Creators API credentials are complete in settings.
1519 - *
1520 - * @param array|false $lasso_settings Settings array. Default false loads current settings.
1521 - * @return bool
1522 - */
1523 - public static function is_amazon_creators_configured( $lasso_settings = false ) {
1524 - if ( ! is_array( $lasso_settings ) ) {
1525 - $lasso_settings = Setting::get_settings();
1526 - }
1527 -
1528 - $fields = array(
1529 - 'amazon_creators_credential_id',
1530 - 'amazon_creators_secret',
1531 - 'amazon_creators_version',
1532 - 'amazon_creators_partner_tag',
1533 - );
1534 -
1535 - foreach ( $fields as $field ) {
1536 - if ( '' === trim( (string) ( $lasso_settings[ $field ] ?? '' ) ) ) {
1537 - return false;
1538 - }
1539 - }
1540 -
1541 - return true;
1542 - }
1543 -
1544 - /**
1545 - * Whether Creators credentials were verified successfully (signature matches stored settings).
1546 - *
1547 - * @param array|false $lasso_settings Settings array. Default false loads current settings.
1548 - * @return bool
1549 - */
1550 - public static function is_amazon_creators_verified( $lasso_settings = false ) {
1551 - if ( ! self::is_amazon_creators_configured( $lasso_settings ) ) {
1552 - return false;
1553 - }
1554 -
1555 - if ( ! is_array( $lasso_settings ) ) {
1556 - $lasso_settings = Setting::get_settings();
1557 - }
1558 -
1559 - $current_signature = self::get_amazon_creators_signature( $lasso_settings );
1560 - $saved_signature = (string) Helper::get_option( Constant::LASSO_OPTION_AMAZON_CREATORS_VERIFIED_SIGNATURE, '' );
1561 -
1562 - return '' !== $current_signature && '' !== $saved_signature && hash_equals( $saved_signature, $current_signature );
1563 - }
1564 -
1565 - /**
1566 - * Build a stable signature for the Creators payload.
1567 - *
1568 - * @param array $settings Settings values.
1569 - * @return string Empty when Creators credentials are incomplete.
1570 - */
1571 - public static function get_amazon_creators_signature( $settings ) {
1572 - if ( ! self::is_amazon_creators_configured( $settings ) ) {
1573 - return '';
1574 - }
1575 -
1576 - return hash(
1577 - 'sha256',
1578 - wp_json_encode(
1579 - array(
1580 - 'credential_id' => (string) ( $settings['amazon_creators_credential_id'] ?? '' ),
1581 - 'secret' => (string) ( $settings['amazon_creators_secret'] ?? '' ),
1582 - 'credential_version' => (string) ( $settings['amazon_creators_version'] ?? '' ),
1583 - 'partner_tag' => (string) ( $settings['amazon_creators_partner_tag'] ?? '' ),
1584 - 'country' => (string) ( $settings['amazon_default_tracking_country'] ?? '' ),
1585 - )
1586 - )
1587 - );
1588 - }
1589 -
1590 - /**
1591 - * Resolve Creators API country from an Amazon URL or default tracking country.
1592 - *
1593 - * @param string $amazon_url Amazon product URL (optional).
1594 - * @param array|false $lasso_settings Settings array. Default false loads current settings.
1595 - * @return string
1596 - */
1597 - public static function get_country_for_creators_api( $amazon_url, $lasso_settings = false ) {
1598 - if ( ! is_array( $lasso_settings ) ) {
1599 - $lasso_settings = Setting::get_settings();
1600 - }
1601 -
1602 - if ( $amazon_url && self::is_amazon_url( $amazon_url ) ) {
1603 - $base_domain = strtolower( Helper::get_base_domain( $amazon_url ) );
1604 - if ( '' !== $base_domain ) {
1605 - foreach ( self::get_amazon_api_countries() as $country_code => $country_data ) {
1606 - $amazon_domain = strtolower( Helper::get_base_domain( (string) ( $country_data['amazon_domain'] ?? '' ) ) );
1607 - if ( $base_domain === $amazon_domain ) {
1608 - return (string) $country_code;
1609 - }
1610 - }
1611 - }
1612 - }
1613 -
1614 - return (string) ( $lasso_settings['amazon_default_tracking_country'] ?? '' );
1615 - }
1616 -
1617 - /**
1618 - * Whether the Lite install is linked to a Lasso account email.
1619 - *
1620 - * @return bool
1621 - */
1622 - public static function is_lite_account_connected() {
1623 - $email = Helper::get_option( Constant::LASSO_ACCOUNT_EMAIL, '' );
1624 -
1625 - return is_string( $email ) && '' !== trim( $email );
1626 - }
1627 -
1628 - /**
1629 - * Fetch product data via direct Amazon Creators API (replaces deprecated PA-API GetItems).
1630 - *
1631 - * @param string $product_id Amazon ASIN.
1632 - * @param bool $store_product Store in local DB.
1633 - * @param bool|string $updated_at Optional updated timestamp.
1634 - * @param string $amz_link Amazon URL.
1635 - * @param array $lasso_settings Plugin settings.
1636 - * @return array|null Same shape as fetch_product_info success/failure, or null to fall back.
1637 - */
1638 - private function fetch_product_info_from_creators_api( $product_id, $store_product, $updated_at, $amz_link, $lasso_settings ) {
1639 - if ( ! self::is_amazon_creators_configured( $lasso_settings ) ) {
1640 - return null;
1641 - }
1642 -
1643 - $api_result = Amazon_Creators_Api::fetch_product(
1644 - $product_id,
1645 - self::get_country_for_creators_api( $amz_link, $lasso_settings ),
1646 - array(
1647 - 'product_only' => false,
1648 - )
1649 - );
1650 -
1651 - if ( 'fail' === ( $api_result['status'] ?? '' ) ) {
1652 - $error_code = (string) ( $api_result['error_code'] ?? '' );
1653 -
1654 - if ( 'NotFound' === $error_code ) {
1655 - return $this->build_fetch_product_info_response( array(), 'yes', array(), 'failed', 'NotFound' );
1656 - }
1657 -
1658 - return null;
1659 - }
1660 -
1661 - $product_data = $api_result['product'] ?? array();
1662 - if ( ! is_array( $product_data ) || empty( $product_data ) ) {
1663 - return null;
1664 - }
1665 -
1666 - $full_item = $api_result['item'] ?? array();
1667 - $product = $this->finalize_fetch_product_info_product(
1668 - $product_data,
1669 - $product_id,
1670 - $store_product,
1671 - $updated_at,
1672 - $amz_link
1673 - );
1674 -
1675 - return $this->build_fetch_product_info_response( $product, 'yes', $full_item, 'success', '' );
1676 - }
1677 -
1678 - /**
1679 - * Build fetch_product_info() return array (same contract as get_product_by_id_v5 path).
1680 - *
1681 - * @param array $product Product fields.
1682 - * @param string $api API source flag.
1683 - * @param array|object $full_item Raw item payload.
1684 - * @param string $status success|failed.
1685 - * @param string $error_code Error code.
1686 - * @return array
1687 - */
1688 - private function build_fetch_product_info_response( $product, $api, $full_item, $status, $error_code ) {
1689 - return array(
1690 - 'product' => $product,
1691 - 'api' => $api,
1692 - 'full_item' => $full_item,
1693 - 'status' => $status,
1694 - 'error_code' => $error_code,
1695 - );
1696 - }
1697 -
1698 - /**
1699 - * Apply the same post-processing as the PA-API branch in fetch_product_info().
1700 - *
1701 - * @param array $product Product fields from API.
1702 - * @param string $product_id Amazon ASIN.
1703 - * @param bool $store_product Store in local DB.
1704 - * @param bool|string $updated_at Optional updated timestamp.
1705 - * @param string $amz_link Amazon URL.
1706 - * @return array
1707 - */
1708 - private function finalize_fetch_product_info_product( $product, $product_id, $store_product, $updated_at, $amz_link ) {
1709 - if ( empty( $product['product_id'] ) ) {
1710 - $product['product_id'] = $product_id;
1711 - }
1712 -
1713 - return $this->enrich_fetched_amazon_product( $product, $store_product, $updated_at, $amz_link );
1714 - }
1715 -
1716 - /**
1717 - * Shared post-fetch enrichment for PA-API and Creators product payloads.
1718 - *
1719 - * @param array $product Product fields.
1720 - * @param bool $store_product Store in local DB.
1721 - * @param bool|string $updated_at Optional updated timestamp.
1722 - * @param string $amz_link Amazon URL.
1723 - * @return array
1724 - */
1725 - private function enrich_fetched_amazon_product( $product, $store_product, $updated_at, $amz_link ) {
1726 - global $wpdb;
1727 -
1728 - $lasso_db = new Lasso_DB();
1729 - $product_url = $amz_link ? $amz_link : ( $product['url'] ?? '' );
1730 - $product['status_code'] = 200;
1731 - $product['url'] = self::get_amazon_product_url( $product_url );
1732 -
1733 - $amazon_product_id = (string) ( $product['product_id'] ?? '' );
1734 - $query = $wpdb->prepare(
1735 - 'SELECT post_id FROM ' . $lasso_db->postmeta . " WHERE meta_key = 'amazon_product_id' AND meta_value = %s",
1736 - $amazon_product_id
1737 - );
1738 - $lasso_id = $lasso_db->get_var( $query );
1739 - $product['lasso_id'] = ( isset( $lasso_id ) ) ? $lasso_id : 0;
1740 -
1741 - if ( $store_product ) {
1742 - $amazon_tracking_id = Setting::get_setting( 'amazon_tracking_id', '' );
1743 - $product['default_url'] = '' === $amazon_tracking_id ? $amz_link : ( $product['default_url'] ?? '' );
1744 - $this->update_amazon_product_in_db( $product, $updated_at );
1745 - }
1746 -
1747 - return $product;
1748 - }
1749 -
1750 - /**
1751 - * Get final url of the amazon shortlink from cache
1752 - *
1753 - * @param string $shortlink Amazon shortlink.
1754 - * @return string|null
1755 - */
1756 - public static function get_shortlink_final_url_cached( $shortlink ) {
1757 - if ( ! self::is_amazon_shortened_url( $shortlink ) ) {
1758 - return null;
1759 - }
1760 - $final_url_cache = get_option( self::build_shortlink_cache_key( $shortlink ) );
1761 -
1762 - if ( $final_url_cache === $shortlink ) {
1763 - return null;
1764 - }
1765 -
1766 - return $final_url_cache ? $final_url_cache : null;
1767 - }
1768 -
1769 - /**
1770 - * Build amazon shortlink cache key
1771 - *
1772 - * @param string $shortlink Amazon shortlink.
1773 - * @return string|null
1774 - */
1775 - public static function build_shortlink_cache_key( $shortlink ) {
1776 - if ( ! self::is_amazon_shortened_url( $shortlink ) ) {
1777 - return null;
1778 - }
1779 -
1780 - $parse = wp_parse_url( $shortlink );
1781 - $host = str_replace( '.', '_', $parse['host'] );
1782 - $id = trim( $parse['path'] ?? '', '/' );
1783 -
1784 - return $host . '_' . $id;
1785 - }
1786 -
1787 - /**
1788 - * Format Amazon URLs
1789 - *
1790 - * @param string $url Amazon product url.
1791 - * @return string URL.
1792 - */
1793 - public static function format_amazon_url( $url ) {
1794 - $is_amazon_link = self::is_amazon_url( $url );
1795 - $product_id = self::get_product_id_by_url( $url );
1796 -
1797 - if ( $is_amazon_link && $product_id && strpos( $url, 'smile.amazon.' ) !== false ) {
1798 - $url = str_replace( 'smile.amazon.', 'amazon.', $url );
1799 - }
1800 -
1801 - return $url;
1802 1277 }
1803 1278 }