Hello Progress 4GL开发人员,
我想在ABL会话中使用UPS跟踪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)时需要以某种方式发送标头,但是我不确定如何发送。
提前感谢!
SET-CALLBACK-PROCEDURE是方法。
在运行SOAP调用之前,您需要执行以下操作(setRequestSessionHandler是过程的名称,因此它可以是您想要的任何名称):
hp:SET-CALLBACK-PROCEDURE("REQUEST-HEADER", "setRequestSessionHeader").
请求回调具有两个输入和两个输出参数(取自文档的名称,只要输入/输出和数据类型正确,它们就可以调用任何名称:]
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标头对象的句柄将要发送的(请求标头)或刚刚被接收的(响应标头)。在回应中标头处理程序,如果SOAP标头对象上的NUM-HEADER-ENTRIES属性没有内容,对象句柄返回值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.