Skip to content
2 changes: 1 addition & 1 deletion dist/main.bundle.js

Large diffs are not rendered by default.

236 changes: 236 additions & 0 deletions examples/stripe-firebase-full-order/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8">
<title>Builton SDK & Firebase example</title>
<style type="text/css">
.contentContainer {
display: flex;
}

#apiResponse {
background-color: #f1f1f1;
;
min-height: 100px;
width: 100%;
overflow: scroll;
margin: 0 10px 0 10px;
padding: 10px;
}

#actionContainer {
background-color: #fcfcfc;
min-height: 100px;
width: 100%;
margin: 0 10px 0 10px;
padding: 10px;
}

#stepButton {
float: right;
}

#cardDetails {
background-color: lightsteelblue;
margin: 100px;
padding: 50px;
}

#cardElement {
margin-top: 20px
}

#cardButton {
margin: 20px 0 20px 20px;
float: right;
}

button {
margin: 10px;
}
</style>
<script src="https://js.stripe.com/v3/"></script>
<!-- <script src="https://unpkg.com/@builton/core-sdk@4/dist/main.bundle.js"></script> -->
<script src="../../dist/main.bundle.js"></script>
<script src="https://www.gstatic.com/firebasejs/6.6.2/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/6.6.2/firebase-auth.js"></script>
</head>

<body>
<div class="contentContainer">
<div id="actionContainer">
<button id="stepButton" onclick="stateMachine()"></button>
<div id="steps"></div>
<div id="cardDetails">
<div>Please use a <a href="https://stripe.com/docs/testing#cards">Stripe test card</a></div>
<div id="cardElement"></div>
<button id="cardButton">send card</button>
</div>
</div>
<pre id="apiResponse"></pre>
</div>
<script>
const conf = {
stripe: {
pk: 'pk_test_fa7Dxe5u3x2dn6DoZNROpKJO00E0earGo8'
},
firebase: {
apiKey: "AIzaSyC3aEQEFUzZjao3XTYfm1yqDXLC-uOcy0Y",
authDomain: "builton-demo.firebaseapp.com",
},
builton: {
apiKey: 'YEX5tfHumpzhlp0UUGJdrkLztQf75ajj9_-T4IesGbxOPootfnMWKf82a9sGyjpDeKtjZU5chmKHKVW9Duc4Gw=='
}
}
const stripe = Stripe(conf.stripe.pk);
let elements = stripe.elements();
let cardElement = elements.create('card');
cardElement.mount('#cardElement');
document.getElementById('cardDetails').style.visibility = "hidden";

let builton = new Builton({
apiKey: conf.builton.apiKey
});

const stripeProvider = new builton.paymentMethods.StripePaymentProvider(
stripe, cardElement
);
// Initialize Firebase
firebase.initializeApp(conf.firebase);

let userRef = null;
let productsRef = null;
let paymentMethodRef = null;
let orderRef = null;

const events = {
listProducts: () => {
return builton.products.get({ urlParams: { type: 'main' } }).then((productPage) => {
productsRef = productPage.current;
return productPage.current;
});
},
authenticate: () => {
return firebase.auth().signInAnonymously()
.then((authResult) => {
addSubStep('Firebase Authentication', true);
return authResult.user.getIdToken()
.then((bearerToken) => {
addSubStep('Got bearerToken', true);
return builton.authenticate({
bearerToken,
refreshTokenFn: async () => {
return await authResult.user.getIdToken();
}
});
})
})
.then((user) => {
addSubStep('BuiltOn Authentication', true);
userRef = user;
return user;
});
},
addAddress: () => {
return userRef.update({
addresses: [{ "street_name": "Nadderudåsen 30", "city": "Bekkestua", "zip_code": "1357", "country": "Norway" }]
}).then((updatedUser) => {
userRef = updatedUser;
return updatedUser;
});
},
addPaymentMethod: () => {
document.getElementById('cardDetails').style.visibility = "visible";
let cardButton = document.getElementById('cardButton');
return new Promise((resolve, reject) => {
cardButton.addEventListener('click', (ev) => {
builton.paymentMethods.createWithProvider(stripeProvider).then(paymentMethod => {
paymentMethodRef = paymentMethod;
document.getElementById('cardDetails').style.visibility = "hidden";
resolve(paymentMethod);
}).catch(err => reject(err));
});
});
},
createOrder: () => {
return builton.orders.create({
items: [{
product: productsRef[0].id,
quantity: '1',
}],
delivery_address: { "street_name": "Slottsplassen 1", "city": "Oslo", "zip_code": "0010", "country": "Norway" },
}).then((order) => {
orderRef = order;
return order;
});
},
payForOrder: () => {
return builton.payments.createWithProvider(
stripeProvider,
{
orders: [orderRef.id],
payment_method: paymentMethodRef.id
}
).then(payments => {
for (let payment of payments) {
if (payment.error) {
return Promise.reject(payments);
}
}
return payments;
});
}
}

