skip to Main Content

I am trying to post product in Amazon Seller account with Laravel. But I am getting error:
XML Parsing Fatal Error at Line 1, Column 1: Content is not allowed in prolog. Content is not allowed in prolog. This is my code, so if someone can help me to solve this.

$requestXml = '<?xml version="1.0" encoding="utf-8"?>
        <AmazonEnvelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:noNamespaceSchemaLocation="amzn-envelope.xsd">
          <Header>
            <DocumentVersion>1.01</DocumentVersion>
            <MerchantIdentifier>Myid</MerchantIdentifier>
          </Header>
          <MessageType>Product</MessageType>
          <PurgeAndReplace>false</PurgeAndReplace>
          <Message>
            <MessageID>1</MessageID>
            <OperationType>Update</OperationType>
            <Product>
              <SKU>56789</SKU>
              <StandardProductID>
                <Type>ASIN</Type>
                <Value>B0EXAMPLEG</Value>
              </StandardProductID>
              <ProductTaxCode>A_GEN_NOTAX</ProductTaxCode>
              <DescriptionData>
                <Title>Example Product Title</Title>
                <Brand>Example Product Brand</Brand>
                <Description>This is an example product description.</Description>
                <BulletPoint>Example Bullet Point 1</BulletPoint>
                <BulletPoint>Example Bullet Point 2</BulletPoint>
                <MSRP currency="USD">25.19</MSRP>
                <Manufacturer>Example Product Manufacturer</Manufacturer>
                <ItemType>example-item-type</ItemType>
              </DescriptionData>
              <ProductData>
                <Health>
                  <ProductType>
                    <HealthMisc>
                      <Ingredients>Example Ingredients</Ingredients>
                      <Directions>Example Directions</Directions>
                    </HealthMisc>
                  </ProductType>
                </Health>
              </ProductData>
            </Product>
          </Message>
        </AmazonEnvelope>';

      /*$requestXml=preg_replace('/^([^w<]+)</', '<', $requestXml);*/
      // $requestXml = trim($requestXml);
      $requestXml = preg_replace('/[[:^print:]]/', '', $requestXml);


      Log::channel('amazon')->info('Amazon create feed request: ', ['request' => $requestXml]);


      $response = Http::withHeaders([
        'Content-Type' => 'text/xml; charset=UTF-8'
      ])->put($url, [
            'body' => $requestXml
          ]);

2

