Thema: Delphi PayPal Soap Anbindung

Einzelnen Beitrag anzeigen

TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.070 Beiträge
 
Delphi 10.4 Sydney
 
#20

AW: PayPal Soap Anbindung

  Alt 18. Jun 2018, 15:24
Für einen "sauberen" Workaround (ohne die gefixte Unit in das .dpr direkt einzubinden) dachte ich eher daran den Original Code zu klonen, und den gefixten Converter explizit an das entsprechende Interface zu übergeben.


Leider erweist sich diese Hoffnung als Trugschluss

Die Superklasse TRIO von THTTPRIO hat zwar die definierte Eigenschaft Converter vom (Interface) Typ IOPConverter, THTTPRIO will aber dennoch den Typ Soap.TOPToSoapDomConvert.

Was ist denn das für ein #&$**!!@ Design bitteschön???

Also kein "sauberer" Workaround möglich, es bleibt bei dem Patch (den ich jezt auch noch 2x pflegen muss, für Seattle und Tokyo, da andere Änderungen an Soap.OPToSoapDomConvert.pas vorgenommen wurden).
So ein Saftladen!!

P.S.:
Für jeden den's interessiert, hier ist das Ticket bei Embarcadero: RAD StudioRSP-20730
Du kannst es - zumindest für Tokyo - wie folgt lösen.
Der entscheidende Punkt ist das Freigeben der betreffenden Klasse in der überschriebenen ConvertSoapToNativeData-Methode.

Delphi-Quellcode:
unit Paypal.View;

interface

uses
  System.SysUtils, System.Variants, System.Classes,
  Vcl.Controls, Vcl.Forms, Vcl.StdCtrls,
  Winapi.ActiveX,
  PayPalSvc,
  Soap.SOAPHTTPClient,
  Soap.InvokeRegistry,
  System.TypInfo,
  Soap.Rio,
  Soap.OPToSOAPDomConv,
  Xml.XMLIntf,
  Soap.SOAPConst,
  Soap.TypeTrans;

type
  TfrmPayPal = class(TForm)
    Button1: TButton;

    procedure Button1Click(Sender: TObject);
  private
  public
  end;

var
  frmPayPal: TfrmPayPal;

implementation

{$R *.dfm}


type
  TMyConverter = class(Soap.OPToSOAPDomConv.TOPToSoapDomConvert)
  public
    procedure ConvertSoapToNativeData(DataP: Pointer; TypeInfo: PTypeInfo;
      RootNode, Node: IXMLNode; Translate: Boolean); override;
  end;

type
  PTObject = ^TObject;

procedure TMyConverter.ConvertSoapToNativeData(DataP: Pointer; TypeInfo: PTypeInfo;
  RootNode, Node: IXMLNode; Translate: Boolean);
var
  TypeUri, TypeName: InvString;
  IsNull: Boolean;
  Obj, DataObj: TObject;
  P: Pointer;
  ID: InvString;
begin
  Node := GetDataNode(RootNode, Node, ID);
  IsNull := NodeIsNull(Node);
  if TypeInfo.Kind = tkVariant then
  begin
    if IsNull then
    begin
      Variant(PVarData(DataP)^) := NULL;
    end
    else
      ConvertSoapToVariant(Node, DataP);
  end
  else if TypeInfo.Kind = tkDynArray then
  begin
    P := DataP;
    P := ConvertSoapToNativeArray(P, TypeInfo, RootNode, Node);
    Pointer(DataP^) := P
  end
  else if TypeInfo.Kind = tkClass then
  begin
    Obj := ConvertSOAPToObject(RootNode, Node, GetTypeData(TypeInfo).ClassType, TypeUri, TypeName, DataP);
    DataObj := PTObject(DataP)^;
    if Assigned(Obj) and Assigned(DataObj) and (Obj.ClassType <> DataObj.ClassType) then
    begin
      DataObj.Free; // <--- hier geben wir das Objekt frei, wenn die Class Types verschieden sind!
    end;

    PTObject(DataP)^ := Obj
  end
  else
  begin
    if Translate then
    begin
      if not TypeTranslator.CastSoapToNative(TypeInfo, GetNodeAsText(Node), DataP, IsNull) then
        raise ESOAPDomConvertError.CreateFmt(STypeMismatchInParam, [Node.nodeName]);
    end;
  end;
end;

procedure TfrmPayPal.Button1Click(Sender: TObject);
var
  Rio: THTTPRIO;
  PaypalInterface: PayPalAPIInterface;
  Sec: RequesterCredentials;
  Request: RefundTransactionReq;
  Response: RefundTransactionResponse;
begin
  CoInitializeEx(nil, 0);
  try
    Rio := THTTPRIO.Create(nil);
    Rio.Converter := TMyConverter.Create(Rio);
    PaypalInterface := GetPayPalAPIInterface(False, 'https://api-3t.sandbox.paypal.com/2.0/', Rio);

    Sec := RequesterCredentials.Create;
    Sec.Credentials := UserIdPasswordType.Create;
    Sec.Credentials.Username := 'hello world';
    Sec.Credentials.Password := 'hello world';
    Sec.Credentials.Signature := 'hello world';

    Rio.SOAPHeaders.Send(Sec);
    Rio.SOAPHeaders.SetOwnsSentHeaders(True);

    Request := RefundTransactionReq.Create;
    try
      Request.RefundTransactionRequest := RefundTransactionRequest.Create;

      Response := PaypalInterface.RefundTransaction(Request);
      if Assigned(Response) then
      begin
        try
          {
            Hier machen wir was Kluges mit dem Response-Objekt
          }

        finally
          Response.Free;
        end;
      end;
    finally
      Request.Free;
    end;
  finally
    PaypalInterface := nil; // nur um zu verdeutlichen, dass hier Schluss ist!
    CoUnInitialize;
  end;
end;

end.
  Mit Zitat antworten Zitat