Xml 如何发送正在进行的SOAP标头4GL

Xml 如何发送正在进行的SOAP标头4GL,xml,soap,openedge,progress-4gl,Xml,Soap,Openedge,Progress 4gl,大家好,Progress 4GL开发者 我想在ABL会话中使用UPS跟踪API。 我已经为UPS WSDL运行了WSDLAnalyzer,并遵循了文档 下面是我希望发送的XML请求示例(包括标头): 我的用户名 我的密码 我的许可证号码 麦可德 马蹄金 当使用SOAPUI发送此请求以测试请求时,此请求将按预期工作。 以下是我的Progress4GL代码,用于尝试提出相同的请求: {us/mf/mfdtitle.i} {/qond/apps/mfgpro/customizations/mfg/

大家好,Progress 4GL开发者

我想在ABL会话中使用UPS跟踪API。
我已经为UPS WSDL运行了WSDLAnalyzer,并遵循了文档

下面是我希望发送的XML请求示例(包括标头):


我的用户名
我的密码
我的许可证号码
麦可德
马蹄金
当使用SOAPUI发送此请求以测试请求时,此请求将按预期工作。 以下是我的Progress4GL代码,用于尝试提出相同的请求:

{us/mf/mfdtitle.i}
{/qond/apps/mfgpro/customizations/mfg/work/src/us/xx/xxwhsxml.i}

define variable hs as handle no-undo.
define variable hp as handle no-undo.
DEFINE VARIABLE cBody  AS LONGCHAR NO-UNDO.
DEFINE VARIABLE cBody2 AS LONGCHAR NO-UNDO.

cBody = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0" xmlns:v2="http://www.ups.com/XMLSchema/XOLTWS/Track/v2.0" xmlns:v11="http://www.ups.com/XMLSchema/XOLTWS/Common/v1.0">
<soapenv:Header>
   <v1:UPSSecurity>
      <v1:UsernameToken>
         <v1:Username>MYUSERNAME</v1:Username>
         <v1:Password>MYPASSWORD</v1:Password>
      </v1:UsernameToken>
      <v1:ServiceAccessToken>
         <v1:AccessLicenseNumber>MYLICENSENUMBER</v1:AccessLicenseNumber>
      </v1:ServiceAccessToken>
   </v1:UPSSecurity>
</soapenv:Header>
<soapenv:Body>
   <v2:TrackRequest>
      <v2:ReferenceNumber>
         <v2:Code>MYCODE</v2:Code>
         <v2:Value>MYORDERNUM</v2:Value>
      </v2:ReferenceNumber>
   </v2:TrackRequest>
</soapenv:Body>
</soapenv:Envelope>'.

create server hs.
hs:connect( "-WSDL /home/jbetts/track/Track.wsdl -Port TrackPort -TargetNamespace http://www.ups.com/WSDL/XOLTWS/Track/v2.0 -nohostverify -nosessionreuse" ). 

run TrackPortType set hp on server hs.
run ProcessTrack in hp ( input cBody, output cBody2 ).

delete procedure hp.
hs:disconnect().
delete object hs.
{us/mf/mfdtitle.i}
{/qond/apps/mfgpro/customizations/mfg/work/src/us/xx/xxwhsxml.i}
将变量hs定义为不撤消的句柄。
将变量hp定义为handle no undo。
将变量cBody定义为LONGCHAR NO-UNDO。
将变量cBody2定义为LONGCHAR NO-UNDO。
cBody=
我的用户名
我的密码
我的许可证号码
麦可德
马蹄金
'.
创建服务器hs。
hs:connect(“-WSDL/home/jbetts/track/track.WSDL-Port-TrackPort-TargetNamespacehttp://www.ups.com/WSDL/XOLTWS/Track/v2.0 -nohostverify-nosessionreuse”)。
在服务器hs上运行TrackPortType set hp。
在hp中运行ProcessTrack(输入cBody,输出cBody2)。
删除程序hp。
hs:disconnect()。
删除对象hs。
我认为问题在于,当我运行ProcessTrack过程(使用SET-CALLBACK-procedure)时,我需要以某种方式发送头,但我不确定如何发送


提前谢谢

SET-CALLBACK-PROCEDURE就是方法

在运行SOAP调用之前,您需要执行以下操作(setRequestSessionHandler是过程的名称,因此它可以是您想要的任何名称):

hp:SET-CALLBACK-PROCEDURE("REQUEST-HEADER", "setRequestSessionHeader").
请求回调有两个输入和两个输出参数(名称取自文档,只要输入/输出和数据类型正确,就可以调用它们):

hSOAPHeader—封装SOAP消息头的SOAP头对象的句柄 即将发送的(请求标头)或刚刚接收的(响应标头)。作为回应 标头处理程序,如果SOAP标头对象上的NUM-header-ENTRIES属性 对象句柄返回值0;否则,它包含一个或多个SOAP头条目。请求 header handler,这是一个输出参数,因此如果传出SOAP消息需要SOAP 标头,您必须为此参数构建SOAP标头以引用,或提供现有SOAP标头 从以前的响应回调保存的标头

CopeOptionNamespace-包含操作限定名称的命名空间部分。用这个 如果需要标识的操作,请将参数与CopeOptionLocalName参数一起使用 正在发送或接收哪个SOAP消息

CopeOptionLocalName-包含操作限定名称的本地名称部分。用这个 如果需要标识的操作,请将参数与CopeOptionNamespace参数一起使用 正在发送或接收哪个SOAP消息

lDeleteOnDone-(仅限请求回调)告诉OpenEdge删除SOAP头对象和所有 SOAP头插入到外绑定SOAP消息后解析的XML

这是我模仿WS-Security所做的,不是您所需要的,而且还有很多代码。你应该能够“挖掘”你需要的任何东西

PROCEDURE setRequestSessionHeader :
/*------------------------------------------------------------------------------
  Purpose:     
  Parameters:  <none>
  Notes:       
------------------------------------------------------------------------------*/

DEFINE OUTPUT PARAMETER phHeader       AS HANDLE    NO-UNDO. 
DEFINE INPUT  PARAMETER pcNamespace    AS CHARACTER NO-UNDO.  
DEFINE INPUT  PARAMETER pcLocalNS      AS CHARACTER NO-UNDO.  
DEFINE OUTPUT PARAMETER plDeleteOnDone AS LOGICAL   NO-UNDO. 

DEFINE VARIABLE hSoapHeaderEntryref1    AS HANDLE      NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref2    AS HANDLE      NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref3    AS HANDLE      NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref4    AS HANDLE      NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref5    AS HANDLE      NO-UNDO.
DEFINE VARIABLE hXDocument              AS HANDLE      NO-UNDO.
DEFINE VARIABLE hOASSecurity            AS HANDLE      NO-UNDO.
DEFINE VARIABLE hOASUsernameToken       AS HANDLE      NO-UNDO.
DEFINE VARIABLE hOASUserName            AS HANDLE      NO-UNDO.
DEFINE VARIABLE hOASPassword            AS HANDLE      NO-UNDO.
DEFINE VARIABLE hOASPasswordType        AS HANDLE      NO-UNDO.
DEFINE VARIABLE hOASNonce               AS HANDLE      NO-UNDO.
DEFINE VARIABLE hWSUCreated             AS HANDLE      NO-UNDO.
DEFINE VARIABLE hADDMessageID           AS HANDLE      NO-UNDO.
DEFINE VARIABLE hADDTo                  AS HANDLE      NO-UNDO.
DEFINE VARIABLE hADDAction              AS HANDLE      NO-UNDO.
DEFINE VARIABLE hAMA_SecurityHostedUser AS HANDLE      NO-UNDO.
DEFINE VARIABLE hUserId                 AS HANDLE      NO-UNDO.
DEFINE VARIABLE hTxt                    AS HANDLE      NO-UNDO.
DEFINE VARIABLE hAttr                   AS HANDLE      NO-UNDO.
DEFINE VARIABLE hRootNode               AS HANDLE      NO-UNDO.

/* Namespaces */
DEFINE VARIABLE cNSAddressing           AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cNSSecurity             AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cNSSecurityUtils        AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cNSAmaSec               AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cMessageId              AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cUserName               AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cPasswordClear          AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cPasswordDigest         AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cCreated                AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cAction                 AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cTo                     AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cNonceB64               AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cOfficeId               AS CHARACTER   NO-UNDO.
DEFINE VARIABLE mNonce                  AS MEMPTR      NO-UNDO.

ASSIGN 
    cNSAddressing     = "http://www.w3.org/2005/08/addressing"
    cNSSecurity       = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
    cNSSecurityUtils  = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    cNSAmaSec         = "http://illkeepthisasecret..."
    cAction           = "http://illkeepthisasecret..."
    cTo               = "https://noded1.production.webservices.amadeus.com/1ASIWIBNAIT".

ASSIGN
    cUserName         = "usernamegoeshere"
    cOfficeId         = "anothersettinggoeshere"
    cPasswordClear    = "passwordgoeshere".

/* Delete header when done! */
ASSIGN 
    plDeleteOnDone = TRUE.

CREATE SOAP-HEADER ghSoapHeader.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref1.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref2.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref3.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref4.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref5.


CREATE X-DOCUMENT hXDocument.
CREATE X-NODEREF hRootNode.
CREATE X-NODEREF hOASSecurity.
CREATE X-NODEREF hTxt.
CREATE X-NODEREF hOASUsernameToken.
CREATE X-NODEREF hOASPassword.
CREATE X-NODEREF hOASUserName.
CREATE X-NODEREF hOASNonce.
CREATE X-NODEREF hADDMessageID.
CREATE X-NODEREF hADDTo.
CREATE X-NODEREF hADDAction.
CREATE X-NODEREF hWSUCreated.
CREATE X-NODEREF hAMA_SecurityHostedUser.
CREATE X-NODEREF hUserId.


/* Not DATETIME-TZ! */
DEFINE VARIABLE dtZuluNow AS DATETIME    NO-UNDO.

/* Genereate a random key and base64-encode it */
SET-SIZE(mNonce) = 16.

mNonce = GENERATE-RANDOM-KEY.

cNonceB64 = BASE64-ENCODE(mNonce).

/* Get time in UTC/GMT/ZULU/Timezone 0 */
dtZuluNow = DATETIME-TZ(NOW,0).

/* Manipulate the date string to fit specs... */
ASSIGN 
    cMessageId = LC(SUBSTRING(STRING(GENERATE-UUID), 8, 20))
    cCreated = STRING(dtZuluNow, "9999-99-99THH:MM:SS") + ":000Z".
/* This is internal stuff for generating a digest... */
RUN generatePasswordDigest( mNonce, cCreated, cPasswordClear, OUTPUT cPasswordDigest).

/* Root node */
hXDocument:CREATE-NODE-NAMESPACE(hRootNode, "", "root", "element").
hXDocument:INSERT-BEFORE(hRootNode, ?).

/**** Addressing ****/
/* MessageID */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref1).
hXDocument:CREATE-NODE-NAMESPACE(hADDMessageID, cNSAddressing, "MessageID", "ELEMENT").
hRootNode:APPEND-CHILD(hAddMessageID).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cMessageId.
hADDMessageId:APPEND-CHILD(hTxt).
hSoapHeaderEntryref1:SET-NODE(hADDMessageID).

/* Action */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref2).
hXDocument:CREATE-NODE-NAMESPACE(hADDAction, cNSAddressing, "Action", "ELEMENT").
hRootNode:APPEND-CHILD(hADDAction).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cAction.
hADDAction:APPEND-CHILD(hTxt).
hSoapHeaderEntryref2:SET-NODE(hADDAction).