Answers


  1. Chosen as BEST ANSWER

    I found solution for this create product feed in Laravel with Amazon SP-API (https://github.com/amazon-php/sp-api-sdk):

    composer require amazon-php/sp-api-sdk
    composer require nyholm/psr7 -W
    
    
    use AmazonPHPSellingPartnerAccessToken;
    use AmazonPHPSellingPartnerModelFeedsCreateFeedDocumentSpecification;
    use AmazonPHPSellingPartnerModelFeedsCreateFeedSpecification;
    use AmazonPHPSellingPartnerRegions;
    use AmazonPHPSellingPartnerSellingPartnerSDK;
    use AppModelsAmazonAmazonAuth;
    use Exception;
    use GuzzleHttpHandlerCurlFactory;
    use IlluminateSupportFacadesLog;
    use IlluminateSupportFacadesHttp;
    use IlluminateSupportFacadesApp;
    use CarbonCarbon;
    use IlluminateSupportFacadesStorage;
    use GuzzleHttpClient;
    use AmazonPHPSellingPartnerApiFeedsApiFeedsSDK;
    use AmazonPHPSellingPartnerConfiguration;
    use AmazonPHPSellingPartnerExceptionApiException;
    use AmazonPHPSellingPartnerExceptionInvalidArgumentException;
    use AmazonPHPSellingPartnerHttpFactory;
    use AmazonPHPSellingPartnerHttpSignatureHeaders;
    use AmazonPHPSellingPartnerObjectSerializer;
    use PsrHttpClientClientExceptionInterface;
    use PsrHttpClientClientInterface;
    use PsrHttpMessageRequestInterface;
    use PsrLogLoggerInterface;
    use AmazonPHPSellingPartnerOAuth;
    use BuzzClientCurl;
    use NyholmPsr7FactoryPsr17Factory;
    use PsrLogNullLogger;
    
    
    public function getAccessToken($channelId)
      {
    
        $amazonAuth = AmazonAuth::where('channel_id', $channelId)->first();  //my local database channel
        $isExpired = Carbon::parse($amazonAuth->expires_at)->isPast();
        $token = null;
    
        if ($isExpired) {
    
          $data = [
            'grant_type' => 'refresh_token',
            'refresh_token' => $amazonAuth->refresh_token,
            'client_id' => TenantService::getLwaClientId(),
            'client_secret' => TenantService::getLwaSecret()
          ];
    
          $response = Http::asForm()->post(
            'https://api.amazon.com/auth/o2/token',
            $data
          );
    
    
          if ($response->successful()) {
            $body = $response->json();
            $amazonAuth->access_token = $body['access_token'];
            $amazonAuth->expires_at = now()->addSeconds($body['expires_in'])->toDateTimeString();
            $amazonAuth->save();
    
            $token = $body['access_token'];
          } else {
            Log::channel('amazon')->info('Amazon access token refresh failed for amazon auth id: ' . $amazonAuth->id);
           
          }
    
        } else {
          $token = $amazonAuth->access_token;
        }
    
        if ($token) {
          $accessToken = new AccessToken(
            $token,
            $amazonAuth->refresh_token,
            'refresh_token',
            (int) $amazonAuth->expires_in,
            'refresh_token'
          );
    
          return $accessToken;
        }
    
    
      }
    
    public function createFeedTest()
      {
    
        $client = new Client();
        $factory = new Psr17Factory();
        // $httpFactory = new HttpFactory($factory, $factory);
        $region = 'eu';
        $accessToken = $this->getAccessToken(150);
        $logger = new NullLogger();
        $configuration = Configuration::forIAMUser(
          $getLwaClientId,
          $getLwaSecret,
          $getAwsAccessKey,
          $getAwsSecretKey,
        );
        $sdk = SellingPartnerSDK::create($client, $factory, $factory, $configuration, $logger);
        $region = Regions::EUROPE;
    
        $specification = new CreateFeedDocumentSpecification;
        $feedDoc = $sdk->feeds()->createFeedDocument(
          $accessToken,
          $region,
          $specification->setContentType('text/xml; charset=utf-8')
        );
        $feedDocID = $feedDoc['feed_document_id'];
        $urlFeedUpload = $feedDoc['url'];
    
        $fileContent = '<?xml version="1.0" encoding="utf-8" ?>
        <AmazonEnvelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:noNamespaceSchemaLocation="amzn-envelope.xsd">
                <Header>
                  <DocumentVersion>1.01</DocumentVersion>
                  <MerchantIdentifier>MYMERCHANTTOKEN</MerchantIdentifier>
                </Header>
                <MessageType>Product</MessageType>
                <PurgeAndReplace>false</PurgeAndReplace>
                <Message>
                  <MessageID>1</MessageID>
                  <OperationType>Update</OperationType>
                  <Product>
                    <SKU>56789</SKU>
                    <StandardProductID>
                      <Type>ASIN</Type>
                      <Value>B0EXAMPLEG</Value>
                    </StandardProductID>
                    <ProductTaxCode>A_GEN_NOTAX</ProductTaxCode>
                    <DescriptionData>
                      <Title>Example Product Title</Title>
                      <Brand>Example Product Brand</Brand>
                      <Description>This is an example product description.</Description>
                      <BulletPoint>Example Bullet Point 1</BulletPoint>
                      <BulletPoint>Example Bullet Point 2</BulletPoint>
                      <MSRP currency="USD">25.19</MSRP>
                      <Manufacturer>Example Product Manufacturer</Manufacturer>
                      <ItemType>example-item-type</ItemType>
                      <CountryOfOrigin>DE</CountryOfOrigin>
                      <UnitCount>1</UnitCount>
                      <PPUCountType>stück</PPUCountType>
                      <IsExpirationDatedProduct>false</IsExpirationDatedProduct>
                    </DescriptionData>
                    <ProductData>
                      <Health>
                        <ProductType>
                          <HealthMisc>
                            <Ingredients>Example Ingredients</Ingredients>
                            <Directions>Example Directions</Directions>
                          </HealthMisc>
                        </ProductType>
                      </Health>
                    </ProductData>
                    <IsHeatSensitive>false</IsHeatSensitive>
    
                  </Product>
                </Message>
              </AmazonEnvelope>';
    
        dump($feedDoc);
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $urlFeedUpload);
        curl_setopt($curl, CURLOPT_UPLOAD, true);
        curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: text/xml; charset=utf-8'));
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_BINARYTRANSFER, 1);
        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_PUT, 1);
        curl_setopt($curl, CURLOPT_INFILE, fopen('data://text/plain,' . $fileContent, 'r'));
        curl_setopt($curl, CURLOPT_INFILESIZE, strlen($fileContent));
        #Only use below option on TEST environment if you have a self-signed certificate!!! On production this can cause security issues
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        $response = curl_exec($curl);
        dump($response);
        curl_close($curl);
        $specificationNewFeed = new CreateFeedSpecification([
          'feed_type' => 'POST_PRODUCT_DATA',
          'marketplace_ids' => ['A1PA6795UKMFR9'],
          'input_feed_document_id' => $feedDocID
    
        ]);
    
    
        $responseFeed = $sdk->feeds()->createFeed(
          $accessToken,
          $region,
          $specificationNewFeed
        );
        dd($responseFeed);
      }
    

  2. I have revised your code for validating string and hidden characters please try this one and also I have removed utf8_encode function as your XML string is already in UTF-8 :

    $requestXml = trim($requestXml); // Remove whitespace from the beginning and end of the XML string
    $requestXml = preg_replace('/[[:^print:]]/', '', $requestXml); 
    
    // Log the XML request after cleaning it
    Log::channel('amazon')->info('Amazon create feed request: ', ['request' => $requestXml]);
    
    $response = Http::withHeaders([
      'Content-Type' => 'text/xml; charset=UTF-8'
    ])->put($url, [
      'body' => $requestXml
    ]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search