Geo based operations on pricing

Hey guys, I’m trying to calculate prices based on the location of users who visit so they see them in their local currency. I’m pulling in FX rates from an external API request using fetch (see from import {fetch} part, I attached full code for clarity). I’m facing two problems:

  1. when I run the code, it produces the following error in the console
    typeError: Cannot read properties of undefined (reading ‘GBP’)
    This looks it may be a parsing error or authentication error due to CORS?
    2. I have selection tags that filter the repeater (first part of the code) but because I pass on the filtered dataset data to the repeater I need to be able to convert the currencies after the selection tags are selected.

Please note I haven’t added the code to identify the country of the user. I do have the code that pulls IP address and gives the country code which I will add later on once the following works.

It’d be great if anyone has any inputs as to how to get this right. Appreciate the help.

import wixData from ‘wix-data’ ;

const databaseName = ‘IVFPackagesbyCountry’ ;
const databaseField = ‘tags’ ;

$w . onReady ( function () {
dataset1_ready ();
$w ( ‘#treatmentTags’ ). onChange (( event ) => {
const selectedTag = $w ( ‘#treatmentTags’ ). value ;
addItemstoRepeater ( selectedTag );
})
});

function addItemstoRepeater ( selectedOption = ) {

let  dataQuery  =  wixData . query ( databaseName ); 

if  ( selectedOption . length  >  0 ) { 
        dataQuery =  dataQuery . hasSome ( databaseField , selectedOption ); 
} 

dataQuery 
    . find () 
    . then ( results  => { 
        const  filtereditemsReady  =  results . items ; 
        $w ( '#packages' ). data  =  filtereditemsReady ; 

    }) 

}

import { fetch } from ‘wix-fetch’ ;

const url = “https://currency-converter5.p.rapidapi.com/currency/convert” ;

