RIO Delphi 错误

RIO Delphi error

我制作了几个使用 SOAP 的应用程序,但这个应用程序给我一个以前从未见过的错误。

这是在 Delphi 中创建的 WSDL 中的函数。

function GetueSoapServerPortType(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): ueSoapServerPortType;


implementation
  uses System.SysUtils;

function GetueSoapServerPortType(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): ueSoapServerPortType;
const
  defWSDL = 'https://sandbox.usaepay.com/soap/gate/1412E031/usaepay.wsdl';
  defURL  = 'https://sandbox.usaepay.com/soap/gate/1412E031';
  defSvc  = 'usaepayService';
  defPrt  = 'ueSoapServerPort';
var
  RIO: THTTPRIO;
begin
  Result := nil;
  if (Addr = '') then
  begin
    if UseWSDL then
      Addr := defWSDL
    else
      Addr := defURL;
  end;
  if HTTPRIO = nil then
    RIO := THTTPRIO.Create(nil)
  else
    RIO := HTTPRIO;
  try
    Result := (RIO as ueSoapServerPortType);
    if UseWSDL then
    begin
      RIO.WSDLLocation := Addr;
      RIO.Service := defSvc;
      RIO.Port := defPrt;
    end else
      RIO.URL := Addr;
  finally
    if (Result = nil) and (HTTPRIO = nil) then
      RIO.Free;
  end;
end;

这是我的函数:

function TEWBModule1.ProcessCreditcard(card,Exp,cvv, Amount, name: String): Boolean;
var
  NewToken: usaepay.ueSecurityToken;
  tran: usaepay.TransactionRequestObject;
  response: usaepay.TransactionResponse;
  Wclient: usaepay.ueSoapServerPortType;
  CData: usaepay.CreditcardData;
  CDetails: usaepay.TransactionDetail;
  NewAmount: Double;
  RIO: TRIO;
begin
     try
        NewAmount := StrToFloat(Amount);

     NewToken := usaepay.ueSecurityToken.Create;
     NewToken := CreateToken(MasterTbl.FieldByName('Merchantnum').AsString, MasterTbl.FieldByName('Mlogin').AsString);

     tran := usaepay.TransactionRequestObject.Create;
     CData:= usaepay.CreditcardData.Create;
     CDetails:= usaepay.TransactionDetail.Create;
     CData.CardNumber := card;
     CData.CardExpiration := Exp;
     CData.CardCode := cvv;
     CDetails.Amount := NewAmount;
     CDetails.AllowPartialAuth := False;
     CDetails.Description := 'Web Payment';
     tran.Command := 'sale';

     Wclient := GetueSoapServerPortType(False,'');

     RIO := (Wclient as IRIOAccess).RIO;
     if RIO is THTTPRIO then
        begin
             THTTPRIO(RIO).HTTPWebNode.ConnectTimeout := 1000 * 30;
             THTTPRIO(RIO).HTTPWebNode.SendTimeout := 1000 * 15;
             THTTPRIO(RIO).HTTPWebNode.ReceiveTimeout := 1000 * 60;
        end;

     response := usaepay.TransactionResponse.Create;

     response := Wclient.runTransaction(NewToken,tran);
     if response.ResultCode = 'A' then
        begin
             result := True;
        end
     else if response.ResultCode = 'D' then
          begin
               //Declined   response.error;
          end
     else
         begin
              // error response.error;
         end;

     finally
     NewToken.Free;
     tran.Free;
     Cdata.Free;
     CDetails.Free;
     response.Free;
     end;
end;

这是我收到错误的地方:

response := Wclient.runTransaction(NewToken,tran);

错误是:

Project myapp.exe raised exception class ESOAPDomConvertError with message 'Conversion from class TRIO.QueryInterface93$ActRec to SOAP is not supported - SOAP classes must derive from TRemotable.

这可能是 md5 令牌错误还是其他原因?

这是我创建令牌的方式:

function TEWBModule1.CreateToken(Key, Pin: String): usaepay.ueSecurityToken;
var
  Token: usaepay.ueSecurityToken;
  PinH: usaepay.ueHash;
  PreHasValue: String;
