diff --git a/functions/debug-timeout.png b/functions/debug-timeout.png deleted file mode 100644 index d87f1c3..0000000 Binary files a/functions/debug-timeout.png and /dev/null differ diff --git a/functions/debug.png b/functions/debug.png deleted file mode 100644 index 1bf6b59..0000000 Binary files a/functions/debug.png and /dev/null differ diff --git a/functions/endpoints/mainnet.js b/functions/endpoints/mainnet.js index 78c802a..88f4604 100644 --- a/functions/endpoints/mainnet.js +++ b/functions/endpoints/mainnet.js @@ -29,12 +29,12 @@ app.put( '/api/rocketeer/:id/outfits', setPrimaryOutfit ) /* /////////////////////////////// // Notification API // /////////////////////////////*/ -app.post( '/api/notifications/:address', ( req, res ) => order_merch( req.body ) ) +app.post( '/api/notifications/:address', subscribe_address_to_notifications ) /* /////////////////////////////// // Merch API // /////////////////////////////*/ -app.post( '/api/merch/order', subscribe_address_to_notifications ) +app.post( '/api/merch/order', order_merch ) // /////////////////////////////// // Static collection data diff --git a/functions/integrations/merch.js b/functions/integrations/merch.js index 03b3f70..018ba84 100644 --- a/functions/integrations/merch.js +++ b/functions/integrations/merch.js @@ -9,15 +9,17 @@ const fetch = require( 'isomorphic-fetch' ) // /////////////////////////////*/ async function call_printapi( endpoint, data, method='POST', format='json', authenticated=true ) { + const logs = [] + try { - log( `Call requested: ${method}/${format} ${endpoint} with `, data ) + logs.push( `Call requested: ${method}/${format} ${endpoint} with `, JSON.stringify( data ) ) // Format url, if it has https use the link as provided const url = endpoint.includes( 'https://' ) ? endpoint : `${ printapi.base_url }${ endpoint }` const access_token = authenticated && await get_auth_token() - if( authenticated ) log( `Found access token: `, access_token.slice( 0, 10 ) ) + if( authenticated ) log( `Found access token: `, access_token && access_token.slice( 0, 10 ) ) if( authenticated && !access_token ) throw new Error( `No access_token found` ) // Generate headers based on input @@ -26,7 +28,7 @@ async function call_printapi( endpoint, data, method='POST', format='json', auth ...( format == 'form' && data && { 'Content-Type': 'application/x-www-form-urlencoded' } ), ...( authenticated && { Authorization: `Bearer ${ access_token }` } ) } - log( `Headers `, headers ) + logs.push( `Headers `, JSON.stringify( headers ) ) // Generate data body let body = {} @@ -36,17 +38,39 @@ async function call_printapi( endpoint, data, method='POST', format='json', auth // Formdata being formdata if( format == 'form' ) body = new URLSearchParams( data ) + logs.push( `API request data `, body ) + // Focmat fetch options const options = { method, headers, body - } + } // Call api - log( `Calling ${ url }`, ) - const response = await fetch( url, options ).then( res => res.json( ) ) - log( `Received `, response ) + logs.push( `Calling ${ url }`, ) + const response = await fetch( url, options ).then( async res => { + + const json_res = res.clone() + const text_res = res.clone() + + try { + + const json_response = await json_res.json() + logs.push( `API json response: `, json_response ) + return json_response + + } catch( e ) { + + const text_response = await text_res.text() + logs.push( `API text response: `, text_response ) + throw new Error( `Non JSON output from API` ) + + } + + } ) + logs.push( `Production call: `, JSON.stringify( { ...headers, ...body } ) ) + logs.push( `Received `, JSON.stringify( response ) ) return response @@ -54,7 +78,8 @@ async function call_printapi( endpoint, data, method='POST', format='json', auth console.error( `Error calling printapi: `, e ) return { - error: e.message + error: e.message, + tracelog: logs } } @@ -64,41 +89,49 @@ async function call_printapi( endpoint, data, method='POST', format='json', auth async function get_auth_token( ) { const token_grace_period = 1000 * 60 + const logs = [] try { // Get cached token let { expires=0, access_token } = await db.collection( 'secrets' ).doc( 'printapi' ).get( ).then( dataFromSnap ) - log( `Old access token: `, access_token && access_token.slice( 0, 10 ) ) + logs.push( `Old access token: `, access_token && access_token.slice( 0, 10 ) ) // If token is still valid if( ( expires - token_grace_period ) > Date.now() ) { - log( `Old access token still valid` ) + logs.push( `Old access token still valid` ) return access_token } // Grab new token and save it - log( `Requesting new token` ) + logs.push( `Requesting new token` ) const credentials = { grant_type: 'client_credentials', client_id: printapi.client_credentials, client_secret: printapi.client_secret } - const { access_token: new_access_token, expires_in } = await call_printapi( `/v2/oauth`, credentials, 'POST', 'form', false ) + const { access_token: new_access_token, expires_in, ...errors } = await call_printapi( `/v2/oauth`, credentials, 'POST', 'form', false ) - log( `New access token: `, new_access_token && new_access_token.slice( 0, 10 ) ) + logs.push( `New access token: `, new_access_token && new_access_token.slice( 0, 10 ) ) + if( errors ) logs.push( `Access token error: `, errors ) + if( !new_access_token ) throw new Error( `No access token available` ) + + // Write new access token to cache await db.collection( 'secrets' ).doc( 'printapi' ).set( { access_token: new_access_token, // expires_in is in seconds expires: Date.now() + ( expires_in * 1000 ) }, { merge: true } ) + + return new_access_token } catch( e ) { console.error( `Error getting auth token `, e ) + console.log( 'Access token error: ', JSON.stringify( logs ) ) return false } @@ -124,6 +157,8 @@ async function make_printapi_order ( { image_url, product_id, quantity=1, addre // } // } + const logs = [] + try { // Validations @@ -144,18 +179,30 @@ async function make_printapi_order ( { image_url, product_id, quantity=1, addre address } } - log( `Creating order: `, order ) - const { checkout, ...details } = await call_printapi( `/v2/orders`, order ) - log( `Order made with `, checkout, details ) + logs.push( `Creating order: `, order ) + const { checkout, error: order_error, ...order_details } = await call_printapi( `/v2/orders`, order ) + logs.push( `Order made with `, checkout, order_details ) + + if( order_error ) { + logs.push( `Order errored with `, order_error ) + throw new Error( order_error ) + } // Generate pament link - const { paymentUrl, amount } = await call_printapi( checkout.setupUrl, { + const { error: checkout_error, paymentUrl, amount, ...checkout_details } = await call_printapi( checkout.setupUrl, { billing: { address }, - returnUrl: `https://tools.rocketeer.fans/#/merch/success/${ details.id }` + returnUrl: `https://tools.rocketeer.fans/#/merch/success/${ order_details.id }` } ) + logs.push( `Checkout responded with`, paymentUrl, amount, checkout_details ) + + if( checkout_error ) { + logs.push( `Checkout errored with `, checkout_error ) + throw new Error( checkout_error ) + } + return { paymentUrl, amount @@ -164,7 +211,8 @@ async function make_printapi_order ( { image_url, product_id, quantity=1, addre } catch( e ) { return { - error: e.message + error: e.message, + tracelog: logs } } @@ -173,16 +221,21 @@ async function make_printapi_order ( { image_url, product_id, quantity=1, addre exports.order_merch = async ( req, res ) => { + const logs = [] + try { + logs.push( `Making API request based on body: `, req.body ) const { error, ...order } = await make_printapi_order( req.body ) + logs.push( `Received: `, error, order ) if( error ) throw new Error( error ) - return res.json( order ) + return res.json( { ...order, tracelog: logs } ) } catch( e ) { return res.json( { - error: e.message + error: e.message, + tracelog: logs } ) } diff --git a/functions/pre-debug.png b/functions/pre-debug.png deleted file mode 100644 index 9c18a30..0000000 Binary files a/functions/pre-debug.png and /dev/null differ diff --git a/minter/src/components/organisms/Merch.js b/minter/src/components/organisms/Merch.js index 1fb9b35..c1468ec 100644 --- a/minter/src/components/organisms/Merch.js +++ b/minter/src/components/organisms/Merch.js @@ -23,7 +23,7 @@ export default function Verifier() { const [ rocketeer, setRocketeer ] = useState( ) const [ order, setOrder ] = useState( { } ) const [ payment, setPayment ] = useState( ) - const { rocketeer_id } = useParams() + const { rocketeer_id, order_id } = useParams() const navigate = useNavigate() const rocketeers = useRocketeers( rocketeer_id ) const [ loading, setLoading ] = useState( ) @@ -83,6 +83,7 @@ export default function Verifier() { product_id: 'kurk_20x20' } ) + log( `API responded with `, error, pending_order ) if( error ) throw new Error( error ) log( `Order created: `, pending_order ) @@ -107,6 +108,11 @@ export default function Verifier() { if( loading ) return + if( order_id ) return +

Order { order_id } confirmed

+ Write that number down in case of apocalypse. You'll be kept up to date via email. Emails might be in Dutch. Sorry, not sorry. +
+ if( payment ) return

Payment link generated