首先,我编写了soap信封,其中包含原始XML文件。肥皂信封使用以下代码制作:
procedure MakeSoapEnvelope(FileNameIn: AnsiString);
Const
SpCon = 0;
MINPERDAY = 1440;
SourceFile = 'XMLFILE';
TargetFile = 'SOAPENVELOP';
Var
AStr, Bapi_Versie_Pen_Soap, StrType: AnsiString;
uNow: _SystemTime;
dtNow: TDateTime;
sNow: String;
FSource, FDest : System.Text;
function FillTag(TagIn, FillPart:AnsiString) : AnsiString;
var
HTr: Integer;
begin
Result := NulStr;
for HTr := 1 to Length(TagIn) do
begin
if (HTr = Length(TagIn)) then //direct voor laatste positie invoegen
Result := Result + Spatie + FillPart;
Result := Result + TagIn[HTr];
end;
end; {func FillTag}
procedure FDestAdd(SpIn : Integer; TagIn, VeldIn, FillIn : AnsiString);
begin
if (FillIn = NulStr) then
begin
WriteLn(FDest, Spatie:(SpIn * AuditSpatieMarge), TagIn, VeldIn, EndTag(TagIn));
end else
begin
Write(FDest, Spatie:(SpIn * AuditSpatieMarge));
Write(FDest, FillTag(TagIn, FillIn));
Write(FDest, VeldIn);
Write(FDest, EndTag(TagIn));
WriteLn(FDest, NulStr);
end;
end; {proc FDestAdd}
function GenerateTimestampId : AnsiString;
var
IntUit : Integer;
begin
IntUit := 1 + Random(100);
Result := '"_' + ItoSNulZonderPunten(IntUit) + '"';
end; {func GenerateTimestampId}
function MaakGUID : AnsiString;
var
Uid: TGuid;
begin
CreateGuid(Uid);
Result := (GuidToString(Uid));
//verwijderen accolades
Result := VerwijderEnkelTeken(Result, '{');
Result := VerwijderEnkelTeken(Result, '}');
end; {func MaakGUID}
function GenerateUserNameTokenId : AnsiString;
begin
Result := MaakGUID;
Result := '"' + Result + '"';
end; {func GenerateUserNameTokenId}
begin {procedure MakeSoapEnvelope}
{ start reserve file }
AssignFile(FDest, TargetFile);
Rewrite(FDest);
//prepare SoAP-envelope-header
WinApi.Windows.GetSystemTime(uNow);
dtNow := SysUtils.SystemTimeToDateTime(uNow);
sNow := FormatDateTime('yyyy-mm-dd"T"hh:mm:ss"Z"', dtNow);
//write SoAP-envelope-header
Bapi_Versie_Pen_Soap := Bapi_Versie_PenSoap_UPA_AGH;
WriteLn(FDest, {Spatie:(0 * AuditSpatieMarge),} Bapi_Versie_Pen_Soap);
WriteLn(FDest, Spatie:(1 * AuditSpatieMarge), Xml_PA_Alg_Soap_Header_Start);
WriteLn(FDest, Spatie:(2 * AuditSpatieMarge), Xml_PA_Upa_AGH_Security_Start);
WriteLn(FDest, Spatie:(3 * AuditSpatieMarge), FillTag(Xml_PA_Upa_AGH_Timestamp, Xml_PA_Upa_AGH_Id + GenerateTimestampId));
WriteLn(FDest, Spatie:(4 * AuditSpatieMarge), Xml_PA_Upa_AGH_Created, FormatDateTime('yyyy-mm-dd"T"hh:mm:ss"Z"', dtNow), EndTag(Xml_PA_Upa_AGH_Created));
WriteLn(FDest, Spatie:(4 * AuditSpatieMarge), Xml_PA_Upa_AGH_Expires, FormatDateTime('yyyy-mm-dd"T"hh:mm:ss"Z"', dtNow + 5 /MINPERDAY), EndTag(Xml_PA_Upa_AGH_Expires));
WriteLn(FDest, Spatie:(3 * AuditSpatieMarge), EndTag(Xml_PA_Upa_AGH_Timestamp));
WriteLn(FDest, Spatie:(3 * AuditSpatieMarge), FillTag(Xml_PA_Upa_UsernameToken_Start, Xml_PA_Upa_AGH_Id + GenerateUserNameTokenId));
FDestAdd(4, Xml_PA_Upa_Username, XmlSendDlg.MeUserName.Text, NulStr);
FDestAdd(4, Xml_PA_Upa_Password, TranslateTo64Base(XmlSendDlg.MePassword.Text), Xml_PA_Upa_AGH_Password_Type);
WriteLn(FDest, Spatie:(3 * AuditSpatieMarge), EndTag(Xml_PA_Upa_UsernameToken_Start));
WriteLn(FDest, Spatie:(2 * AuditSpatieMarge), Xml_PA_Upa_Security_Stop);
WriteLn(FDest, Spatie:(2 * AuditSpatieMarge), Xml_PA_Upa_AGH_To);
WriteLn(FDest, Spatie:(2 * AuditSpatieMarge), Xml_PA_Upa_AGH_Action);
WriteLn(FDest, Spatie:(1 * AuditSpatieMarge), Xml_PA_Alg_Soap_Header_Stop);
WriteLn(FDest, Spatie:(1 * AuditSpatieMarge), Xml_PA_Alg_Soap_Body_Start);
WriteLn(FDest, Spatie:(2 * AuditSpatieMarge), Xml_PA_Upa_ZendBerichtAlsZIP_Start);
FDestAdd(3, Xml_PA_Upa_idLcr, Bepaal_Upa_IdLcr, NulStr);
FDestAdd(3, Xml_PA_Upa_idBer, XmlSendDlg.OrIdBericht, NulStr);
WriteLn(FDest, Spatie:(3 * AuditSpatieMarge), Xml_PA_Upa_berichtZIP_Start);
{ open original xml file }
SourceFile := FileNameIn;
{$I-}
AssignFile(FSource, SourceFile);
Reset(FSource);
{ incorporate original xml file in soapenvelope}
while not Eof(FSource) do
begin
ReadLn(FSource, AStr);
WriteLn(FDest, Spatie:(4 * AuditSpatieMarge), AStr);
end;
CloseFile(FSource);
{add endtag xml file in soapenvelope}
WriteLn(FDest, 3 * AuditSpatieMarge, EndTag(Xml_PA_Upa_berichtZIP_Start));
WriteLn(FDest, Spatie:(2 * AuditSpatieMarge), EndTag(Xml_PA_Upa_ZendBerichtAlsZIP_Start));
{write end soap-envelope }
WriteLn(FDest, Spatie:(1 * AuditSpatieMarge), EndTag(Xml_PA_Alg_Soap_Body_Start));
WriteLn(FDest, {Spatie:(0 * AuditSpatieMarge),} Xml_PA_Alg_Soap_Envelope_Einde);
CloseFile(FDest);
{ save nieuwe file op in oude file }
RenameResFile(SourceFile, TargetFile);
{$I+}
end; { func MakeSoapEnvelope }
请注意:我不确定转换为Base64的MePassword.Text
是否足以支持WS Security。
在此之后,肥皂信封看起来像这样:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsu:Timestamp wsu:Id="_83">
<wsu:Created>2017-11-06T12:29:14Z</wsu:Created>
<wsu:Expires>2017-11-06T12:34:14Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken wsu:Id="C2F32D7E-805F-466C-BD2B-FB0B28C01E24">
<wsse:Username>MeUsername.Text</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">This line represents the MePassword.Text in 64Base</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<To soapenv:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">https://localhost:44300/UPAWebService.svc</To>
<Action soapenv:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://www.pensioenfederatie.nl/uniformePensioenAangifte/2015/05/WS/UPAWebService/ZendBerichtAlsZIP</Action>
</soapenv:Header>
<soapenv:Body>
<ws:ZendBerichtAlsZIP>
<ws:idLcr>A95972643</ws:idLcr>
<ws:idBer>CLIENT-PA-01A-20171106132913</ws:idBer>
<ws:berichtZIP>This line represents the original xml-file</ws:berichtZIP>
</ws:ZendBerichtAlsZIP>
使用以下代码发送soap信封:
procedure Send_HTTP;
var
XMLFileStream : TFileStream;
begin {procedure Send_HTTP}
XMLFileStream := TFileStream.Create(XmlSendDlg.XmlFileIn, fmOpenRead Or fmShareDenyWrite);
Try
IdHTTP1.HandleRedirects := True;
IdHTTP1.HTTPOptions := [hoInProcessAuth, hoKeepOrigProtocol, hoForceEncodeParams];
IdHTTP1.IoHandler.Port := Port_HTTPS;
IdHTTP1.Request.ContentType := 'text/xml';
IdHTTP1.Request.CharSet := 'utf-8';
IdHTTP1.Request.Username := MeUsername.Text;
IdHTTP1.Request.Password := MePassword.Text;
IdHTTP1.Request.BasicAuthentication := False;//True;
IdHTTP1.ReadTimeout := ReadTimeoutConst;
IdHTTP1.Request.CustomHeaders.Clear;
IdHTTP1.Request.CustomHeaders.Add('SOAPAction: "' + MeSoapAction.Text + '"');
Try
ReturnStr := IdHTTP1.Post(MeWebSite.Text, XMLFileStream);
Except
On E: Exception Do
begin
Memo1.Lines.Add('Fout: ' + E.Message);
end;
end;
IdHTTP1.Disconnect;
Finally
XMLFileStream.Free;
end;
end; {proc Send_HTTP}
发送肥皂信封会产生HTTP/1.1 400 Bad Request
响应。收到的完整信息是:
HTTP/1.1 400 Bad Request Cache-Control: private,no-cache, no-store, must-revalidate Server: Microsoft-IIS/8.5 X-AspNet-Version: 4.0.30319 Strict-Transport-Security: max-age=31536000 X-FRAME-OPTIONS: SAMEORIGIN X-Content-Type-Options: nosniff Date: Mon, 06 Nov 2017 12:29:15 GMT Content-Length: 0
出了什么问题?