Can't find what you're looking for? Try our AI Chat Bot in the bottom right corner!

Articles in this section

Address Validation

Address Validation

Miva 10 introduces native address validation which supports validating against USPS or UPS data. Once enabled, the address the customer enters during checkout will be validated in real-time and the customer will be presented with any suggested changes before they continue.

By default only the validated shipping address is presented to the customer however, it's possible to have both the shipping address as well as the billing address validated and let the customer choose both.

On this Page

Setup and Configuration

Miva supports two data sources for Address Validation by default. UPS and USPS, One of these two shipping modules must be installed for the address validation to work. Shipping rates do not need to be displayed to use address validation.

Once either of the shipping modules has been installed in a store, enabling address validation can be done under Shipping Settings -> Setting -> Shipping Rules .

Note

A valid shipping module must be installed to see options in the Address Validation list.

In addition to choosing the data source, there are two additional options which are both selected by default:

Validate Addresses at Checkout – If enabled when the customer enters their address during checkout (OCST) and clicks continue, they will be required to pick a validated address before continuing to the next page.

Validate Customer Address – If enabled, when a customer is logged in and adds a new address in their address book, Miva will first validate the address before saving and force the customer to choose a validated address (or accept the original).

Template Changes

Template changes are required for address validation to work. Default CSSUI template changes for address validation can be found here: https://www.miva.com/template-changes

Since Miva 10 now ships with and defaults to the Shadows ReadyTheme, the template changes it implements for Address Validation are likely what most customers will want to implement.

Shadows stores the Address Validation code in a Content Section Theme Component:

