Entries tagged api

Herausfinden zu welchem Versanddienstleister eine Tracking ID gehört

Posted on 29. Juli 2016 Comments

Wir hatten erst letztens das Problem, dass wir automatisiert Tracking IDs zugespielt bekommen, die von mehreren Versanddienstleistern stammen könnten. Dies ist z. B. beim ERP Plentymarkets der Fall, wenn man Pakete per FBA verschickt. Allerdings nur, wenn die Aufträge nicht von Amazon kommen, sondern ein sog. Multichannel Auftrag vorliegt, also Amazon nur als Logistiker benutzt wird. In der API Rückmeldung steht zwar m.E. der Versanddienstleister, allerdings implementiert Plentymarkets kein Mapping.

Um den richtigen Provider zu finden, ohne jedes mal alle Websites abzuklappern habe ich das PHP Paket shipping-service-providers-check geschrieben und über composer verfügbar gemacht. Es macht automatisiert genau das. Falls es nicht geht, weil z.B. die Flash oder JavaScript im Spiel sind oder es gar keine öffentliche Seite gibt (->Amazon Logistics), kann die Nummer auch anhand des Formats geprüft werden, also mit einem regulärem Ausdruck.

Theoretisch ist es möglich, dass die Tracking ID gleichzeitig bei mehreren Providern für unterschiedliche Sendungen gültig ist. Das ist zugegebenermaßen extrem unwahrscheinlich. Dennoch gibt mein Paket ein Array von Paketdienstleistern, jeweils mit einem Boolean (true/false), zurück.

Code Erklärung

Die Abhängigkeiten sind fabpot/goutte (ein Website scraper) und danielstjules/stringy (für Stringvergleiche). Da ich von PHPs use function Gebrauch mache, ist PHP Version 5.6 notwendig.

Die Klasse Check enthält neben dem Konstruktur, der die TrackingID erwartet, 3 weitere Methoden.

  • getProviders() – gibt alle Provider zurück
  • checkAll($extraProviders) – gibt das eben erwähnte Array zurück. Das hier ist die eigentlich wichtige öffentliche Methode
  • check() – private, wird in einer Schleife von checkAll() aufgerufen

In der Datei default_providers.php sind in einem Array alle implementierten Versanddienstleister aufgeführt. Hier können auch weitere hinzugefügt werden, bzw. in diesem Format an checkAll() übergeben werden. Jeder Dienstleister hat 3 Parameter:

  • base_url – URL, die goutte zusammen mit der tracking ID aufrufen wird
  • filter – HTML Tag auf der Seite, nach dem gesucht bzw. das durchsucht werden soll
  • search_string  – nach diesem String wird in dem HTML Tag gesucht

Der eigentlich wichtige Teil ist deswegen die Methode checkOnline()

$crawler = $this->client->request('GET', $parameters["base_url"] . $this->trackingId);

in dieser Zeile ruft goutte die vorher definierte base_url mit der Tracking ID auf. Die URL muss deshalb im Format http://example.com?tracking_id= vorliegen. Aus der Tracking ID 123456 lautet dann der Aufruf http://example.com?tracking_id=123456.