/* To */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref3).
hXDocument:CREATE-NODE-NAMESPACE(hADDTo, cNSAddressing, "To", "ELEMENT").
hRootNode:APPEND-CHILD(hADDTo).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cTo.
hADDTo:APPEND-CHILD(hTxt).
hSoapHeaderEntryref3:SET-NODE(hADDTo).

/**** Security ****/
/* Root node */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref4).
hXDocument:CREATE-NODE-NAMESPACE(hOASSecurity, cNSSecurity, "Security", "ELEMENT").
hRootNode:APPEND-CHILD(hOASSecurity).

/* UserNameToken node */
hXDocument:CREATE-NODE-NAMESPACE(hOASUsernameToken, cNSSecurity, "UsernameToken", "ELEMENT").
hOASUsernameToken:SET-ATTRIBUTE("Id", "UsernameToken-1").
hOASSecurity:INSERT-BEFORE(hOASUsernameToken, ?).

/* Username */
hXDocument:CREATE-NODE-NAMESPACE(hOASUserName, cNSSecurity, "Username", "ELEMENT").
hRootNode:APPEND-CHILD(hOASUserName).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cUserName.
hOASUserName:APPEND-CHILD(hTxt).
hOASUsernameToken:APPEND-CHILD(hOASUserName).

