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;
我制作了几个使用 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;