$crawler->filter($parameters["filter"])->each(function ($node) use ($parameters) {
            if (s($node->text())->contains($parameters["search_string"])) {
                return true;
            }
            return false;

In dem HTML Tag aus dem filter Parameter wird jetzt nach dem String search_string mittels stringys contains() gesucht. Sollte das der Fall sein, wird true zurückgegeben. Da die Funktion each ein Array zurückgibt und es möglich ist, dass das relevante HTML Tag mehrmals vorkommt, wird danach geguckt ob true in diesem array überhaupt vorkommt, auch wenn andere Einträge in diesem Array eben false sind.

return in_array(true, ...)

Dies wird in einer Schleife in checkAll() durchgegangen:

        foreach ($shippingProviders as $shippingProvider => $parameters) {
            $response[$shippingProvider] = $this->check($parameters);
        }

Außerdem ist es durch folgende Zeile möglich einen Versanddienstleister hinzuzufügen oder zu ersetzen (beides passiert durch array_merge())

  if (isset($shippingProviders)) {
            $shippingProviders = array_merge($defaultShippingProviders, $shippingProviders);
        } else {
            $shippingProviders = $defaultShippingProviders;
        }

Die Methode zum Überprüfen des regulärem Ausdrucks checkFormat() ist denkbar simpel:

  boolval(preg_match($parameters["regex"], $this->trackingId))

Da preg_match 1 zurückgibt, falls der Regex zutrifft, und 0 falls nicht (false wenn ein Fehler aufgetreten ist), muss um das Ergebnis noch boolval().

Die Anleitung zum Benutzen des Pakets ist auf GitHub bzw. Packagist. Zur Zeit des Verfassens dieses Artikels sind die folgenden Versanddienstleister implementiert:

  • DHL
  • GLS
  • UPS
  • Hermes
  • Amazon Logistics

Fedex, DPD und TNT gestalten sich schwierig, da diese Informationen per JavaScript nachladen und goutte das nicht beherrscht. Ggf. werde ich nochmal ein npm Paket mit zombie.js und/oder phantomjs schreiben.

Auftragsstatus bei Rakuten

Posted on 22. Juli 2015 Comments

Rakuten.de hat eine REST API, über die z.B. Aufträge abgefragt werden können. Die Doku gibt dazu folgende Auskunft:

pending = Bestellung ist neu eingegangen
editable = Bestellung ist zur Bearbeitung freigegeben
shipped = Bestellung ist versendet
payout = Bestellung ist ausbezahlt
cancelled = Bestellung ist storniert

Eine ausgiebiere Erklärung könnt so aussehen:

pending = Bestellung ist neu eingegangen. Wenn der Kunde über PayPal oder Kreditkarte bezahlt hat, wird dieser Zustand eigentlich sofort wieder verlassen. Eigentlich braucht man sich Aufträge mit diesem Status nicht angucken, weil im Normalfall Ware erst versandt wird, wenn sie auch bezahlt ist. Vorkasse Aufträge können z.B. länger in diesem Status verbleiben, eben so lange bis das Geld bei Rakuten eingegangen ist.
editable = Bestellung ist zur Bearbeitung freigegeben. Das heißt im Normalfall, dass der Kunde die Ware auch bezahlt hat. Diese Aufträge sollte man sich ins System holen, sie intern bearbeiten und kann dann in den nächsten Status springen
shipped = Bestellung ist versendet. Dies wird z.B. erreicht, indem eine Trackingnummer für das Paket eingegeben wird. Dies muss durch den Händler passieren, Rakuten wird diesen Status nie von alleine setzen.
payout = Bestellung ist ausbezahlt. Rakuten hat nach einer bestimmten Frist das aufsummierte Geld der Bestellungen (in der die aktuelle Bestellung enthalten ist) an den Händler überwiesen.
cancelled = Bestellung ist storniert. Der Kunde hat sich umentschieden oder der Händler hat die Bestellung storniert (etwa durch Fehlbestand)

 

Morsecode As A Service: node.js app with restify and Heroku

Posted on 22. Januar 2015 Comments

I wanted to play around with node.js and REST APIs. Heroku is widely used for deploying node.js app, last but not least because they give you one free instance to test your code and the possibility to use your own domain name (via CNAME).

Until now the code is rather trivial. This for example is the encode function (plaintext->morsecode). It uses the npm module morse to encode the given string in the request parameters and returns it with the plaintext in an array. The requests are handled by restify.
function encode(req, res, next) {
var answer = {}
answer.plaintext = req.params.string.toUpperString();
answer.morsecode = morse.encode(req.params.string);
res.send(answer);
next();
}

This function gets called later here.
server.get('/encode/:string', app.encode);

This starts the server on the port from the Heroku instance.
var port = process.env.PORT || 8080;
server.listen(port, function() {
console.log('%s listening at %s', server.name, server.url);
});

The decode function is equivalent, except that I test if there are only „.“, „-“ and white spaces in the request.

I wrote the documentation with the automatic page generator from GitHub Pages in the repository and so with the following code the user is redirected there when entering the root „/“.

 

function redirectToDocumentation(req,res,next) {
res.send(302, null, {
Location: API_DOKU
});
next();
}

It’s reachable under morsecode-api.de or morsecodeapi.herokuapp.com.

Automate selling at LaRedoute #2: Parse order files

Posted on 16. Dezember 2014 Comments

This blog post is part of the series Automize selling at LaRedoute.

  • Part 1: Get new orders
  • Part 2: Parse order files
  • Part 3: Upload response files
  • Part 4: update quantity and price feed

Update 2016: La Redoute is going to stop using CSV and moves everything to SOAP Webservices. Tutorials will follow


In part 1 the files containing orders are downloaded into a folder called OrdersFromLaRedoute. The next script is going to go through that folder, parse the file and insert it into a table.

These are the values the table must have because we’re just going to insert everything that’s in the CSV files.


$dbValues = ['MarketplaceID', 'OrderID', 'StorefrontOrderID', 'OrderDate', 'BuyerEmailAddress', 'BuyerName', 'BuyerPhoneNumber', 'OrderItemCode', 'ItemStatus', 'SKU', 'Title', 'Quantity', 'ItemPrice', 'ItemTax', 'ShippingCharge', 'ShippingTax','ItemFee', 'Currency', 'ShippingOption', 'PaymentInfo', 'ShippingAddressName', 'ShippingAddressFieldOne', 'ShippingAddressFieldTwo', 'ShippingAddressFieldThree', 'ShippingCity', 'ShippingStateOrRegion', 'ShippingPostalCode', 'ShippingCountryCode', 'ShippingPhoneNumber', 'BillingAddressName', 'BillingAddressFieldOne', 'BillingAddressFieldTwo', 'BillingAddressFieldThree', 'BillingCity', 'BillingStateOrRegion', 'BillingPostalCode', 'BillingCountryCode', 'BillingPhoneNumber'];

 

Therefore I created the table more or less like this:

CREATE TABLE `ORDERS-HISTORY` (
`MarketplaceID` int(11) DEFAULT NULL,
`OrderID` varchar(50) DEFAULT NULL,
`StorefrontOrderID` varchar(50) DEFAULT NULL,
`OrderDate` varchar(50) DEFAULT NULL,
`BuyerEmailAddress` varchar(50) DEFAULT NULL,
`BuyerName` varchar(50) DEFAULT NULL,
`BuyerPhoneNumber` varchar(50) DEFAULT NULL,
`OrderItemCode` varchar(50) NOT NULL DEFAULT '',
`ItemStatus` varchar(10) NOT NULL DEFAULT '',
`SKU` int(11) DEFAULT NULL,
`Title` varchar(50) DEFAULT NULL,
`Quantity` int(11) DEFAULT NULL,
`ItemPrice` decimal(8,2) DEFAULT NULL,
`ItemTax` decimal(8,2) DEFAULT NULL,
`ShippingCharge` decimal(8,2) DEFAULT NULL,
`ShippingTax` decimal(8,2) DEFAULT NULL,
`ItemFee` decimal(8,2) DEFAULT NULL,
`Currency` varchar(3) DEFAULT NULL,
`ShippingOption` varchar(10) DEFAULT NULL,
`PaymentInfo` varchar(50) DEFAULT NULL,
`ShippingAddressName` varchar(70) DEFAULT NULL,
`ShippingAddressFieldOne` varchar(70) DEFAULT NULL,
`ShippingAddressFieldTwo` varchar(70) DEFAULT NULL,
`ShippingAddressFieldThree` varchar(70) DEFAULT NULL,
`ShippingCity` varchar(70) DEFAULT NULL,
`ShippingStateOrRegion` varchar(70) DEFAULT NULL,
`ShippingPostalCode` int(11) DEFAULT NULL,
`ShippingCountryCode` varchar(3) DEFAULT NULL,
`ShippingPhoneNumber` varchar(50) DEFAULT NULL,
`BillingAddressName` varchar(70) DEFAULT NULL,
`BillingAddressFieldOne` varchar(70) DEFAULT NULL,
`BillingAddressFieldTwo` varchar(70) DEFAULT NULL,
`BillingAddressFieldThree` varchar(70) DEFAULT NULL,
`BillingCity` varchar(70) DEFAULT NULL,
`BillingStateOrRegion` varchar(70) DEFAULT NULL,
`BillingPostalCode` int(11) DEFAULT NULL,
`BillingCountryCode` varchar(3) DEFAULT NULL,
`BillingPhoneNumber` varchar(50) DEFAULT NULL,
PRIMARY KEY (`OrderID`,`OrderItemCode`,`ItemStatus`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

As you can see, the primary key consists of OrderID, OrderItemCode and ItemStatus. An OrderID is the unique identifier of one order, consisting of possibly many but at least one OrderItemCode. An OrderItemCode is representing an SKU + Quantity. For newly created orders, the ItemStatus will appear as „Created“. Once an item is accepted, LaRedoute will put a file into the ToSupplier folder with exactly the same OrderID, OrderItemCode but the ItemStatus „ToShip“. This will be important in Step 3.

Then, use a CSV library like league/csv and insert it with e.g. medoo.


$dirAsArray = scandir("OrdersFromLaRedoute");

foreach($dirAsArray as $file) {
// parse and INSERT
}

Automate selling at LaRedoute #1: Get new orders

Posted on 16. Dezember 2014 Comments

This blog post is part of the series Automize selling at LaRedoute.


The french marketplace LaRedoute unfortunately doesn’t have a real API, but they do have ways to automize some processes. A lot of smaller marketplaces have this concept as well. You will get credentials for an SFTP server. On this server you will find the folders ToSupplier and FromSupplier, where the „supplier“ (aka you) can up- and download a range files documented by Merchantry in their blog. The processing of the uploaded files can take up to 6 hours, but is sometimes done in only a couple of minutes, so I’m going to assume the worst case of 6 hours in this post.

While programming a couple of scripts I found the following problems:

  • the server is incredibly slow sometimes (better at nights), so sometimes the connections just time out
  • sometimes the listing for the ToSupplier folder times out because there are too many files (according to support…huh?), so they have to be deleted regularly
  • not only the connection to LaRedoute but also the connection to my local MySQL server times out
  • I have to reserve a purchased item once I accepted it on LaRedoute immediately, because it could be sold elsewhere in the 6 hours LaRedoute might take to give me the shipping address

New orders can be found in the ToSupplier folder in tab seperated CSV files (but .txt ending) with the format OrdersYYYY-MM-DD-hh-mm-ss.txt.

Since PHP is the companies main language I will show a couple of scripts which automize downloading and processing those files. The code is of course simplified for better understanding. We’re using SFTP instead of FTP and I found using the phpseclib to be the most usable library.

I will propose the use of 2 Tables in the MySQL database: TEMP-FILENAMES and FILENAMES-HISTORY. Both have a the unique column filename. FILENAMES-HISTORY will contain the name of every file ever processed by the following script, TEMP-FILENAMES is a helper table that will be truncated after every run.

First, we need to establish a connection


$sftp = new Net_SFTP(SFTP_LAREDOUTE_HOST);
if (!$sftp->login(SFTP_LAREDOUTE_USER, SFTP_LAREDOUTE_PASS)) {
exit('Login Failed');
}

Then we change directory. This is a command that usually involves listing the directory changed into, but since this is not a graphical client, the real timeout might come on line below. $nlist will just be null if the listing fails, and I will assume it didn’t work if it takes more than 30 seconds.

$sftp->chdir('/ToSupplier');

$beforetime = time();
$nlist = $sftp->nlist();
$aftertime = time();
if(($aftertime-$beforetime) > 30 ) {
exit('Timeout while Listing directory');
}

The next piece of code is only executed if the listing worked. Every filename that includes the word „Order“ is now inserted into the temporary table:

foreach($nlist as $filename) {
if (strpos($filename, 'Order') !== false) {
$qry = "INSERT INTO `TEMP-FILENAMES`(`filename`) VALUES ('". $filename . "')";
$insert = mysql_query($qry,MYSQLCONNECTION) or print mysql_error();
}
}

You can look at the difference between the filenames in your HISTORY table and the possibly new ones in the temporary table.

$tmpCmpFilenames = array();
$qry = "SELECT `filename` FROM `TEMP-FILENAMES` WHERE `filename` NOT IN (SELECT `filename` FROM `FILENAMES-HISTORY`)";
$select = mysql_query($qry, MYSQLCONNECTION) or print mysql_error();
while ($row = mysql_fetch_assoc($select)) {
$tmpCmpFilenames[] = $row['filename-id'];
}

Now we have all the new files in the array $tmpCmpFilenames. The correct way would be make sure the downloaded files are correct with hashes. Instead we decided to misuse the filesize, since it’s a good indicator something didn’t work properly;) The files not downloaded correctly are deleted from the array. They will appear next time the script is run.

foreach($tmpCmpFilenames as $filename) {
$remotefilesize = $sftp->size($filename);
$sftp->get($filename, 'OrdersFromLaRedoute/' . $filename);
$localfilesize = filesize('OrdersFromLaRedoute/' . $filename);
if ($remotefilesize != $localfilesize) {
unset($tmpCmpFilenames[$filename]);
}
}

We can now insert the filenames into the HISTORY table.

foreach($tmpCmpFilenames as $filename) {
$qry = "INSERT INTO `FILENAMES-HISTORY`(`filename`) VALUES ('". $filename . "')";
$insert = mysql_query($qry, MYSQLCONNECTION) or print mysql_error();
}

Last but not least, the temporary table needs to be truncated for the next run.

$truncate=mysql_query("TRUNCATE TABLE `TEMP-FILENAMES`",MYSQLCONNECTION) or print mysql_error();

The next step is described in part 2 of this series.

Anleitung: Produkte bei eBay über API mit PHP SDK listen – Teil 4: Aufträge löschen, Artikel aktualisieren

Posted on 13. Oktober 2014 Comments

Dieser Blog Post ist Teil der Reihe Produkte bei eBay listen.


4.1. Jobs abbrechen

Es kann immer mal vorkommen, dass es bei der Feed-Erstellung Fehler gibt. Dann wird ggf. von large-merchant-services/02-add-fixed-price-item.php ein Job erstellt. Diesen muss man erst abbrechen um einen neuen Job derselben Art zu erstellen. Dazu braucht man die jobID. Normalerweise wird diese beim Erstellen des Jobs mit angezeigt. Sollte man sie aus irgendeinem Grund nicht zur Verfügung haben, kann man sie aber auch mit large-merchant-services/01-get-jobs.php erfragen. Da hier aber alle Jobs, die jemals ausgeführt wurden, angezeigt werden, muss man noch ein paar kleine Änderungen vornehmen. Als erstes sollte man aber wie auch in Teil 3 sicherstellen, dass man auf der richtigen Plattform arbeitet (hier: Sandbox):

'authToken' => $config['sandbox']['userToken'],
'sandbox' => true

Weiter unten, in der letzten if-Abfrage, sollte man die folgende Line ändern:

$upTo = min(count($response->jobProfile), 500);

Das sollte erstmal reichen. Außerdem kann folgende Zeile hinzufügen

$job = $response->jobProfile[$x]; // alte Zeile (Z. 89 bei mir)
if ($job->jobStatus != "Completed") { // das hier einfügen
...
} // if-Abfrage weiter unten schließen

Jetzt bekommt man nur die Jobs, die noch nicht fertig gestellt sind. Allerdings sind hier auch die Abgebrochenen dabei, also könnte man auch  ein != „Aborted“ hinzufügen.

Hat man nun die jobID, kann man die Vorlage large-merchant-services/01-get-jobs.php ein bisschen abändern. Ich habe die Datei large-merchant-services/04-abort-job.php genannt. Dafür muss in Zeile 58 den richtigen Request und die jobID eingetragen.

$request = new Types\AbortJobRequest(array('jobId' => '4711'));

Eine Zeile darunter:

$response = $service->abortJob($request);

Sollte man das öfter brauchen, sollte es auch nicht allzu schwer sein, die jobID aus den Parametern zu ziehen.

4.2. Preise und Verfügbarkeit aktualisieren

Wie viele andere Marktplätze, gibt eBay auch die Möglichkeit mit einem reduzierten Feed für zuvor gelistete Produkte die Verfügbarkeit und Preise zu updaten. Eine genaue Erklärung der einzelnen Tags findet sich im ersten Teil. Der reduzierte Feed folgendermaßen aus:

<?xml version="1.0" encoding="UTF-8"?>
<BulkDataExchangeRequests>
<Header>
<Version>669</Version>
<SiteID>77</SiteID>
</Header>
<ReviseFixedPriceItemRequest xmlns="urn:ebay:apis:eBLBaseComponents">
<ErrorLanguage>de_DE</ErrorLanguage>
<WarningLevel>Low</WarningLevel>
<Version>619</Version>

Jetzt kommen die Informationen das Item, also der Eltern-/Parent-Artikel

<Item>
<SKU>26754</SKU>
<InventoryTrackingMethod>SKU</InventoryTrackingMethod>

Mehr ist nicht von nöten, da die Verfügbarkeiten und Preise ja auf Variationsebene festgelegt sind.

<Variations>
<Variation>
<SKU>4711</SKU>
<Quantity>23</Quantity>
<StartPrice>12.34</StartPrice>
</Variation>
<Variation>
<SKU>4712</SKU>
<Quantity>42</Quantity>
<StartPrice>56.78</StartPrice>
</Variation>
... <!-- mehr Variationen hier -->
</Variations>
</Item>
</ReviseFixedPriceItemRequest>
</BulkDataExchangeRequests>

Das war es auch schon. Für das Updaten der Angebote (revise) gibt es noch keine Vorlage von dts. Allerdings kann man das Beispiel für AddFixedPriceItem mit wenigen Änderungen auch dafür benutzen. In Zeile 75 wird statt AddFixedPriceItem einfach ReviseFixedPriceItem eingesetzt:

$createUploadJobRequest->uploadJobType = 'ReviseFixedPriceItem';

Außerdem ändern sich natürlich noch die Dateinamen der hochzuladenen Datei und der Antwort von eBay:

$uploadFileRequest->attachment(file_get_contents(__DIR__.'/ReviseFixedPriceItem.xml.gz'));
...
$tempFilename = tempnam(sys_get_temp_dir(), 'revise-fixed-price-item-responses-').'.zip';

Natürlich kann man auch jede beliebige Änderung über ReviseFixedPriceItem vornehmen. Allerdings funktioniert alles außer Verfügbarkeit und Preis nur, solange noch keine Variation des Artikels gekauft wurde. Manchmal kann es auch gut sein, den Artikel einfach ganz zu löschen und noch einmal neu hochzuladen (Achtung: in Production kann das Geld kosten!). Dafür braucht man den folgenden API Call.

4.3. EndFixedPriceItem

Möchte man ein Angebot komplett löschen, kann man einen einfachen Feed für diese Items schreiben (für Varianten reicht es die Quantity auf 0 zu setzen). Ist bei allen Varianten die Quantity auf 0, wird der Artikel automatisch entfernt (und muss ggf. mit kostenpflichtig wieder erstellt werden), außer man hat beim Einstellen, wie in Teil 1 erwähnt, die Option OutOfStockControl gesetzt. In diesem Fall wird der Artikel bloß ausgeblendet. Die SKU ist hier dementsprechend die Eltern-/Parent-SKU. Der Feed sieht wie folgt aus:

<?xml version="1.0" encoding="utf-8"?>
<BulkDataExchangeRequests xmlns="urn:ebay:apis:eBLBaseComponents">
<Header>
<Version>659</Version>
<SiteID>77</SiteID>
</Header>
<EndFixedPriceItemRequest xmlns="urn:ebay:apis:eBLBaseComponents">
<EndingReason>NotAvailable</EndingReason>
<SKU>4711</SKU>
<ErrorLanguage>de_DE</ErrorLanguage>
<WarningLevel>High</WarningLevel>
<Version>859</Version>
</EndFixedPriceItemRequest>
...
<!-- Mehr EndFixedPriceItemRequests -->
</BulkDataExchangeRequests >

Das Prinzip ist dasselbe wie bei AddFixedPriceItem und ReviseFixedPriceItem: einfach die Strings im Quellcode ändern und man kann die Datei auch für EndFixedPriceItem benutzen.

Anleitung: Produkte bei eBay über API mit PHP SDK listen – Teil 3: Keys, Sandbox und AddFixedPriceItem

Posted on 13. Oktober 2014 Comments

Dieser Blog Post ist Teil der Reihe Produkte bei eBay listen.


3.1/3.2. Keys und Sandbox

Um die Beispiele von dts ausführen zu können muss man sich am eBay Developer Program anmelden. Man kann hier nicht seinen normalen eBay Account benutzen. Nach der Anmeldung kann man sich jeweils eine DEVID, AppID und CertID für Sandbox und Production erstellen. Erstmal ist es sicher sinnvoll Sandbox Keys zu erstellen. Anschließend musst man sich noch einen User Token generieren lassen. Die mit den Sandbox Keys eingestellten Angebote wird man später unter sandbox.ebay.com bzw. in der deutschen Version finden.

3.3. Vorbereitung des SDK

Abhängigkeiten installieren:

git clone https://github.com/davidtsadler/ebay-sdk-examples.git
curl -sS https://getcomposer.org/installer | php
php composer.phar install

Jetzt müssen nur noch die eben erstellen Keys und der Usertoken in die configuration.php eingetragen werden. Das eigentliche SDK befindet sich in vendor/dts, man muss also nichts anderes von GitHub herunterladen.

3.4. AddFixedPriceItem

Die benötigten Dateien befindet sich im Ordner large-merchant-services, für das Hinzufügen von Artikel wird die 02-add-fixed-price-item.php gebraucht. Sie ist relativ gut verständlich geschrieben. Man sollte darauf achten, dass in den Variablen $exchangeService und $transferService die Sandbox Keys benutzt werden:

'authToken' => $config['sandbox']['userToken'],
'sandbox' => true

Man kann diese Datei mehr oder weniger so benutzen. Sie wird eine .gz-gezippte Datei namens AddFixedPriceItem.xml.gz aus demselben Ordner hochladen. Wenn die .xml-Datei bzw. .gz-Datei wie in Teil 1 und 2 beschrieben erstellt ist und im selben Ordner liegt, kann diese .php-Datei einfach ausgeführt werden. Das Hochladen bzw. Verarbeiten seitens eBay kann eine ganze Weile dauern. Es wird auf jeden Fall eine .xml-Datei gezippt zurückkommen. In ihr findet man ggf. Fehlermeldungen, Warnings und was das Erstellen gekostet hat. In der Sandbox ist dies natürlich kostenlos, es werden 0.0 € berechnet. Es ist deshalb, vor allem bei größeren Tests, wichtig noch einmal die Keys zu überprüfen, so dass nicht ungewollt Kosten entstehen. Möchte man irgendwann umstellen, sehen die beiden Variablen oben folgendermaßen aus:

'authToken' => $config['production']['userToken'],
'sandbox' => false

Außerdem müssen dann in der configuration.php die entsprechenden keys bzw. ein neuer Usertoken für die Production Keys eingetragen sein.

Wird die Datei ausgeführt, die AddFixedPriceItem.xml.gz liegt aber nicht im gleichen Verzeichnis oder wird das Hochladen abgebrochen ist trotzdem ein Job erstellt. Ein weiterer Job des Typs AddFixedPriceItem ist nicht möglich und so muss erst der Job abgebrochen werden. Zu diesen und weiteren nützlichen API, siehe Teil 4.

How to disable ACK with xbee-arduino API

Posted on 23. April 2014 Comments

It might be useful to disable all the ACK packages(0x8B) for testing purposes. That’s possible with all packages that inherit from XBeeRequest, my example shows a ZBTxRequest.

txRequest.setFrameId(NO_RESPONSE_FRAME_ID);

Set Window position under Windows 7

Posted on 10. Oktober 2013 Comments

Apparently there is no way of setting/configuring a windows position on the screen. I couldn’t find a place to define X and Y or top and left. There is however  a function, if you write your own application in C++(SetWindowPos). Also deleting [-HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\BagMRU] and the like didn’t work for me, especially since the (current) user, wasn’t allowed to use regedit.

Thanks to paradroid on superuser.com, I found another, reasonably usable solution: Hold down CTRL while clicking on the [X]-button of a window. Windows will then remember the position for the next start.

-.-

Scuttle Bookmarks in Owncloud App

Posted on 21. Juni 2013 Comments

Ich habe ein kleines PHP-Skript geschrieben, was aus einer Scuttle Installation die Bookmarks ausliest und in die Owncloud Bookmark App einfügt.

In der jetzigen Version wird nur MySQL (noch kein SQLite) unterstützt und aus  einem mir nicht erklärlichen Grund funktionieren die Tags nicht. Vielleicht kommt ja jemand dahinter.

Den Quellcode findet man auf github.