/* Nonce */
hXDocument:CREATE-NODE-NAMESPACE(hOASNonce, cNSSecurity, "Nonce", "ELEMENT").
hOASNonce:SET-ATTRIBUTE("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary").
hOASUsernameToken:APPEND-CHILD(hOASNonce).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cNonceB64.
hOASNonce:APPEND-CHILD(hTxt).

/* Password hash */
hXDocument:CREATE-NODE-NAMESPACE(hOASPassword, cNSSecurity, "Password", "ELEMENT").
hOASPassword:SET-ATTRIBUTE("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest").
hOASUsernameToken:APPEND-CHILD(hOASPassword).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cPasswordDigest.
hOASPassword:APPEND-CHILD(hTxt).

/* Created - timestamp */
hXDocument:CREATE-NODE-NAMESPACE(hWSUCreated, cNSSecurityUtils, "Created", "ELEMENT").
hOASUsernameToken:APPEND-CHILD(hWSUCreated).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cCreated.
hWSUCreated:APPEND-CHILD(hTxt).
hSoapHeaderEntryref4:SET-NODE(hOASSecurity).

/**** AMA_SecurityHostedUser ****/
/* Root node */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref5).
hXDocument:CREATE-NODE-NAMESPACE(hAMA_SecurityHostedUser, cNSAMASec, "AMA_SecurityHostedUser", "ELEMENT").
hRootNode:APPEND-CHILD(hAMA_SecurityHostedUser).