Copy
<mvt:if expr="NOT ISNULL l.settings:customer:validated_ship_addresses OR NOT ISNULL l.settings:customer:validated_bill_addresses OR NOT ISNULL l.settings:addressfields:validated_addresses">
    <div class="c-dialog" data-dialog="address-validation" aria-hidden="true">
        <div class="c-dialog__overlay" tabindex="-1">
            <div class="c-dialog__container" aria-labelledby="address-validation-title" aria-describedby="address-validation-description" aria-modal="true" role="alertdialog">
                <header class="c-dialog__header">
                    <h2 id="address-validation-title" class="c-dialog__title c-heading-delta u-text-uppercase">
                        Address Verification<br><br>
                        <span id="address-validation-description" class="c-heading--subheading u-text-revert">
                            <strong class="u-font-large">Shipping Address</strong><br>
                            The shipping address you entered appears to be incorrect or incomplete. Please verify your address to ensure a timely delivery.
                        </span>
                    </h2>
                    <button class="c-dialog__close" aria-label="Close Dialog" data-dialog-close></button>
                </header>
                <div class="c-dialog__content">
                    <div class="o-layout u-grids-1 u-grids-2--s">
                        <mvt:if expr="l.settings:page:code EQ 'CADA' OR l.settings:page:code EQ 'CADE'">
                            <mvt:assign name="l.settings:addressArray" value="l.settings:addressfields:validated_addresses"/>
                        <mvt:else>
                            <mvt:assign name="l.settings:addressArray" value="l.settings:customer:validated_ship_addresses"/>
                        </mvt:if>
                        <div class="o-layout__item">
                            <mvt:foreach array="addressArray" iterator="address">
                                <mvt:if expr="NOT l.settings:address:validated">
                                    <label class="c-form-checkbox">
                                        <input class="c-form-checkbox__input" type="radio" name="ShipValidatedSelector" data-mm_address_addr1="&mvte:address:addr1;" data-mm_address_addr2="&mvte:address:addr2;" data-mm_address_city="&mvte:address:city;" data-mm_address_comp="&mvte:address:comp;" data-mm_address_country="&mvte:address:country;" data-mm_address_resdntl="&mvte:address:resdntl;" data-mm_address_state="&mvte:address:state;" data-mm_address_zip="&mvte:address:zip;">
                                        <span class="c-form-checkbox__caption u-text-bold">Use&nbsp;<span class="u-hide-visually">Shipping Address&nbsp;</span>As Entered</span>
                                    </label>
                                    <p class="u-font-small">
                                        <mvt:if expr="NOT ISNULL l.settings:address:comp">
                                            &mvte:address:comp;<br>
                                        </mvt:if>
                                        <mvt:if expr="NOT ISNULL l.settings:address:addr1 OR NOT ISNULL l.settings:address:addr2 OR NOT ISNULL l.settings:address:city OR NOT ISNULL l.settings:address:state OR NOT ISNULL l.settings:address:zip OR NOT ISNULL l.settings:address:cntry OR NOT ISNULL l.settings:address:res">
                                            &mvte:address:addr1;<br>
                                            <mvt:if expr="NOT ISNULL l.settings:address:addr2">
                                                &mvte:address:addr2;<br>
                                            </mvt:if>
                                            <mvt:if expr="(NOT ISNULL l.settings:address:city) AND (NOT ISNULL l.settings:address:state)">
                                                &mvte:address:city;, &mvte:address:state; &mvte:address:zip; &mvte:address:country;
                                            <mvt:else>
                                                &mvte:address:city; &mvte:address:state; &mvte:address:zip; &mvte:address:country;
                                            </mvt:if>
                                            <mvt:if expr="l.settings:address:resdntl">
                                                <br>Residential Address
                                            </mvt:if>
                                        </mvt:if>
                                    </p>
                                    <hr class="c-keyline c-keyline--small">
                                </mvt:if>
                            </mvt:foreach>
                        </div>
                        <div class="o-layout__item">
                            <mvt:assign name="l.settings:address_count" value="1" />
                            <mvt:foreach array="addressArray" iterator="address">
                                <mvt:if expr="l.settings:address:validated">
                                    <label class="c-form-checkbox">
                                        <input class="c-form-checkbox__input" type="radio" name="ShipValidatedSelector" data-mm_address_addr1="&mvte:address:addr1;" data-mm_address_addr2="&mvte:address:addr2;" data-mm_address_city="&mvte:address:city;" data-mm_address_comp="&mvte:address:comp;" data-mm_address_country="&mvte:address:country;" data-mm_address_resdntl="&mvte:address:resdntl;" data-mm_address_state="&mvte:address:state;" data-mm_address_zip="&mvte:address:zip;" aria-describedby="address-&mvt:address_count;">
                                        <span class="c-form-checkbox__caption u-text-bold">Verified&nbsp;<span class="u-hide-visually">Shipping&nbsp;</span>Address <span class="u-hide-visually">&mvt:address_count;</span></span>
                                    </label>
                                    <p id="address-&mvt:address_count;" class="u-font-small">
                                        <mvt:if expr="NOT ISNULL l.settings:address:comp">
                                            &mvte:address:comp;<br>
                                        </mvt:if>
                                        <mvt:if expr="NOT ISNULL l.settings:address:addr1 OR NOT ISNULL l.settings:address:addr2 OR NOT ISNULL l.settings:address:city OR NOT ISNULL l.settings:address:state OR NOT ISNULL l.settings:address:zip OR NOT ISNULL l.settings:address:cntry OR NOT ISNULL l.settings:address:res">
                                            &mvte:address:addr1;<br>
                                            <mvt:if expr="NOT ISNULL l.settings:address:addr2">
                                                &mvte:address:addr2;<br>
                                            </mvt:if>
                                            <mvt:if expr="(NOT ISNULL l.settings:address:city) AND (NOT ISNULL l.settings:address:state)">
                                                &mvte:address:city;, &mvte:address:state; &mvte:address:zip; &mvte:address:country;
                                            <mvt:else>
                                                &mvte:address:city; &mvte:address:state; &mvte:address:zip; &mvte:address:country;
                                            </mvt:if>
                                            <mvt:if expr="l.settings:address:resdntl">
                                                <br>Residential Address
                                            </mvt:if>
                                        </mvt:if>
                                    </p>
                                    <hr class="c-keyline c-keyline--small">
                                    <mvt:assign name="l.settings:address_count" value="l.settings:address_count + 1" />
                                </mvt:if>
                            </mvt:foreach>
                        </div>
                    </div>
                    
                    <mvt:if expr="l.settings:page:code NE 'CADA' AND l.settings:page:code NE 'CADE'">
                        <mvt:if expr="g.billing_to_show NE 1">
                            <br>
                            <p class="u-font-tiny" data-billing-shown>
                                <strong class="u-font-large">Billing Address</strong><br>
                                We were unable to verify the billing address you provided.
                            </p>
                            <div class="o-layout u-grids-1 u-grids-2--s">
                                <div class="o-layout__item">
                                    <mvt:foreach array="customer:validated_bill_addresses" iterator="address">
                                        <mvt:if expr="NOT l.settings:address:validated">
                                            <label class="c-form-checkbox">
                                                <input class="c-form-checkbox__input" type="radio" name="BillValidatedSelector" data-mm_address_addr1="&mvte:address:addr1;" data-mm_address_addr2="&mvte:address:addr2;" data-mm_address_city="&mvte:address:city;" data-mm_address_comp="&mvte:address:comp;" data-mm_address_country="&mvte:address:country;" data-mm_address_state="&mvte:address:state;" data-mm_address_zip="&mvte:address:zip;">
                                                <span class="c-form-checkbox__caption u-text-bold">Use&nbsp;<span class="u-hide-visually">Billing Address&nbsp;</span>As Entered</span>
                                            </label>
                                            <p class="u-font-small">
                                                <mvt:if expr="NOT ISNULL l.settings:address:comp">
                                                    &mvte:address:comp;<br>
                                                </mvt:if>
                                                <mvt:if expr="NOT ISNULL l.settings:address:addr1 OR NOT ISNULL l.settings:address:addr2 OR NOT ISNULL l.settings:address:city OR NOT ISNULL l.settings:address:state OR NOT ISNULL l.settings:address:zip OR NOT ISNULL l.settings:address:cntry">
                                                    &mvte:address:addr1;<br>
                                                    <mvt:if expr="NOT ISNULL l.settings:address:addr2">
                                                        &mvte:address:addr2;<br>
                                                    </mvt:if>
                                                    <mvt:if expr="(NOT ISNULL l.settings:address:city) AND (NOT ISNULL l.settings:address:state)">
                                                        &mvte:address:city;, &mvte:address:state; &mvte:address:zip; &mvte:address:country;
                                                    <mvt:else>
                                                        &mvte:address:city; &mvte:address:state; &mvte:address:zip; &mvte:address:country;
                                                    </mvt:if>
                                                </mvt:if>
                                            </p>
                                            <hr class="c-keyline c-keyline--small">
                                        </mvt:if>
                                    </mvt:foreach>
                                </div>
                                <div class="o-layout__item">
                                    <mvt:assign name="l.settings:bill_address_count" value="0" />
                                    <mvt:foreach array="customer:validated_bill_addresses" iterator="address">
                                        <mvt:if expr="l.settings:address:validated">
                                            <label class="c-form-checkbox">
                                                <input class="c-form-checkbox__input" type="radio" name="BillValidatedSelector" data-mm_address_addr1="&mvte:address:addr1;" data-mm_address_addr2="&mvte:address:addr2;" data-mm_address_city="&mvte:address:city;" data-mm_address_comp="&mvte:address:comp;" data-mm_address_country="&mvte:address:country;" data-mm_address_state="&mvte:address:state;" data-mm_address_zip="&mvte:address:zip;" aria-describedby="bill-address-&mvt:bill_address_count;">
                                                <span class="c-form-checkbox__caption u-text-bold">Verified&nbsp;<span class="u-hide-visually">Billing&nbsp;</span>Address <span class="u-hide-visually">&mvt:address_count;</span></span>
                                            </label>
                                            <p id="bill-address-&mvt:bill_address_count;" class="u-font-small">
                                                <mvt:if expr="NOT ISNULL l.settings:address:comp">
                                                    &mvte:address:comp;<br>
                                                </mvt:if>
                                                <mvt:if expr="NOT ISNULL l.settings:address:addr1 OR NOT ISNULL l.settings:address:addr2 OR NOT ISNULL l.settings:address:city OR NOT ISNULL l.settings:address:state OR NOT ISNULL l.settings:address:zip OR NOT ISNULL l.settings:address:cntry">
                                                    &mvte:address:addr1;<br>
                                                    <mvt:if expr="NOT ISNULL l.settings:address:addr2">
                                                        &mvte:address:addr2;<br>
                                                    </mvt:if>
                                                    <mvt:if expr="(NOT ISNULL l.settings:address:city) AND (NOT ISNULL l.settings:address:state)">
                                                        &mvte:address:city;, &mvte:address:state; &mvte:address:zip; &mvte:address:country;
                                                    <mvt:else>
                                                        &mvte:address:city; &mvte:address:state; &mvte:address:zip; &mvte:address:country;
                                                    </mvt:if>
                                                </mvt:if>
                                            </p>
                                            <hr class="c-keyline c-keyline--small">
                                            <mvt:assign name="l.settings:bill_address_count" value="l.settings:bill_address_count + 1" />
                                        </mvt:if>
                                    </mvt:foreach>
                                </div>
                            </div>
                        </mvt:if>
                    </mvt:if>
                    <br>
                    <div class="c-control-group o-layout--justify-end">
                        <button class="c-button c-button--hollow c-control-group__button u-color-primary" data-edit-address>Cancel</button>
                        <button class="c-button c-control-group__button u-bg-primary" data-update-address>Update Address</button>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <script>
        (function () {
            'use strict';
    
            const billAddresses = document.querySelectorAll('[name="BillValidatedSelector"]');
            const cancel = document.querySelector('[data-edit-address]');
            const dialogElement = document.querySelector('[data-dialog="address-validation"]');
            const formElement = document.querySelector('[data-validate-address]');
            const shipAddresses = document.querySelectorAll('[name="ShipValidatedSelector"]');
            const showBilling = document.querySelector('[data-billing-shown]');
            const update = document.querySelector('[data-update-address]');
            let billPrefix;
            let shipPrefix;
    
            if (formElement.elements.hasOwnProperty('Action') && (formElement.elements.Action.value === 'ORDR')) {
                billPrefix = 'Bill';
                shipPrefix = 'Ship';
            }
            else if (formElement.elements.hasOwnProperty('Action') && (formElement.elements.Action.value === 'ICST' || formElement.elements.Action.value === 'UCST')) {
                billPrefix = 'Customer_Bill';
                shipPrefix = 'Customer_Ship';
            }
            else if (formElement.elements.hasOwnProperty('Action') && (formElement.elements.Action.value === 'ICSA' || formElement.elements.Action.value === 'UCSA')) {
                shipPrefix = 'Address_';
            }
        
            function findFormInputs(form, prefix) {
                return {
                    billing: {
                        comp: form.elements[prefix + 'Company'],
                        addr1: form.elements[prefix + 'Address1'],
                        addr2: form.elements[prefix + 'Address2'],
                        city: form.elements[prefix + 'City'],
                        state: form.elements[prefix + 'State'],
                        stateSelect: form.elements[prefix + 'StateSelect'],
                        country: form.elements[prefix + 'Country'],
                        zip: form.elements[prefix + 'Zip'],
                        validated: form.elements[prefix + 'Validated']
                    },
                    shipping: {
                        comp: form.elements[prefix + 'Company'],
                        addr1: form.elements[prefix + 'Address1'],
                        addr2: form.elements[prefix + 'Address2'],
                        city: form.elements[prefix + 'City'],
                        state: form.elements[prefix + 'State'],
                        stateSelect: form.elements[prefix + 'StateSelect'],
                        country: form.elements[prefix + 'Country'],
                        zip: form.elements[prefix + 'Zip'],
                        validated: form.elements[prefix + 'Validated']
                    }
                };
            }
    
            function getSelectedShipAddress(){
                for (let i = 0; i < shipAddresses.length; i++) {
                    if (shipAddresses[i].checked) {
                        return {
                            comp: typeof shipAddresses[i].getAttribute('data-mm_address_comp') === 'string' ? shipAddresses[i].getAttribute('data-mm_address_comp') : '',
                            addr1: typeof shipAddresses[i].getAttribute('data-mm_address_addr1') === 'string' ? shipAddresses[i].getAttribute('data-mm_address_addr1') : '',
                            addr2: typeof shipAddresses[i].getAttribute('data-mm_address_addr2') === 'string' ? shipAddresses[i].getAttribute('data-mm_address_addr2') : '',
                            city: typeof shipAddresses[i].getAttribute('data-mm_address_city') === 'string' ? shipAddresses[i].getAttribute('data-mm_address_city') : '',
                            state: typeof shipAddresses[i].getAttribute('data-mm_address_state') === 'string' ? shipAddresses[i].getAttribute('data-mm_address_state') : '',
                            country: typeof shipAddresses[i].getAttribute('data-mm_address_country') === 'string' ? shipAddresses[i].getAttribute('data-mm_address_country') : '',
                            zip: typeof shipAddresses[i].getAttribute('data-mm_address_zip') === 'string' ? shipAddresses[i].getAttribute('data-mm_address_zip') : ''
                        };
                    }
                }
            }
    
            function getSelectedBillAddress(){
                for (let i = 0; i < billAddresses.length; i++) {
                    if (billAddresses[i].checked) {
                        return {
                            comp: typeof billAddresses[i].getAttribute('data-mm_address_comp') === 'string' ? billAddresses[i].getAttribute('data-mm_address_comp') : '',
                            addr1: typeof billAddresses[i].getAttribute('data-mm_address_addr1') === 'string' ? billAddresses[i].getAttribute('data-mm_address_addr1') : '',
                            addr2: typeof billAddresses[i].getAttribute('data-mm_address_addr2') === 'string' ? billAddresses[i].getAttribute('data-mm_address_addr2') : '',
                            city: typeof billAddresses[i].getAttribute('data-mm_address_city') === 'string' ? billAddresses[i].getAttribute('data-mm_address_city') : '',
                            state: typeof billAddresses[i].getAttribute('data-mm_address_state') === 'string' ? billAddresses[i].getAttribute('data-mm_address_state') : '',
                            country: typeof billAddresses[i].getAttribute('data-mm_address_country') === 'string' ? billAddresses[i].getAttribute('data-mm_address_country') : '',
                            zip: typeof billAddresses[i].getAttribute('data-mm_address_zip') === 'string' ? billAddresses[i].getAttribute('data-mm_address_zip') : ''
                        };
                    }
                }
            }
    
            function setFirstSuggestion(){
                for (let i = 0; i < shipAddresses.length; i++) {
                    if (shipAddresses.length === 1) {
                        shipAddresses[0].checked = true;
                    }
                    else if (shipAddresses.length > 1) {
                        shipAddresses[1].checked = true;
                    }
                }
                
                if (showBilling !== null) {
                    for (let i = 0; i < billAddresses.length; i++) {
                        if (billAddresses.length === 1) {
                            billAddresses[0].checked = true;
                        }
                        else if (billAddresses.length > 1) {
                            billAddresses[1].checked = true;
                        }
                    }
                }
            }
    
            cancel.addEventListener('click', function (clickEvent) {
                clickEvent.preventDefault();
                findFormInputs(formElement, shipPrefix).shipping.validated.value = 0;
                if (showBilling !== null) {
                    findFormInputs(formElement, billPrefix).billing.validated.value = 0;
                }
                window.closeDialog();
            });
    
            update.addEventListener('click', function (clickEvent) {
                clickEvent.preventDefault();
                findFormInputs(formElement, shipPrefix).shipping.comp.value = getSelectedShipAddress().comp;
                findFormInputs(formElement, shipPrefix).shipping.addr1.value = getSelectedShipAddress().addr1;
                findFormInputs(formElement, shipPrefix).shipping.addr2.value = getSelectedShipAddress().addr2;
                findFormInputs(formElement, shipPrefix).shipping.city.value = getSelectedShipAddress().city;
                findFormInputs(formElement, shipPrefix).shipping.state.value = getSelectedShipAddress().state;
                findFormInputs(formElement, shipPrefix).shipping.stateSelect.value = getSelectedShipAddress().state;
                findFormInputs(formElement, shipPrefix).shipping.country.value = getSelectedShipAddress().country;
                findFormInputs(formElement, shipPrefix).shipping.zip.value = getSelectedShipAddress().zip;
                if (showBilling !== null) {
                    findFormInputs(formElement, billPrefix).billing.comp.value = getSelectedBillAddress().comp;
                    findFormInputs(formElement, billPrefix).billing.addr1.value = getSelectedBillAddress().addr1;
                    findFormInputs(formElement, billPrefix).billing.addr2.value = getSelectedBillAddress().addr2;
                    findFormInputs(formElement, billPrefix).billing.city.value = getSelectedBillAddress().city;
                    findFormInputs(formElement, billPrefix).billing.state.value = getSelectedBillAddress().state;
                    findFormInputs(formElement, billPrefix).billing.stateSelect.value = getSelectedBillAddress().state;
                    findFormInputs(formElement, billPrefix).billing.country.value = getSelectedBillAddress().country;
                    findFormInputs(formElement, billPrefix).billing.zip.value = getSelectedBillAddress().zip;
                }
                window.closeDialog();
                formElement.submit();
            });
 
            /**
             * When closing the dialog by clicking on the `X`, set the hidden input confirming that
             * the address has been validated to `0`.
             */
            document.querySelector('[data-dialog-close]').addEventListener('click', function (clickEvent) {
                if (dialogElement) {
                    if (dialogElement.getAttribute('aria-hidden') === 'false') {
                        findFormInputs(formElement, shipPrefix).shipping.validated.value = 0;
                        if (showBilling !== null) {
                            findFormInputs(formElement, billPrefix).billing.validated.value = 0;
                        }
                    }
                }
            });
 
            /**
             * When closing the dialog by clicking on the background, set the hidden input confirming that
             * the address has been validated to `0`.
             */
            document.addEventListener('click', function (clickEvent) {
                let clickEventTarget = clickEvent.target;
                
                if (dialogElement) {
                    if (clickEventTarget === dialogElement.firstElementChild) {
                        if (dialogElement.getAttribute('aria-hidden') === 'false') {
                            findFormInputs(formElement, shipPrefix).shipping.validated.value = 0;
                            if (showBilling !== null) {
                                findFormInputs(formElement, billPrefix).billing.validated.value = 0;
                            }
                        }
                    }
                }
            });
 
            /**
             * On page load, open the dialog and set the first suggestion as `checked`.
             */
            window.addEventListener('load', function () {
                if (this.showBilling !== null) {
                    const billingToShow = document.getElementById('billing_to_show');
        
                    if (billingToShow) {
                        billingToShow.click();
                    }
                }
 
                window.openDialog('address-validation');
                setFirstSuggestion();
            });
        }());
    </script>
