When business info step loads with a ZIP code, automatically looks up the combined sales tax rate and pre-fills the field. User can still edit if needed. Field gets light green background to indicate auto-fill. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
72 lines
2.8 KiB
Text
72 lines
2.8 KiB
Text
<cfsetting showdebugoutput="false">
|
|
<cfsetting enablecfoutputonly="true">
|
|
<cfcontent type="application/json; charset=utf-8" reset="true">
|
|
<cfheader name="Cache-Control" value="no-store">
|
|
|
|
<cfset response = { "OK": false, "taxRate": 0, "message": "" }>
|
|
|
|
<cftry>
|
|
<!--- Get ZIP code from URL or form --->
|
|
<cfset zipCode = "">
|
|
<cfif structKeyExists(url, "zip")>
|
|
<cfset zipCode = trim(url.zip)>
|
|
<cfelseif structKeyExists(form, "zip")>
|
|
<cfset zipCode = trim(form.zip)>
|
|
</cfif>
|
|
|
|
<!--- Validate ZIP code format (5 digits or 5+4) --->
|
|
<cfif NOT reFind("^\d{5}(-\d{4})?$", zipCode)>
|
|
<cfset response.message = "Invalid ZIP code format">
|
|
<cfoutput>#serializeJSON(response)#</cfoutput>
|
|
<cfabort>
|
|
</cfif>
|
|
|
|
<!--- Use just the 5-digit portion --->
|
|
<cfset zipCode = left(zipCode, 5)>
|
|
|
|
<!--- Call API Ninjas Sales Tax API --->
|
|
<cfhttp url="https://api.api-ninjas.com/v1/salestax?zip_code=#zipCode#" method="GET" timeout="10" result="httpResult">
|
|
<cfhttpparam type="header" name="X-Api-Key" value="free">
|
|
</cfhttp>
|
|
|
|
<cfif httpResult.statusCode CONTAINS "200">
|
|
<cfset apiData = deserializeJSON(httpResult.fileContent)>
|
|
|
|
<!--- API returns an array, get first result --->
|
|
<cfif isArray(apiData) AND arrayLen(apiData) GT 0>
|
|
<cfset taxData = apiData[1]>
|
|
|
|
<!--- overall_rate is decimal (e.g., 0.095 for 9.5%) --->
|
|
<cfif structKeyExists(taxData, "overall_rate")>
|
|
<cfset overallRate = val(taxData.overall_rate)>
|
|
<!--- Convert to percentage --->
|
|
<cfset response.taxRate = round(overallRate * 10000) / 100>
|
|
<cfset response.OK = true>
|
|
<cfset response.message = "Tax rate found">
|
|
|
|
<!--- Include breakdown for transparency --->
|
|
<cfif structKeyExists(taxData, "state_rate")>
|
|
<cfset response.stateRate = round(val(taxData.state_rate) * 10000) / 100>
|
|
</cfif>
|
|
<cfif structKeyExists(taxData, "county_rate")>
|
|
<cfset response.countyRate = round(val(taxData.county_rate) * 10000) / 100>
|
|
</cfif>
|
|
<cfif structKeyExists(taxData, "city_rate")>
|
|
<cfset response.cityRate = round(val(taxData.city_rate) * 10000) / 100>
|
|
</cfif>
|
|
<cfelse>
|
|
<cfset response.message = "No rate data in response">
|
|
</cfif>
|
|
<cfelse>
|
|
<cfset response.message = "No results for ZIP code">
|
|
</cfif>
|
|
<cfelse>
|
|
<cfset response.message = "API returned status: #httpResult.statusCode#">
|
|
</cfif>
|
|
|
|
<cfcatch type="any">
|
|
<cfset response.message = "Error: #cfcatch.message#">
|
|
</cfcatch>
|
|
</cftry>
|
|
|
|
<cfoutput>#serializeJSON(response)#</cfoutput>
|