/* UserID */
hXDocument:CREATE-NODE-NAMESPACE(hUserID, cNSAMASec, "UserID", "ELEMENT").

hUserID:SET-ATTRIBUTE("AgentDutyCode", "SU"). 
hUserID:SET-ATTRIBUTE("RequestorType", "U").
hUserID:SET-ATTRIBUTE("PseudoCityCode", cOfficeId).
hUserID:SET-ATTRIBUTE("POS_Type", "1").

hAMA_SecurityHostedUser:APPEND-CHILD(hUserID).
hSoapHeaderEntryref5:SET-NODE(hAMA_SecurityHostedUser).

/* Output the header */
phHeader = ghSoapHeader.

/* Cleanup */
IF VALID-HANDLE(hOASSecurity) THEN 
    DELETE OBJECT hOASSecurity.
IF VALID-HANDLE(hOASUsernameToken) THEN
    DELETE OBJECT hOASUsernameToken.
IF VALID-HANDLE(hOASUserName) THEN
    DELETE OBJECT hOASUserName.
IF VALID-HANDLE(hOASPassword) THEN
    DELETE OBJECT hOASPassword.
IF VALID-HANDLE(hADDMessageID) THEN
    DELETE OBJECT hADDMessageID.  
IF VALID-HANDLE(hOASNonce) THEN
    DELETE OBJECT hOASNonce.
IF VALID-HANDLE(hTxt) THEN
    DELETE OBJECT hTxt.