export function dataset1_ready () {
$w ( “#packages” ). forEachItem ( ( $item , itemData , index ) => {
let initialAmount = Number ( $item ( “#text25” ). text . split ( ‘$’ )[ 1 ][ 0 ]);
let sourceSymbol = ‘USD’ ;
let targetSymbol = ‘GBP’ ;
let fullUrl = ${ url } ?format=json&from= ${ sourceSymbol } &to= ${ targetSymbol } &amount=1 ;

    fetch ( fullUrl , { 

        "method" :  "GET" , 
        "headers" : { 
            "x-rapidapi-host" :  "currency-converter5.p.rapidapi.com" , 
            "x-rapidapi-key" :  getSecret ( "Currency_Converter_API_Key" ) 
            } 
        
    }) 
    . then ( response  => { 
        // $item("#text25").text = String(initialAmount * 1.3); 
        $item ( "#text25" ). text  =  String ( initialAmount   *  response [ 'rates' ][ targetSymbol ][ 'rate' ]); 
        console . log ( response ); 
    }) 
    . catch ( err  => { 
        console . error ( err ); 
    }); 

}); 

}

// import {getSecret} from ‘wix-secrets-backend’;

export async function getSecret ( key ) {
const mySecret = await getSecret ( key );
return mySecret
}

I don’t know about your issue but I think you have a problem with your function getSecret which call itself indefinitely. Since it does not do anything I would delete it and call getSecret directly

to solve your cors issue, make the fetch call in the backend via a web module (.JSW )

Also, I’m not sure Wix supports multi-currency payment. So your user will have to paid in your main currency anyway

Thanks for the catch. I created two modules. On the pricing not looking to get paid in the currency shown, just want to show the right local currency.

GetFXRates.jsw
import { GetKey } from ‘backend/GetSecretKey.jsw’ ;
import { fetch } from ‘wix-fetch’ ;

export function GetFXRates ( url ) {

fetch ( url , { 

    "method" :  "GET" , 
    "headers" : { 
        "x-rapidapi-host" :  "currency-converter5.p.rapidapi.com" , 
        "x-rapidapi-key" :  GetKey ( "Currency_Converter_API_Key" ) 
        } 
    
}) 

. then ( response  => { 
    console . log ( response ); 
    **return**  response ; 
}) 

. catch ( err  => { 
    console . error ( err ); 
}) 

}

GetSecretKey.jsw
import { getSecret } from ‘wix-secrets-backend’ ;

export async function GetKey ( key ) {
const mySecret = await getSecret ( key );
return mySecret
}

Main Code
import wixData from ‘wix-data’ ;
import { GetFXRates } from ‘backend/GetFXRates.jsw’ ;

const databaseName = ‘IVFPackagesbyCountry’ ;
const databaseField = ‘tags’ ;

$w . onReady ( function () {
dataset1_ready ();
$w ( ‘#treatmentTags’ ). onChange (( event ) => {
const selectedTag = $w ( ‘#treatmentTags’ ). value ;
addItemstoRepeater ( selectedTag );
})
});

function addItemstoRepeater ( selectedOption = ) {

let  dataQuery  =  wixData . query ( databaseName ); 

if  ( selectedOption . length  >  0 ) { 
        dataQuery =  dataQuery . hasSome ( databaseField , selectedOption ); 
} 

dataQuery 
    . find () 
    . then ( results  => { 
        const  filtereditemsReady  =  results . items ; 
        $w ( '#packages' ). data  =  filtereditemsReady ; 

    }) 

}

const url = “https://currency-converter5.p.rapidapi.com/currency/convert” ;
export function dataset1_ready () {
$w ( “#packages” ). forEachItem ( ( $item , itemData , index ) => {
let initialAmount = Number ( $item ( “#text25” ). text . split ( ‘$’ )[ 1 ][ 0 ]);
let sourceSymbol = ‘USD’ ;
let targetSymbol = ‘GBP’ ;
let fullUrl = ${ url } ?format=json&from= ${ sourceSymbol } &to= ${ targetSymbol } &amount=1 ;
$item ( “#text25” ). text = String ( initialAmount * GetFXRates ( fullUrl )[ ‘rates’ ][ targetSymbol ][ ‘rate’ ]);

}); 

}

It gives me 401 Unathorized error when I run the main code. The GetKey() isn’t working. I tested this by replacing GetKey ( “Currency_Converter_API_Key” ) with the actual key and it gives 200 Success.

getKeys is probably asynchronious therefor you should wait for it to return a value (in your fetch call)

Perfect, now the GetKey() works. I have to get the GetFXRates() to work. Here’s my new GetFXRates.jsw file
import { GetKey } from ‘backend/GetSecretKey.jsw’ ;
import { fetch } from ‘wix-fetch’ ;

export async function GetFXRates ( url ) {

fetch ( "https://currency-converter5.p.rapidapi.com/currency/convert?format=json&from=USD&to=GBP&amount=1" , { 
    method :  "GET" , 
    headers : { 
        "x-rapidapi-host" :  "currency-converter5.p.rapidapi.com" , 
        "x-rapidapi-key" :  **await**  GetKey ( "Currency_Converter_API_Key" ) 
    } 
}) 
. catch (() => { 
  console . log ( "Fail zone" ); 
}) 
. then (( response ) => { 
    if  ( response [ 'status' ] ==  200 ) { 
        console . log ( JSON . stringify ( response ,  **null** ,  2 )); 
        **return**  response ; 
        
    }  **else**  { 
    
        console . log ( "error" ,  response ); 
    } 
}); 

}

Gives me 200 code with success but no FX rates anywhere. A similar code works in JSfiddle without an issue. So bizarre. This is the output in wix
{
“url”: “https://currency-converter5.p.rapidapi.com/currency/convert?format=json&from=USD&to=GBP&amount=1”,
“status”: 200,
“statusText”: “OK”,
“headers”: {
“_headers”: {
“age”: [
“514”
],
“alt-svc”: [
“h3=":443"; ma=86400, h3-29=":443"; ma=86400, h3-28=":443"; ma=86400, h3-27=":443"; ma=86400”
],
“cache-control”: [
“max-age=7200”
],
“cf-cache-status”: [
“HIT”
],
“cf-ray”: [
“69349e4c2a2a5722-IAD”
],
“content-encoding”: [
“gzip”
],
“content-type”: [
“application/json”
],
“date”: [
“Thu, 23 Sep 2021 14:56:12 GMT”
],
“expect-ct”: [
“max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\”"
],
“last-modified”: [
“Thu, 23 Sep 2021 14:43:45 GMT”
],
“nel”: [
“{"success_fraction":0,"report_to":"cf-nel","max_age":604800}”
],
“report-to”: [
“{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=zc5sQY1qayFIPSVdbKj8T7P%2BAzruTAGl0KFihzgvOUz%2Fb9vUolW2l2OKYhZiGgq%2BjWA%2F5lwk2whpzFgnh13dXUcAh%2F2Njqs66cUTP2a%2FI7HXVuxIjERJmnJJOS2xRKjGAKjX4w%3D%3D"}],"group":"cf-nel","max_age":604800}”
],
“server”: [
“RapidAPI-1.2.8”
],
“vary”: [
“Accept-Encoding”
],
“x-rapidapi-region”: [
“AWS - us-east-1”
],
“x-rapidapi-version”: [
“1.2.8”
],
“x-ratelimit-requests-limit”: [
“100”
],
“x-ratelimit-requests-remaining”: [
“52”
],
“x-ratelimit-requests-reset”: [
“1015”
],
“content-length”: [
“171”
],
“connection”: [
“Close”
]
}
},
“ok”: true,
“body”: {
“_writeState”: {
“0”: 0,
“1”: 0
},
“_readableState”: {
“objectMode”: false,
“highWaterMark”: 16384,
“buffer”: {
“head”: null,
“tail”: null,
“length”: 0
},
“length”: 0,
“pipes”: ,
“flowing”: null,
“ended”: false,
“endEmitted”: false,
“reading”: false,
“sync”: false,
“needReadable”: false,
“emittedReadable”: false,
“readableListening”: false,
“resumeScheduled”: false,
“errorEmitted”: false,
“emitClose”: true,
“autoDestroy”: true,
“destroyed”: false,
“errored”: null,
“closed”: false,
“closeEmitted”: false,
“defaultEncoding”: “utf8”,
“awaitDrainWriters”: null,
“multiAwaitDrain”: false,
“readingMore”: false,
“decoder”: null,
“encoding”: null
},
“_events”: {},
“_eventsCount”: 5,
“_writableState”: {
“objectMode”: false,
“highWaterMark”: 16384,
“finalCalled”: false,
“needDrain”: false,
“ending”: true,
“ended”: true,
“finished”: false,
“destroyed”: false,
“decodeStrings”: true,
“defaultEncoding”: “utf8”,
“length”: 171,
“writing”: true,
“corked”: 0,
“sync”: false,
“bufferProcessing”: false,
“writelen”: 171,
“afterWriteTickInfo”: null,
“buffered”: ,
“bufferedIndex”: 0,
“allBuffers”: true,
“allNoop”: true,
“pendingcb”: 1,
“prefinished”: false,
“errorEmitted”: false,
“emitClose”: true,
“autoDestroy”: true,
“errored”: null,
“closed”: false
},
“allowHalfOpen”: true,
“bytesWritten”: 0,
“_handle”: {
“buffer”: {
“type”: “Buffer”,
“data”: [

Really Long Data Omitted for better display
]
},
“_outOffset”: 0,
“_chunkSize”: 16384,
“_defaultFlushFlag”: 0,
“_finishFlushFlag”: 4,
“_defaultFullFlushFlag”: 3,
“_maxOutputLength”: 4294967295,
“_level”: -1,
“_strategy”: 0
},
“bodyUsed”: false,
“size”: 0,
“timeout”: 0,
“_raw”: ,
“_abort”: false
}

vs output in jsfiddle

{
  "base_currency_code": "USD",
  "base_currency_name": "United States dollar",
  "amount": "1.0000",
  "updated_date": "2021-09-23",
  "rates": {
    "GBP": {
      "currency_name": "Pound sterling",
      "rate": "0.7313",
      "rate_for_amount": "0.7313"
    }
  },
  "status": "success"
}

Any help is appreciated.

You did not parse the response into a json

Thanks Quentin for all the help. I got the backend module to fetch and post correct FX rate to the console but can’t seem to be figuring out how to assign it to a variable rate in the main module so I can perform price conversions. I hard coded rate = 0.7298 to get the final result to work and it does but I need the 0.7298 from the GetFXRates() which I’m currently struggling with.

import { GetKey } from ‘backend/GetSecretKey.jsw’ ;
import { fetch } from ‘wix-fetch’ ;

export async function GetFXRates ( url ) {

fetch ( "https://currency-converter5.p.rapidapi.com/currency/convert?format=json&from=USD&to=GBP&amount=1" , { 
    method :  "GET" , 
    headers : { 
        "x-rapidapi-host" :  "currency-converter5.p.rapidapi.com" , 
        "x-rapidapi-key" :  **await**  GetKey ( "Currency_Converter_API_Key" ) 
    } 
}) 
. catch (() => { 
  console . log ( "Fail zone" ); 
}) 
// .then((response) =>  { 
//  if (response['status'] == 200) { 
//      console.log(JSON.stringify(response, null, 2)); 
//          return response; 
        
//      } else { 
    
//      console.log("error", response); 
//      } 
// }); 
. then (( response ) => { 
    if  ( response . ok ) { 
        response . json (). then (( json ) => { 
            // .then(response => response.json()) 
            // .then(json => console.log(JSON.stringify(json))); 
            console . log ( JSON . stringify ( parseFloat ( json [ 'rates' ][ 'GBP' ][ 'rate' ]))) 
            **return**  parseFloat ( json [ 'rates' ][ 'GBP' ][ 'rate' ]) 
            
        }) 
    } 
}) 

}

Main code

import wixData from ‘wix-data’ ;
import { GetFXRates } from ‘backend/GetFXRates.jsw’ ;

const databaseName = ‘IVFPackagesbyCountry’ ;
const databaseField = ‘tags’ ;

$w . onReady ( function () {
dataset1_ready ();
$w ( ‘#treatmentTags’ ). onChange (( event ) => {
const selectedTag = $w ( ‘#treatmentTags’ ). value ;
addItemstoRepeater ( selectedTag );
})
});

function addItemstoRepeater ( selectedOption = ) {

let  dataQuery  =  wixData . query ( databaseName ); 

if  ( selectedOption . length  >  0 ) { 
        dataQuery =  dataQuery . hasSome ( databaseField , selectedOption ); 
} 

dataQuery 
    . find () 
    . then ( results  => { 
        const  filtereditemsReady  =  results . items ; 
        $w ( '#packages' ). data  =  filtereditemsReady ; 

    }) 

}

const url = “https://currency-converter5.p.rapidapi.com/currency/convert” ;
export async function dataset1_ready () {
let sourceSymbol = ‘USD’ ;
let targetSymbol = ‘GBP’ ;
let fullUrl = ${ url } ?format=json&from= ${ sourceSymbol } &to= ${ targetSymbol } &amount=1 ;
// GetFXRates(fullUrl).then(data => {

//     console.log(data); 
// }); 
// const rate = async() =>{ 

//     const a = await GetFXRates(fullUrl); 
//     console.log(a); 
// }  

// const a = await GetFXRates(fullUrl).then(function(result) { 
//     console.log(result); 
//     return result; 
// }); 

const  a  =   **await**  GetFXRates ( fullUrl ); 
console . log ( a ) 
const  rate  =  0.7298 ; 

$w ( "#packages" ). forEachItem ( ( $item ,  itemData ,  index ) => { 
    let  initialAmount  =  parseFloat ( $item ( "#text25" ). text . replace ( /[^\d\.\-]/ **g** ,  "" )); 
    // let finalAmount = (Math.ceil(initialAmount  * rate/100.0) * 100).toString(); 
    let  finalAmount  =  Math . ceil ( initialAmount   *  rate / 100.0 ) *  100 ; 
    $item ( "#text25" ). text  =  "£"  + ( finalAmount . toString (). replace ( /\B(?=(\d{3})+(?!\d))/ **g** ,  "," )); 
    console . log ( "£"  +  finalAmount . toString (). replace ( /\B(?=(\d{3})+(?!\d))/ **g** ,  "," )); 

}); 

}

Any quick thoughts, I know it’s got to do with await as I tried a few variations and it posts a promise. I need to figure out how to correctly get data from promise.

there is a mistake in your code

if(response.ok){
    //YOU were missing the RETURN statement
    return response.json().then((json)=> {                     
    ///...