Source Member: QRPGLESRC,FDXAV
H NOMAIN
*
*?FedEx Address Verification
*
*?This module contains the FDX_verifyAddress() procedure, which
*?allows the user to pass in an address or partial address and
*?return a list of matching addresses.
*
*=====================================================================
/copy rxs,rxscp ?RPG-XML Suite
/copy rxs,fdxcp ?FedEx Address Verification
D atoi pr 10i 0 Extproc('atoi')
D string * value options(*string)
D validate pr
D compose pr
D transmit pr
D parse pr
D allHandler pr
D pType value like(RXS_Type)
D pXPath value like(RXS_XPath)
D pData value like(RXS_XmlData)
D pDataLen value like(RXS_Length)
D errHandler pr
D pCurLine 10i 0 value
D pCurCol 10i 0 value
D pErrStr 1024a value varying
D TransactionID s 40a inz
D gInput ds Inz Likeds(FDXAV_Input)
D gOutput ds Inz Likeds(FDXAV_Output)
D gError ds Inz Likeds(RXS_Error)
D addr ds inz likeds(address_t)
D gInCfg ds likeds(RXS_GetUriIn) inz
D gReqData s like(RXS_XmlData)
D gRspData s like(RXS_XmlData)
D gRspHttpHdr s like(RXS_XmlData)
D gPfx s 256a varying
*=====================================================================
*?FDX_verifyAddress(): Verify an address using FedEx.
*=====================================================================
P FDX_verifyAddress...
P b Export
D pi
D pInput Const Likeds(FDXAV_Input)
D pOutput Likeds(FDXAV_Output)
D pError Likeds(RXS_Error)
*---------------------------------------------------------------------
D pssr s n inz
*---------------------------------------------------------------------
/free
//?Set global variables
gInput = pInput;
clear gOutput;
clear gError;
gPfx = '/FDXAddressVerificationReply';
//?Create a unique transaction ID
TransactionID = RXS_nextUnqChar();
//?Validate the input address details
validate();
if gError.code <> *blanks;
exsr return;
endif;
//?Compose request
compose();
if gError.code <> *blanks;
exsr return;
endif;
//?Send request
transmit();
if gError.code <> *blanks;
exsr return;
endif;
//?Parse response
parse();
if gError.code <> *blanks;
exsr return;
endif;
exsr return;
//?return: Set parameters and return to caller
begsr return;
pOutput = gOutput;
pError = gError;
return;
endsr;
//?*pssr: Error-handling subroutine
begsr *pssr;
if pssr = *off;
pssr = *on;
if gError.code = *blanks;
gError = RXS_catchError();
endif;
pError = gError;
endif;
return;
endsr;
/end-free
P e
*=====================================================================
*?validate(): Validate the address
*=====================================================================
P validate b
D pi
*---------------------------------------------------------------------
/free
select;
when gInput.CarrierCode <> 'FDXE' and
gInput.CarrierCode <> 'FDXG';
gError.text = 'Invalid carrier code';
when gInput.Line1 = *blanks;
gError.text = 'No address line 1 specified';
when gInput.City = *blanks and gInput.ZipCode = *blanks;
gError.text = 'City and Zip Code are both blank';
when gInput.CarrierCode = 'FDXG' and
%subst( gInput.City : 21 ) <> *blanks;
gError.text = 'City name too long for Fedex Ground';
when gInput.State = *blanks and gInput.ZipCode = *blanks;
gError.text = 'State and Zip Code are both blank';
when %check( '0123456789' : %trim( gInput.ZipCode ) ) > 0;
gError.text = 'Zip Code must be numeric only';
when gInput.MaxMatch <= 0 or gInput.MaxMatch > 10;
gError.text = 'Invalid number of entries to check';
endsl;
if gError.text <> *blanks;
exsr *pssr;
endif;
return;
//?*pssr: Error-handling subroutine
begsr *pssr;
gError.code = 'FDXAV';
gError.severity = 100;
gError.pgm = 'FDXAV.validate';
if gError.text = *blanks;
gError.text = 'Error in FDXAV.validate()';
endif;
return;
endsr;
/end-free
P e
*=====================================================================
*?compose(): Compose the message
*=====================================================================
P compose b
D pi
*---------------------------------------------------------------------
/free
RXS_initTplEng(RXS_VAR: *omit: *omit: *omit: *omit: *on);
RXS_loadTpl('fdx_av_req.tpl');
//?Write start section
RXS_updVar( 'CustomerTransactionIdentifier' : TransactionID );
RXS_updVar( 'AccountNumber' : gInput.AccountNbr );
RXS_updVar( 'MeterNumber' : gInput.MeterNbr );
RXS_updVar( 'CarrierCode' : gInput.CarrierCode );
RXS_updVar( 'CompanyName' : gInput.Company );
RXS_updVar( 'Line1' : gInput.Line1 );
RXS_wrtSection( 'FDXAddressVerificationRequest_begin' );
//?Write optional sections
if gInput.Line2 <> *blanks;
RXS_updVar( 'Line2' : gInput.line2 );
RXS_wrtSection( 'Line2Exists' );
endif;
if gInput.City <> *blanks;
RXS_updVar( 'City' : gInput.City );
RXS_wrtSection( 'CityExists' );
endif;
if gInput.State <> *blanks;
RXS_updVar( 'StateOrProvinceCode' : gInput.State );
RXS_wrtSection( 'StateOrProvinceCodeExists' );
endif;
if gInput.ZipCode <> *blanks;
RXS_updVar( 'PostalCode' : gInput.ZipCode );
RXS_wrtSection( 'PostalCodeExists' );
endif;
if gInput.UrbName <> *blanks;
RXS_updVar( 'Urbanization' : gInput.UrbName );
RXS_wrtSection( 'UrbanizationExists' );
endif;
//?Write end section
RXS_updVar( 'MaximumMatchCount' : %char( gInput.MaxMatch ) );
RXS_wrtSection( 'FDXAddressVerificationRequest_end' );
//?Clear buffer after retrieval
gReqData = RXS_getBuffData(*on);
//?*pssr: Error-handling subroutine
begsr *pssr;
gError = RXS_catchError();
return;
endsr;
/end-free
P E
*=====================================================================
*?transmit(): Transmit the request
*=====================================================================
P transmit B
D PI
*---------------------------------------------------------------------
/free
clear gInCfg;
gInCfg.URI = 'https://gatewaybeta.fedex.com/GatewayDC';
gInCfg.Port = 443;
gInCfg.SSL = RXS_YES;
RXS_getUri(gInCfg: gReqData: gRspData: gRspHttpHdr);
return;
//?*pssr: Error-handling subroutine
begsr *pssr;
gError = RXS_catchError();
return;
endsr;
/end-free
P E
*=====================================================================
*?parse(): Parse the response
*=====================================================================
P parse B
D PI
*---------------------------------------------------------------------
/free
RXS_allElemEndHandler(%paddr(allHandler));
RXS_allElemContentHandler(%paddr(allHandler));
RXS_allAttrHandler(%paddr(allHandler));
RXS_parse(gRspData: RXS_VAR: %paddr(errHandler));
return;
//?*pssr: Error-handling subroutine
begsr *pssr;
gError = RXS_catchError();
return;
endsr;
/end-free
P E
*=====================================================================
*?allHandler(): Process the response
*=====================================================================
P allHandler B
D PI
D pType value like(RXS_Type)
D pXPath value like(RXS_XPath)
D pData value like(RXS_XmlData)
D pDataLen value like(RXS_Length)
*---------------------------------------------------------------------
/free
//?End of Match, so load address into output address array
if pType = '/>';
if pXPath = gPfx + '/Match/>';
gOutput.NbrEntRtn = gOutput.NbrEntRtn + 1;
gOutput.AddressArray(gOutput.NbrEntRtn) = addr;
clear addr;
endif;
return;
endif;
//?Ignore blank entries
pData = %xlate( x'25' : x'40' : pData );
if pData = *blanks;
return;
endif;
select;
//?Non-matching response
when pXPath = gPfx + '/ReplyHeader/CustomerTransactionIdentifier/';
if pData <> TransactionID;
//?error - response doesn't match request
gError.text = 'Non-matching customer transaction identifier';
exsr *pssr;
endif;
//?Hard error information
when pXPath = gPfx + '/Error/Code/';
gOutput.HErrCode = pData;
when pXPath = gPfx + '/Error/Message/';
gOutput.HErrMsg = pData;
//?Matching address information
when pXPath = gPfx + '/Match/Score/';
addr.Score = atoi(pData);
when pXPath = gPfx + '/Match/Rank/';
addr.Rank = %triml( pData );
when pXPath = gPfx + '/Match/SingleHouseNumber/';
addr.House = %triml( pData );
when pXPath = gPfx + '/Match/CompanyName/';
addr.Company = %triml( pData );
when pXPath = gPfx + '/Match/Line1/';
addr.Line1 = %triml( pData );
when pXPath = gPfx + '/Match/Line2/';
addr.Line2 = %triml( pData );
when pXPath = gPfx + '/Match/City/';
addr.City = %triml( pData );
when pXPath = gPfx + '/Match/StateOrProvinceCode/';
addr.State = %triml( pData );
when pXPath = gPfx + '/Match/PostalCode/';
addr.ZipCode = %triml( pData );
when pXPath = gPfx + '/Match/Urbanization/';
addr.UrbName = %triml( pData );
when pXPath = gPfx + '/Match/ResidentialDelivery/';
addr.Residence = atoi(pData);
//?Soft error information
when pXPath = gPfx + '/Match/SoftError/Type/';
addr.SErrType = pData;
when pXPath = gPfx + '/Match/SoftError/Code/';
addr.SErrCode = pData;
when pXPath = gPfx + '/Match/SoftError/Message/';
addr.SErrMsg = pData;
endsl;
return;
//?*pssr: Error-handling subroutine
begsr *pssr;
gError.code = 'FDXAV';
gError.severity = 100;
gError.pgm = 'FDXAV.allHandler';
if gError.text = *blanks;
gError.text = 'Error in FDXAV.allHandler()';
endif;
return;
endsr;
/end-free
P E
*=====================================================================
*?errHandler(): Error handler
*=====================================================================
P errHandler B
D PI
D pCurLine 10i 0 value
D pCurCol 10i 0 value
D pErrStr 1024a value varying
*---------------------------------------------------------------------
/free
gError.code = 'FDXAV';
gError.severity = 100;
gError.pgm = 'FDXAV.errHandler';
gError.text = 'Line: ' + %char( pCurLine ) +
' Column: ' + %char( pCurCol ) +
' ' + pErrStr;
return;
begsr *pssr;
return;
endsr;
/end-free
P E