Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi DPD Webservice (https://www.delphipraxis.net/213468-dpd-webservice.html)

horstmeyer 3. Aug 2023 14:45

DPD Webservice
 
Hallo Leute,

hat jemand schon mal mit DPD Webservice gearbeitet? Ich versuche gerade das Java-Beispiel nach Delphi zu konvertieren, komme aber leider nicht klar.

Das Beispiel in Java:
Code:
      // printOptions   
      PrintOption[] myPrintOptionList = new PrintOption[1];
      PrintOption myPrintOption = new PrintOption();   
      myPrintOption.setPaperFormat(com.dpd.common.service.types.ShipmentService._4_4.PrintOptionPaperFormat.A4);
      myPrintOption.setStartPosition(com.dpd.common.service.types.ShipmentService._4_4.StartPosition.UPPER_LEFT);
      myPrintOption.setOutputFormat(com.dpd.common.service.types.ShipmentService._4_4.OutputFormatType.PDF);
      myPrintOptionList[0] = myPrintOption;
Ich habe es mal so versucht, die Zuweisung funktioniert aber nicht:
Code:
procedure TForm1.MLButton2Click(Sender: TObject);
var
  ret : storeOrdersResponseType;
  myShipmentService44Client : ShipmentService_4_4;
  apiAuth : authentication;
  myPrintOptionList : array of PrintOption;
  myPrintOption : PrintOption;
begin

  if myAuthToken.Length>0 then begin
    showmessage('StoreOrders'+chr(13)+
                'delisId:'+mylogin.delisId+chr(13)+
                'customerUid:'+mylogin.customerUid+chr(13)+
                'authToken:'+myAuthToken+chr(13)+
                'depot:'+mylogin.depot+chr(13)+
                'System:'+sSystem);

    with apiAuth do begin
      delisId:=EditLogin.Text;
      authToken := myAuthToken;
      messageLanguage := 'de_DE';
    end;

    try

    myPrintOption.paperFormat:=printOption.PaperFormat.A4;
      // printOptions
//      PrintOption[] myPrintOptionList = new PrintOption[1];
//      PrintOption myPrintOption = new PrintOption();
//      myPrintOption.setPaperFormat(com.dpd.common.service.types.ShipmentService._4_4.PrintOptionPaperFormat.A4);
//      myPrintOption.setStartPosition(com.dpd.common.service.types.ShipmentService._4_4.StartPosition.UPPER_LEFT);
//      myPrintOption.setOutputFormat(com.dpd.common.service.types.ShipmentService._4_4.OutputFormatType.PDF);
//      myPrintOptionList[0] = myPrintOption;

      showmessage('storeorder');
    except
      showmessage('Fehler');
    end;
  end else begin
    showmessage('Bitte erst anmelden.');
  end;

end;
Hier der Ausschnitt der Klasse PrintOption:
Code:
  // ************************************************************************ //
  // XML      : printOption, global, <complexType>
  // Namespace : http://dpd.com/common/service/types/ShipmentService/4.4
  // ************************************************************************ //
  printOption = class(TRemotable)
  private
    FoutputFormat: OutputFormatType;
    FpaperFormat: paperFormat;
    FpaperFormat_Specified: boolean;
    Fprinter: printer;
    Fprinter_Specified: boolean;
    FstartPosition: startPosition;
    FstartPosition_Specified: boolean;
    procedure SetpaperFormat(Index: Integer; const ApaperFormat: paperFormat);
    function paperFormat_Specified(Index: Integer): boolean;
    procedure Setprinter(Index: Integer; const Aprinter: printer);
    function printer_Specified(Index: Integer): boolean;
    procedure SetstartPosition(Index: Integer; const AstartPosition: startPosition);
    function startPosition_Specified(Index: Integer): boolean;
  public
    destructor Destroy; override;
  published
    property outputFormat: OutputFormatType Index (IS_UNQL) read FoutputFormat write FoutputFormat;
    property paperFormat:  paperFormat      Index (IS_OPTN or IS_UNQL) read FpaperFormat write SetpaperFormat stored paperFormat_Specified;
    property printer:      printer          Index (IS_OPTN or IS_UNQL) read Fprinter write Setprinter stored printer_Specified;
    property startPosition: startPosition    Index (IS_OPTN or IS_UNQL) read FstartPosition write SetstartPosition stored startPosition_Specified;
  end;

Union 3. Aug 2023 17:55

AW: DPD Webservice
 
In der Hoffnung, dass Code in der Art nie produktiv geht.

Es fehlt die Elternklasse (Ich symbolisiere den Klassentyp hier als TDruckKlasse), in der die printOption Einträge vermutlich als array verwaltet werden. Generelle Vorgehensweise bei solchen WSDLGen Klassen:

Delphi-Quellcode:
// Übergeordnete Klasse erzeugen
printObject := TDruckKlasse.Create;
// Optionsobject erzeugen
printoptionObject := printoption.Create;
// Optionsobject an das Array der übergeordneten Klasse hängen (alternativ als Zuweisung mit ":=" anstelle von "<TArray> +"
printObject.printOptions := printObject .printOptions + [printOptionObject]
// Hier die Properties der Option füllen
printoptionObject.startPosition := 0;

horstmeyer 4. Aug 2023 09:01

AW: DPD Webservice
 
Nein, dass funktioniert leider nicht! Für die Printoption habe ich die Deklaration jetzt herausbekommen, aber wie man den array of printoption deklariert, ist mir immer noch nicht klar:
Code:
procedure TForm1.MLButton2Click(Sender: TObject);
var
  ret : storeOrdersResponseType;
  myShipmentService44Client : ShipmentService_4_4;
  apiAuth : authentication;
  myPrintOptionList : array of PrintOption;
  myPrintOption : PrintOption;
begin

    try

    // Übergeordnete Klasse erzeugen
    myPrintOption := PrintOption.Create;
    // Optionsobject erzeugen ???
    //printoptionObject := printoption.Create;
    // Optionsobject an das Array der übergeordneten Klasse hängen (alternativ als Zuweisung mit ":=" anstelle von "<TArray> +" ??
    //myPrintObject.printOptions := printObject .printOptions + [printOptionObject]
    // Hier die Properties der Option füllen
//    myPrintoption.startPosition := 0;
    myPrintoption.paperFormat:=paperFormat(0);
    myPrintoption.startPosition:=StartPosition(0);
    myPrintoption.outputFormat:=Outputformattype(0);

      // printOptions
//      PrintOption[] myPrintOptionList = new PrintOption[1];
//      PrintOption myPrintOption = new PrintOption();
//      myPrintOption.setPaperFormat(com.dpd.common.service.types.ShipmentService._4_4.PrintOptionPaperFormat.A4);
//      myPrintOption.setStartPosition(com.dpd.common.service.types.ShipmentService._4_4.StartPosition.UPPER_LEFT);
//      myPrintOption.setOutputFormat(com.dpd.common.service.types.ShipmentService._4_4.OutputFormatType.PDF);
//      myPrintOptionList[0] = myPrintOption;

      showmessage('storeorder');
    except
      showmessage('Fehler');
    end;

end;
Muss ich für myPrintOptionList evtl. einen eigenen Type anlegen?

Union 4. Aug 2023 09:48

AW: DPD Webservice
 
Nein eben nicht, da sonst die Typen nicht übereinstimmen. Du solltest den Typ oder Alias verwenden, den dir das WSDLGen erzeugt hat. Das ist dann typischerweise so etwas wie ArrayOfprintoption oder ArrayOfprintoption2.

Ohne den vollständigen Code ist das aber ein Ratespiel.

horstmeyer 4. Aug 2023 14:05

AW: DPD Webservice
 
Den vollständige Quellcode des Webservice kann ich hier leider nicht einstellen, da dieser zu lang ist. Und man kann ihn nur abfragen, wenn man einen Zugang auf das DPD-Portal hat.
Ich kann nur die Demo-Anwendung in Java bereitstellen:
Code:
package test;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.xml.soap.SOAPException;
import java.net.URL;

import org.apache.axis.AxisFault;
import com.dpd.common.service.types.Authentication._2_0.AuthenticationFault;

import com.dpd.common.service.LoginService._2_0.*;
import com.dpd.common.service.types.LoginService._2_0.*;

import com.dpd.common.service.ShipmentService._4_4.*;
import com.dpd.common.service.types.ShipmentService._4_4.*;

import org.apache.axis.message.MessageElement;
import org.apache.axis.message.SOAPHeaderElement;
import org.apache.axis.Constants;
import org.apache.axis.client.Stub;
import org.apache.axis.encoding.Base64;

import java.io.FileOutputStream;
import java.io.IOException;

public class ShipmentService44_storeOrders {

   public static void main(String[] args) throws SOAPException, IOException {
      LoginServiceProxy myApiSoapClient = new LoginServiceProxy();
      Login myLogin = new Login();

      try {
         myLogin = myApiSoapClient.getAuth("xxx", "xxx", "de_DE");
      } catch (RemoteException ex) {
         if (ex instanceof AxisFault) {
            if (ex instanceof AuthenticationFault) {
               System.out.println("FAULT CODE Login Service 2.0: " + ((AuthenticationFault) ex).getErrorCode());
               System.out.println("FAULT STRING Login Service 2.0: " + ((AuthenticationFault) ex).getErrorMessage());
            }
         }
      }
   
      // printOptions   
      PrintOption[] myPrintOptionList = new PrintOption[1];
      PrintOption myPrintOption = new PrintOption();   
      myPrintOption.setPaperFormat(com.dpd.common.service.types.ShipmentService._4_4.PrintOptionPaperFormat.A4);
      myPrintOption.setStartPosition(com.dpd.common.service.types.ShipmentService._4_4.StartPosition.UPPER_LEFT);
      myPrintOption.setOutputFormat(com.dpd.common.service.types.ShipmentService._4_4.OutputFormatType.PDF);
      myPrintOptionList[0] = myPrintOption;

      PrintOptions myPrintOptions = new PrintOptions();
      myPrintOptions.setSplitByParcel(false);
      myPrintOptions.setPrintOption(myPrintOptionList);   
      
      // order (1-30)
      ShipmentServiceData[] DPDOrderDataList = new ShipmentServiceData[1];
      DPDOrderDataList[0] = new ShipmentServiceData();

      // ----------- generalShipmentData
      GeneralShipmentData myGeneralShipmentData = new GeneralShipmentData();
      myGeneralShipmentData.setMpsCustomerReferenceNumber1("Article 123");
      myGeneralShipmentData.setMpsCustomerReferenceNumber2("Order 456");
      myGeneralShipmentData.setIdentificationNumber("Article 456");
      myGeneralShipmentData.setSendingDepot("0190");
      myGeneralShipmentData.setProduct(GeneralShipmentDataProduct.CL);
      myGeneralShipmentData.setMpsWeight(500);

      // ---------------------- sender
      AddressWithType mySender = new AddressWithType();
      mySender.setName1("Matratzen Direct AG");
      mySender.setName2("Christoph Bong");
      mySender.setStreet("Max-Planck-Str.");
      mySender.setHouseNo("35");
      mySender.setState(null);
      mySender.setCountry("DE");
      mySender.setZipCode("50858");
      mySender.setCity("Köln, Junkersdorf");
      mySender.setCustomerNumber("");
      mySender.setContact("");
      mySender.setPhone("+491786787676");
      myGeneralShipmentData.setSender(mySender);

      // ---------------------- recipient
      AddressWithType myRecipient = new AddressWithType();
      myRecipient.setName1("DPD Deutschland GmbH");
      myRecipient.setName2("");
      myRecipient.setStreet("Wailandtstr.");
      myRecipient.setHouseNo("1");
      myRecipient.setState(null);
      myRecipient.setCountry("DE");
      myRecipient.setZipCode("63741");
      myRecipient.setCity("Aschaffenburg");
      myRecipient.setCustomerNumber("");
      myRecipient.setContact("");
      myRecipient.setPhone("");
      myGeneralShipmentData.setRecipient(myRecipient);

      DPDOrderDataList[0].setGeneralShipmentData(myGeneralShipmentData);

      // ----------- parcels
      Parcel[] myParcelList = new Parcel[1];
      Parcel myParcel = new Parcel();
      myParcel.setCustomerReferenceNumber1("Article 123");
      myParcel.setCustomerReferenceNumber2("Order 456");
      myParcel.setWeight(500);
      myParcel.setContent("Smartphones");
      myParcelList[0] = myParcel;
      DPDOrderDataList[0].setParcels(myParcelList);

      // ----------- productAndServiceData
      ProductAndServiceData myProductAndServiceData = new ProductAndServiceData();

      myProductAndServiceData.setOrderType(ProductAndServiceDataOrderType.value1);

      // ---------------------- pickup
      Pickup myPickup = new Pickup();
      myPickup.setTour(0);
      myPickup.setQuantity(1);
      myPickup.setDate(20230803);
      myPickup.setFromTime1("1300");
      myPickup.setToTime1("1700");
      myPickup.setExtraPickup(1);

      // --------------------------------- collectionrequestaddress
      Address myCollectionRequestAddress = new Address();
      myCollectionRequestAddress.setName1("Matratzen Direct AG");
      myCollectionRequestAddress.setName2("Christoph Bong");
      myCollectionRequestAddress.setStreet("Max-Planck-Str.");
      myCollectionRequestAddress.setHouseNo("35");
      myCollectionRequestAddress.setState(null);
      myCollectionRequestAddress.setCountry("DE");
      myCollectionRequestAddress.setZipCode("50858");
      myCollectionRequestAddress.setCity("Köln, Junkersdorf");
      myCollectionRequestAddress.setCustomerNumber("");
      myCollectionRequestAddress.setContact("");
      myCollectionRequestAddress.setPhone("+491786787676");
      myPickup.setCollectionRequestAddress(myCollectionRequestAddress);

      myProductAndServiceData.setPickup(myPickup);

      // ---------------------- predict
      Notification myNotification = new Notification();
      myNotification.setChannel(NotificationChannel.value1);
      myNotification.setValue("m.mustermann@dpd.de");
      myNotification.setLanguage("DE");
      myProductAndServiceData.setPredict(myNotification);

      DPDOrderDataList[0].setProductAndServiceData(myProductAndServiceData);
      
      // storeOrders
      StoreOrders myStoreOrders = new StoreOrders();
      myStoreOrders.setPrintOptions(myPrintOptions);
      myStoreOrders.setOrder(DPDOrderDataList);
      
      // RESPONSE
      try {
         URL myEndpointURL = new URL("https://public-ws-stage.dpd.com/services/ShipmentService/V4_4/");
         ShipmentServicePublic_4_4Locator myShipmentService44Locator = new ShipmentServicePublic_4_4Locator();
         ShipmentServicePublic_4_4_SOAPStub myShipmentService44Webservice = new ShipmentServicePublic_4_4_SOAPStub(
               myEndpointURL, myShipmentService44Locator);
         Stub myStub = (Stub) myShipmentService44Webservice;

         SOAPHeaderElement header = new SOAPHeaderElement("http://dpd.com/common/service/types/Authentication/2.0",
               "authentication") {
            /**
                   * 
                   */
            private static final long serialVersionUID = 1L;

            @Override
            public void setAttribute(String namespace, String localName, String value) {
               if (!Constants.ATTR_MUST_UNDERSTAND.equals(localName)) {
                  super.setAttribute(namespace, localName, value);
               }
            }
         };
         
         MessageElement myDelisIDElement = new MessageElement();
         myDelisIDElement.setName("delisId");
         myDelisIDElement.setValue("sandboxdpd");
         header.addChild(myDelisIDElement);

         MessageElement myAuthTokenElement = new MessageElement();
         myAuthTokenElement.setName("authToken");
         myAuthTokenElement.setValue(myLogin.getAuthToken());
         header.addChild(myAuthTokenElement);

         MessageElement myMessageLanguage = new MessageElement();
         myMessageLanguage.setName("messageLanguage");
         myMessageLanguage.setValue("de_DE");
         header.addChild(myMessageLanguage);
         
         header.setActor(null);
         myStub.setHeader(header);

         // storeOrders   
         StoreOrdersResponse myStoreOrdersResponse = new StoreOrdersResponse();
         
         myStoreOrdersResponse = myShipmentService44Webservice.storeOrders(myStoreOrders);
      
         StoreOrdersResponseType myStoreOrdersResponseType = new StoreOrdersResponseType();
         myStoreOrdersResponseType = myStoreOrdersResponse.getOrderResult();
            
         List&lt;ShipmentResponse&gt; myShipmentResponseList = new ArrayList&lt;ShipmentResponse&gt;();
         myShipmentResponseList = Arrays.asList(myStoreOrdersResponseType.getShipmentResponses());
         if (myShipmentResponseList != null &amp;&amp; myShipmentResponseList.size() &gt; 0) {
            for (ShipmentResponse item : myShipmentResponseList) {
               if (item.getFaults() != null) {
                  // Error Handling
                  for (FaultCodeType myFault : item.getFaults()) {
                     System.out.println("FAULT CODE Shipment Service 4.3: " + myFault.getFaultCode());
                     System.out.println("FAULT STRING Shipment Service 4.3: " + myFault.getMessage() + "\n\n");
                  }
               }
               {
                  // Label PDF
                  if (myStoreOrdersResponseType.getOutput() != null) {            
                     String myBase64PDF = new String(Base64.encode(myStoreOrdersResponseType.getOutput().getContent()));
                     System.out.println("Base64 PDF String: " + myBase64PDF + "\n\n");
                     byte[] pdf_bytes = myStoreOrdersResponseType.getOutput().getContent();
                     FileOutputStream fos = new FileOutputStream(
                           "C://Users/.../Desktop/Test-PDF.pdf");
                     fos.write(pdf_bytes);
                     fos.close();
                  }

                  System.out.println("identificationNumber: " + item.getIdentificationNumber());
                  System.out.println("mpsId: " + item.getMpsId());
                  for (ParcelInformationType myParcelInformation : item.getParcelInformation()) {
                     System.out.println("parcelLabelNumber: " + myParcelInformation.getParcelLabelNumber());
                  }
               }
            }
         }

      } catch (RemoteException ex) {
         System.out.println(ex.toString());
         if (ex instanceof AxisFault) {
            if (ex instanceof AuthenticationFault) {
               System.out.println("FAULT CODE Shipment Service 4.4: " + ((AuthenticationFault) ex).getErrorCode());
               System.out.println("FAULT STRING Shipment Service 4.4: " + ((AuthenticationFault) ex).getErrorMessage());
            }
         }
      }
   }
}
Diesen muss ich jetzt nach Delphi überführen. Für die Login-Funktion ist mir dies schon gelungen, aber für die storeOrders-Funktion finde ich es schon deutlich schwieriger die Parameter richtig zu erstellen und zu übergeben. Hier mein funktionierendes Beispiel für die Login-Funktion:
Code:
procedure TForm1.MLButton1Click(Sender: TObject);
var
  myloginservice : LoginService;
begin
  try
    sSystem:='Testsystem';
    mylogin:=GetLoginService().getAuth(editlogin.Text,editpasswort.Text,'de_DE');
    myAuthToken:=mylogin.authToken;
    showmessage('delisId:'+mylogin.delisId+chr(13)+
                'customerUid:'+mylogin.customerUid+chr(13)+
                'authToken:'+myAuthToken+chr(13)+
                'depot:'+mylogin.depot+chr(13)+
                'System:'+sSystem);
  except
    showmessage('Bei der Anmeldung ist ein Fehler aufgetreten!');
  end;
end;

Bbommel 4. Aug 2023 16:32

AW: DPD Webservice
 
Also, wenn ich mir mal die Adressen in der Java-Klasse anschaue und dann das hier aufrufe:
https://public-ws-stage.dpd.com/serv...ice/V4_4/?wsdl
Dann bekomme ich eine WSDL-Struktur. Und diese Adresse kann ich auch in Delphi im WSDL-Importer angeben und Delphi zaubert dann daraus eine Unit mit der storeOrders-Funktion.

Hast du es mal auf diesem Weg probiert?

horstmeyer 8. Aug 2023 12:00

AW: DPD Webservice
 
ja, schon längst! Das Problem war ja wie ich die Arrays zugeordnet bekomme. Dies konnte mir bisher leider keiner wirklich beantworten. Mit einigem rumprobieren habe ich es jetzt aber selber herausgefunden:
Code:
      myPrintOption := PrintOption.Create;
      myPrintoption.paperFormat:=paperFormat(0);
      myPrintoption.startPosition:=StartPosition(0);
      myPrintoption.outputFormat:=Outputformattype(0);
      myPrintOptions := PrintOptions.create;
      myPrintOptions.splitByParcel:=false;
      setlength(myPrintOptionList,1);
      myPrintOptionList[0]:=myPrintOption;
      myPrintOptions.printOption:=myPrintOptionList;
Jetzt stehe ich aber vor einem neuen Problem: Ich weiß nicht wie ich den Login zuweisen soll und die DPD-Hotline will mir da nicht weiterhelfen, daher hatte ich ja gehofft hier jemanden zu finden, der diese Schnittstelle schon mal programmiert hat. Im .net Beispiel wird dies wie folgt gemacht:
Code:
  myStoreOrdersResponse = myShipmentService44Client.storeOrders(apiAuth, dpdStoreOrders)
In der eingelesenen Klasse muss ich es aber wie folgt übergeben:
Code:
  ret:=GetShipmentService_4_4().storeOrders(myPrintOptions,DPDOrderDataList);
aber wo übergebe ich das apiAuth?

Guido R. 23. Okt 2024 14:12

AW: DPD Webservice
 
Bist Du mit der Geschichte weiter gekommen?
Ich muss auch gerade eine solche Schnittstelle umsetzen und habe ähnliche Probleme.

Guido R. 26. Okt 2024 16:10

AW: DPD Webservice
 
Zitat:

Jetzt stehe ich aber vor einem neuen Problem: Ich weiß nicht wie ich den Login zuweisen soll und die DPD-Hotline will mir da nicht weiterhelfen, daher hatte ich ja gehofft hier jemanden zu finden, der diese Schnittstelle schon mal programmiert hat.
Für alle, die an der gleichen Stelle hängen:

Anstatt die importierte WSDL ein eigenes tHTTPRIO erzeugen zu lassen, dieses manuell erstellen:

Delphi-Quellcode:
if SandBox
 then Adr := 'https://public-ws-stage.dpd.com/services/ShipmentService/V4_4/'
 else Adr := 'https://public-ws.dpd.com/services/ShipmentService/V4_4/';    

RIO      := tHTTPRIO.Create(nil);

Shipment := GetShipmentService_4_4(False, Adr, RIO);
Dann kann man die Authentication (Klasse TSOAPHeader) an diese übergeben, bevor man storeOrders aufruft:

Delphi-Quellcode:
Auth                 := Authentication.Create;
Auth.delisId         := Username;
Auth.authToken       := Token;
Auth.messageLanguage := 'de_DE';

RIO.SOAPHeaders.Send(Auth);


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:16 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 by Thomas Breitkreuz