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: https://stripe.com/docs/stripe-js. 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:
1) 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>
2) 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!
I have this code working so far as it is sending it to stripe and stripe and stripe is registering the charge, but then nothing. I am trying to figure out where to insert the code for successful info? I used the code on page one but had to make two tiny tweaks and voila:
IFrame:
<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>
var stripe = Stripe('pk_test_ANxA3x3NylBEghIiVeWrfra1');
var elements = stripe.elements();
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'
}
};
const card = elements.create('card', {style});
card.mount('#card-element');
card.addEventListener('change', ({error}) => {
const displayError = document.getElementById('card-errors');
if (error) {
displayError.textContent = error.message;
} else {
displayError.textContent = '';
}
});
const form = document.getElementById('payment-form');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const {token, error} = await stripe.createToken(card);
if (error) {
const errorElement = document.getElementById('card-errors');
errorElement.textContent = error.message;
} else {
stripeTokenHandler(token);
}
});
const stripeTokenHandler = (token) => {
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, "*");
form.submit();
}
</script>
<style>
Page Code:
import {charge} from 'backend/stripecharge'; $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" }; }
backend:
import {fetch} from 'wix-fetch'; export function charge(token, cart) { const apiKey = "sk_test_c2l6Vig1HQhdlJ6b31nATHl0";
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: encodeBodyToken(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; }
any help would be greatly appreciated!
Hello everyone! Not getting Customers Records in Stripe :(
Hoping to get some answers here...
I have this website taking bookings and Events payments (the Wix apps) and I have configured the payment system from Stripe. Everything looks brilliant and I am getting the payments as expected BUT for some reason I cannot get the customer records in Stripe. This is something I really need as part of other integrations.
Does Anyone know how to resolve this issue? Do I need to add backend code in Stripe or Wix in order to get Customer records from transactions made from the website?
any information would be appreciated.
Thanks!
I have to say, I find it absolutely pathetic that this has been an issue for over 2 years and yet it is still this difficult to properly implement a Stripe payment solution into Wix websites. I appreciate all the time that was put into this thread. I have a lot of work to do to get this to work on my site. Thanks for the advice. PLEASE Wix, fix this. Add PHP. Make a better integration with Stripe. Whatever. Just get it done.
I have successfully built a form that will accept payments after a user inputs all of their information. I would like to create a confirmation message (maybe a lightbox) once the card is charged. Can someone lead me to resources to do this?
I would also like for Stripe to automatically send a receipt to the user's emails address. Any advice on that would be appreciated.
Wix Paid Plans With a Free Trial Period Using Stripe Payments
Hi,
Here's an issue I'm scratching my head with:
Requirement:
I'd like to create a Wix Paid Plan with a 3-month free trial period - after which, the card details collected at commencement of the free trial period will be charged.
My Understanding:
It seems that Wix Paid Plans allow one to either have free plans or charge for paid plans immediately using the Stripe card payment solution.
Solution?
Is there a way to achieve the requirement above or will I need to ignore Wix Paid Plans and build my own plans and code using the Stripe API. i.e.
1. Create a Stripe Customer
2. Submit the card details to Stripe
3. Then charge the card later when the 3-months are up
4. Assuming of course that the customer hasn't expressed that he/she no longer wishes to continue with the subscription following the trial period.
Thanks for any advice David Seroy, Wix, or this community can give.
Finally, let me also thank this community of Wix developers and the guys and gals at Wix who have allowed me to do some really cool stuff with Wix.
Riaz
Hey David, I like this process, is there anyway when a customer fills this out that the amount is already in the code. I sell a product for a fixed price and would like the fixed price it be in the amount filed and when the customer clicks to pay that amount would be charged. thanks
Hi everyone,
We are building a very simple marketplace and I am currently struggling to get the simple first step to setup Stripe Connect for seller accounts. Our Stripe account is all setup to connect with Standard accounts.
I followed the steps listed on the Stripe site here https://stripe.com/docs/connect/standard-accounts.
Steps 1 to 3 are fine - we have a button on a register page which routes sellers so they can setup / connect their account, then when they’re done we route them back to a URI page we setup where the seller would get some kind of “you’re all set” message. When the user is routed to the URI page in the URL I can get the “ac_xxxxx” code.
This is where it becomes an issue. In the Stripe instructions of step 4 it says to make a POST request to fetch the seller’s credentials
curl https://connect.stripe.com/oauth/token \ -d client_secret=sk_test_XXXXX \ -d code="{AUTHORIZATION_CODE}" \ -d grant_type=authorization_code
which I have translated to the code below, however when I run my code I get the following error.
{ "error": { "code": "parameter_missing", "doc_url": "https://stripe.com/docs/error-codes/parameter-missing", "message": "You must supply either a card, customer, PII data, bank account, or account legal entity to create a token. If you're making this request with a library, be sure to pass all of the required parameters for creating a token. If you're making this request manually, be sure your POST parameters begin with the token type. For example, a PII token would require `pii[personal_id_number]`, while an account token would require a parameter beginning with `account[legal_entity]`. See the API reference for more information: https://stripe.com/docs/api#token_object", "type": "invalid_request_error" } }
I don't see any other option than having a card or account[legal_entity] parameter in the POST method which makes no sense when looking at the instructions for step 4.
I am going mad… Can anyone help please?
Thanks!!
FRONT END CODE
This is the code of the URI page, where sellers are routed to once having agreed to link their Stripe account to ours. The "completeRegistration" function is where the POST request to Stripe is made to retrieve credentials and I would then parse those in the "response" object once it works.
import wixLocation from 'wix-location'; import { completeRegistration} from 'backend/stripeProxy'; var authCode; $w.onReady(function () { let query = wixLocation.query; authCode = query['code']; if (authCode === undefined) { console.log(query['error_description']); } else { completeRegistration(authCode) .then((response) => { console.log(response); console.log("Stripe user ID: " + response['stripe_user_id']); }).catch(e => { console.log(e); }); } });
BACKEND CODE
I build the object following the curl code found on the Stripe page, injecting the seller's code provided in the URI when connection is made to our Stripe account. I then believe a fetch to the token page needs to be made, but this is where I must be doing something wrong.
export async function completeRegistration(auth_code) { const apiKey = "sk_test_XXXXX"; var object = { "client_secret": apiKey, "code": auth_code, "grant_type": "authorization_code" }; const response = await fetch("https://api.stripe.com/v1/tokens", { method: 'post', headers: { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Bearer " + apiKey }, body: encodeBody(object) }); if (response.status >= 200 && response.status < 300) { const json = await response.json() return json.id; } const responseText = await response.text(); console.log(responseText); return response; } function encodeBody(body) { var formBody = []; for (var property in body) { var encodedKey = encodeURIComponent(property); var encodedValue = encodeURIComponent(body[property]); formBody.push(encodedKey + "=" + encodedValue); } formBody = formBody.join("&"); console.log(formBody); return formBody; }
Hi all,
I have very little code experience if any. So far i have built an website out for a buddy of mine. They later wanted a payment sections. I have completed the payment inputs and have been able to have a single button token created and charge.
My issue is that now i would like to have Stripe send the Auto receipt after the sucessful payment.
Can someone please help me with the code for this
Hi All,
I am in dire need of some help. I have 0 code exp and i just build out a site without any and its great. i need some help with the code though. I had added the Stripe integration and have been able get tokens and card the card. I just want to be able to some how pull the email to stripe from that form so i can send auto receipts from Stripe.
Can anyone help
Thanks, David - that worked!
You have your wires crossed. Expand corresponds with collapse and hide with show. If you change your code to .show() intead of expand() it will work.
hide/show literally hides or shows your element visually, but it technically is still on the page. collapse/expand is basically minimizing or expanding that element.
You can build your website accordingly. You could do both, it really doesn't matter
Collapse totally works, thanks! I'm having trouble with expanding "complete" though? I have it hidden on load and added the code as such:
Sweet - I will try that for sure. Thanks so much for your quick response, David, and for sharing your expertise! So very appreciated!
For simplicity, keep your first example and don't use the one in this post. Easiest solution, after your console.log("Charge Id"...) add:
$w("#html1").collapse(); $w("#newElement).expand();
Make newElement some sort of "Complete!" text message or box. Essentially, after the code succesfully returns a ChargeResponse, it means the payment went through. In that case you can collapse the payment window and confirm to them it is complete.
**Edit** If you want to take it one step further you would have to edit the HTML code and Disable the submit payment button after it has been clicked. Shouldn't be necessary though.
Another newbie to code here... I want to learn it and am in a huge time crunch right now to get my client's website integrated with Stripe. I have been trying to get this going for 3 days, literally been at my desk 12+ hours each day doing nothing but trying to get Stripe integrated. I was on the phone with them 4 times yesterday, which was not actually helpful, and beginning to feel really dense, having a total mind melt.
I followed a tutorial I found in the Wix group on Facebook using Javascript. I was successful both with test mode and live mode, but have a BIG problem, which is when I hit submit in the JavaScript form I created, the charge goes through, but there is no indication of it to the user, no success message or anything like that. I ended up hitting it 4x and my card was charged 4x (luckily just $1 each). As yet I know just about nothing regarding code, except for the crash course I have been getting watching tutorials, YouTube videos, searching the forum... which is where I found this thread this evening.
So I followed the HTML instructions using the iframe, and at first I was able to get the tokens at least, but I hadn't created the "amount" or "description" input fields. So I did that, and I am still getting the token, but it's not recognizing the amount and when I hit "submit payment" nothing happens on the user end, it just sits there. I tried to use some of what (I thought) I learned using Javascript, but am sincerely at a loss???
Here is what the code looks like from the first form I created and the form itself:
So when I got stuck I created the HTML form instead... the code is exactly what you posted at the start of the thread, I only changed the pk key. Here's the page code that I copied/pasted with slight adjustment to figure in the amount and description. I've obviously done something wrong, though.
I would be so appreciative for any advice/input! Thanks!
David - Many many thanks - thats seems to have solved my problem - everything completes then I get the message at the end.
Huge thank you.
Remove wixLocation.to("/copy-of-thank-you"); from your top code and paste it after your charge function. Like this:
.then((chargeResponse) => {
wixLocation.to("/copy-of-thank-you");
}
Basically you're telling the code execute the payNow function, which first creates a token, then and only after the token has been succesfully created, take that token and execute the charge function, then once that is complete, go to this link
This is a standard copy that I got from a user on this site.
export function payNow() { createToken(encodeCard(createCard())) .then((token) => { charge(token,getCart()) .then((chargeResponse) => { }); }); }
Need your payNow() function code as well. What is happening is your wixLocation code is running before the payNow function is completed. So, we either need to wait until PayNow is completed or just move the wixLocation into the PayNow function so we know exactly when to go to the link
So this code in the light box which contain the payment details. Its the "paynow" button.
If I have the wixLocation element in there, it works but the payment fails to go through.
If the wixlocation is removed the payment completes , but obviosuly I dont have the ability to show a "thank you" or other such page.
I am sure this is probably something to do with having to wait for the payNow to complete, but I have to admit my coding skills are average.
export function payTest_click (event, $w) { console.log("clicked"); payNow(); wixLocation.to("/copy-of-thank-you"); }