Skip to content

Commit bbfc20d

Browse files
chore: wip
1 parent 05c1edf commit bbfc20d

File tree

4 files changed

+73
-64
lines changed

4 files changed

+73
-64
lines changed

resources/functions/billing/payments.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,23 @@ export function useBillable() {
2323
return clientSecret
2424
}
2525

26+
async function subscribeToPlan(body: { type: string, plan: string }): Promise<string> {
27+
const url = 'http://localhost:3008/stripe/create-subscription'
28+
29+
const response = await fetch(url, {
30+
method: 'POST',
31+
headers: {
32+
'Content-Type': 'application/json',
33+
'Accept': 'application/json',
34+
},
35+
body: JSON.stringify(body),
36+
})
37+
38+
const client: any = await response.json()
39+
40+
return client
41+
}
42+
2643
async function loadStripeElement(clientSecret: string): Promise<boolean> {
2744
stripe.value = await loadStripe(publishableKey)
2845

@@ -61,5 +78,5 @@ export function useBillable() {
6178
}
6279
}
6380

64-
return { fetchSetupIntent, loadStripeElement, handleAddPaymentMethod }
81+
return { fetchSetupIntent, loadStripeElement, handleAddPaymentMethod, subscribeToPlan }
6582
}

resources/stores/payment.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,15 @@ export const usePaymentStore = defineStore('payment', {
8383
},
8484

8585
getters: {
86-
getPaymentMethods(state): any[] {
86+
getPaymentMethods(state): StripePaymentMethod[] {
8787
return state.paymentMethods
8888
},
89-
getDefaultPaymentMethod(state): any[] {
89+
hasPaymentMethods(state): boolean {
90+
return state.paymentMethods.length || !(!state.defaultPaymentMethod // Checks for null or undefined
91+
|| (typeof state.defaultPaymentMethod === 'object'
92+
&& Object.keys(state.defaultPaymentMethod).length === 0))
93+
},
94+
getDefaultPaymentMethod(state): StripePaymentMethod[] {
9095
return state.defaultPaymentMethod
9196
},
9297
},

resources/views/dashboard/components/billing/plans.vue

Lines changed: 15 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
<script setup lang="ts">
2+
import { useBillable } from '../../../../functions/billing/payments'
3+
24
const checkedPlanType = ref('monthly')
35
const selectedPlan = ref('')
6+
const paymentStore = usePaymentStore()
47
const planTypeKey = ref('stacks_hobby_early_monthly')
5-
let elements
6-
let stripe
8+
9+
const { subscribeToPlan } = useBillable()
710
811
const loading = ref(true)
912
@@ -37,40 +40,16 @@ const proPrice = computed(() => {
3740
return 749
3841
})
3942
40-
// async function subscribePlan() {
41-
// const body = {
42-
// type: planTypeKey.value,
43-
// plan: selectedPlan.value,
44-
// }
45-
46-
// const url = 'http://localhost:3008/stripe/create-subscription'
47-
48-
// const response = await fetch(url, {
49-
// method: 'POST',
50-
// headers: {
51-
// 'Content-Type': 'application/json',
52-
// 'Accept': 'application/json',
53-
// },
54-
// body: JSON.stringify(body),
55-
// })
56-
57-
// const client: any = await response.json()
5843
59-
// const clientSecret = client.client_secret
44+
async function subscribePlan() {
45+
const subscriptionIntent = await subscribeToPlan({
46+
type: planTypeKey.value,
47+
plan: selectedPlan.value,
48+
})
6049
61-
// stripe = await loadStripe(publishableKey)
62-
63-
// if (stripe) {
64-
// elements = stripe.elements({clientSecret});
65-
// const paymentElement = elements.create('payment');
66-
67-
// paymentElement.mount("#payment-element");
68-
// const linkAuthenticationElement = elements.create("linkAuthentication");
69-
// linkAuthenticationElement.mount("#link-authentication-element");
70-
// }
71-
72-
// loading.value = false
73-
// }
50+
// TODO: fire a toast or something
51+
if (subscriptionIntent) alert('success!')
52+
}
7453
</script>
7554

7655
<template>
@@ -162,7 +141,8 @@ const proPrice = computed(() => {
162141
<div class="flex justify-end pt-8">
163142
<button
164143
type="button"
165-
class="rounded-md bg-blue-600 px-2.5 py-1.5 text-sm text-white font-semibold shadow-sm hover:bg-blue-gray-500 focus-visible:outline-2 focus-visible:outline-blue-600 focus-visible:outline-offset-2 focus-visible:outline"
144+
:disabled="!paymentStore.hasPaymentMethods"
145+
class="rounded-md disabled:bg-gray-600 bg-blue-600 px-2.5 py-1.5 text-sm text-white font-semibold shadow-sm hover:bg-blue-gray-500 focus-visible:outline-2 focus-visible:outline-blue-600 focus-visible:outline-offset-2 focus-visible:outline"
166146
@click="subscribePlan()"
167147
>
168148
Subscribe

storage/framework/core/payments/src/billable/subscription.ts

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,46 @@ export interface SubscriptionManager {
1212
}
1313

1414
export const manageSubscription: SubscriptionManager = (() => {
15-
async function create(user: UserModel, type: string, lookupKey: string, params: Partial<Stripe.SubscriptionCreateParams>): Promise<Stripe.Response<Stripe.Subscription>> {
16-
const price = await managePrice.retrieveByLookupKey(lookupKey)
17-
18-
if (!price)
19-
throw new Error('Price does not exist in stripe')
20-
21-
const subscriptionItems = [{
22-
price: price.id,
23-
quantity: 1,
24-
}]
25-
15+
async function create(
16+
user: UserModel,
17+
type: string,
18+
lookupKey: string,
19+
params: Partial<Stripe.SubscriptionCreateParams>
20+
): Promise<Stripe.Response<Stripe.Subscription>> {
21+
const price = await managePrice.retrieveByLookupKey(lookupKey);
22+
23+
if (!price) {
24+
throw new Error('Price does not exist in Stripe');
25+
}
26+
27+
const subscriptionItems = [
28+
{
29+
price: price.id,
30+
quantity: 1,
31+
},
32+
];
33+
2634
const customerId = await manageCustomer.createOrGetStripeUser(user, {}).then((customer) => {
2735
if (!customer || !customer.id) {
28-
throw new Error('Customer does not exist in Stripe')
36+
throw new Error('Customer does not exist in Stripe');
2937
}
30-
31-
return customer.id
32-
})
33-
38+
return customer.id;
39+
});
40+
3441
const defaultParams: Stripe.SubscriptionCreateParams = {
3542
customer: customerId,
36-
payment_behavior: 'default_incomplete',
43+
payment_behavior: 'allow_incomplete', // or omit this line entirely
3744
expand: ['latest_invoice.payment_intent'],
3845
items: subscriptionItems,
39-
}
40-
41-
const mergedParams = { ...defaultParams, ...params }
42-
43-
const subscription = await stripe.subscription.create(mergedParams)
44-
45-
await storeSubscription(user, type, subscription)
46-
47-
return subscription
46+
};
47+
48+
const mergedParams = { ...defaultParams, ...params };
49+
50+
const subscription = await stripe.subscription.create(mergedParams);
51+
52+
await storeSubscription(user, type, subscription);
53+
54+
return subscription;
4855
}
4956

5057
async function isActive(subscription: SubscriptionModel): Promise<boolean> {

0 commit comments

Comments
 (0)