|
/* |
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED |
|
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
|
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
DEALINGS IN THE SOFTWARE. |
|
*/ |
|
|
|
const axios = require('axios'); |
|
|
|
const getCert = (async (email, password) => { |
|
const ed = await import("@noble/ed25519"); |
|
|
|
const privKey = ed.utils.randomPrivateKey(); // Secure random private key |
|
const pubKey = await ed.getPublicKeyAsync(privKey); |
|
|
|
console.log("Privkey = " + Buffer.from(privKey).toString('base64')); |
|
console.log("Pubkey = " + Buffer.from(pubKey).toString('base64')); |
|
|
|
console.log(""); |
|
|
|
try { |
|
const authResponse = await axios.post('https://my.vanmoof.com/api/v8/authenticate', null, { |
|
headers: { |
|
'Authorization': "Basic "+Buffer.from(email+':'+password).toString('base64'), |
|
'Api-Key': "fcb38d47-f14b-30cf-843b-26283f6a5819", |
|
'User-Agent': "VanMoof/20 CFNetwork/1404.0.5 Darwin/22.3.0", |
|
} |
|
}); |
|
|
|
const authToken = authResponse.data.token; |
|
|
|
const appTokenResponse = await axios.get('https://api.vanmoof-api.com/v8/getApplicationToken', { |
|
headers: { |
|
'Authorization': "Bearer "+authToken, |
|
'Api-Key': "fcb38d47-f14b-30cf-843b-26283f6a5819", |
|
'User-Agent': "VanMoof/20 CFNetwork/1404.0.5 Darwin/22.3.0", |
|
} |
|
}); |
|
|
|
const appToken = appTokenResponse.data.token; |
|
|
|
const bikeDataResponse = await axios.get('https://my.vanmoof.com/api/v8/getCustomerData?includeBikeDetails', { |
|
headers: { |
|
'Authorization': "Bearer "+authToken, |
|
'Api-Key': "fcb38d47-f14b-30cf-843b-26283f6a5819", |
|
'User-Agent': "VanMoof/20 CFNetwork/1404.0.5 Darwin/22.3.0", |
|
} |
|
}); |
|
|
|
for (const bikeIdx in bikeDataResponse.data.data.bikes) { |
|
const bike = bikeDataResponse.data.data.bikes[bikeIdx]; |
|
|
|
console.log("Bike "+bike.name); |
|
console.log("Bike ID: "+ bike.bikeId); |
|
console.log("Frame number: "+ bike.frameNumber); |
|
console.log("Frame serial: "+ bike.frameSerial); |
|
|
|
if (bike.bleProfile === 'ELECTRIFIED_2022') { |
|
console.log("Bike is an SA5"); |
|
console.log("ECU Serial: "+ bike.mainEcuSerial); |
|
|
|
const certificateResponse = await axios.post('https://bikeapi.production.vanmoof.cloud/bikes/'+bike.bikeId+'/create_certificate', { |
|
'public_key': Buffer.from(pubKey).toString('base64'), |
|
}, { |
|
headers: { |
|
'Authorization': "Bearer "+appToken, |
|
'User-Agent': "VanMoof/20 CFNetwork/1404.0.5 Darwin/22.3.0", |
|
} |
|
}); |
|
|
|
console.log("Certificate below:") |
|
console.log("-----------"); |
|
console.log(certificateResponse.data); |
|
console.log("-----------"); |
|
} else { |
|
console.log("Not an SA5.") |
|
} |
|
} |
|
|
|
console.log(""); |
|
console.log(""); |
|
} catch (error) { |
|
console.log(error); |
|
} |
|
}); |
|
|
|
getCert("YOUR_VANMOOF_EMAIL", 'YOUR_VANMOOF_PASSWORD'); |
Yes, create a new json file called package.json in the same directory, navigate to the directory in Terminal or command line. Enter the command ‘npm install’ (you should have the latest node version installed locally) and then follow the instructions above.