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