Hi All –
If you want to talk about payment processing through Stripe and how to implement it in Wix Code - Post it here.
This forum post is a work in progress that I’ll try to keep up to date. However, there are no solid resources on how to use Stripe in Wix Code, so I want to pool it all into one post and we can all help each other. Payment processing is so instrumental to online businesses, so hopefully this is very helpful. I’ve gone back and forth with Stripe Support and the Wix Code team over the past couple of weeks.
Please add any insights you may have or corrections to the below code. I have all of 2 month of coding experience, so there is very likely errors or inefficiencies in here.
I’ve listed my discoveries and also working code:
STRIPE BASICS:
In theory, if you’re using Stripe to process payments, a visitor will come to your website, inputs their credit card information, it gets sent to Stripe, code stuff happens on their server and they send you back a “token”. You can then use this token to charge a credit card. This prevents us from storing credit card information, meaning we are PCI (Credit Card Laws) compliant and won’t get sued.
TOKENIZATION:
One way to perform tokenziation through Wix Code is to use Wix Code Fetch API to perform our own tokenziation. Yoav’s post here: https://www.wix.com/code/home/forum/questions-answers/stripe-recurring-payment-integration explains that. However, Stripe’s Support Team recommended we don’t do this as it would dance the line of being PCI compliant and could subject you to yearly payment processing audits. Or something funky. I don’t know, probably just avoid it.
The true way Stripe recommends doing Tokenization is through their pre-built code guides: Stripe Web Elements | Stripe Documentation. The bad news is these code snippets they’ve only work in HTML, which Wix Code does not support. Unless, you use an iFrame.
So, if you want to use Stripe on your Wix website, use an iFrame (HTML Component). This allows all the tokenization and risk to be handled by Stripe, they can return to us a token, then we can feed any information to our Wix Code.
HOW TO SET UP PAYMENTS:
- Create an HTML Component: Add the code below. NOTE: This is purely for functionality, you can change out the formatting using CSS yourself:
<script src="https://js.stripe.com/v3/"></script>
<form action="/charge" method="post" id="payment-form">
<div class="form-row">
<label for="card-element">
Credit or debit card
</label>
<div id="card-element">
</div>
<!-- Used to display form errors -->
<div id="card-errors" role="alert"></div>
<button>SUBMIT PAYMENT</button>
</form>
<script>
// Create a Stripe client
// Be sure to paste your key in the pk_test section. This is unique to you when you sign up to Stripe.
var stripe = Stripe('pk_test_XXXXXXXXXXXXXXXXXXXXXXXXXXXX');
// Create an instance of Elements
var elements = stripe.elements();
// Custom styling can be passed to options when creating an Element.
// (Note that this demo uses a wider set of styles than the guide below.)
var style = {
base: {
color: '#32325d',
lineHeight: '22px',
fontFamily: 'avenir-lt-w01_85-heavy1475544, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '18px',
'::placeholder': {
color: '#aab7c4'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
}
};
// Create an instance of the card Element
const card = elements.create('card', {style});
// Add an instance of the card Element into the `card-element` <div>
card.mount('#card-element');
card.addEventListener('change', ({error}) => {
const displayError = document.getElementById('card-errors');
if (error) {
displayError.textContent = error.message;
} else {
displayError.textContent = '';
}
});
// Create a token or display an error when the form is submitted.
const form = document.getElementById('payment-form');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const {token, error} = await stripe.createToken(card);
if (error) {
// Inform the customer that there was an error
const errorElement = document.getElementById('card-errors');
errorElement.textContent = error.message;
} else {
// Send the token to your server
stripeTokenHandler(token);
}
});
const stripeTokenHandler = (token) => {
// Insert the token ID into the form so it gets submitted to the server
const form = document.getElementById('payment-form');
const hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
const jsonToken = JSON.stringify(token);
window.parent.postMessage(jsonToken, "*");
// Submit the form
// form.submit();
}
</script>
<style>
/**
* The CSS shown here will not be introduced in the Quickstart guide, but shows
* how you can use CSS to style your Element's container.
*/
.StripeElement {
background-color: white;
padding: 10px 12px;
border-radius: 4px;
border: 1px solid transparent;
box-shadow: 0 1px 3px 0 #e6ebf1;
-webkit-transition: box-shadow 150ms ease;
transition: box-shadow 150ms ease;
}
.StripeElement--focus {
box-shadow: 0 1px 3px 0 #cfd7df;
}
.StripeElement--invalid {
border-color: #fa755a;
}
.StripeElement--webkit-autofill {
background-color: #fefde5 !important;
}
button {
background-color: #fefde5;
font: 'avenir';
font-size: 16px;
font-weight: 500;
letter-spacing: 0.2em;
padding: 10px 12px
}
</style>
- In your page code:
import {charge} from 'backend/stripeProxy';
$w.onReady(() => {
$w("#html1").postMessage("");
$w("#html1").onMessage( (event) => {
let token = JSON.parse(event.data);
console.log(token);
charge(token.id, getCart())
.then((chargeResponse) => {
console.log("Charge ID: " + chargeResponse.id);
});
});
});
function getCart(){
return {
"amount": $w("#amount").value * 100,
"currency": "USD",
"description": "whatever"
};
}
In your backend code:
import {fetch} from 'wix-fetch';
export function charge(token, cart) {
//Go to stripe.com to create a test key and replace the one in the example
const apiKey = "sk_test_B0b0hiSJcxMVZIXlqWWEX2kq";
return fetch("https://api.stripe.com/v1/charges", {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': "application/x-www-form-urlencoded",
'Authorization': "Bearer " + apiKey
},
body: encodeBody(token, cart)
})
.then( (httpResponse) => {
if (httpResponse.ok) {
return httpResponse.json();
}
});
}
function encodeBodyToken(token, cart) {
let encoded = "";
for (let [k, v] of Object.entries(cart)) {
encoded = encoded.concat(k,"=", encodeURI(v), "&");
}
encoded = encoded.concat("source=", encodeURI(token));
console.log("Encoded" + encoded);
return encoded;
}
The only other thing you need to do is create a text input for the $ amount you want to charge, then link it to the code.
Hope this helps!