begin
     Token := usaepay.ueSecurityToken.Create;
     Token.SourceKey := Key;
     Token.ClientIP := '127.0.0.1';

     PinH := usaepay.ueHash.Create;
     PinH.Seed := '5678';
     PinH.Type_ := 'md5';
     PreHasValue := Token.SourceKey + PinH.Seed + Pin;
     PinH.HashValue := MD5String(PreHasValue);

     Result := Token;
     Token.Free;
     PinH.Free;
end;

function TEWBModule1.MD5String(myStr: String): String;
var
  HashMessageDigest: TIdHashMessageDigest5;
begin
     HashMessageDigest := nil;
     Try
       HashMessageDigest := TIdHashMessageDigest5.Create;
       Result := IdGlobal.IndyLowerCase(HashMessageDigest.HashStringASHex(myStr));
     Finally
       HashMessageDigest.Free;
     End;

end;

我可以在 CreateToken 中看到一些错误。释放 return 值(令牌)是错误的。我猜是少了一行Token.PinHash:=PinH。释放 PinH 也是错误的。尝试这样的事情

function TEWBModule1.CreateToken(Key, Pin: String): usaepay.ueSecurityToken;
var
Token: usaepay.ueSecurityToken;
PinH: usaepay.ueHash;
PreHasValue: String;
begin
     Token := usaepay.ueSecurityToken.Create;
     Token.SourceKey := Key;
     Token.ClientIP := '127.0.0.1';

     PinH := usaepay.ueHash.Create;
     PinH.Seed := '5678';
     PinH.Type_ := 'md5';
     PreHasValue := Token.SourceKey + PinH.Seed + Pin;
     PinH.HashValue := MD5String(PreHasValue);
     Token.PinHash:=PinH;

     Result := Token;
end;

这是我对 ProcessCreditcard 函数的看法。我已经为我添加的行和应该删除的行添加了注释。

function TEWBModule1.ProcessCreditcard(card,Exp,cvv, Amount, name: String): Boolean;
var
  NewToken: usaepay.ueSecurityToken;
  tran: usaepay.TransactionRequestObject;
  response: usaepay.TransactionResponse;
  Wclient: usaepay.ueSoapServerPortType;
  CData: usaepay.CreditcardData;
  CDetails: usaepay.TransactionDetail;
  NewAmount: Double;
  RIO: TRIO;
begin
  NewToken := nil;  //New line
  tran := nil;  //New line
  Response := nil;  //New line
  try
    NewAmount := StrToFloat(Amount);

    //NewToken := usaepay.ueSecurityToken.Create;   //This line would result in a memory leak
    NewToken := CreateToken(MasterTbl.FieldByName('Merchantnum').AsString, MasterTbl.FieldByName('Mlogin').AsString);

    tran := usaepay.TransactionRequestObject.Create;
    tran.Command := 'sale';

    CData:= usaepay.CreditcardData.Create;
    tran.CreditCardData:=CData;  //New line
    CDetails:= usaepay.TransactionDetail.Create;
    tran.Details:=CDetails;  //New line

    CData.CardNumber := card;
    CData.CardExpiration := Exp;
    CData.CardCode := cvv;
    CDetails.Amount := NewAmount;
    CDetails.AllowPartialAuth := False;
    CDetails.Description := 'Web Payment';

    Wclient := GetueSoapServerPortType(False,'');

    RIO := (Wclient as IRIOAccess).RIO;
    if RIO is THTTPRIO then
    begin
      THTTPRIO(RIO).HTTPWebNode.ConnectTimeout := 1000 * 30;
      THTTPRIO(RIO).HTTPWebNode.SendTimeout := 1000 * 15;
      THTTPRIO(RIO).HTTPWebNode.ReceiveTimeout := 1000 * 60;
    end;

    //response := usaepay.TransactionResponse.Create;   //This line would result in a memory leak
    response := Wclient.runTransaction(NewToken,tran);
    if response.ResultCode = 'A' then
    begin
      result := True;
    end
    else if response.ResultCode = 'D' then
    begin
      //Declined   response.error;
    end
    else
    begin
      // error response.error;
    end;

  finally
     NewToken.Free;
     tran.Free;
     //Cdata.Free;  //This object is destroyed by TransactionRequestObject
     //CDetails.Free;  //This object is destroyed by TransactionRequestObject
     response.Free;
  end;
end;