IF VALID-HANDLE(hADDTo) THEN
    DELETE OBJECT hADDTo.    
IF VALID-HANDLE(hWSUCreated) THEN
    DELETE OBJECT hWSUCreated.
IF VALID-HANDLE(hADDAction) THEN
    DELETE OBJECT hADDAction.     
IF VALID-HANDLE(hXDocument) THEN
    DELETE OBJECT hXDocument.
IF VALID-HANDLE(hRootNode) THEN
    DELETE OBJECT hRootNode.
IF VALID-HANDLE(hSoapHeaderEntryRef1) THEN
    DELETE OBJECT hSoapHeaderEntryRef1.
IF VALID-HANDLE(hSoapHeaderEntryRef2) THEN
    DELETE OBJECT hSoapHeaderEntryRef2.
IF VALID-HANDLE(hSoapHeaderEntryRef3) THEN
    DELETE OBJECT hSoapHeaderEntryRef3.
IF VALID-HANDLE(hSoapHeaderEntryRef4) THEN
    DELETE OBJECT hSoapHeaderEntryRef4.
IF VALID-HANDLE(hSoapHeaderEntryRef5) THEN
    DELETE OBJECT hSoapHeaderEntryRef5.
IF VALID-HANDLE(hAMA_SecurityHostedUser) THEN
    DELETE OBJECT hAMA_SecurityHostedUser.
IF VALID-HANDLE(hUserId) THEN
    DELETE OBJECT hUserId.

END.
过程setRequestSessionHeader:
/*------------------------------------------------------------------------------
目的:
参数:
笔记:
------------------------------------------------------------------------------*/
将输出参数phHeader定义为句柄NO-UNDO。
将输入参数pcNamespace定义为字符NO-UNDO。
将输入参数pcLocalNS定义为字符NO-UNDO。
将输出参数plDeleteOnDone定义为逻辑NO-UNDO。
将变量hSoapHeaderEntryref1定义为句柄NO-UNDO。
将变量hSoapHeaderEntryref2定义为句柄NO-UNDO。
将变量hSoapHeaderEntryref3定义为句柄NO-UNDO。
将变量hSoapHeaderEntryref4定义为句柄NO-UNDO。
将变量hSoapHeaderEntryref5定义为句柄NO-UNDO。
将变量hXDocument定义为句柄NO-UNDO。
将变量hOASSecurity定义为句柄NO-UNDO。
将变量hOASUsernameToken定义为句柄NO-UNDO。
将变量hOASUserName定义为句柄NO-UNDO。
将变量hOASPassword定义为句柄NO-UNDO。
将变量hOASPasswordType定义为句柄NO-UNDO。
将变量hOASNonce定义为句柄NO-UNDO。
将变量hWSUCreated定义为句柄NO-UNDO。
将变量hADDMessageID定义为句柄NO-UNDO。
将变量hADDTo定义为句柄NO-UNDO。
将变量hADDAction定义为句柄NO-UNDO。
将变量hAMA_SecurityHostedUser定义为句柄NO-UNDO。
将变量hUserId定义为句柄NO-UNDO。
将变量hTxt定义为句柄NO-UNDO。
将变量hAttr定义为句柄NO-UNDO。
将变量hRootNode定义为句柄NO-UNDO。
/*名称空间*/
将变量cNSAddressing定义为字符NO-UNDO。
将变量cNSSecurity定义为字符NO-UNDO。
将变量cNSSecurityUtils定义为字符NO-UNDO。
将变量cNSAmaSec定义为字符NO-UNDO。
将变量cMessageId定义为字符NO-UNDO。
将变量cUserName定义为字符NO-UNDO。
将变量cPasswordClear定义为字符NO-UNDO。
将变量cPasswordDigest定义为字符NO-UNDO。
将变量C定义为字符NO-UNDO。
判定元件
DEFINE OUTPUT PARAMETER hSOAPHeader         AS HANDLE    NO-UNDO. 
DEFINE INPUT  PARAMETER cOperationNamespace AS CHARACTER NO-UNDO.  
DEFINE INPUT  PARAMETER cOperationLocalName AS CHARACTER NO-UNDO.  
DEFINE OUTPUT PARAMETER plDeleteOnDone AS LOGICAL   NO-UNDO. 
PROCEDURE setRequestSessionHeader :
/*------------------------------------------------------------------------------
  Purpose:     
  Parameters:  <none>
  Notes:       
------------------------------------------------------------------------------*/

