@@ -12,6 +12,8 @@ import {
1212 validateNewUser ,
1313} from './users.mjs'
1414
15+ import { actualRequestUrl } from 'actual-request-url'
16+
1517import {
1618 defaultTemplateData ,
1719 showPage ,
@@ -52,9 +54,27 @@ routes.get('/pricing', log, async (req, res) => {
5254routes . post ( '/plan' , log , mustLogin , async ( req , res ) => {
5355 const { plan } = req . body
5456 const user = req . cookies . user
55- await tier . subscribe ( `org:${ user } ` , plan )
57+ const reqUrl = actualRequestUrl ( req )
58+ const successUrl = String ( new URL ( '/checkout_success?plan=' + plan , reqUrl ) )
59+ const cancelUrl = String ( new URL ( '/checkout_cancel' , reqUrl ) )
60+ const { url } = await tier . checkout ( `org:${ user } ` , successUrl , {
61+ cancelUrl,
62+ features : plan ,
63+ } )
64+ res . redirect ( url )
65+ } )
66+
67+ // just set the cookie and take them back to the pricing page
68+ routes . get ( '/checkout_success' , log , mustLogin , async ( req , res ) => {
69+ const { plan } = req . query
5670 res . cookie ( 'plan' , plan , { httpOnly : true } )
57- res . send ( { ok : 'updated plan' } )
71+ res . redirect ( '/pricing' )
72+ } )
73+
74+ // just redirect back to the pricing page
75+ // In a real app, you'd probably want to do something here
76+ routes . get ( '/checkout_cancel' , log , mustLogin , async ( _ , res ) => {
77+ res . redirect ( '/pricing' )
5878} )
5979
6080// This is the application endpoint, where we convert temperatures
@@ -66,7 +86,7 @@ routes.post('/convert', log, mustLogin, async (req, res) => {
6686
6787 // Check whether the user has access to this feature. This call
6888 // will tell us the limit and usage of the feature we care about.
69- const usage = await tier . limit ( `org:${ user } ` , 'feature:convert' )
89+ const usage = await tier . lookupLimit ( `org:${ user } ` , 'feature:convert' )
7090 if ( usage . used >= usage . limit ) {
7191 return res . status ( 402 ) . send ( { error : 'not allowed by plan' } )
7292 }
@@ -121,7 +141,7 @@ const loginUser = async (res, user) => {
121141 // get the user's current plan
122142 // We don't need this for much, but it's handy when we show
123143 // the pricing page to be able to highlight their current plan.
124- const phase = await tier . phase ( `org:${ user . id } ` )
144+ const phase = await tier . lookupPhase ( `org:${ user . id } ` )
125145 res . cookie ( 'plan' , phase . plans [ 0 ] )
126146
127147 await setSecureLoginCookies ( res , user )
@@ -196,84 +216,8 @@ routes.use('/ping', log, (req, res) => {
196216// let them do a few things before actually requiring a credit card.
197217routes . get ( '/payment' , log , mustLogin , async ( req , res ) => {
198218 const user = req . cookies . user
199- // This is one of the rare cases where we need to know the actual
200- // Stripe identifier for this customer.
201- const { stripe_id : customerID } = await tier . whois ( `org:${ user } ` )
202-
203- const options = {
204- customer : await getStripeCustomer ( customerID ) ,
205- setupIntent : await createStripeSetupIntent ( customerID ) ,
206- stripePublishableKey : process . env . STRIPE_PUBLISHABLE_KEY ,
207- }
208- showPage ( req , res , 'payment.ejs' , options )
209- } )
210-
211- const getStripeCustomer = async ( customerID ) => {
212- const url = new URL ( 'https://api.stripe.com/v1/customers/' + customerID )
213- url . searchParams . set ( 'expand[]' , 'invoice_settings' )
214- url . searchParams . append ( 'expand[]' , 'invoice_settings.default_payment_method' )
215- const stripeRes = await fetch ( url . href , {
216- method : 'GET' ,
217- headers : {
218- authorization : `Bearer ${ process . env . STRIPE_KEY } ` ,
219- } ,
220- } )
221- return await stripeRes . json ( )
222- }
223-
224- const createStripeSetupIntent = async ( customerID ) => {
225- const setupIntent = await fetch ( 'https://api.stripe.com/v1/setup_intents' , {
226- method : 'POST' ,
227- headers : {
228- authorization : `Bearer ${ process . env . STRIPE_KEY } ` ,
229- 'content-type' : 'application/x-www-form-urlencoded' ,
230- } ,
231- body : new URLSearchParams ( {
232- customer : customerID ,
233- 'payment_method_types[]' : 'card' ,
234- } ) ,
235- } )
236- const seti = await setupIntent . json ( )
237- if ( seti . error ) {
238- throw seti . error
239- }
240- return seti
241- }
242-
243- // redirected here by Stripe
244- // /attach-payment-method?setup_intent=seti_...&setup_intent_client_secret=seti_..._secret_...&redirect_status=succeeded
245- routes . get ( '/attach-payment-method' , log , mustLogin , async ( req , res ) => {
246- const parsed = new URLSearchParams ( req . url . substring ( req . url . indexOf ( '?' ) ) )
247- const setup_intent = parsed . get ( 'setup_intent' )
248- const redirect_status = parsed . get ( 'redirect_status' )
249-
250- const u = new URL ( `https://api.stripe.com/v1/setup_intents/${ setup_intent } ` )
251- const setupIntent = await fetch ( u . href , {
252- method : 'GET' ,
253- headers : {
254- authorization : `Bearer ${ process . env . STRIPE_KEY } ` ,
255- } ,
256- } )
257- const seti = await setupIntent . json ( )
258- if ( redirect_status === 'succeeded' && seti . payment_method ) {
259- // attach to customer
260- const { stripe_id : customerID } = await tier . whois ( `org:${ req . cookies . user } ` )
261- const url = 'https://api.stripe.com/v1/customers/' + customerID
262- const stripeRes = await fetch ( url , {
263- method : 'POST' ,
264- headers : {
265- authorization : `Bearer ${ process . env . STRIPE_KEY } ` ,
266- 'content-type' : 'application/x-www-form-urlencoded' ,
267- } ,
268- body : new URLSearchParams ( {
269- 'invoice_settings[default_payment_method]' : seti . payment_method ,
270- } ) . toString ( ) ,
271- } )
272- await stripeRes . json ( )
273- return res . redirect ( 303 , '/payment' )
274- }
275-
276- // some kind of error or thing requiring user action
277- // TODO: pass this info to the payment page to resolve
278- return res . json ( [ seti , redirect_status ] )
219+ const reqUrl = actualRequestUrl ( req )
220+ const success = String ( new URL ( '/' , reqUrl ) )
221+ const { url } = await tier . checkout ( `org:${ user } ` , success )
222+ res . redirect ( url )
279223} )
0 commit comments