Stripe Subscription JS issues - javascript

I use the following code to create a stripe customer and create a subscription for that customer
stripe.subscriptions.create({
customer: customer_id,
items: [
{
plan: plan_id
},
],
trial_period_days: 7,
expand: ['latest_invoice.payment_intent'],
}, function (err, subscription) {
stripe.customers.create({
email: email,
source: token,
metadata: {
userid: userId
}
}, function (err, customer) {
I want users to subscription to subscribe to a 1 week free trial, Monthly plan (they pay after 7 days)
I am running into the following issues
Stripe does not validate the credit card number on prod. You can enter any credit card number and the payment goes through
Can someone please help?
Here's the client code
submit(event) {
event.preventDefault();
if ( this.props.planid) {
setTimeout(() => {
this.setState({loading: true});
}, 0);
var planId = this.props.planid;
this.props.stripe.createToken({name: "Name"}).then( token => {
axios.post("/charge/process/" + planId, {
token: token.id
}).then(response => {
if (response.data.status === "ok") {
this.setState({complete: true, loading: false})
} else if (response.data.error) {
this.setState({error: response.data.error, loading: false});
}
}).catch(error => {
this.setState({error: "There was an error.", loading: false});
});
})
} else {
this.setState({error: "Invalid plan id", loading: false});
}
}
render() {
if (this.state.loading) return (<Spinner />)
if (this.state.complete) return (<p align="center">Thanks for purchasing! You can now access the book summaries.</p>);
var error = "";
if (this.state.error) {
error = (<p>{this.state.error}</p>);
}
return (
<div className="CheckoutForm" style={{width: "400px", margin: "0 auto", "textAlign": "center"}}>
{error}
<fieldset>
<legend className="card-only">Pay with card</legend>
<div className="container">
<div id="example4-card" className="StripeElement StripeElement--empty">
<div style={{width: "300px", margin: "0 auto"}}>
<CardElement/>
<br/>
<br/>
<button onClick={this.submit.bind(this)} className="btn btn-primary purchasebtn">Purchase</button>
</div>
</div>
</div>
</fieldset>
</div>
);
}

Related

react-paypal-js runs onApprove function but no money is sent

I tried to do some 1€ payments with a paypal.
And it it shows me that it's successful.
It does everything what is in my onApprove function and no error is showing but when i check my 2 paypal account there is no money sent!
Neither the balance of one account reduce nor the other gain balance.
Any ideas?
const initialOptions = {
'client-id': 'MY_CLIENT_ID',
components: 'buttons',
'data-namespace': 'PayPalSDK',
currency: 'EUR',
intent: 'capture',
'enable-funding': ['sofort', 'giropay'],
'disable-funding': ['card', 'sepa'],
};
<PayPalButtons
key={Math.random()}
createOrder={(data, actions) => {
return actions.order.create({
purchase_units: [
{
description: 'Restaurant',
amount: {
value: carttotal,
currency_code: 'EUR',
}
},
],
application_context: {
shipping_preference: 'NO_SHIPPING',
},
});
}}
onApprove={(data, actions) => {
actions.order.capture().then(() => {
axios
.post(
'/api/paypal',
{
cartItems: cartItems,
}
)
}
}}
onCancel={() => {
toast.error('Cancel', {
position: toast.POSITION.BOTTOM_RIGHT,
});
}}
onError={() => {
//setPaid(false);
toast.error('Error', {
position: toast.POSITION.BOTTOM_RIGHT,
});
}}
/>
You are using actions.order.create() to create the order for approval on the client side, but there is no call to actions.order.capture() after approval, so no transaction is created.
(If you need to store the result or do anything automated with the transaction result, you should not use either of those server-side functions, but rather the v2/checkout/orders API to create and capture on a backend, paired with a frontend that calls those backend routes.)

Simple validation in vue

I am beginner web developer.
I make my first application in vue project.
I have this code:
<template>
<CRow>
<CCol col="12" lg="6">
<CCard no-header>
<CCardBody>
<h3>
Create Note
</h3>
<CAlert
:show.sync="dismissCountDown"
color="primary"
fade
>
({{ dismissCountDown }}) {{ message }}
</CAlert>
<CInput label="Title" type="text" id="title" placeholder="Title" v-model="note.title"></CInput>
<CInput textarea="true" label="Content" id="content" :rows="9" placeholder="Content.."
v-model="note.content"></CInput>
<CInput label="Applies to date" type="date" id="applies_to_date" v-model="note.applies_to_date"></CInput>
<CSelect id="status_id"
label="Status"
:value.sync="note.status_id"
:plain="true"
:options="statuses"
>
</CSelect>
<CInput label="Note type" type="text" id="note_type" v-model="note.note_type"></CInput>
<template>
<div id="app">
<ckeditor v-model="editorData" :config="editorConfig"></ckeditor>
</div>
</template>
<CButton color="primary" #click="store()">Create</CButton>
<CButton color="primary" #click="goBack">Back</CButton>
</CCardBody>
</CCard>
</CCol>
</CRow>
</template>
import axios from 'axios';
import Vue from 'vue';
import CKEditor from 'ckeditor4-vue';
Vue.use(CKEditor);
export default {
name: 'EditUser',
props: {
caption: {
type: String,
default: 'User id'
},
},
data: () => {
return {
note: {
title: '',
content: '',
applies_to_date: '',
status_id: null,
note_type: '',
},
statuses: [],
message: '',
dismissSecs: 7,
dismissCountDown: 0,
showDismissibleAlert: false,
editorData: '',
editorConfig: {
// The configuration of the editor.
filebrowserImageBrowseUrl: Vue.prototype.$apiAdress+'/api/laravel-filemanager?token=' + localStorage.getItem("api_token"),
filebrowserImageUploadUrl: Vue.prototype.$apiAdress+'/api/laravel-filemanager/upload?type=Images&_token=&token=' + localStorage.getItem("api_token"),
filebrowserBrowseUrl: Vue.prototype.$apiAdress+'/api/laravel-filemanager?type=Files&token=' + localStorage.getItem("api_token"),
filebrowserUploadUrl: Vue.prototype.$apiAdress+'/api/laravel-filemanager/upload?type=Files&_token=&token=' + localStorage.getItem("api_token"),
height: 500,
language: 'pl',
//extraPlugins: 'facebookvideo, youtube, html5video',
editorUrl: "facebookvideo.js",
extraPlugins: 'a11yhelp,about,basicstyles,bidi,blockquote,clipboard,colorbutton,colordialog,contextmenu,copyformatting,dialogadvtab,div,editorplaceholder,elementspath,enterkey,entities,exportpdf,filebrowser,find,flash,floatingspace,font,format,forms,horizontalrule,htmlwriter,iframe,image,indentblock,indentlist,justify,language,link,list,liststyle,magicline,maximize,newpage,pagebreak,pastefromgdocs,pastefromlibreoffice,pastefromword,pastetext,preview,print,removeformat,resize,save,scayt,selectall,showblocks,showborders,smiley,sourcearea,specialchar,stylescombo,tab,table,tableselection,tabletools,templates,toolbar,undo,uploadimage, wysiwygarea,autoembed,image2,embedsemantic',
image2_alignClasses: ['image-align-left', 'image-align-center', 'image-align-right'],
image2_disableResizer: true,
}
}
},
methods: {
goBack() {
this.$router.go(-1)
// this.$router.replace({path: '/users'})
},
store() {
let self = this;
axios.post(this.$apiAdress + '/api/notes?token=' + localStorage.getItem("api_token"),
self.note
)
.then(function (response) {
self.note = {
title: '',
content: '',
applies_to_date: '',
status_id: null,
note_type: '',
};
self.message = 'Successfully created note.';
self.showAlert();
}).catch(function (error) {
if (error.response.data.message == 'The given data was invalid.') {
self.message = '';
for (let key in error.response.data.errors) {
if (error.response.data.errors.hasOwnProperty(key)) {
self.message += error.response.data.errors[key][0] + ' ';
}
}
self.showAlert();
} else {
console.log(error);
self.$router.push({path: 'login'});
}
});
},
countDownChanged(dismissCountDown) {
this.dismissCountDown = dismissCountDown
},
showAlert() {
this.dismissCountDown = this.dismissSecs
},
},
mounted: function () {
let self = this;
axios.get(this.$apiAdress + '/api/notes/create?token=' + localStorage.getItem("api_token"))
.then(function (response) {
self.statuses = response.data;
}).catch(function (error) {
console.log(error);
self.$router.push({path: 'login'});
});
}
}
I need add to my project validation with alert box when input is empty.
I need required for title and content. When user click button "Create" I need check this inputs. If it's empty - then I need show alert().
How can I make it?
Please help me :)
You can make method:
checkInputs() {
if(!this.note.title) {
this.message = 'pls enter title'
this.showAlert()
return true
}
if(!this.note.content) {
this.message = 'pls enter content'
this.showAlert()
return true
}
return false
}
and in store method:
store() {
if(this.checkInputs()) return
...

Error: MercadoPago.js - Could not find HTML element for provided id: MPHiddenInputPaymentMethod

I have an Nuxt desktop app here, am i am facing this problem with MERCADO PAGO API.
This is part of the Mercado documentation : https://www.mercadopago.com.br/developers/pt/guides/online-payments/checkout-api/v2/testing
The problem is:
I make use of the index.vue that makes use of the default form from the documentation itself:
<template>
<div >
<form id="form-checkout" >
<input type="text" name="cardNumber" id="form-checkout__cardNumber" />
<input type="text" name="cardExpirationMonth" id="form-checkout__cardExpirationMonth" />
<input type="text" name="cardExpirationYear" id="form-checkout__cardExpirationYear" />
<input type="text" name="cardholderName" id="form-checkout__cardholderName"/>
<input type="email" name="cardholderEmail" id="form-checkout__cardholderEmail"/>
<input type="text" name="securityCode" id="form-checkout__securityCode" />
<select name="issuer" id="form-checkout__issuer"></select>
<select name="identificationType" id="form-checkout__identificationType"></select>
<input type="text" name="identificationNumber" id="form-checkout__identificationNumber"/>
<select name="installments" id="form-checkout__installments"></select>
<button type="submit" id="form-checkout__submit">Pagar</button>
<progress value="0" class="progress-bar">Carregando...</progress>
</form>
</div>
</template>
nuxt.config:
export default{
head:{
...
script: [
{ src: 'https://sdk.mercadopago.com/js/v2' },
{src: "/js/index.js", },
}
}
and the "/js/index.js file in static folder:
//i know the YOU_PUBLIC_KEY must be from the Mercado Pago account, i have one already
const mp = new MercadoPago('YOUR_PUBLIC_KEY', {
locale: 'pt-BR',
})
const cardForm = mp.cardForm({
amount: '100.5',
autoMount: true,
processingMode: 'aggregator',
form: {
id: 'form-checkout',
cardholderName: {
id: 'form-checkout__cardholderName',
placeholder: 'Cardholder name',
},
cardholderEmail: {
id: 'form-checkout__cardholderEmail',
placeholder: 'Email',
},
cardNumber: {
id: 'form-checkout__cardNumber',
placeholder: 'Card number',
},
cardExpirationMonth: {
id: 'form-checkout__cardExpirationMonth',
placeholder: 'MM'
},
cardExpirationYear: {
id: 'form-checkout__cardExpirationYear',
placeholder: 'YYYY'
},
securityCode: {
id: 'form-checkout__securityCode',
placeholder: 'CVV',
},
installments: {
id: 'form-checkout__installments',
placeholder: 'Total installments'
},
identificationType: {
id: 'form-checkout__identificationType',
placeholder: 'Document type'
},
identificationNumber: {
id: 'form-checkout__identificationNumber',
placeholder: 'Document number'
},
issuer: {
id: 'form-checkout__issuer',
placeholder: 'Issuer'
}
},
callbacks: {
onFormMounted: error => {
if (error) return console.warn('Form Mounted handling error: ', error)
console.log('Form mounted')
},
onFormUnmounted: error => {
if (error) return console.warn('Form Unmounted handling error: ', error)
console.log('Form unmounted')
},
onIdentificationTypesReceived: (error, identificationTypes) => {
if (error) return console.warn('identificationTypes handling error: ', error)
console.log('Identification types available: ', identificationTypes)
},
onPaymentMethodsReceived: (error, paymentMethods) => {
if (error) return console.warn('paymentMethods handling error: ', error)
console.log('Payment Methods available: ', paymentMethods)
},
onIssuersReceived: (error, issuers) => {
if (error) return console.warn('issuers handling error: ', error)
console.log('Issuers available: ', issuers)
},
onInstallmentsReceived: (error, installments) => {
if (error) return console.warn('installments handling error: ', error)
console.log('Installments available: ', installments)
},
onCardTokenReceived: (error, token) => {
if (error) return console.warn('Token handling error: ', error)
console.log('Token available: ', token)
},
onSubmit: (event) => {
event.preventDefault();
const cardData = cardForm.getCardFormData();
console.log('CardForm data available: ', cardData)
},
onFetching: (resource) => {
console.log('Fetching resource: ', resource)
// Animate progress bar
const progressBar = document.querySelector('.progress-bar')
progressBar.removeAttribute('value')
return () => {
progressBar.setAttribute('value', '0')
}
},
}
})
Anyone can help me with this? And is facing more problems with the MERCADO PAGO's API?
Thanks for the atention!
Use iframe to render custom vanilla HTML/CSS/JS.
I'm using vue/quasar2 and my workaround was using an Iframe to render a custom page which can use this lib, you can see the directory structure here.
I created a page to and use an iframe tag to render the custom page:
<template>
<q-page class="flex flex-center">
<iframe width="100%" height="545vh" style="border: none;" :src='`static_site/index.html?obj=${JSON.stringify(getQueryParameters())}`'/>
</q-page>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
name: 'PageIndex',
setup () {
function getQueryParameters () {
return {
name: "name",
email: "name#gmail.com",
valor: "20"
}
}
return {
getQueryParameters,
}
}
})
</script>
I'm using the query parameters ( obj ) in the iframe src to pass down information from vue to the lib. In the callbacks section of the cardForm function, I used the URLSearchParams object to catch the information I sended, you can see it here.
OBS: I just found this workaround yesterday and haven't tested in production yet, but in dev it's working fine, will test soon in production and update this answer, hope it's useful to you.

How to use spinner to show axios status on a specific button

i am using a v-for to display list of product from an api request, the product card contains three buttons, one of the Adds item to cart,with a shopping-cart icon.
i want it so that when a user clicks the add to cart button, the shopping-cart icon changes to a spinner icon
I try declaring a "loading" in the data object, default set to false, so in my add to cart function, before the function is called, loading is set to true,
And in my template i use a v-show="loading" which set the visibility of the fa-spin to true if loading is true
//template
<template>
<div class="row">
<div v-for="product in products" v-bind:key="product_slug"
class="col-md-auto mx-auto card text-center card-product">
<div class="card-product__img">
<img class="card-img" src="img/product/product1.png" alt="">
<ul class="card-product__imgOverlay">
<li>
<button><i class="ti-search"></i></button>
</li>
<li>
<button #click="addToCart(product.id, product.slug, product.price)"><i
class="ti-shopping-cart"></i> <i v-show="loading" class="fa fa-spinner fa-spin"></i>
</button>
</li>
<li>
<button><i class="ti-heart"></i></button>
</li>
</ul>
</div>
<div class="card-body">
<p>Accessories</p>
<h4 class="card-product__title">{{ product.slug }}</h4>
<p class="card-product__price">₦ {{ product.price}}</p>
</div>
</div>
//script
<script>
export default {
data() {
return {
loading: false,
products: [],
product: {
"id": '',
"slug": '',
"product_image_1": '',
"product_image_2": '',
"product_image_3": '',
"product_image_4": '',
"price": '',
"qty": '',
"stock_status": '',
"sku": '',
"short_description": '',
"description": '',
},
product_slug: '',
pagination: {},
}
},
created() {
this.fetchProduct();
},
methods: {
fetchProduct(page_url) {
//assign variable to this
let vm = this;
// check if page url exist, = page url else = /api/shop
page_url = page_url || '/api/shop';
fetch(page_url)
.then(res => res.json())
.then(res => {
this.products = res.data;
vm.makePagination(res.links, res.meta);
})
.catch(err => console.log(err));
},
makePagination(links, meta) {
//Make an object made up of meta, page details from the api response
let pagination = {
current_page: meta.current_page,
last_page: meta.last_page,
next_page_url: links.next,
prev_page_url: links.prev,
};
// Set the object to the pagination value
this.pagination = pagination;
},
addToCart(id, slug, price) {
this.loading = true;
axios.post('/api/cart', {
id: id,
name: slug,
price: price,
})
.then(function (response) {
this.loading = false;
console.log(response.data);
})
.catch(function (err) {
this.loading = false;
this.addToCart = err;
});
}
}
}
</script>
The problems are
1) Once the add to cart button is clicked, the spinner shows in all of the product's card.
2) fa-cart icon is not hiding, shows side-by-side with the shopping-cart icon
3) fa-spin continues, even after success of api request
You need to maintain a dictionary of the loading state. In addToCart function, you need to set true for particular product id. Try this code.
addToCart(id, slug, price) {
this.loading[id] = true;
axios.post('/api/cart', {
id: id,
name: slug,
price: price,
})
.then(function (response) {
this.loading[id] = false;
console.log(response.data);
})
.catch(function (err) {
this.loading[id] = false;
this.addToCart = err;
});
}
In Fetch product function made some changes.
fetchProduct(page_url) {
//assign variable to this
let vm = this;
// check if page url exist, = page url else = /api/shop
page_url = page_url || '/api/shop';
fetch(page_url)
.then(res => res.json())
.then(res => {
this.products = res.data;
this.products.filter(function (item) {
vm.loading[item.id]=false;
return item;
})
vm.makePagination(res.links, res.meta);
})
.catch(err => console.log(err));
},
html changes.
<button #click="addToCart(product.id, product.slug, product.price)"><i
class="ti-shopping-cart"></i> <i v-show="loading[product.id]" class="fa fa-spinner fa-spin"></i>
</button>

How to accept Bitcoin and USD payments using Stripe?

REFERENCE:
https://stripe.com/docs/sources/bitcoin
QUESTION:
I am trying to integrate Bitcoin payments to my code using Stripe.
From my understanding of the docs, I should create a Source object by creating a new form and on submit feed the data (in this case email and amount) to :
stripe.createSource({
type: 'bitcoin',
amount: 1000,
currency: 'usd',
owner: {
email: 'jenny.rosen#example.com',
},
}).then(function(result) {
// handle result.error or result.source
});
Then pass the result to the server to charge the Source object. Only issue: I don't see how to pass the result to the server. Should I create a new handler ?
var handler = StripeCheckout.configure({
key: 'key',
locale: 'auto',
name: 'website',
description: 'Secure Payment',
token: function(token) {
$('#stripeToken').val(token.id);
$("#stripeEmail").val(token.email);
$('form').submit();
}
});
I am lost.
Here is the code I currently have that works perfectly for USD payments.
MY CODE:
clientside (payment.ejs)
<% include partials/header %>
<div class="background">
<div class="message">
<div class="paymentBlock">
<h1 class="title">TITLE</h1>
<form class="paymentForm" action="/payment/charge" method="POST">
<input id="inputAmount" class="amountInput" name="amount" type="number/>
<input type="hidden" id="stripeToken" name="stripeToken" />
<input type="hidden" id="stripeEmail" name="stripeEmail"/>
<button type="submit" class="btn btn-success" id="paymentButton" >Submit Payment</button>
</form>
</div>
</div>
</div>
<script src="https://checkout.stripe.com/checkout.js"></script>
<script>
var handler = StripeCheckout.configure({
key: 'key',
locale: 'auto',
name: 'website',
description: 'Secure Payment',
token: function(token) {
$('#stripeToken').val(token.id);
$("#stripeEmail").val(token.email);
$('form').submit();
}
});
$('#paymentButton').on('click', function(e) {
e.preventDefault();
$('#error_explanation').html('');
var amount = $('#inputAmount').val();
amount = amount.replace(/\$/g, '').replace(/\,/g, '');
amount = parseFloat(amount);
if (isNaN(amount)) {
$('#error_explanation').html('<p>Please enter a valid amount in USD ($).</p>');
}
else if (amount < 1.00) {
$('#error_explanation').html('<p>Payment amount must be at least $1.</p>');
}
else {
amount = amount * 100;
handler.open({
amount: Math.round(amount)
})
}
});
// Close Checkout on page navigation
$(window).on('popstate', function() {
handler.close();
});
</script>
<% include partials/indexScripts %>
serverside (payment.js)
router.post("/", (req, res) => {
var amount = req.body.amount;
var object;
var ARef = admin.database().ref("ref");
var ARefList;
amount = amount * 100;
var object = {
amount: amount,
email: email,
inversedTimeStamp: now
}
stripe.customers.create({
email: req.body.stripeEmail,
source: req.body.stripeToken
})
.then(customer =>
stripe.charges.create({
amount: amount,
description: "desc",
currency: "usd",
customer: customer.id
})
)
.then(charge =>
ARef.transaction(function(dbAmount){
if (!dbAmount) {
dbAmount = 0;
}
dbAmount = dbAmount + amount/100;
return dbAmount;
})
)
.then( () =>
ARef.push(object)
)
.then ( () =>
ARefList.push(object)
)
.then( () =>
res.render("received",{amount:amount/100})
);
});
Thank you to "pksk321" from the freenode IRC #stripe for helping me with this !
Apparently, all that was needed was to add bitcoin: true to the handler, like so :
clientside
var handler = StripeCheckout.configure({
key: 'key',
locale: 'auto',
name: 'website',
description: 'Secure Payment',
bitcoin: true,
token: function(token) {
$('#stripeToken').val(token.id);
$("#stripeEmail").val(token.email);
$('form').submit();
}
});

Categories

Resources