Also mit diesem xml
<xml>
<kundennummer>347105</kundennummer>
<artikelliste>
<position>
<nummer>179</nummer>
<preis>79.95</preis>
<menge>1</menge>
<waehrung>EUR</waehrung>
</position>
</artikelliste>
</xml>
wobei kundennummer NICHT die ID des kunden ist, klappt es problemlos.
Ich feuere curl via php ab. Nur so nebenbei. Da funktionieren in der tat alle API-Aufrufe, die man in der doku findet.
Danke jav666.
Ich hatte ein ähnliches minimales Beispiel, allerdings
- mit <adresse>ID statt wie bei dir <kundennummer>KNR und
- mit <position><id>ID statt wie bei dir <position><nummer>ANR
Aber wenn ich deine XML einsetze und nur Kundennummer und Artikelnummer abändere kommt bei mir nach wie vor der gleiche Fehler.
wollte dir einen link schicken, mit dem du das testen kannst…
aber darf man hier nicht.
das funktioniert einwandfrei. knappe 20 zeilen gecurlt mit php...
Array
(
status] => Array
(
action] => AngebotCreate
message] => OK
messageCode] => 1
)
xml] => Array
(
id] => 2
belegnr] => 100001
)
)
<?php
$xml = "<xml>
<kundennummer>10000</kundennummer>
<artikelliste>
<position>
<nummer>179</nummer>
<preis>79.95</preis>
<menge>1</menge>
<waehrung>EUR</waehrung>
</position>
</artikelliste>
</xml>";
$apiAufruf = "AngebotCreate";
$username = "blabla";
$password = "blubb";
$deineZahlen = "1234afc6b1234";
$curl = curl_init();
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($curl, CURLOPT_USERPWD, "$username:$password");
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://' . $deineZahlen . '.xentral.biz/api/' . $apiAufruf,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_POSTFIELDS =>$xml,
CURLOPT_HTTPHEADER => array(
'Content-Type: application/xml'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo "<pre>";
echo htmlentities($response);
echo "</pre>";
sollte klappen.
Danke, das funktioniert bei mir auch!
In deinem Code steht CUSTOMREQUEST = ‘GET’, obwohl es ja ein POST ist. Weißt du warum?
Ich hab content type header und request GET mit command-line curl versucht, aber daran liegt’s wohl noch nicht.
Ich werde mal weiter deine CURL Optionen durchgehen.
Gute Frage Google findet da ja einiges hochwissentschaftliches zum Thema “CUSTOMREQUEST” … ich glaube, so genau muss ich das nicht wissen ;)
Hab’s! Anscheinend darf man bei AngebotCreate nur ein XML-Snippet übergeben, aber nicht den kompletten, validen XML-Request aus der Doku. Bei AngebotGet darf (oder muss?) man dagegen den kompletten XML-Request übergeben.
Das funktioniert:
declare methodname=AngebotCreate
curl --data @- --digest -su "$XENTRAL_API_USER_SCRIPT_USER:$XENTRAL_API_USER_SCRIPT_PASSWORD" "${XENTRAL_API_URL_STANDARD}$methodname" \
-H 'Content-Type: application/xml' <<TEXT
<xml>
<kundennummer>10405</kundennummer>
<artikelliste>
<position>
<nummer>5027</nummer>
<preis>79.95</preis>
<menge>1</menge>
<waehrung>EUR</waehrung>
</position>
</artikelliste>
</xml>
TEXT
Und weil man kein gültiges XML-Dokument sendet, muss man den Content-Type Header selbst setzen. Das ist der Diff zu meiner ursprünglichen Lösung von ganz oben:
declare methodname=AngebotCreate
-curl --data @- --digest -su "$XENTRAL_API_USER_SCRIPT_USER:$XENTRAL_API_USER_SCRIPT_PASSWORD" "${XENTRAL_API_URL_STANDARD}$methodname" <<TEXT
- <?xml version="1.0" encoding="UTF-8"?>
- <request>
- <status>
- <function>$methodname</function>
- </status>
+curl --data @- --digest -su "$XENTRAL_API_USER_SCRIPT_USER:$XENTRAL_API_USER_SCRIPT_PASSWORD" "${XENTRAL_API_URL_STANDARD}$methodname" \
+ -H 'Content-Type: application/xml' <<TEXT
<xml>
<<xml-for-angebotcreate>>
</xml>
- </request>
TEXT
PS: Anscheinend geht AngebotGet dann auch ohne XML als reines HTTP GET:
declare methodname=AngebotGet
declare id=995
curl --digest -su "$XENTRAL_API_USER_SCRIPT_USER:$XENTRAL_API_USER_SCRIPT_PASSWORD" "${XENTRAL_API_URL_STANDARD}$methodname?id=$id"
auf jeden Fall. Bei allen “blablablaGets” kann das XML leer bleiben. Gefordert wird nur die ID oder belegnr
Weißt du zufällig, wenn wir schon dabei sind, ob bei den Positionen <id> und <menge> ausreicht? Alles andere könnte ja theoretisch aus den Stammdaten gezogen werden. Das wäre voll praktisch! Andernfalls muss ich ja bei jeder Änderung in den Artikelstammdaten die Artikelliste exportieren und in meinem API-Client hinterlegen...
war schwer untergwegs in ganz, ganz weit weg ;)
id und menge reicht!
Danke! OK, leider der gleiche Bug wie beim Belege Importer: Artikelbeschreibung taucht nicht im Angebot auf. Diese muss ich also im API Client und in Xentral pflegen :(
Die JSON-API hat leider auch nen Bug:
{
"kundennummer": "10405",
"artikelliste": [
{
"nummer": "5034",
"menge": 1
}
]
}
Angebot wird zwar angelegt, es wird auch eine Position mit Menge 1 hinzugefügt, aber diese Position hat keine Artikelnummer/Artikelname/Preis. Die selben Nummern mit XML funktionieren.
Noch ein Bug :(
Die Artikelbeschreibung wird ja leider nicht aus den Stammdaten gezogen; wenn man sie aber aus Xentral exportiert und diese dann dann mit AngebotCreate wieder importiert kommt diese vielsagende Fehlermeldung:
<?xml version="1.0" encoding="UTF-8"?>
<response>
<status>
<action>AngebotCreate</action>
<message>Invalid key (id)</message>
<messageCode>5</messageCode>
</status>
<xml>address not found</xml>
</response>
XML-Input des API-Aufrufs war:
<artikelliste>
<position>
<nummer>1118</nummer>
<menge>1</menge>
<beschreibung>Verschweißung</beschreibung>
</position>
</artikelliste>
<kundennummer>10465</kundennummer>
<projekt>1</projekt>
<status>angelegt</status>
Grund für den Bug: XML-Entities mit Namen (z.B. ß für ß) werden von Xentral exportiert aber werden beim API-Aufruf nicht verstanden. Der entsprechende Zahlencode ß würde funktionieren.
Aber das bedeuted, dass ich alle von Xentral exportierten Daten erst umkodieren muss :(
Und der schlimmste Bug bis jetzt:
Angebot kann nicht freigegeben werden, weil es angeblich bereits freigegeben ist. #159923
Wahrscheinlich der gleiche Bug wie beim Belege-Importer #155591.