![]() |
AW: Soap-Service: XML-Fehler
Danke für die Tips.
Ich probiere momentan etwas mit SoapUI ![]() |
AW: Soap-Service: XML-Fehler
Auf der
![]() Wenn ich es mit mORMot umsetze, stehen mir viele Wege offen. Von holzschnittartig bis fein ziseliert. Deine Daten bekommst du am einfachsten mit einem TWinHttp.Get Aufruf. mORMot beherrscht SSL/TLS. Im Folgenden verwende ich Curl, weil der Quellcode aus dem DHL Beispiel kopiert werden kann. Der JSON Response wird mit der Funktion RecordLoadJson in eine Record Struktur deserialisiert. Möglich wäre auch ein Objekt, oder ohne vorherige Definition einer Struktur mit der Funktion InitJson ein DocVariant. Dies ist vorteilhaft, wenn nur einige Werte von Interesse sind. Mit der Funktion GetValueByPath ist ein Direktzugriff möglich. Informationen zu mORMot mit Curl findest du im ![]() Abgebildet ist der Fall Rating GET /rates (Retrieve Rates for a one piece Shipment):
Delphi-Quellcode:
Disclaimer: ohne Gewähr
uses
mormot.core.base, mormot.core.data, mormot.core.text, mormot.core.json, mormot.core.buffers, mormot.core.variants, mormot.core.os, mormot.lib.curl, mormot.net.client; type TRateRequestResult = packed record products: array of record productName: RawUtf8; productCode: RawUtf8; localProductCode: RawUtf8; localProductCountryCode: RawUtf8; networkTypeCode: RawUtf8; isCustomerAgreement: Boolean; weight: record volumetric: Double; provided: Double; unitOfMeasurement: RawUtf8; end; totalPrice: array of record currencyType: RawUtf8; priceCurrency: RawUtf8; price: Currency; end; totalPriceBreakdown: array of record currencyType: RawUtf8; priceCurrency: RawUtf8; priceBreakdown: array of record typeCode: RawUtf8; price: Currency; end; end; detailedPriceBreakdown: array of record currencyType: RawUtf8; priceCurrency: RawUtf8; breakdown: array of record name: RawUtf8; serviceCode: RawUtf8; localServiceCode: RawUtf8; typeCode: RawUtf8; serviceTypeCode: RawUtf8; price: Currency; isCustomerAgreement: Boolean; isMarketedService: Boolean; isBillingServiceIndicator: Boolean; priceBreakdown: array of record priceType: RawUtf8; typeCode: RawUtf8; price: Currency; rate: Double; basePrice: Currency; end; end; end; pickupCapabilities: record nextBusinessDay: Boolean; localCutoffDateAndTime: TDateTime; GMTCutoffTime: TDateTime; pickupEarliest: TDateTime; pickupLatest: TDateTime; originServiceAreaCode: RawUtf8; originFacilityAreaCode: RawUtf8; pickupAdditionalDays: Integer; pickupDayOfWeek: Integer; end; deliveryCapabilities: record deliveryTypeCode: RawUtf8; estimatedDeliveryDateAndTime: TDateTime; destinationServiceAreaCode: RawUtf8; destinationFacilityAreaCode: RawUtf8; deliveryAdditionalDays: Integer; deliveryDayOfWeek: Integer; totalTransitDays: Integer; end; items: array of record number: Integer; breakdown: array of record name: RawUtf8; serviceCode: RawUtf8; localServiceCode: RawUtf8; typeCode: RawUtf8; serviceTypeCode: RawUtf8; price: Currency; priceCurrency: RawUtf8; isCustomerAgreement: Boolean; isMarketedService: Boolean; isBillingServiceIndicator: Boolean; priceBreakdown: array of record priceType: RawUtf8; typeCode: RawUtf8; price: Currency; rate: Double; basePrice: Currency; end; end; end; pricingDate: TDateTime; end; exchangeRates: array of record currentExchangeRate: Double; currency: RawUtf8; baseCurrency: RawUtf8; end; warnings: array of RawUtf8; end; var hnd: TCurl; res: TCurlResult; headers: Pointer; responseData: RawByteString; responseSize: Int64; requestResult: TRateRequestResult; begin if not CurlIsAvailable then Exit; //=> hnd := curl.easy_init; if hnd <> Nil then begin curl.easy_setopt(hnd, coSSLVerifyPeer, 0); curl.easy_setopt(hnd, coSSLVerifyHost, 0); curl.easy_setopt(hnd, coWriteFunction, @CurlWriteRawByteString); curl.easy_setopt(hnd, coWriteData, @responseData); var docQuery: TDocVariantData; docQuery.Init(JSON_FAST_EXTENDED, dvObject); docQuery.U['accountNumber'] := '123456789'; docQuery.U['originCountryCode'] := 'CZ'; docQuery.U['originCityName'] := 'Prague'; docQuery.U['destinationCountryCode'] := 'CZ'; docQuery.U['destinationCityName'] := 'Prague'; docQuery.I['weight'] := 5; docQuery.I['length'] := 15; docQuery.I['width'] := 10; docQuery.I['height'] := 5; docQuery.U['plannedShippingDate'] := '2020-02-26'; docQuery.B['isCustomsDeclarable'] := False; docQuery.U['unitOfMeasurement'] := 'metric'; curl.easy_setopt(hnd, coURL, Pointer(docQuery.ToUrlEncode('https://api-mock.dhl.com/mydhlapi/rates'))); var docHeader: TDocVariantData; docHeader.Init(JSON_FAST_EXTENDED, dvObject); docHeader.U['Message-Reference'] := 'd0e7832e-5c98-11ea-bc55-0242ac13'; docHeader.U['Message-Reference-Date'] := 'Wed, 21 Oct 2015 07:28:00 GMT'; docHeader.U['Plugin-Name'] := ''; docHeader.U['Plugin-Version'] := ''; docHeader.U['Shipping-System-Platform-Name'] := ''; docHeader.U['Shipping-System-Platform-Version'] := ''; docHeader.U['Webstore-Platform-Name'] := ''; docHeader.U['Webstore-Platform-Version'] := ''; headers := Nil; var headerField: TDocVariantFields; headers := curl.slist_append(headers, Pointer(FormatUtf8('accept: %', [JSON_CONTENT_TYPE]))); headers := curl.slist_append(headers, Pointer(FormatUtf8('Authorization: Basic %', ['ZGVtby1rZXk6ZGVtby1zZWNyZXQ=']))); for headerField in docHeader.Fields do begin if headerField.Value <> Nil then headers := curl.slist_append(headers, Pointer(FormatUtf8('%: %', [headerField.Name^, headerField.Value^]))); end; curl.easy_setopt(hnd, coHttpHeader, headers); curl.easy_setopt(hnd, coCustomRequest, RawUtf8('GET')); res := curl.easy_perform(hnd); if res = crOk then begin FileFromString(responseData, MakePath([Executable.ProgramFilePath, 'ResponseData.json'])); curl.easy_getinfo(hnd, ciSizeDownloadT, responseSize); ShowMessage(Format('Download completed: %s', [KB(responseSize)])); if RecordLoadJson(requestResult, responseData, TypeInfo(TRateRequestResult)) then ShowMessage(Utf8ToString(RawUtf8ArrayToCsv(requestResult.warnings, sLineBreak))); end else ShowMessage(Format('Curl told us %d (%s)', [Ord(res), curl.easy_strerror(res)])); curl.slist_free_all(headers); curl.easy_cleanup(hnd); end; end; Auch für Query und Header Teil musst du keinen DocVariant verwenden, sondern kannst es als Record oder Objekt abbilden und mit UrlEncode/ToCSV Funktionen aufbereiten. Bis bald... Thomas |
AW: Soap-Service: XML-Fehler
Zitat:
|
AW: Soap-Service: XML-Fehler
Falls eine OpenAPI Doc vorliegt für den REST Service, kannst Du auch diese Objekte automatisch generieren.
|
AW: Soap-Service: XML-Fehler
Zitat:
![]() (Gefunden in ![]() |
AW: Soap-Service: XML-Fehler
Der genannte Generator erzeugt OpenApi docs.Gesucht ist ja der umgekehrte Weg, aus einer OpenAPI Definition Delphi Code zu erstellen.
Sorry, hatte den verwechselt, es sollte gehen. |
AW: Soap-Service: XML-Fehler
So, jetzt funktioniert es.
Der Fehler war, dass im XML ein Namespace nicht definiert war. Dass ist passiert, weil ich den <SOAP-ENV:Header> über einen TSoapHeader selbst ins XML eingefügt habe. Ansonsten erzeugt SOAP das XML ja automatisch. Daraufhin der der Server dann überhaupt nichts mehr zurückgegeben. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:17 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz