【问题标题】:How to send a SOAP headers in Progress 4GL如何在 Progress 4GL 中发送 SOAP 标头
【发布时间】:2020-09-21 07:41:09
【问题描述】:

您好,Progress 4GL 开发人员,

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

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

<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>

当使用 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.

我认为问题在于,当我运行 ProcessTrack 过程(使用 SET-CALLBACK-PROCEDURE)时,我需要以某种方式发送标头,但我不确定如何。

提前致谢!

【问题讨论】:

  • 你好约瑟夫。我也在尝试使用 Progress4GL 的跟踪网络服务。但是我遇到了一个问题,即我的会话在执行请求时崩溃了。一些答案指出我在使用 11.5 时升级到版本 11.7。只是想检查您是否遇到类似的问题,如果是,您是如何解决的。任何提示都会帮助我。这是我的question的链接
  • 你好 davidbilla,对于这个特定的 SOAP Web 服务,我没有遇到任何问题,但是我确实遇到了一些问题,使用 HTTPClientLibrary 尝试在我的 OpenEdge 环境中使用不同的 REST Web 服务.使用 .NET 运行时会发生这种情况。为了克服这个问题,我实际上最终调整了我的代码版本,改为进入操作系统并使用 CURL 而不是 HTTPClient。因此,例如,代替 HTTPClientBuilder,我将使用以下过程(将 URL 作为输入):```
  • 谢谢约瑟夫。我也接受了休息服务。

标签: xml soap openedge progress-4gl


【解决方案1】:

SET-CALLBACK-PROCEDURE 是一种方式。

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

hp:SET-CALLBACK-PROCEDURE("REQUEST-HEADER", "setRequestSessionHeader").

request-callback 有两个输入和两个输出参数(名称取自文档,只要输入/输出和数据类型正确,就可以调用任何名称):

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. 

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

cOperationNamespace — 包含操作限定名称的命名空间部分。用这个 如果您需要识别操作,请与 cOperationLocalName 参数一起使用 正在发送或接收的 SOAP 消息。

cOperationLocalName — 包含操作限定名称的本地名称部分。用这个 如果您需要识别操作,则参数连同 cOperationNamespace 参数 正在发送或接收的 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.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-10
    • 1970-01-01
    • 1970-01-01
    • 2014-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多