</mvt:if>
 

This item should be added to the following pages:

Copy
<mvt:item name="readytheme" param="contentsection( 'address_validation' )" />

OCST, ACAD, ACED, CADE, CADA

Customer Experience

With address validation enabled, when a customer enters their billing and shipping address, it will via validated against the data source (USPS, UPS) set in the configuration.

By default in the Shadows ReadyTheme, this information displays in a modal lightbox on the page, however its possible to customize this layout and experience.

If more than one address is sent back, multiple suggested addresses will be displayed:

If enabled, the customer address will also be validated when a logged-in customer adds an address to their address book.

Admin Address Validation

Miva 10 also supports address validation when manually creating or editing an order from within the Miva admin:

Note

With address validation enabled, any change to the customer information in the admin will re-trigger the address validation.

When adding a customer account manually via the Miva admin, there is an option to validate an address:

International Address Validation

Currently, both USPS and UPS offer address validation for only US addresses. International address validation is not supported at this time.

Building Custom Address Validation Integrations

The Miva address validation API is extensible to allow for custom integration to any address validation service. Below is an example of the function required to implement the address validation feature in your module:

Copy
<MvFUNCTION NAME = "Module_Description" PARAMETERS = "module var" STANDARDOUTPUTLEVEL = "">
<MvASSIGN NAME = "l.module:code" VALUE = "address_validation">
<MvASSIGN NAME = "l.module:name" VALUE = "Address Validation Example">
<MvASSIGN NAME = "l.module:provider" VALUE = "Miva Merchant">
<MvASSIGN NAME = "l.module:version" VALUE = "1.0000">
<MvASSIGN NAME = "l.module:api_ver" VALUE = "5.72">
<MvASSIGN NAME = "l.module:description" VALUE = "Simple Address Validation Example">
<MvASSIGN NAME = "l.module:features" VALUE = "addrval">
</MvFUNCTION>
<MvCOMMENT>
|
| Required Function for Address Validation Feature (addrval)
|
</MvCOMMENT>
<MvFUNCTION NAME = "AddressValidationModule_Validate_Address" PARAMETERS = "module var, address var, verified_addresses var" STANDARDOUTPUTLEVEL = "">
<MvCOMMENT>
| Make API Request to Address Validation Service. Address custromer entered during checkout
| is available in the l.address structure.
<MvIF EXPR = "{ NOT AddressValidation_BuildRequest( l.address, l.request_json ) }">
<MvFUNCTIONRETURN VALUE = 0>
</MvIF>
<MvCOMMENT>
| Make API Request to Address Validation Service
</MvCOMMENT>
<MvIF EXPR = "{ NOT AddressValidation_API_Call( l.request_json, l.response ) }">
<MvFUNCTIONRETURN VALUE = 0>
</MvIF>
<MvCOMMENT>
| Generate Verified Address Array. Here you would have a function to parse the JSON response and add each address the l.verified_addresses array
| Function should return the number of verified addresses
</MvCOMMENT>
<MvFUNCTIONRETURN VALUE = "{ AddressValidation_Build_VerifiedAddresses( l.address, l.response, l.verified_addresses ) }">
</MvFUNCTION>
<MvFUNCTION NAME = "AddressValidation_BuildRequest" PARAMETERS = "address var, request_json var" STANDARDOUTPUTLEVEL = "">
<MvCAPTURE VARIABLE = "l.request_json">
[
{
"address_line1": "<MvEVAL EXPR = "{ [ g.Module_JSON ].JSON_Encode( l.address:addr1 $ l.address:addr2 ) }">",
"city_locality": "<MvEVAL EXPR = "{ [ g.Module_JSON ].JSON_Encode( l.address:city ) }">",
"state_province": "<MvEVAL EXPR = "{ [ g.Module_JSON ].JSON_Encode( l.address:state ) }">",
"postal_code": "<MvEVAL EXPR = "{ [ g.Module_JSON ].JSON_Encode( l.address:zip ) }">",
"country_code": "<MvEVAL EXPR = "{ [ g.Module_JSON ].JSON_Encode( l.address:cntry ) }">"
}
</MvCAPTURE>
<MvFUNCTIONRETURN VALUE = 1>
</MvFUNCTION>
<MvFUNCTION NAME = "AddressValidation_API_Call" PARAMETERS = "request_json var, response var" STANDARDOUTPUTLEVEL = "">
<MvASSIGN NAME = "l.url" VALUE = "https://api.shipengine.com//v1/addresses/validate">
<MvASSIGN NAME = "l.api_key" VALUE = "__YOUR_API_KEY_HERE__">
<MvCAPTURE VARIABLE = "l.response:raw">
<MIVA MvCALL_Error = "nonfatal, nodisplay">
<MvCALL METHOD = "POST"
ACTION = "{ l.url }"
CONTENT-TYPE = "application/json"
HEADERS = "{ 'API-Key: ' $ l.api_key $ asciichar( 13 ) $ asciichar( 10 ) }"
FIELDS = "l.request_json"
FLAGS = "noparse">
<MvEVAL EXPR = "{ s.callvalue }">
</MvCALL>
<MIVA MvCALL_Error = "fatal, display">
</MvCAPTURE>
<MvIF EXPR = "{ NOT ISNULL g.MvCALL_Error }">
<MvFUNCTIONRETURN VALUE = "{ [ g.Module_Library_Utilities ].Error( 'ERROR_CODE', g.MvCALL_Error ) }">
</MvIF>
<MvCOMMENT>Convert JSON to a Miva Variable</MvCOMMENT>
<MvIF EXPR = "{ NOT miva_json_decode( l.response:raw, l.response:data ) }">
<MvFUNCTIONRETURN VALUE = "{ [ g.Module_Library_Utilities ].Error( 'ERROE_CODE', miva_json_decode_last_error() ) }">
</MvIF>
<MvFUNCTIONRETURN VALUE = 1>
<MvFUNCTION>
<MvFUNCTION NAME = "AddressValidation_Build_VerifiedAddresses" PARAMETERS = "original_address var, response var, verified_addresses var" STANDARDOUTPUTLEVEL = "">
<MvASSIGN NAME = "l.verified_addresses" VALUE = "">
<MvASSIGN NAME = "l.verified_address_count" VALUE = 0>
<MvFOREACH ITERATOR = "l.address" ARRAY = "l.response:data:Address">
<MvASSIGN NAME = "l.verified_address" VALUE = "">
<MvASSIGN NAME = "l.verified_address:addr1" VALUE = "{ trim( l.address:Address1 ) }">
<MvASSIGN NAME = "l.verified_address:addr2" VALUE = "{ trim( l.address:Address2 ) }">
<MvASSIGN NAME = "l.verified_address:comp" VALUE = "{ trim( l.original_address:comp ) }">
<MvASSIGN NAME = "l.verified_address:city" VALUE = "{ trim( l.address:City ) }">
<MvASSIGN NAME = "l.verified_address:state" VALUE = "{ trim( l.address:State ) }">
<MvASSIGN NAME = "l.verified_address:country" VALUE = "{ trim( l.address:country ) }">
<MvASSIGN NAME = "l.verified_address:zip" VALUE = "{ trim( l.address:zip ) }">
<MvCOMMENT>Residential Address Flag</MvCOMMENT>
<MvASSIGN NAME = "l.verified_address:resdntl" VALUE = "{ [ g.Module_Admin ].Trim_Boolean( l.original_address:resdntl ) }">
<MvASSIGN NAME = "l.verified_address_count" VALUE = "{ miva_array_insert( l.verified_addresses, l.verified_address, -1 ) }">
</MvFOREACH>
<MvFUNCTIONRETURN VALUE = "{ l.verified_address_count }">
</MvFUNCTION>

10.01.00 Address Validation Bug Fix

10.01.00 fixed a UPS bug where incorrect permissions were being issued to the UPS Access Key in the setup Wizard. Now in 10.01.00 there is a link you can click to request address validtion permissions. Once granted you can see the status as Active. For all new setups of the UPS module, the correct permissions for Address Validation will automatically be created and no additional steps are needed.

Stores which use UPS and upgrade to 10.01.00 will be presented with a link to relaunch the UPS Developer Kit Registration in order to request Address Validation permissions.

UPS Address Validation Inactive
Was this article helpful?
0 out of 0 found this helpful