DEFINE OUTPUT PARAMETER phHeader       AS HANDLE    NO-UNDO. 
DEFINE INPUT  PARAMETER pcNamespace    AS CHARACTER NO-UNDO.  
DEFINE INPUT  PARAMETER pcLocalNS      AS CHARACTER NO-UNDO.  
DEFINE OUTPUT PARAMETER plDeleteOnDone AS LOGICAL   NO-UNDO. 

DEFINE VARIABLE hSoapHeaderEntryref1    AS HANDLE      NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref2    AS HANDLE      NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref3    AS HANDLE      NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref4    AS HANDLE      NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref5    AS HANDLE      NO-UNDO.
DEFINE VARIABLE hXDocument              AS HANDLE      NO-UNDO.
DEFINE VARIABLE hOASSecurity            AS HANDLE      NO-UNDO.
DEFINE VARIABLE hOASUsernameToken       AS HANDLE      NO-UNDO.
DEFINE VARIABLE hOASUserName            AS HANDLE      NO-UNDO.
DEFINE VARIABLE hOASPassword            AS HANDLE      NO-UNDO.
DEFINE VARIABLE hOASPasswordType        AS HANDLE      NO-UNDO.
DEFINE VARIABLE hOASNonce               AS HANDLE      NO-UNDO.
DEFINE VARIABLE hWSUCreated             AS HANDLE      NO-UNDO.
DEFINE VARIABLE hADDMessageID           AS HANDLE      NO-UNDO.
DEFINE VARIABLE hADDTo                  AS HANDLE      NO-UNDO.
DEFINE VARIABLE hADDAction              AS HANDLE      NO-UNDO.
DEFINE VARIABLE hAMA_SecurityHostedUser AS HANDLE      NO-UNDO.
DEFINE VARIABLE hUserId                 AS HANDLE      NO-UNDO.
DEFINE VARIABLE hTxt                    AS HANDLE      NO-UNDO.
DEFINE VARIABLE hAttr                   AS HANDLE      NO-UNDO.
DEFINE VARIABLE hRootNode               AS HANDLE      NO-UNDO.

/* Namespaces */
DEFINE VARIABLE cNSAddressing           AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cNSSecurity             AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cNSSecurityUtils        AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cNSAmaSec               AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cMessageId              AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cUserName               AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cPasswordClear          AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cPasswordDigest         AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cCreated                AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cAction                 AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cTo                     AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cNonceB64               AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cOfficeId               AS CHARACTER   NO-UNDO.
DEFINE VARIABLE mNonce                  AS MEMPTR      NO-UNDO.

ASSIGN 
    cNSAddressing     = "http://www.w3.org/2005/08/addressing"
    cNSSecurity       = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
    cNSSecurityUtils  = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    cNSAmaSec         = "http://illkeepthisasecret..."
    cAction           = "http://illkeepthisasecret..."
    cTo               = "https://noded1.production.webservices.amadeus.com/1ASIWIBNAIT".

ASSIGN
    cUserName         = "usernamegoeshere"
    cOfficeId         = "anothersettinggoeshere"
    cPasswordClear    = "passwordgoeshere".

/* Delete header when done! */
ASSIGN 
    plDeleteOnDone = TRUE.

CREATE SOAP-HEADER ghSoapHeader.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref1.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref2.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref3.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref4.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref5.


