I have a problem with stripe cashier; i get
This customer has no attached payment source
I don't know why, hope someone could help me... many thanks in advance.
I tried to look a lot of tutorials but i can't get any good results.
Maybe it's a problem with the token ? i tried to enter the credit card test :
4242 4242 4242 4242
I would like to use it as a subscription.
Here my view
<div class="container">
<div class="row">
<script src="https://js.stripe.com/v3/"></script>
<form action="{{route('checkout')}}" method="post" id="payment-form">
{{csrf_field()}}
<div class="form-row">
<label for="card-element">
Credit or debit card
</label>
<div id="card-element">
<!-- a Stripe Element will be inserted here. -->
</div>
<!-- Used to display form errors -->
<div id="card-errors" role="alert"></div>
</div>
<button>Submit Payment</button>
</form>
</div>
</div>
</div>
<script>
// Create a Stripe client
var stripe = Stripe('.....');
// 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: '18px',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#aab7c4'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
}
};
// Create an instance of the card Element
var card = elements.create('card', {style: style});
// Add an instance of the card Element into the `card-element` <div>
card.mount('#card-element');
// Handle real-time validation errors from the card Element.
card.addEventListener('change', function(event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
// Handle form submission
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
stripe.createToken(card).then(function(result) {
if (result.error) {
// Inform the user if there was an error
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server
stripeTokenHandler(result.token);
}
});
});
</script>
Here my checkout controller :
public function checkout(Request $request)
{
try {
Stripe::setApiKey('.....');
$user = User::find(1);
$user->newSubscription('main', 'monthly')->create($request->stripeToken);
return 'Subscription successful, you get the course!';
} catch (\Exception $ex) {
return $ex->getMessage();
}
}
Related
I am taking coding courses online, so I can build my app sometime next year...
Can you help me with this instant message code please?
a. I am supposed to display an alert message when the user is not logged in.
b. Display the usename in the header.
c. Display the username with his instant message.
Since insecure is removed, I have to use Meteor.methods and meteor.call. I cannot use Sessions. I keep getting weird errors...
Here is the javascript code I have tried based on the course module, but I get errors that don't make sense to me...
Messages = new Mongo.Collection("messages");
if (Meteor.isClient) {
// this will configure the sign up field so it
// they only need a username
Accounts.ui.config({
passwordSignupFields: 'USERNAME_ONLY',
});
Template.messageForm.events({
// this event listener is triggered when they click on
// the post! button on the message form template
'click .js-save-message': function (event) {
var messageText = $('#message-text-input').val();
// notice how tihs has changed since the lsat time
// now we read the username from the Meteor.user()
var messageNickname = "Anon";
if (Meteor.user()) {
messageNickname = Meteor.user().username;
}
var message = {
messageText: messageText,
nickname: messageNickname,
createdOn: new Date()
};
// HERE is where you come in ....
// call a meteor method
// on the server here instead of
if (Meteor.isServer) {
Meteor.methods({ // defines a method, adds extra security layer to app
insertMessage: function () {
var doc, user, euser;
doc = Message.findOne();
if (!doc) {
return;
} // no logged in user, give up
// now I have a doc and possibly a user
user = Meteor.user().profile;
eusers = insertMessage.findOne({ docid: doc._id });
if (!eusers) {
eusers = {
docid: doc._id,
users: {},
};
}
user.lastEdit = new Date();
eusers.users[this.userId] = user;
insertMessage.upsert({ _id: eusers._id }, eusers);
}
}
)
}
// comment out this code, which won't work as we removed insecure...
//Messages.insert(message); // the insecure way of doing it
// ... put code here that calls the
Meteor.call('insertMesage', message, function (err, res) {
if (!res) {
alert('You need to log in!');
}
});
Template.header.helpers({
// HERE is another one for you - can you
// complete the template helper for the 'header' template
// called 'nickname' that
// returns the nickname from the Session variable?, if they have set it
nickname: function () {
if (Meteor.user()) {
return Meteor.user().username;
}
},
});
Template.messageList.helpers({
// this helper provides the list of messages for the
// messageList template
messages: function () {
return Messages.find({}, { sort: { createdOn: -1 } })
}
});
},
});
}
Here is the html file
<body>
{{>header}}
{{>nicknameForm}}
{{>messageList}}
{{>messageForm}}
</body>
<template name="header">
<h1>Welcome to M-Instant {{nickname}}</h1>
</template>
<template name="messageList">
{{#each messages}}
{{>messageItem}}
{{/each}}
</template>
<template name="messageItem">
<h3>{{nickname}} - {{messageText}}</h3>
</template>
<template name="nicknameForm">
<div class="form-group">
<label for="nickname-input">Nickname:</label>
<input type="text" class="form-control" id="nickname-input"
placeholder="Type message here...">
<button type="submit" class="btn btn-default js-set-nickname">Set my
nickname!</button>
</div>
</template>
<template name="messageForm">
<div class="form-group">
<label for="message-text-input">Message:</label>
<input type="text" class="form-control" id="message-text-input"
placeholder="Type message here...">
<button type="submit" class="btn btn-primary js-save-message">Post!
</button>
</div>
</template>
Here is the Methods file
Meteor.methods({
'insertMessage':function(message){
console.log("If you manage to call the method, you'll see this
message in the server console");
if (!Meteor.user()){
return;
}
else {
return Messages.insert(message);
}
}
})
Please if anyone has any idea why I keep getting this error when I submitted the stripe subscription form should please help, this error got me stuck for a while now, just trying to create a subscription from the pricing page or subscription plan page, I have the plans stored in my database in a model called Plan. so what I want is for users to select a pricing plan monthly or yearly and it will take them to the payment page where they can make payment and activate a subscription. I am using Laravel Cashier with stripe.
Full error message
Unrecognized request URL (GET: /v1/customers/). If you are trying to list objects, remove the trailing slash. If you are trying to retrieve an object, make sure you passed a valid (non-empty) identifier in your code. Please see https://stripe.com/docs or we can help at https://support.stripe.com/.
The Plans Model
The Route
Route::group(['namespace' => 'Subscriptions'], function() {
Route::get('plans', 'SubscriptionPlanController#index')->name('plans');
Route::get('/payments', 'PaymentsController#index')->name('payments');
Route::post('/payments', 'PaymentsController#store')->name('payments.store');
});
The Plans page
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Subscription Plans') }}</div>
<div class="card-body">
#foreach($plans as $plan)
<div>
{{$plan->title}}
{{-- {{dd($plan->stripe_id)}} --}}
</div>
#endforeach
</div>
</div>
</div>
</div>
</div>
This is The Form
<form action="{{ route('payments.store')}}" method="POST" id="payment-form">
#csrf
<div class="form-content">
<input type="hidden" name="plan" id="subscription-plan" value="{{ request('plan') }}">
<div class="field">
<input type="text" autocorrect="off" spellcheck="false" id="card-holder-name" maxlength="25" />
<span class="focus-bar"></span>
<label for="cardholder">Card holder (Name on card)</label>
</div>
<div class="field mb-5" id="card-element">
<!-- Stripe Elements Placeholder -->
</div>
<button id="card-button" type="submit" data-secret="{{ $intent->client_secret }}">
<span>Pay</span></button>
</div>
</form>
This is the PaymentsController
public function index()
{
$user = auth()->user();
$data = [
'intent' => $user->createSetupIntent(),
];
return view('subscriptions.payments')->with($data);
}
public function store(Request $request)
{
$user = auth()->user();
$paymentMethod = $request->payment_method;
$plan = Plans::where('identifier', $request->plan)
->orWhere('identifier', 'basic_product')
->first();
$request->user()->newSubscription('default', $plan->stripe_id)->create($paymentMethod);
return response(['status' => 'success']);
}
This is the JavaScript
// Create a Stripe client.
const stripe = Stripe('pk_test_51H2OqqLzAo4pwMcyT4h405wpFRAn3FWhvByfvmVnW6tabrIsDoU1dBXJ0UaWexUJeacCJ9uKpb5OBmmA2KaCg4sd00ZZ5tj2q8');
// Create an instance of Elements.
const 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.)
// const cardElement = elements.create('card', {style: style});
// Create an instance of the card Element.
const cardElement = elements.create('card');
// Add an instance of the card Element into the `card-element` <div>.
cardElement.mount('#card-element');
const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');
const clientSecret = cardButton.dataset.secret;
const plan = document.getElementById('subscription-plan').value;
// Handle form submission.
var form = document.getElementById('payment-form');
form.addEventListener('submit', async (e) => {
e.preventDefault();
cardButton.disabled = true
const { setupIntent, error } = await stripe.confirmCardSetup(
cardButton.dataset.secret, {
payment_method: {
card: cardElement,
billing_details: {
name: cardHolderName.value
}
}
}
);
if (error) {
// Display "error.message" to the user...
} else {
var paymentMethod = setupIntent.payment_method;
var form = document.getElementById('payment-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'payment_method');
hiddenInput.setAttribute('value', paymentMethod);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
// });
});
I had this problem tonight. It turned out to be because "stripe_id" in the database was stored as a "" (blank) vs NULL.
In the stripe ManagesCustomer function, it does logic based on !is_null($this->stripe_id) to then assume that this has a stripe id if its an empty string.
I am using Vue component for my checkout form.
The stripe js (v3) file was included in the header section.
The form was in Component
This component has two section. One is to get payment details from the user and another is to submit card details.
<template>
<div class="payment_form">
<div id="payment_details" v-if="showPaymentDetails">
<!-- User input goes here. Like username phone email -->
</div>
<div id="stripe-form" v-if="showStripeForm">
<form action="/charge" method="post" id="payment-form" #submit.prevent="createStripeToken()">
<div class="form-row">
<label for="card-element">
Credit or debit card
</label>
<div id="card-element">
<!-- a Stripe Element will be inserted here. -->
</div>
<!-- Used to display Element errors -->
<div id="card-errors" role="alert"></div>
</div>
<button>Submit Payment</button>
</form>
</div>
</div>
</template>
<script>
import { Validator } from 'vee-validate';
export default {
data() {
return {
stripeToken: '',
showPaymentDetails: true,
showStripeForm: true,
}
},
created() {
},
methods: {
validateForm() {
self = this;
this.$validator.validateAll().then(result => {
if (result) {
// eslint-disable-next-line
alert('From Submitted!');
console.log(this.$data);
axios.post('/data',{
name:this.name,
})
.then(function (response) {
self.showStripeForm = true;
console.log(response);
})
.catch(function (error) {
console.log(error);
});
return;
}
});
},
createStripeToken(){
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
window.stripe.createToken(card).then(function(result) {
if (result.error) {
// Inform the user if there was an error
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server
console.log(result.token);
}
});
});
},
initStripe(){
window.stripe = Stripe('stripe_test_key_here');
var elements = stripe.elements();
var style = {
base: {
// Add your base input styles here. For example:
fontSize: '16px',
lineHeight: '24px'
}
};
// Create an instance of the card Element
window.card = elements.create('card', {style: style});
// Add an instance of the card Element into the `card-element` <div>
window.card.mount('#card-element');
}
},
mounted() {
this.initStripe();
setTimeout(function () {
this.showStripeForm = false;
},2000);
}
}
</script>
I try to load the stripe form on page load and try to disable the element via showStripeForm.
But vue unset the loaded stripe card form from the stripe server and saved the dom to its original state.
So i can't trigger the stripe form on the axios callback.
I don't want to user stripe checkout and stripe js v1(getting input on your own form is deprecated after this version).
In mounted. Change the setTimeout callback to an arrow function, otherwise, this will point to Window instead of Vue.
mounted() {
setTimeout(() => {
this.showStripeForm = false
}, 2000)
}
Also, the way you access the DOM is not so Vue-ish. You could use ref on the DOM element you want to use in your code. For example:
<form action="/charge" method="post" ref="payment-form" #submit.prevent="createStripeToken()">
Then access it from $refs like this:
var form = this.$refs['payment-form']
/*
Same result as document.getElementById('payment-form')
but without using an id attribute.
*/
Im trying to do the login in laravel via ajax so I want this function to return only json object in case of errors
the function returns json only when a input (email or password is empty) , but I insert wrong data in bought of theme the function returns a html page with errors include; but I want to return only these errors without html page (I assume that it it dose return response()->back()->withErrors('errors') )
my Js code :
$('#form-login').submit(function(event) {
event.stopPropagation(); // Stop stuff happening
event.preventDefault(); // Totally stop stuff happening
var data = {
email : $('#login_email').val(),
password : $('#login_password').val(),
}
$.ajax({
url: '/login',
type: 'post',
data: data,
success:function(data, textStatus, jqXHR) {
if (jqXHR.getResponseHeader('Content-Type').includes('json')) {
window.location.reload();
}
},
error:function(data) {
// console.log(data['email'])
// console.log(data.email)
if(data.responseJSON.email){
$('#Email-help-block').html(data.responseJSON.email[0])
}else{
$('#Email-help-block').html('')
}
if(data.responseJSON.password){
$('#Password-help-block').html(data.responseJSON.password[0])
}else{
$('#Password-help-block').html('')
}
},
})
});
the function login :
public function login(Request $request)
{
$this->validateLogin($request); // this is where it returns errors
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
$throttles = $this->isUsingThrottlesLoginsTrait();
if ($throttles && $lockedOut = $this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
$credentials = $this->getCredentials($request);
if (Auth::guard($this->getGuard())->attempt($credentials, $request->has('remember'))) {
return $this->handleUserWasAuthenticated($request, $throttles);
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
if ($throttles && ! $lockedOut) {
$this->incrementLoginAttempts($request);
}
return $this->sendFailedLoginResponse($request);
}
My solution to this problem is:
<body>
<main class="container small">
<div class="middle">
<body>
<main class="container small">
<div class="middle">
<img
<br>
<div class="error valign-wrapper" style=" border: 2px solid red; border-radius: 7px;" hidden>
<h5 class="center-align"> Helaas zijn uw inloggegevens incorrect </h5>
</div>
<form method="POST" action="/api/v1/login" class="login">
{!! csrf_field() !!}
<input type="text" name="email" class="emailaddress" placeholder="Je e-mailadres..." style="background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGP6zwAAAgcBApocMXEAAAAASUVORK5CYII="); cursor: auto;" autocomplete="off">
<input type="password" name="password" class="password" placeholder="Je wachtwoord..." style="background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGP6zwAAAgcBApocMXEAAAAASUVORK5CYII="); cursor: auto;" autocomplete="off">
<div class="left">
Wachtwoord vergeten?
← Terug
</div>
<div class="right">
<input type="submit" class="button" value="Log in">
</div>
</form>
</div>
</main>
</body>
#include('footer')
#push('scripts')
<script>
$('form.login').submit(function(e) {
$form = $(this);
e.preventDefault();
$.post(window.location.origin + $form.attr('action'), $form.serialize())
.done(function(data) {
window.location.href = 'account';
})
.fail(function() {
$('.error').show();
});
});
</script>
#endpush
This is html with the error hidden (or you could show it with just ajax) on error. My javascript is pushed to a javascript stack at the bottom.
As a marionnette beginner, I am trying to make a simple chat application using Collection and CollectionViews.
My collection won't have a fetch method since the messages only come from a particular event.
In the piece of code below my click event is not catched and I wonder why.
Should the 'send message' event be handled by the Collection view ?
Do I need to call App.chat.show(MsgListView) to display the messages ?
TBox.module("ChatApp", function(ChatApp, App, Backbone, Marionette, $, _) {
App.addRegions({
chat: "#chat-messages",
});
// Models
// ------
MsgEntry = Backbone.Model.extend({});
// Collections
// -----------
MsgCollection = Backbone.Collection.extend({
model: MsgEntry
})
// VIews
// -----
MsgView = Backbone.Marionette.ItemView.extend({
template: '#chat-entry-template',
});
MsgListView = Backbone.Marionette.CollectionView.extend({
itemView: MsgView,
events: {
"click #chat-send-btn": "handleNewMessage"
},
handleNewMessage: function(data) {
console.log("CLICK" + data);
},
});
// Init & Finalize
// ---------------
ChatApp.addInitializer(function() {
var msgCollection = new MsgCollection({});
var msgEntry = new MsgEntry({'msg': 'Hello World'});
msgCollection.add(msgEntry);
var msgListView = new MsgListView({collection: msgCollection});
});
});
HTML template
<body>
<!-- templates -->
<script type="text/template" id="status-view-template">
<div>Connecting ...</div>
</script>
<script type="text/template" id="chat-entry-template">
Hello <%= msg =>
</script>
<div id="app">
<div id="sidebar">
<div id="chat">
<h3>Chat</h3>
<div id="chat-messages">
</div>
<div id-"chat-input">
<input type="text" name="msg" />
<button id="chat-send-btn">Send</button>
</div>
</div>
</div>
<!-- main -->
<div id="page">
</div>
<div>
</body>
Ok I made it work with App.chat.show(msgListView);
Also the events hash only takes car of the ItemView events, not other dom events.
// Init & Finalize
// ---------------
ChatApp.addInitializer(function() {
App.vent.trigger("app:started", "ChatApp");
var msgCollection = new MsgCollection([{foo :'bar', foo: 'lol'}]);
var msgListView = new MsgListView({collection: msgCollection});
// render and display the view
App.chat.show(msgListView);
});