Amazon SP API拉取listing 和 批量调价
2022-08-18 11:47 天心PHP 阅读(1708) 评论(0) 编辑 收藏 举报文档地址:https://developer-docs.amazon.com/sp-api/docs
class AmazonList{ /**拉取amazonlisting 文档:https://developer-docs.amazon.com/sp-api/docs/reports-api-v2021-06-30-use-case-guide * 1.申请报告 * 2.拉取报告状态 * 3.得到下载报告的URL * 4.下载报告,解析报告 */ public function getAmazonListing(){ $account_id = 106; $requestReport = new AmazonAllListingNew();//创建实例 $account = YbModel::model('AmazonAccount')->findByPk($account_id);//根据账户ID获取账户信息 //申请报告返回一个 ['reportId'=>607810323249222] $result = $requestReport->applicationreport($account->merchant_id,strtolower($account->site),'/reports/2021-06-30/reports',"",["reportType"=>'GET_MERCHANT_LISTINGS_ALL_DATA',"marketplaceIds"=>[$account->market_place_id]]); //获取报告结果 reports后面的数字是上一步返回的结果reportId $result = $requestReport->getreportstatus($account->merchant_id,strtolower($account->site),'/reports/2021-06-30/reports/607810323249222',"","","GET"); //得到结果 /* Array ( [reportType] => GET_MERCHANT_LISTINGS_ALL_DATA [processingEndTime] => 2022-08-18T07:40:12+00:00 [processingStatus] => DONE [marketplaceIds] => Array ( [0] => A1PA6795UKUSNDMFR9 ) [reportDocumentId] => amzn1.spdoc.1.3.35adbdc99-fse83-4c07-a097-9059sd6a3aa6b8.T399XP0BSE3YDD4II.47700 [reportId] => 601310019222 [dataEndTime] => 2022-08-18T07:39:56+00:00 [createdTime] => 2022-08-18T07:39:56+00:00 [processingStartTime] => 2022-08-18T07:40:00+00:00 [dataStartTime] => 2022-08-18T07:39:56+00:00 ) */ //获取报告下载链接 documents后面的参数就是上一步返回的 reportDocumentId $res = $requestReport->getreportsurl($account->merchant_id,strtolower($account->site),'/reports/2021-06-30/documents/amzn1.spdoc.1.3.35adbdc99-fse83-4c07-a097-9059sd6a3aa6b8.T399XP0BSE3YDD4II.47700',"","","GET");//获取报告下载链接 //得到结果 /* Array ( [reportDocumentId] => amzn1.spdoc.1.3.35adbc99-fe83-4c07-a097-90596a3aa6b8.T399XP0B3YD4II.47700 [compressionAlgorithm] => GZIP [url] => https://tortuga-prod-eu.s3-eu-west-1.amazonaws.com/%2FNinstetyDays/amzn1.tortuga.3.bf2b549f-14bc-48484-a4da8-51es52f9e0462.T2TYSPCHTORURJ?X-Amz-Algosrithm=AWS4-HMAC-SHA256&X-Amz-Date=202203818T08043556Z&X-Amz-SignedHeaders=host&X-Amz-Expires=300&X-Amz-Credential=AKIAX2ZVOZFBIW3AHAR5%2F20220818%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=6dbe4f1764c511b7c5a5d5db3ba0c87a1b37eb007d2763803e2b26c44cf7e0d5 ) */ //下载文件 $tmp_name = md5(uniqid(md5(microtime(true)),true));//重命名 if(isset($res['url'])){ $url = Yii::getPathOfAlias('webroot') . '/upload/amazoncsv/';//保存下载文件的路径 $filename = $tmp_name.'.gz';//gz压缩包 //下载文件 $requestReport->getFile($res['url'],$url,$filename);//下载文件 $content = $requestReport->read_gz($url.$filename);//读取压缩包里面的内容 if($content){ @unlink($url . $filename);//读取内容了 删除下载的包 //解析内容 不同的站点解析规则不同 if(strtolower($account->site)=='jp'){ handleListItemJP($content, $account); }elseif (strtolower($account->site)=='fr'){ handleListItemFr($content, $account); }else{ handleListItem($content, $account); } } } } /**amazon调价 文档:https://developer-docs.amazon.com/sp-api/docs/feeds-api-v2021-06-30-use-case-guide * 1.调用createFeedDocument操作,为您提交的提要指定内容类型。返回一个feedDocumentId值和一个用于上传 feed 内容的 URL。(步骤 1. 创建提要文件) * 2.组建xml格式(步骤 2. 构建提要) * 3.将您的提要文档内容上传到上一步中的 URL。(步骤 3. 上传 Feed 数据) * 4.调用createFeed操作。使用inputFeedDocumentId参数传入步骤 1 中的feedDocumentId值。指定您希望应用该提要的市场以及任何相关的提要选项。亚马逊返回一个feedId值(第 4 步:创建提要) * 5.获取 /feeds/2021-06-30/feeds/{feedId}结果状态(Step 5. 确认饲料加工) * 6.Feed 处理报告指出您提交的 Feed 中哪些记录成功,哪些记录产生了错误。在此步骤中,您将获得一个用于下载 Feed 处理报告的预签名 URL。(步骤 6. 获取信息以检索 Feed 处理报告) * 7.下载处理的结果 (步骤 7. 下载 Feed 处理报告) */ public function putAmazonPrice(){ $account_id = 106; $requestReport = new AmazonAllListingNew(); $account = YbModel::model('AmazonAccount')->findByPk($account_id);//根据账户ID获取账户信息 $payload =["contentType"=>"text/xml; charset=UTF-8"]; //第一步 获取上传的url $res = $requestReport->applicationreport($account->merchant_id,strtolower($account->site),'/feeds/2021-06-30/documents','',$payload,'POST'); //得到结果 /*Array ( [feedDocumentId] => amzn1.tortuga.3.c1862c93-d899-4529-866a-035c3ed971d4.T2OJ5JLG154REG [url] => https://tortuga-prod-eu.s3-eu-west-1.amazonaws.com/%2FNinetyDays/amzn1.tortuga.3.c18s62c93-d899-4529-866a-035c3ed971d4.T2OJ5JLG154REG?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20220818T092528Z&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Expires=300&X-Amz-Credential=AKIAX2ZVOZFBIW3AHAR5%2F20220818%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=7a0a7b8fc15f0ed3ff0372eead322d4617eaf07f03c39330ad0da46acef14756 )*/ //第二步 组织xml格式 $feeddata = [ [ 'sku'=>'FBA - RC-Winschset', 'stdprice'=>30.19, 'BusinessPrice'=>29.59, 'currency'=>'EUR' ], [ 'sku'=>'FBA - 1000pcs Screws', 'stdprice'=>10.49, 'BusinessPrice'=>10.29, 'currency'=>'EUR' ] ]; $xml = $requestReport->getxml($account->merchant_id,$feeddata); //得到结果 /* * <?xml version="1.0"?> <amazonenvelope xsi:nonamespaceschemalocation="amzn-envelope.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <header> <documentversion>1.01</documentversion> <merchantidentifier>A68YOTXQQLJUV</merchantidentifier> </header> <messagetype>Price</messagetype> <message> <messageid>1</messageid> <price> <sku>FBA - RC-Winschset</sku> <standardprice currency="EUR">30.19</standardprice> <businessprice>29.59</businessprice> </price> </message> <message> <messageid>2</messageid> <price> <sku>FBA - 1000pcs Screws</sku> <standardprice currency="EUR">10.49</standardprice> <businessprice>10.29</businessprice> </price> </message> </amazonenvelope> */ //第三步 上传xml $res1 = $requestReport->cur_request($res['url'],'PUT',$xml,["Content-Type:text/xml; charset=UTF-8"]); //结果 $res1[0]==200 上传成功 //第四步 createFeed操作 inputFeedDocumentId 为第一步得到的 feedDocumentId $payload2 = ["feedType"=>"POST_PRODUCT_PRICING_DATA","marketplaceIds"=>[$account->market_place_id],"inputFeedDocumentId"=>$res['feedDocumentId']]; $res2 = $requestReport->applicationreport($account->merchant_id,strtolower($account->site),'/feeds/2021-06-30/feeds','',$payload2,'POST'); //得到结果 ["feedId"=>542852019132] //第五步 获取结果状态 feeds后面的数组 是第四步获取得到 $feedsinfo = $requestReport->applicationreport($account->merchant_id,strtolower($account->site),'/feeds/2021-06-30/feeds/542852019132','','','GET'); //得到结果 /* Array ( [processingEndTime] => 2022-08-18T02:13:15+00:00 [processingStatus] => DONE //代表成功 [marketplaceIds] => Array ( [0] => A1PA6795UKMFR9 ) [feedId] => 601176019222 [feedType] => POST_PRODUCT_PRICING_DATA [createdTime] => 2022-08-18T02:08:40+00:00 [processingStartTime] => 2022-08-18T02:08:48+00:00 [resultFeedDocumentId] => amzn1.tortuga.3.b0b72a07-653f-43cc-81c4-f6dcdde3494e.T3EM20FN5I647Q ) */ //第六步 获取信息以检索 Feed 处理报告 documents后面的数组 为 第五步得到的 resultFeedDocumentId if(isset($feedsinfo['processingStatus'])&&$feedsinfo['processingStatus']=='DONE'){ $xmlurl = $requestReport->applicationreport($account->merchant_id,$account->site,'/feeds/2021-06-30/documents/'.$feedsinfo['resultFeedDocumentId'],'','','GET'); if(isset($xmlurl['url'])){ //第七步得到 xml内容查看结果 $xml = file_get_contents($xmlurl['url']); //结果 /* <AmazonEnvelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="amzn-envelope.xsd"> <Header> <DocumentVersion>1.02</DocumentVersion> <MerchantIdentifier>A68YOTXQQLJUV</MerchantIdentifier> </Header> <MessageType>ProcessingReport</MessageType> <Message> <MessageID>1</MessageID> <ProcessingReport> <DocumentTransactionID>601176019222</DocumentTransactionID> <StatusCode>Complete</StatusCode> <ProcessingSummary> <MessagesProcessed>489</MessagesProcessed> <MessagesSuccessful>489</MessagesSuccessful> //成功的数量 <MessagesWithError>0</MessagesWithError> <MessagesWithWarning>0</MessagesWithWarning> </ProcessingSummary> </ProcessingReport> </Message> </AmazonEnvelope> */ } } } public static function handleListItemJp($filename, $accountInfo) { $tmp_name = md5(uniqid(md5(microtime(true)),true)); file_put_contents($tmp_name,$filename); $status = array('Active'=>1, 'Inactive'=>2, 'Incomplete'=>9); $model = YbModel::model('AmazonLog'); $i = 0; $c = []; $file = fopen($tmp_name,"rb"); while(!feof($file)) { $data = null; $items = null; $str = null; $title_items = null; $str = fgets($file); $items = explode("\t",$str); if (++$i == 1) { $column_len = count($items); foreach ($items as $k => $v) { $str = iconv('Shift-JIS','utf-8', trim($v)); $title_items[] = $str; } $c = array_reverse($title_items); $c = array_flip($c); continue; } $data = array_reverse($items); if (count($data) < $column_len) { self::mylog($model, $accountInfo->account_name, 'err_col > '.addslashes($str), '异常数据',1); continue; } if (trim($data[$c['ステータス']]) == 'Incomplete') continue; $line_data = null; //获取表格内指定行数据 $line_data = json_encode([ 'account_id' => $accountInfo->id, 'item_name' => CHelper::TrimStr(trim($data[$column_len - 1])), 'listing_id' => CHelper::TrimStr($data[$c['出品ID']]), 'seller_sku' => CHelper::TrimStr($data[$c['出品者SKU']]), 'price' => is_numeric(CHelper::TrimStr($data[$c['価格']])) ? CHelper::TrimStr($data[$c['価格']]) : "NULL", 'quantity' => is_numeric(CHelper::TrimStr($data[$c['数量']])) ? CHelper::TrimStr($data[$c['数量']]) : "NULL", 'open_date' => CHelper::TrimStr($data[$c['出品日']]), 'image_url' => '', 'item_is_marketplace' => '', 'item_condition' => is_numeric(CHelper::TrimStr($data[$c['コンディション']])) ? CHelper::TrimStr($data[$c['コンディション']]) : "NULL", 'asin1' => '', 'product_id' => CHelper::TrimStr($data[$c['商品ID']]), 'product_id_type' => CHelper::TrimStr($data[$c['商品IDタイプ']]), 'add_delete' => '', 'pending_quantity' => is_numeric(CHelper::TrimStr($data[$c['在庫数']])) ? CHelper::TrimStr($data[$c['在庫数']]) : "NULL", 'fulfillment_channel' => CHelper::TrimStr($data[$c['フルフィルメント・チャンネル']])=='DEFAULT' ? 'DEF': 'AMA', 'status' => $status[CHelper::TrimStr(trim($data[$c['ステータス']]))] ],JSON_UNESCAPED_UNICODE); if (empty($line_data)) { self::mylog($model, $accountInfo->account_name, 'err_col > '.addslashes($str), '空数据',1); continue; } $insert_data[] = [ 'report_type' => self::LISTING, 'account_id' => $accountInfo->id, 'report_data' => addslashes($line_data), 'site' => $accountInfo->site ]; //如果待写入数据到了500则开始写入数据 if (count($insert_data) >= 500) { self::_insertData($model,$insert_data,$accountInfo->account_name); unset($insert_data); } } fclose($file); if (is_file($tmp_name)) { unlink($tmp_name); self::saveTmpFile($tmp_name, $accountInfo->id, $accountInfo->site); } if (!empty($insert_data)) { self::_insertData($model,$insert_data,$accountInfo->account_name); } return $i; } public static function handleListItemFr($filename, $accountInfo) { $tmp_name = md5(uniqid(md5(microtime(true)),true)); file_put_contents($tmp_name,$filename); $status = array('Active'=>1, 'Inactive'=>2, 'Incomplete'=>9); $model = YbModel::model('AmazonLog'); $i = 0; $c = []; $col_len = 0; $file = fopen($tmp_name,"rb"); while(!feof($file)) { $data = null; $items = null; $str = null; $title_items = null; $str = fgets($file); $items = explode("\t",$str); if (++$i == 1) { $column_len = count($items); foreach ($items as $k => $v) { $title_items[] = trim($v); } $c = array_reverse($title_items); $c = array_flip($c); continue; } $data = array_reverse($items); if (count($data) < $column_len) { self::mylog($model, $accountInfo->account_name, 'err_col > '.addslashes($str), '异常数据',1); continue; } if (trim($data[$c['status']]) == 'Incomplete') continue; $line_data = null; //获取表格内指定行数据 if(isset($c['fulfilment-channel'])){ $fulfillment_channel = $data[$c['fulfilment-channel']] == 'DEFAULT' ? 'DEF' : 'AMA'; }else if(isset($c['fulfillment-channel'])){ $fulfillment_channel = $data[$c['fulfillment-channel']] == 'DEFAULT' ? 'DEF' : 'AMA'; }else{ $fulfillment_channel = 'DEF'; } $line_data = json_encode([ 'account_id' => $accountInfo->id, 'item_name' => utf8_encode(trim($data[$column_len-1])), 'listing_id' => $data[$c['listing-id']], 'seller_sku' => $data[$c['seller-sku']], 'price' => is_numeric($data[$c['price']]) ? $data[$c['price']] : "NULL", 'quantity' => is_numeric($data[$c['quantity']]) ? $data[$c['quantity']] : "NULL", 'open_date' => $data[$c['open-date']], 'image_url' => '', 'item_is_marketplace' => '', 'item_condition' => is_numeric($data[$c['item-condition']]) ? $data[$c['item-condition']] : "NULL", 'asin1' => '', 'product_id' => $data[$c['product-id']], 'product_id_type' => $data[$c['product-id-type']], 'add_delete' => '', 'pending_quantity' => is_numeric($data[$c['pending-quantity']]) ? $data[$c['pending-quantity']] : "NULL", 'fulfillment_channel' => $fulfillment_channel, 'status' => $status[trim($data[$c['status']])] ], JSON_UNESCAPED_UNICODE); if (empty($line_data)) { self::mylog($model, $accountInfo->account_name, 'err_col > '.addslashes($str), '空数据',1); continue; } $insert_data[] = [ 'report_type' => self::LISTING, 'account_id' => $accountInfo->id, 'report_data' => addslashes($line_data), 'site' => $accountInfo->site ]; //如果待写入数据到了500则开始写入数据 if (count($insert_data) >= 500) { self::_insertData($model,$insert_data,$accountInfo->account_name); unset($insert_data); } } fclose($file); if (is_file($tmp_name)) { unlink($tmp_name); self::saveTmpFile($tmp_name, $accountInfo->id, $accountInfo->site); } if (!empty($insert_data)) { self::_insertData($model,$insert_data,$accountInfo->account_name); } return $i; } public static function handleListItem($filename, $accountInfo) { $tmp_name = md5(uniqid(md5(microtime(true)),true)); file_put_contents($tmp_name,$filename); $model = YbModel::model('AmazonLog'); $status = array( 'Active' => 1, 'Inactive' => 2, 'Incomplete' => 9 ); $index = $accountInfo->site == 'ae' ? 27 : 28; $i = 0; $column_len = 0; $file = fopen($tmp_name,"rb"); while(!feof($file)) { $data = null; $items = null; $str = null; $title_items = null; $str = fgets($file); $items = explode("\t",$str); if (++$i == 1) { $column_len = count($items); $sp_bm = []; foreach ($items as $k => $v) { if (trim($v) == '商品编码') { if (in_array($v,$sp_bm)) { $v = '商品编码2'; } else { $sp_bm[] = $v; } } $title_items[] = trim($v); } $c = array_reverse($title_items); $c = array_flip($c); continue; } $data = array_reverse($items); if (count($data) < $column_len) { self::mylog($model, $accountInfo->account_name, 'err_col > '.addslashes($str), '异常数据',1); continue; } $line_data = null; //获取表格内指定行数据 $listing_id = ''; $seller_sku = ''; $price = ''; $quantity = ''; $open_date = ''; $item_is_marketplace = ''; $item_condition = ''; $asin1 = ''; $product_id = ''; $product_id_type = ''; $pending_quantity = ''; $fulfillment_channel = ''; $status_report = ''; if (isset($c['status'])) { $listing_id = $data[$c['listing-id']]; $seller_sku = $data[$c['seller-sku']]; $price = is_numeric($data[$c['price']]) ? $data[$c['price']] : "NULL"; $quantity = is_numeric($data[$c['quantity']]) ? $data[$c['quantity']] : "NULL"; $open_date = $data[$c['open-date']]; $item_is_marketplace = $data[$c['item-is-marketplace']]; $item_condition = is_numeric($data[$c['item-condition']]) ? $data[$c['item-condition']] : "NULL"; $asin1 = $data[$c['asin1']]; $product_id = $data[$c['product-id']]; $product_id_type = $data[$c['product-id-type']]; $pending_quantity = is_numeric($data[$c['pending-quantity']]) ? $data[$c['pending-quantity']] : "NULL"; if(isset($c['fulfilment-channel'])){ $fulfillment_channel = $data[$c['fulfilment-channel']] == 'DEFAULT' ? 'DEF' : 'AMA'; }else if(isset($c['fulfillment-channel'])){ $fulfillment_channel = $data[$c['fulfillment-channel']] == 'DEFAULT' ? 'DEF' : 'AMA'; }else{ $fulfillment_channel = 'DEF'; } $status_report = $status[trim($data[$c['status']])]; $items_status = trim($data[$c['status']]); } elseif (isset($c['状态'])) { $listing_id = $data[$c['商品编码']]; $seller_sku = $data[$c['卖家 SKU']]; $price = is_numeric($data[$c['价格']]) ? $data[$c['价格']] : "NULL"; $quantity = is_numeric($data[$c['数量']]) ? $data[$c['数量']] : "NULL"; $open_date = $data[$c['开售日期']]; $item_is_marketplace = $data[$c['是否为商城中的商品']]; $item_condition = is_numeric($data[$c['商品状况']]) ? $data[$c['商品状况']] : "NULL"; $asin1 = $data[$c['ASIN1']]; $product_id = $data[$c['商品编码2']]; $product_id_type = $data[$c['商品编码类型']]; $pending_quantity = is_numeric($data[$c['等待购买数量']]) ? $data[$c['等待购买数量']] : "NULL"; $fulfillment_channel = $data[$c['配送渠道']] == 'DEFAULT' ? 'DEF' : 'AMA'; $status_report = $status[trim($data[$c['状态']])]; $items_status = trim($data[$c['状态']]); } else { self::mylog($model, $accountInfo->account_name, 'err_col > '.addslashes($str), '未匹配到数据',1); continue; } //未完成状态不下载 if ($items_status == 'Incomplete') continue; if (empty($open_date) || empty($asin1)) { self::mylog($model, $accountInfo->account_name, 'err_col > '.addslashes($str), '字段数据缺失',1); continue; } $line_data = json_encode([ 'account_id' => $accountInfo->id, 'item_name' => utf8_encode(trim($data[$column_len-1])), 'listing_id' => $listing_id, 'seller_sku' => $seller_sku, 'price' => $price, 'quantity' => $quantity, 'open_date' => $open_date, 'image_url' => '', 'item_is_marketplace' => $item_is_marketplace, 'item_condition' => $item_condition, 'asin1' => $asin1, 'product_id' => $product_id, 'product_id_type' => $product_id_type, 'add_delete' => '', 'pending_quantity' => $pending_quantity, 'fulfillment_channel' => $fulfillment_channel, 'status' => $status_report ], JSON_UNESCAPED_UNICODE); if (empty($line_data)) { self::mylog($model, $accountInfo->account_name, 'err_col > '.addslashes($str), '空数据',1); continue; } $insert_data[] = [ 'report_type' => self::LISTING, 'account_id' => $accountInfo->id, 'report_data' => addslashes($line_data), 'site' => $accountInfo->site ]; //如果待写入数据到了500则开始写入数据 file_put_contents("dump_0813.txt",date("Y-m-d H:i:s")."--001"."\n".var_export($insert_data,true).PHP_EOL, FILE_APPEND); if (count($insert_data) >= 500) { self::_insertData($model,$insert_data,$accountInfo->account_name); unset($insert_data); } } fclose($file); if (is_file($tmp_name)) { unlink($tmp_name); self::saveTmpFile($tmp_name, $accountInfo->id, $accountInfo->site); } if (!empty($insert_data)) { self::_insertData($model,$insert_data,$accountInfo->account_name); } return $i; } /** * 通过标识符(ASIN)检索Amazon目录中单个商品的详细信息 * @throws Exception * /services/amazon/amazonfbainventoryplanning/getbrand */ public function actionGetBrand(){ $requestReport = new AmazonAllListingNew(); $account = YbModel::model('AmazonAccount')->findByPk(7); $result = $requestReport->applicationreport($account->merchant_id,strtolower($account->site),'/catalog/2022-04-01/items/B0B936PZDF',['marketplaceIds'=>$account->market_place_id],"",'GET'); print_r('<pre>'); print_r($result); print_r('</pre>'); exit(); } /** * 按ASIN或产品标识符搜索一个或多个项目 * @throws Exception * /services/amazon/amazonfbainventoryplanning/getbrandlist */ public function actionGetBrandList(){ $requestReport = new AmazonAllListingNew(); $account = YbModel::model('AmazonAccount')->findByPk(7); $result = $requestReport->applicationreport($account->merchant_id,strtolower($account->site),'/catalog/2022-04-01/items',['marketplaceIds'=>$account->market_place_id,'identifiersType'=>'ASIN','identifiers'=>'B0B93M87Z8,B0B936PZDF'],"",'GET'); print_r('<pre>'); print_r($result); print_r('</pre>'); exit(); } }
基础类:
class AmazonAllListingNew { private $url = "http://s1.xxxxxx.com/amz_sp_sign_v1.php"; //授权获取token是另一个系统做的 private $amzurl = "https://sellingpartnerapi-na.amazon.com"; private $amzurl1 = "https://sellingpartnerapi-eu.amazon.com"; private $amzurl2 = "https://sellingpartnerapi-fe.amazon.com"; private $sitelist = [ 'us' => 1, 'uk' => 2, 'de' => 3, 'fr' => 4, 'it' => 5, 'jp' => 6, 'ca' => 8, 'es' => 9, 'sp' => 9, 'mx' => 11, 'br' => 14, 'tr' => 15, 'nl' => 17, 'se' => 19, 'pl' => 20 ]; private $token, $SellerId, $SiteID; public function __construct() { $this->token = AmazonModelHelper::getecpptoken();//调用另一个系统的token } //不同的站点域名不同 public function geturl($site) { if (in_array($site, ['us', 'br', 'ca', 'mx'])) { $url = $this->amzurl; } elseif (in_array($site, ['jp', 'sg', 'au'])) { $url = $this->amzurl2; } else { $url = $this->amzurl1; } return $url; } //得到调价的xml public function getxml($merchant_id, $feeddata) { $xml = '<?xml version="1.0" encoding="UTF-8"?><AmazonEnvelope xsi:noNamespaceSchemaLocation="amzn-envelope.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Header><DocumentVersion>1.01</DocumentVersion><MerchantIdentifier>' . $merchant_id . '</MerchantIdentifier></Header><MessageType>Price</MessageType>'; foreach ($feeddata as $key => $val) { $xml .= '<Message><MessageID>' . ($key + 1) . '</MessageID><Price><SKU>' . $val['sku'] . '</SKU>'; if (isset($val['saleprice'])) { $xml .= '<Sale><StartDate>' . $val['stime'] . '</StartDate><EndDate>' . $val['etime'] . '</EndDate><SalePrice currency="' . $val['currency'] . '">' . $val['saleprice'] . '</SalePrice></Sale>'; } $xml .= '<StandardPrice currency="' . $val['currency'] . '">' . $val['stdprice'] . '</StandardPrice><BusinessPrice>' . $val['BusinessPrice'] . '</BusinessPrice></Price></Message>'; } $xml .= '</AmazonEnvelope>'; return $xml; } //得到调库存的xml public function getstockxml($merchant_id, $feeddata) { $xml = '<?xml version="1.0" encoding="utf-8"?><AmazonEnvelope xsi:noNamespaceSchemaLocation="amzn-envelope.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Header><DocumentVersion>1.01</DocumentVersion><MerchantIdentifier>' . $merchant_id . '</MerchantIdentifier></Header><MessageType>Inventory</MessageType>'; foreach ($feeddata as $key => $val) { $xml .= '<Message><MessageID>' . ($key + 1) . '</MessageID><OperationType>Update</OperationType><Inventory><SKU>' . $val['sku'] . '</SKU><Quantity>' . $val['qty'] . '</Quantity><FulfillmentLatency>' . $val['latency'] . '</FulfillmentLatency></Inventory></Message>'; } $xml .= '</AmazonEnvelope>'; return $xml; } /** 获取报告下载链接 * @param $SellerId * @param $Path * @param string $QueryParams * @param string $Payload * @param string $type * @return array|mixed */ public function getreportsurl($SellerId, $site, $Path, $QueryParams = '', $Payload = '', $type = 'GET') { $headers = $this->getheaders($SellerId, $site, $Path, $QueryParams, $Payload, $type); $url = $this->geturl($site) . $Path; $data2 = $type == 'GET' ? $QueryParams : $Payload; $res2 = $this->cur_request($url, $type, "", $headers); $list = []; if ($res2[0] == 200) { $list = $res2[1]; } return $list; } /** 获取报告状态 * @param $SellerId * @param $Path * @param string $QueryParams * @param string $Payload * @param string $type * @return * [0]=>200 * [1]=>[ * [reportType] => GET_MERCHANT_LISTINGS_ALL_DATA * [processingEndTime] => 2022-08-18T07:40:12+00:00 * [processingStatus] => DONE * [marketplaceIds] => Array * ( * [0] => A1PA6795UKMFR9 * ) * [reportDocumentId] => amzn1.spdoc.1.3.35adbc99-fe83-4c07-a097-90596a3sdfasdsdfsdaa6b8.T399XP0B3YD4II.47700 * [reportId] => 6013100123239222 * [dataEndTime] => 2022-08-18T07:39:56+00:00 * [createdTime] => 2022-08-18T07:39:56+00:00 * [processingStartTime] => 2022-08-18T07:40:00+00:00 * [dataStartTime] => 2022-08-18T07:39:56+00:00 * ] */ public function getreportstatus($SellerId, $site, $Path, $QueryParams = '', $Payload = '', $type = 'GET') { $headers = $this->getheaders($SellerId, $site, $Path, $QueryParams, $Payload, $type); $url = $this->geturl($site) . $Path; $data2 = $type == 'GET' ? $QueryParams : $Payload; $res2 = $this->cur_request($url, $type, "", $headers); $list = []; if ($res2[0] == 200) { $list = $res2[1]; } return $list; } /** 申请报告 * @param $SellerId * @param $Path * @param string $QueryParams * @param string $Payload * @param string $type * @return * [0]=>202 * [1]=>['reportId'=>607810349222] */ public function applicationreport($SellerId, $site, $Path, $QueryParams = '', $Payload = '', $type = 'POST') { $headers = $this->getheaders($SellerId, $site, $Path, $QueryParams, $Payload, $type); $url = $this->geturl($site) . $Path;//不同的站点对应的url不同 if($type=='GET' && $QueryParams){ $url = $url.'?'; foreach ($QueryParams as $key=>$val){ $url.=$key.'='.$val.'&'; } } $url = rtrim($url,"&"); $data2 = $type == 'GET' ? $QueryParams : $Payload;//内容 $res2 = $this->cur_request($url, $type, is_array($data2)?json_encode($data2):$data2, $headers); $list = []; $list = $res2[1]; return $list; } /** 获取订单 * @param $SellerId * @param $Path * @param string $QueryParams * @param string $Payload * @param string $type * @return array|mixed */ public function getorders($SellerId, $Path, $QueryParams = '', $Payload = '', $type = 'GET') { $headers = $this->getheaders($SellerId, $Path, $QueryParams, $Payload, $type); $url = $this->amzurl . $Path; if ($type == 'GET' && $QueryParams) { $url = $url . '?'; foreach ($QueryParams as $key => $val) { $url .= $key . '=' . $val . '&'; } } $url = rtrim($url, "&"); $data = $type == 'GET' ? $QueryParams : $Payload; $res = $this->cur_request($url, $type, $data, $headers); if ($res[0] == 200) { return $res[1]['payload']; } return []; } /** 获取签名加密的头部信息 * @param $SellerId APPID * @param $Path 路径 * @param string $QueryParams URL参数 * @param string $Payload Http Body参数 * @return * data =>[ * 'content-type'=>'application/json', * 'host'=>'sellingpartnerapi-eu.amazon.com', * 'x-amz-access-token'=>'Atza|IwEBIFeKuf0TMLRiErT21YMvY7zuvL2s7VU5-_Mo9hP3yMWPgY5_ojxZ0FfTceO8ml8670zIXMbFAg1aH7aTYnCyzYV1kqkOvzzS7__9zUmP8u0SU2f72hqxQ2xJ_0jfDauI547puR5fdOfESpAK3RlnngOr22RMzs1...', * 'x-amz-date'=>'20220818T073502Z', * 'Authorization'=>'AWS4-HMAC-SHA256 Credential=AKIAVXZJUCM74Z3OQDQ5/20220818/eu-west-1/execute-api/aws4_request, SignedHeaders=host;x-amz-access-token;x-amz-date, Signature=50f9c73125dc65c7e57a8beeca3af999fece248f0b96084abf9fdddec2ccba3e' * ] */ public function getheaders($SellerId, $site, $Path, $QueryParams = '', $Payload = '', $type = 'GET') { if (!$SellerId || !$Path) { return '参数错误'; exit(); } $tdata = date('YmdHi', (time() - 8 * 3600)); $tdata = substr_replace($tdata, 'T', 8, 0); $access_token = $this->gettoken($SellerId); $data = [ "token" => $this->token, "action" => "Signature", "SellerId" => $SellerId, "config" => ["SiteID" => $this->sitelist[strtolower($site)], "Path" => $Path], "parameters" => [ "AccessToken" => $access_token, "HttpMethod" => $type, "QueryParams" => $QueryParams, "Payload" => $Payload, "Timestamp" => $tdata . "02Z", "headers" => ["content-type" => "application/json"] ] ]; $headers = []; $res = $this->cur_request($this->url, 'POST', json_encode($data), ''); if ($res[0] == 200 && $res[1]['success'] == 1) { foreach ($res[1]['data']['headers'] as $key => $val) { $headers[] = $key . ":" . $val; } } return $headers; } /**获取access_token (因为是从ecpp获取的token,刷新token) * @param $SellerId * @return * data = [ * 'access_token'=>'Atza|IwEBIDAOKLIaQGdlwms0KXma2ezFoJkfC6VkbuvWXGPhP8Yfpmyufcx-trU7Q4d5WbqS9pqTfh-Lqkg1LB81BOdiuCY....', * 'refresh_token'=>'Atzr|IwEBIAeGmiOy6aCYcAWzF2f6mxkfYJui7q5HFaVu94VdTS7yrTvqJWDVm2peQCMtvx0AhC6...', * 'token_type'=>'bearer', * 'expires_in'=>3600 * ] */ public function gettoken($SellerId) { $data = [ "token" => $this->token,//ecpp的token "SellerId" => $SellerId,//appid也就是merchant_id "action" => "RefreshToken", "parameters" => [ "RefreshToken" => $this->getecppinfo()[$SellerId] ] ]; $res = $this->cur_request($this->url, 'POST', json_encode($data), ''); $access_token = ''; if ($res[0] == 200 && $res[1]['success'] == 1) { $access_token = $res[1]['data']['access_token']; } return $access_token; } public function getecppinfo() {//ecpp的token $url = "http://publish.xxxxx.com/services/yunyi/amazonapi/getecppinfo"; $data = $this->cur_request($url, 'GET', "", ""); return $data[1]; } //请求函数 public function cur_request($URL, $type, $params, $headers, $types = 0) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $URL); if ($headers != "") { curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); } else { curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json')); } curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); switch ($type) { case "GET" : curl_setopt($ch, CURLOPT_HTTPGET, true); break; case "POST": curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $params); break; case "PUT" : curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); curl_setopt($ch, CURLOPT_POSTFIELDS, $params); break; case "PATCH": curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH'); curl_setopt($ch, CURLOPT_POSTFIELDS, $params); break; case "DELETE": curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE"); curl_setopt($ch, CURLOPT_POSTFIELDS, $params); break; } $file_contents = curl_exec($ch);//获得返回值 if ($types) { print_r('<pre>'); print_r($file_contents); print_r('</pre>'); } $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($types) { print_r('<pre>'); print_r($responseCode); print_r('</pre>'); } curl_close($ch); return [$responseCode, json_decode($file_contents, true)]; } /** * description: 文件下载 * @throws CException */ public function getFile($url, $save_dir = '', $filename = '', $type = 0) { if (trim($url) == '') { return false; } if (trim($save_dir) == '') { $save_dir = './'; } if (0 !== strrpos($save_dir, '/')) { $save_dir .= '/'; } //创建保存目录 if (!file_exists($save_dir) && !mkdir($save_dir, 0777, true)) { return false; } //获取远程文件所采用的方法 if ($type) { $ch = curl_init(); $timeout = 5; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); $content = curl_exec($ch); curl_close($ch); } else { ob_start(); readfile($url); $content = ob_get_contents(); ob_end_clean(); } //echo $content; $size = strlen($content); //文件大小 $fp2 = @fopen($save_dir . $filename, 'a'); @fwrite($fp2, $content); @fclose($fp2); unset($content, $url); return array( 'status' => 1, 'file_name' => $filename, 'save_path' => $save_dir . $filename, 'file_size' => $size ); } //得到.gz压缩包的内容 public function read_gz($gz_file) { $buffer_size = 4096; // read 4kb at a time $file = gzopen($gz_file, 'rb'); $str = ''; while (!gzeof($file)) { $str .= gzread($file, $buffer_size); } gzclose($file); return $str; } //用yield读取大文件 public function read_yield_gz($gz_file) { $buffer_size = 4096; // read 4kb at a time $file = gzopen($gz_file, 'rb'); while (!gzeof($file)) { yield gzread($file, $buffer_size); } gzclose($file); } /** * description: 读取CSV * @throws CException * 使用 $csvlist = $this->modelapi->readCSV($url.'kaufland_'.$val['id_report'].'.csv'); * foreach ($csvlist as $key=>$vd){} */ public function readCSV($filename) { $fp = fopen($filename, 'rb'); while (!feof($fp)) { yield fgetcsv($fp); } fclose($fp); } //过滤表情信息 private function filter_emoji($str = '') { preg_match_all('/[\x{4e00}-\x{9fff}\d\w\s[:punct:]]+/u', $str, $result); return join('', $result[0]); } //对文本文件结果进行解析 public function turnTxt2Array($txt, $account_id) { $array = array(); $txt = explode("\n", $txt); $keys = array_map('trim', explode("\t", str_replace('-', '_', array_shift($txt)))); array_push($keys, 'account_id', 'update_time');//添加自己的 账户ID和时间 foreach ($txt as $unit) { $unit = str_replace('--', 0, $unit); $unit = array_map('trim', explode("\t", $unit)); $unit[3] = base64_encode($unit[3]); array_push($unit, $account_id, time());//对应的账户和时间内容 if (count($keys) != count($unit)) { continue; } $array[] = array_combine($keys, $unit); } return $array; } }
拉取listing GET_MERCHANT_LISTINGS_ALL_DATA
拉取库龄报告 GET_FBA_INVENTORY_AGED_DATA
FBA管理库存健康报告 GET_FBA_INVENTORY_PLANNING_DATA
fba退货报告 GET_FBA_FULFILLMENT_CUSTOMER_RETURNS_DATA
fba移除报告 GET_FBA_FULFILLMENT_REMOVAL_ORDER_DETAIL_DATA
抓取fba配送费 GET_PAN_EU_OFFER_STATUS
fba配送费报告 GET_FBA_ESTIMATED_FBA_FEES_TXT_DATA
亚马逊预留库存 GET_RESERVED_INVENTORY_DATA
自发货退货报告(每次只能拉取60天的数据) GET_XML_RETURNS_DATA_BY_RETURN_DATE
日期范围报告(无法申请报告的爬虫模拟后台登陆点击申请报告再接口拉取) GET_DATE_RANGE_FINANCIAL_TRANSACTION_DATA
#自发货退货报告
$time = date("Y-m-d H:i:s");
$start_date = str_replace(' ','T',$start_date1);
$end_date = str_replace(' ','T',$end_date1);
$result = $requestReport->applicationreport($account->merchant_id,strtolower($account->site),'/reports/2021-06-30/reports',"",["reportType"=>self::REPORT_TYPE,'dataStartTime'=>$start_date,'dataEndTime'=>$end_date,"marketplaceIds"=>[$account->market_place_id]]);
日期范围报告 GET_DATE_RANGE_FINANCIAL_TRANSACTION_DATA
#获取报告结果 $result = $requestReport->applicationreport($account->merchant_id,strtolower($account->site),'/reports/2021-06-30/reports?reportTypes='.self::REPORT_TYPE.'&marketplaceIds='.$account->market_place_id,'','','GET'); #得到下载连接 $result = $requestReport->getreportsurl($account->merchant_id,$account->site,'/reports/2021-06-30/documents/'.$val['reportdocumentid'],"","","GET");//获取报告下载链接