CREATE X-DOCUMENT hXDocument.
CREATE X-NODEREF hRootNode.
CREATE X-NODEREF hOASSecurity.
CREATE X-NODEREF hTxt.
CREATE X-NODEREF hOASUsernameToken.
CREATE X-NODEREF hOASPassword.
CREATE X-NODEREF hOASUserName.
CREATE X-NODEREF hOASNonce.
CREATE X-NODEREF hADDMessageID.
CREATE X-NODEREF hADDTo.
CREATE X-NODEREF hADDAction.
CREATE X-NODEREF hWSUCreated.
CREATE X-NODEREF hAMA_SecurityHostedUser.
CREATE X-NODEREF hUserId.


/* Not DATETIME-TZ! */
DEFINE VARIABLE dtZuluNow AS DATETIME    NO-UNDO.

/* Genereate a random key and base64-encode it */
SET-SIZE(mNonce) = 16.

mNonce = GENERATE-RANDOM-KEY.

cNonceB64 = BASE64-ENCODE(mNonce).

/* Get time in UTC/GMT/ZULU/Timezone 0 */
dtZuluNow = DATETIME-TZ(NOW,0).

/* Manipulate the date string to fit specs... */
ASSIGN 
    cMessageId = LC(SUBSTRING(STRING(GENERATE-UUID), 8, 20))
    cCreated = STRING(dtZuluNow, "9999-99-99THH:MM:SS") + ":000Z".
/* This is internal stuff for generating a digest... */
RUN generatePasswordDigest( mNonce, cCreated, cPasswordClear, OUTPUT cPasswordDigest).

/* Root node */
hXDocument:CREATE-NODE-NAMESPACE(hRootNode, "", "root", "element").
hXDocument:INSERT-BEFORE(hRootNode, ?).

/**** Addressing ****/
/* MessageID */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref1).
hXDocument:CREATE-NODE-NAMESPACE(hADDMessageID, cNSAddressing, "MessageID", "ELEMENT").
hRootNode:APPEND-CHILD(hAddMessageID).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cMessageId.
hADDMessageId:APPEND-CHILD(hTxt).
hSoapHeaderEntryref1:SET-NODE(hADDMessageID).

/* Action */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref2).
hXDocument:CREATE-NODE-NAMESPACE(hADDAction, cNSAddressing, "Action", "ELEMENT").
hRootNode:APPEND-CHILD(hADDAction).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cAction.
hADDAction:APPEND-CHILD(hTxt).
hSoapHeaderEntryref2:SET-NODE(hADDAction).

/* To */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref3).
hXDocument:CREATE-NODE-NAMESPACE(hADDTo, cNSAddressing, "To", "ELEMENT").
hRootNode:APPEND-CHILD(hADDTo).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cTo.
hADDTo:APPEND-CHILD(hTxt).
hSoapHeaderEntryref3:SET-NODE(hADDTo).

/**** Security ****/
/* Root node */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref4).
hXDocument:CREATE-NODE-NAMESPACE(hOASSecurity, cNSSecurity, "Security", "ELEMENT").
hRootNode:APPEND-CHILD(hOASSecurity).

/* UserNameToken node */
hXDocument:CREATE-NODE-NAMESPACE(hOASUsernameToken, cNSSecurity, "UsernameToken", "ELEMENT").
hOASUsernameToken:SET-ATTRIBUTE("Id", "UsernameToken-1").
hOASSecurity:INSERT-BEFORE(hOASUsernameToken, ?).

/* Username */
hXDocument:CREATE-NODE-NAMESPACE(hOASUserName, cNSSecurity, "Username", "ELEMENT").
hRootNode:APPEND-CHILD(hOASUserName).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cUserName.
hOASUserName:APPEND-CHILD(hTxt).
hOASUsernameToken:APPEND-CHILD(hOASUserName).

/* Nonce */
hXDocument:CREATE-NODE-NAMESPACE(hOASNonce, cNSSecurity, "Nonce", "ELEMENT").
hOASNonce:SET-ATTRIBUTE("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary").
hOASUsernameToken:APPEND-CHILD(hOASNonce).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cNonceB64.
hOASNonce:APPEND-CHILD(hTxt).

