I don't see any payment method specified in your code.
Jul 23, 2023
34
Level 7
payment fail invalid payment method
I am trying to subscribe a user on my application using stripe I keep getting:
"message": "The payment attempt failed because of an invalid payment method.",
"exception": "Laravel\Cashier\Exceptions\IncompletePayment",
"file": "/Users/johnbiddulph/Documents/SITES/jb-admin-api/vendor/laravel/cashier/src/Exceptions/IncompletePayment.php",
"line": 42,
"trace": [
{
"file": "/Users/johnbiddulph/Documents/SITES/jb-admin-api/vendor/laravel/cashier/src/Payment.php",
"line": 162,
"function": "paymentMethodRequired",
"class": "Laravel\Cashier\Exceptions\IncompletePayment",
"type": "::"
},
{
.... and so on.....
Here is my code:
<template>
<div id="register">
<TopNavigation />
<div class="w-full p-6 flex justify-center items-center">
<div class="w-full max-w-xs">
<div class="bg-gray-600 p-8 shadow rounded mb-6">
<h1 class="mb-6 text-lg text-gray-100 font-thing">
Let's get rocking
</h1>
<div class="mb-4">
<SelectInput
label="Client"
:labelColor="false"
:options="transformedOptions"
placeholder="Please select"
v-model:input="clientId"
:error="errors.client_id ? errors.client_id[0] : ''"
/>
</div>
<div class="mb-4">
<TextInput
label="First Name"
:labelColor="false"
placeholder="John"
v-model:input="firstName"
inputType="text"
:error="errors.first_name ? errors.first_name[0] : ''"
/>
</div>
<div class="mb-4">
<TextInput
label="Last Name"
:labelColor="false"
placeholder="John"
v-model:input="lastName"
inputType="text"
:error="errors.last_name ? errors.last_name[0] : ''"
/>
</div>
<div class="mb-4">
<TextInput
label="Email"
:labelColor="false"
placeholder="[email protected]"
v-model:input="email"
inputType="text"
:error="errors.email ? errors.email[0] : ''"
/>
</div>
<div class="mb-4">
<TextInput
label="Password"
:labelColor="false"
placeholder="john123456"
v-model:input="password"
inputType="password"
:error="errors.password ? errors.password[0] : ''"
/>
</div>
<div class="mb-4">
<TextInput
label="Confirm Password"
:labelColor="false"
placeholder="john123456"
v-model:input="confirmPassword"
inputType="password"
/>
</div>
<label>
Card Details
<!-- <div id="card-element" ref="cardElement"></div> -->
<div id="card-number-element"></div>
<div id="card-expiry-element"></div>
<div id="card-cvc-element"></div>
</label>
<button
class="block w-full bg-green-500 text-white rounded-sm py-3 text-sm tracking-wide"
type="submit"
@click="register"
>
Register
</button>
</div>
<p class="text-center text-md text-gray-900">
Already have an account?...
<router-link
class="text-blue-500 no-underline hover:underline"
to="/login"
>
Login
</router-link>
</p>
</div>
</div>
</div>
</template>
<script setup>
import { loadStripe } from '@stripe/stripe-js';
import { ref, onMounted, computed } from "vue";
import { useUserStore } from '../store/UserStore';
import { useClientStore } from '../store/ClientStore';
import { useProfileStore } from '../store/ProfileStore';
import { usePostStore } from '../store/PostStore';
import { useRouter } from 'vue-router';
import TextInput from "@/components/global/TextInput.vue";
import SelectInput from "@/components/global/SelectInput.vue";
import axios from "axios";
import TopNavigation from "@/components/structure/TopNavigation.vue";
const userStore = useUserStore();
const clientStore = useClientStore();
const router = useRouter();
const profileStore = useProfileStore();
const postStore = usePostStore();
let errors = ref([]);
let clientId = ref(null);
let firstName = ref(null);
let lastName = ref(null);
let email = ref(null);
let password = ref(null);
let confirmPassword = ref(null);
let clients = ref([]);
let stripe = ref(null); // Declare stripe as a reactive property
let cardNumberElement = ref(null);
let cardExpiryElement = ref(null);
let cardCvcElement = ref(null);
let transformedOptions = computed(() => {
return clients.value.map(client => ({
value: client.id,
label: client.name
}));
});
onMounted(async () => {
await clientStore.fetchClients();
clients.value = clientStore.clients;
stripe.value = await initializeStripe(); // Assign the initialized stripe value
const elements = stripe.value.elements(); // Get the Stripe elements instance
cardNumberElement.value = elements.create('cardNumber');
cardExpiryElement.value = elements.create('cardExpiry');
cardCvcElement.value = elements.create('cardCvc');
cardNumberElement.value.mount('#card-number-element');
cardExpiryElement.value.mount('#card-expiry-element');
cardCvcElement.value.mount('#card-cvc-element');
});
const initializeStripe = async () => {
const stripe = await loadStripe('pk_test_51LGnwdH8B3O205oeNawhEVgb4g7R3iFEQjPk25ScCUvq0jYgv46VQCDH2tpDnJW08WYdjYzXNvDZYLB2oDUjavWd0044IrAwxH'); // Replace with your Stripe publishable key
//const stripe = await loadStripe('pk_live_51LGnwdH8B3O205oeOdsDQZ10MwxqRwREqVLTHXBTKXddrsAV8KDBDCzHP7YW2jv4N4LdXYxEYon8guwdqWka92q900K5AijE1d');
return stripe;
}
const register = async () => {
errors.value = [];
try {
let res = await axios.post('api/register', {
client_id: clientId.value,
first_name: firstName.value,
last_name: lastName.value,
email: email.value,
password: password.value,
password_confirmation: confirmPassword.value
});
axios.defaults.headers.common['Authorization'] = 'Bearer ' + res.data.token;
console.log('Response Data: ', res);
const user = res.data.user;
userStore.setUserDetails(res);
console.log('UserStore: ', userStore);
await profileStore.fetchProfileById(userStore.id);
await postStore.fetchPostsByUserId(userStore.id);
const stripeInstance = await initializeStripe();
console.log('stripeInstance: ', stripeInstance)
// Make an API request to your backend to create a customer and subscription
const subscriptionResponse = await axios.post('api/create-subscription', {
user,
customerEmail: email.value,
customerName: firstName.value + ' ' + lastName.value,
priceId: 'price_1NSmEQH8B3O205oeHPngASZm', // Replace with your actual Stripe price ID
cardNumber: cardNumberElement.value,
cardExpiry: cardExpiryElement.value,
cardCvc: cardCvcElement.value,
});
console.log('subscriptionResponse: ', subscriptionResponse)
// Handle the subscription response as needed
const subscriptionId = subscriptionResponse.data.subscriptionId;
// ...
console.log('subscriptionId: ', subscriptionId)
router.push('/account/profile/' + userStore.id);
} catch (error) {
if (error.response && error.response.data && error.response.data.errors) {
errors.value = error.response.data.errors;
} else {
errors.value = ['An error occurred. Please try again.'];
}
}
};
</script>
Level 63
@boyjarv For me too, it's probably necessary in some countries.
You can customize some fields with the available options.
https://stripe.com/docs/js/elements_object/create_element?type=card
Please or to participate in this conversation.