I have a Javascript function in a leaf page using Vapor 3 the function should trigger a post to an api to save a customers card detials and return a token representing that card. I would normally do this in swift on our vapor server but to be PCI complient we are not allowed to take the customers credit card detials onto our server they must go directly to Sum Up (payment provider) I have no experiance with javascript and after lots of googling this it the fucntion I came up with.
<script>
function savecard() {
var name = document.getElementById("nameonCard").value
var cardNo = document.getElementById("cardNumber").value
var expiry_year = document.getElementById("expiryMonth").value
var expiry_month = document.getElementById("expiryYear").value
var cvv = document.getElementById("cvc").value
var body = `{"type":"card","card":{"name":"${name}","number":"${cardNo}", "expiry_month": "${expiry_month}", "expiry_year": "${expiry_year}","cvv": "${cvv}"}}`
return fetch("https://api.sumup.com/v0.1/customers/" + #(sumCustId) + "/payment-instruments", {
method: "POST"
headers: {
"Authorization": "Basic " + #(auth),
"Content-Type": "application/json"
},
data: body,
})
.then(function(response){
document.getElementById("response").value = response.text()
return response.text();
})
.then(function(data){
console.log(data)//text version
var data_obj = JSON.parse(data);
document.getElementById("data_obj").value = data_obj
return data_obj
})
}
</script>
I don't appear to be getting anything back but I'm not sure where I am going wrong, any help is much appreciated.
Here is the entire leaf page.
<!doctype html>
<html lang="en">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>Pay for Membership</title>
<body>
<div class="card bg-dark text-white h-100">
<img class="card-img bg-dark img-fluid" src="https://images.unsplash.com/photo-1575151772039-542722abbf63?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format" alt="Card image">
<div class="card-img-overlay">
<div class="card-deck">
<div class="card bg-transparent border-warning align-self-start ">
<div class="card-header">
<h4 class="card-title text-center">Order Summary</h4>
</div>
<div class="card-body">
<ul>
#for(sum in orderSum){
#if(isLast == false){
<li class="list-group-item bg-transparent d-flex justify-content-between align-items-centert">#noam(sum)
<span class="badge badge-info badge-pill text-right align-self-center">#am(sum)</span>
</li>
}
}
</ul>
</div>
<div class="card-footer text-center">
#for(sum in orderSum){
#if(isLast){
<h5>#(sum)</h5>
}
}
</div>
</div>
<div class="card bg-dark border-warning">
<div class="card-header">
<h4 class="card-title">Payment Details</h4>
</div>
<div class="card-body">
<form method="post" action="/completedsumupmember" id="paymentForm">
<div class="row form-group" hidden>
<input type="number" class="form-control" id="amount" name="amount" value =#(amount) hidden>
<input type="text" class="form-control" id="currency" name="currency" value =#(currency) hidden>
<input type="text" class="form-control" id="orderId" name="orderId" value =#(orderId) hidden>
<input type="text" class="form-control" id="desc" name="desc" value =#(desc) hidden>
<input type="text" class="form-control" id="type" name="type" value =#(type) hidden>
<input type="text" class="form-control" id="orgId" name="orgId" value =#(orgId) hidden>
<input type="text" class="form-control" id="payToEmail" name="payToEmail" value =#(payToEmail) hidden>
<input type="text" class="form-control" id="auth" name="auth" value =#(auth) hidden>
<input type="hidden" class="form-control" id="response" name="response" value ="" hidden>
<input type="hidden" class="form-control" id="data_obj" name="data_obj" value ="" hidden>
<input type="text" class="form-control" id="customerId" name="customerId" value =#(sumCustId) hidden>
</div>
<div class="row form-group">
<div class = "col-md">
<label for="nameonCard">Name on the Card</label>
<input type="text" class="form-control" id="nameonCard" name="nameonCard" placeholder="John Smith" required>
</div>
</div>
<div class ="row form-group">
<div class ="col-lg">
<label for="cardNumber">Card Number</label>
<input type="number" class="form-control" id="cardNumber" name="cardNumber" placeholder="1111 2222 3333 4444" required>
</div>
</div>
<div class = "row form-group">
<div class = "col-md">
<label for="expiryMonth">Expriy Month</label>
<input type="text" class="form-control" id="expiryMonth" name="expiryMonth" placeholder="mm" required>
</div>
<div class = "col-md">
<label for="expiry">Expriy Year</label>
<input type="text" class="form-control" id="expiryYear" name="expiryYear" placeholder="yy" required>
</div>
<div class = "col-md">
<label for="cvc">CVV</label>
<input type="text" class="form-control" id="cvc" name="cvc" placeholder="000" required>
</div>
</div>
<div class="card-footer text-center">
<button class="btn btn-warning btn-block" type="submit" onclick="savecard()">Pay Now</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script>
function savecard() {
console.log('do something ')
var name = document.getElementById("nameonCard").value
var cardNo = document.getElementById("cardNumber").value
var expiry_year = document.getElementById("expiryMonth").value
var expiry_month = document.getElementById("expiryYear").value
var cvv = document.getElementById("cvc").value
var body = `{"type":"card","card":{"name":"${name}","number":"${cardNo}", "expiry_month": "${expiry_month}", "expiry_year": "${expiry_year}","cvv": "${cvv}"}}`
return fetch("https://api.sumup.com/v0.1/customers/" + #(sumCustId) + "/payment-instruments", {
method: "POST"
headers: {
"Authorization": "Basic " + #(auth),
"Content-Type": "application/json"
},
data: body,
})
.then(function(response){
document.getElementById("response").value = response.text()
return response.text();
})
.then(function(data){
console.log(data)//text version
var data_obj = JSON.parse(data);
document.getElementById("data_obj").value = data_obj
return data_obj
})
}
</script>
</body>
</html>
I have finally managed to get a function that works, which is below.
<script>
function savecard() {
let customerId = document.getElementById("customerId").value;
let url = "https://api.sumup.com/v0.1/customers/" + customerId + "/payment-instruments"
let auth = " Basic " + document.getElementById("auth").value;
alert(auth);
let cardBody = {
type:"card",
card: {
name: document.getElementById("nameonCard").value,
cardNo: document.getElementById("cardNumber").value,
expiry_year: document.getElementById("expiryMonth").value,
expiry_month: document.getElementById("expiryYear").value,
cvv: document.getElementById("cvc").value
}
};
alert(cardBody.card.name);
let options = {
//mode: 'no-cors',
method: 'POST',
body: JSON.stringify(cardBody),
headers: {
'Content-Type': 'application/json',
'Authorization': auth
}
}
fetch(url, options)
.then(res => res.json())
.then(res => alert(res))
.catch(err => alert(`Error with message: ${err}`));;
}
</script>
However I am now getting an error in the catch
SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data
Seems like this is a simple typo, but I've been looking at it to long to see what it is.
In the end this worked. I thin by placing it in the head of the leaf file and removing any leaf tags fixed the issues. Instead of using leaf tags I added hidden form inputs with the values set by the leaf tag then accessed that value in the function.
<script>
function savecard() {
let customerId = document.getElementById("customerId").value; // for testing hard code value in form
let url = "https://api.sumup.com/v0.1/customers/" + customerId + "/payment-instruments"
let auth = " Basic " + document.getElementById("auth").value; // for testing hard code value in form
let cardBody = {
type:"card",
card: {
name: document.getElementById("nameonCard").value,
cardNo: document.getElementById("cardNumber").value,
expiry_year: document.getElementById("expiryMonth").value,
expiry_month: document.getElementById("expiryYear").value,
cvv: document.getElementById("cvc").value
}
};
let headers = {
'Authorization': auth,
'Content-Type': 'application/json'
}
let options = {
//mode: 'no-cors',
method: 'POST',
body: JSON.stringify(cardBody), //
headers: headers
}
fetch(url, options)
.then(res => res.json())
var token = res.token
document.getElementById("token").value = token
.then(res => console.log(res))
.catch(err => alert(`Error with message: ${err}`));;
document.getElementById("paymentForm").submit()
}
</script>
Hopefully that helps someone.