/* Password hash */
hXDocument:CREATE-NODE-NAMESPACE(hOASPassword, cNSSecurity, "Password", "ELEMENT").
hOASPassword:SET-ATTRIBUTE("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest").
hOASUsernameToken:APPEND-CHILD(hOASPassword).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cPasswordDigest.
hOASPassword:APPEND-CHILD(hTxt).

/* Created - timestamp */
hXDocument:CREATE-NODE-NAMESPACE(hWSUCreated, cNSSecurityUtils, "Created", "ELEMENT").
hOASUsernameToken:APPEND-CHILD(hWSUCreated).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cCreated.
hWSUCreated:APPEND-CHILD(hTxt).
hSoapHeaderEntryref4:SET-NODE(hOASSecurity).

/**** AMA_SecurityHostedUser ****/
/* Root node */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref5).
hXDocument:CREATE-NODE-NAMESPACE(hAMA_SecurityHostedUser, cNSAMASec, "AMA_SecurityHostedUser", "ELEMENT").
hRootNode:APPEND-CHILD(hAMA_SecurityHostedUser).


/* UserID */
hXDocument:CREATE-NODE-NAMESPACE(hUserID, cNSAMASec, "UserID", "ELEMENT").

hUserID:SET-ATTRIBUTE("AgentDutyCode", "SU"). 
hUserID:SET-ATTRIBUTE("RequestorType", "U").
hUserID:SET-ATTRIBUTE("PseudoCityCode", cOfficeId).
hUserID:SET-ATTRIBUTE("POS_Type", "1").

hAMA_SecurityHostedUser:APPEND-CHILD(hUserID).
hSoapHeaderEntryref5:SET-NODE(hAMA_SecurityHostedUser).

/* Output the header */
phHeader = ghSoapHeader.

/* Cleanup */
IF VALID-HANDLE(hOASSecurity) THEN 
    DELETE OBJECT hOASSecurity.
IF VALID-HANDLE(hOASUsernameToken) THEN
    DELETE OBJECT hOASUsernameToken.
IF VALID-HANDLE(hOASUserName) THEN
    DELETE OBJECT hOASUserName.
IF VALID-HANDLE(hOASPassword) THEN
    DELETE OBJECT hOASPassword.
IF VALID-HANDLE(hADDMessageID) THEN
    DELETE OBJECT hADDMessageID.  
IF VALID-HANDLE(hOASNonce) THEN
    DELETE OBJECT hOASNonce.
IF VALID-HANDLE(hTxt) THEN
    DELETE OBJECT hTxt.
IF VALID-HANDLE(hADDTo) THEN
    DELETE OBJECT hADDTo.    
IF VALID-HANDLE(hWSUCreated) THEN
    DELETE OBJECT hWSUCreated.
IF VALID-HANDLE(hADDAction) THEN
    DELETE OBJECT hADDAction.     
IF VALID-HANDLE(hXDocument) THEN
    DELETE OBJECT hXDocument.
IF VALID-HANDLE(hRootNode) THEN
    DELETE OBJECT hRootNode.
IF VALID-HANDLE(hSoapHeaderEntryRef1) THEN
    DELETE OBJECT hSoapHeaderEntryRef1.
IF VALID-HANDLE(hSoapHeaderEntryRef2) THEN
    DELETE OBJECT hSoapHeaderEntryRef2.
IF VALID-HANDLE(hSoapHeaderEntryRef3) THEN
    DELETE OBJECT hSoapHeaderEntryRef3.
IF VALID-HANDLE(hSoapHeaderEntryRef4) THEN
    DELETE OBJECT hSoapHeaderEntryRef4.
IF VALID-HANDLE(hSoapHeaderEntryRef5) THEN
    DELETE OBJECT hSoapHeaderEntryRef5.
IF VALID-HANDLE(hAMA_SecurityHostedUser) THEN
    DELETE OBJECT hAMA_SecurityHostedUser.
IF VALID-HANDLE(hUserId) THEN
    DELETE OBJECT hUserId.

END.