const camelCaseToWords = (str) => {
return str.match(/^[a-z]+|[A-Z][a-z]*/g).map((x) => {
return x[0].toUpperCase() + x.substr(1).toLowerCase();
}).join(' ');
};

const steps = Object.keys(events);
let currentStep = 0;
const stepButton = document.getElementById("stepButton");
stepButton.innerHTML = camelCaseToWords(steps[currentStep]);
const stateMachine = () => {
stepButton.disabled = true;
document.getElementById('apiResponse').innerHTML = '';
events[steps[currentStep]]().then((response) => {
displayResponse(response);
addStep(steps[currentStep], response ? true : false);
currentStep += 1;
if (currentStep < steps.length) {
stepButton.innerHTML = camelCaseToWords(steps[currentStep]);
stepButton.disabled = false;
} else {
stepButton.innerHTML = 'Done!';
}
}).catch((error) => {
displayResponse(error);
addStep(steps[currentStep], false);
});
}

const displayResponse = (response) => {
console.log(response);
document.getElementById('apiResponse').innerHTML = JSON.stringify(response, null, 2);
}

const addStep = (step, success) => {
console.info(step);
const div = document.createElement('div');
div.innerHTML = `${success ? '✅' : '❌'} ${camelCaseToWords(step)}`;
document.getElementById('steps').appendChild(div);
}

const addSubStep = (step, success) => {
console.info(step);
const div = document.createElement('div');
div.innerHTML = `&#09;┌ ${success ? '✅' : '❌'} ${step}`;
document.getElementById('steps').appendChild(div);
}
</script>
</body>

</html>
2 changes: 1 addition & 1 deletion src/collection/objects/_objects.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class Component {
}).then((res) => {
const obj = parseJson(res, ResConstructor, json);
return Promise.resolve({ res, obj });
}).catch((err) => Promise.reject(err));
}).catch((err) => Promise.reject(new Error.BadRequest(err)));
} catch (err) {
return Promise.reject(err);
}
Expand Down
2 changes: 1 addition & 1 deletion src/collection/resources/_resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class Components {
}).then((res) => {
const obj = parseJson(res, ResConstructor, json);
return Promise.resolve({ res, obj });
}).catch((err) => Promise.reject(err));
}).catch((err) => Promise.reject(new Error.BadRequest(err)));
} catch (err) {
return Promise.reject(err);
}
Expand Down
56 changes: 56 additions & 0 deletions src/collection/resources/paymentMethods.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
/* eslint-disable max-classes-per-file */
const Components = require('./_resources');
const PaymentMethod = require('../objects/paymentMethod');
const Error = require('../../utils/error');
const StripePaymentProvider = require('../../functionality/paymentProvider/stripe');
const VippsPaymentProvider = require('../../functionality/paymentProvider/vipps');
const {
create,
del,
Expand All @@ -16,6 +20,58 @@ class PaymentMethods extends Components {
this.request = request;
this.apiPath = 'payment_methods';
this.ResConstructor = PaymentMethod;
this.StripePaymentProvider = StripePaymentProvider;
this.VippsPaymentProvider = VippsPaymentProvider;
}

createWithProvider(provider, { urlParams, json = false } = {}, done) {
const createWithStripe = (stripe, cardElement) => this.create({
payment_method: 'stripe',
})
.catch((err) => {
if (done) {
done(err);
}
return Promise.reject(err);
})
.then((holderPaymentMethod) => stripe.handleCardSetup(
holderPaymentMethod.setup_intent.client_secret,
cardElement,
)
.catch((err) => {
const error = new Error.StripeError(err);
if (done) {
done(error);
}
return Promise.reject(error);
})
.then((stripeResponse) => {
if (stripeResponse.error) {
const error = new Error.StripeError(stripeResponse.error);
if (done) {
done(error);
}
return Promise.reject(error);
}
return holderPaymentMethod.update({
payment_method_id: stripeResponse.setupIntent.payment_method,
}, { urlParams, json }, done);
}));

const createWithVipps = () => this.create({
payment_method: 'vipps',
});
switch (provider.name) {
case 'StripePaymentProvider':
if (provider.stripe && provider.element) {
return createWithStripe(provider.stripe, provider.element);
}
break;
case 'VippsPaymentProvider':
return createWithVipps();
default:
throw new Error.UnknownPaymentProvider();
}
}
}

Expand Down
Loading