From a80c0446647f9fd83f796dda1b8ae6d84925f56c Mon Sep 17 00:00:00 2001 From: jonniebigodes Date: Sat, 3 Oct 2020 19:51:28 +0100 Subject: [PATCH] Updates example code and dependencies --- examples/using-square-payments/README.md | 107 ++++++++++++------ .../config/webpack.functions.js | 4 + .../functions/processpay.js | 98 ++++++++++++++++ .../using-square-payments/gatsby-config.js | 36 ++++-- examples/using-square-payments/netlify.toml | 4 + examples/using-square-payments/package.json | 37 +++--- .../src/components/image.js | 32 ------ .../src/components/paymentForm.js | 17 ++- .../using-square-payments/src/pages/index.js | 24 ++-- .../using-square-payments/src/pages/page-2.js | 16 --- .../src/pages/paymentreciept.js | 28 +++++ 11 files changed, 284 insertions(+), 119 deletions(-) create mode 100644 examples/using-square-payments/config/webpack.functions.js create mode 100644 examples/using-square-payments/functions/processpay.js create mode 100644 examples/using-square-payments/netlify.toml delete mode 100644 examples/using-square-payments/src/components/image.js delete mode 100644 examples/using-square-payments/src/pages/page-2.js create mode 100644 examples/using-square-payments/src/pages/paymentreciept.js diff --git a/examples/using-square-payments/README.md b/examples/using-square-payments/README.md index 2b670dd63ad28..d74184ba1b5d3 100644 --- a/examples/using-square-payments/README.md +++ b/examples/using-square-payments/README.md @@ -5,84 +5,121 @@

- Gatsby's default starter + Gatsby's Square payments starter

-Kick off your project with this default boilerplate. This starter ships with the main Gatsby configuration files you might need to get up and running blazing fast with the blazing fast app generator for React. +Kick off your next Gatsby project with [Square](https://squareup.com/us/en) using this starter. -_Have another more specific idea? You may want to check out our vibrant collection of [official and community-created starters](https://www.gatsbyjs.org/docs/gatsby-starters/)._ +This minimal starter ships with the main Gatsby configuration files you might need to get up and running blazing fast with the blazing fast app generator for React and also a sample serverless function to complete the payment process. -## πŸš€ Quick start +As this starter matures it will probably offer more possibilities and options based on the Square payments options. Be on the lookout. + +If you want to get a sneak peak of how the starter looks like, take a look [here](https://example-site-for-square-starter.netlify.com/) for the deployed version and the code used for it in [here](https://github.com/jonniebigodes/example-site-for-square-starter) + +## Quick start 1. **Create a Gatsby site.** - Use the Gatsby CLI to create a new site, specifying the default starter. + Use the Gatsby CLI to create a new site, specifying the square starter. + + ```shell + # create a new Gatsby site using square + gatsby new [my-awesome-site] https://github.com/jonniebigodes/gatsby-starter-square + ``` + Alternatively you can directly clone the repo with: + ```shell - # create a new Gatsby site using the default starter - gatsby new my-default-starter https://github.com/gatsbyjs/gatsby-starter-default + git clone https://github.com/jonniebigodes/gatsby-starter-square ``` -1. **Start developing.** + You might have noticed that the development command is a bit different from other starters used by Gatsby. + + The reason behind this is simple, when you issue this command it will concurrently create a development build for your site and also build the sample serverless function, to allow the full extent of this starter. + + Should you have your own backend solution, you'll need to adjust accordingly. + +2. **Setup a Square account** + + Set up a developer account in the [Square developer portal](https://squareup.com/signup?v=developers) to get started. + + Go through the steps to create a app (don't use the word **square** as it's a reserved word) and don't forget to save the token, application id and localization id provided. As they are required for your project. + +3. **Start developing.** + + Navigate into your new site’s directory and take a look at the `.env.sample` file, this file works as a baseline to store your Square application keys. - Navigate into your new site’s directory and start it up. + Create your own `.env` file with the information provided in the Square developer portal. + + Run the following command to start your site in development: + + When using yarn you should issue: ```shell - cd my-default-starter/ - gatsby develop + yarn start ``` -1. **Open the source code and start editing!** + If you don't have Yarn installed, or prefer to use npm, you can still use this starter without any issues. Just use the following command: - Your site is now running at `http://localhost:8000`! + ```shell + npm run start + ``` + + +4. **Open the source code and start editing!** - _Note: You'll also see a second link: _`http://localhost:8000/___graphql`_. This is a tool you can use to experiment with querying your data. Learn more about using this tool in the [Gatsby tutorial](https://www.gatsbyjs.org/tutorial/part-five/#introducing-graphiql)._ + Your site is now running at `http://localhost:8000`! - Open the `my-default-starter` directory in your code editor of choice and edit `src/pages/index.js`. Save your changes and the browser will update in real time! + Open the `my-awesome-site` directory in your code editor of choice and edit `src/pages/index.js`. Save your changes and the browser will update in real time! -## 🧐 What's inside? +## What's inside? A quick look at the top-level files and directories you'll see in a Gatsby project. . β”œβ”€β”€ node_modules + β”œβ”€β”€ config + β”œβ”€β”€ functions β”œβ”€β”€ src β”œβ”€β”€ .gitignore + β”œβ”€β”€ .env.sample β”œβ”€β”€ .prettierrc - β”œβ”€β”€ gatsby-browser.js β”œβ”€β”€ gatsby-config.js - β”œβ”€β”€ gatsby-node.js - β”œβ”€β”€ gatsby-ssr.js β”œβ”€β”€ LICENSE - β”œβ”€β”€ package-lock.json + β”œβ”€β”€ netlify.toml + β”œβ”€β”€ yarn.lock β”œβ”€β”€ package.json └── README.md 1. **`/node_modules`**: This directory contains all of the modules of code that your project depends on (npm packages) are automatically installed. -2. **`/src`**: This directory will contain all of the code related to what you will see on the front-end of your site (what you see in the browser) such as your site header or a page template. `src` is a convention for β€œsource code”. +2. **`/config`**: Inside this directory is a custom webpack config file for the serverless function to allow the the square payments sdk to run in a serverless environmnent. You can also add you own files here. + +3. **`/functions`**: Inside this directory you'll find a sample serverless function that will use the square payments sdk to finalize your payment process. + +4. **`/src`**: This directory will contain all of the code related to what you will see on the front-end of your site (what you see in the browser) such as your site header or a page template. `src` is a convention for β€œsource code”. -3. **`.gitignore`**: This file tells git which files it should not track / not maintain a version history for. +5. **`.gitignore`**: This file tells git which files it should not track / not maintain a version history for. -4. **`.prettierrc`**: This is a configuration file for [Prettier](https://prettier.io/). Prettier is a tool to help keep the formatting of your code consistent. +6. **`.env.sample`**: This is a sample file to demonstrate the usage of the environment variables required for the starter to run properly. -5. **`gatsby-browser.js`**: This file is where Gatsby expects to find any usage of the [Gatsby browser APIs](https://www.gatsbyjs.org/docs/browser-apis/) (if any). These allow customization/extension of default Gatsby settings affecting the browser. +7. **`.prettierrc`**: This is a configuration file for [Prettier](https://prettier.io/). Prettier is a tool to help keep the formatting of your code consistent. -6. **`gatsby-config.js`**: This is the main configuration file for a Gatsby site. This is where you can specify information about your site (metadata) like the site title and description, which Gatsby plugins you’d like to include, etc. (Check out the [config docs](https://www.gatsbyjs.org/docs/gatsby-config/) for more detail). -7. **`gatsby-node.js`**: This file is where Gatsby expects to find any usage of the [Gatsby Node APIs](https://www.gatsbyjs.org/docs/node-apis/) (if any). These allow customization/extension of default Gatsby settings affecting pieces of the site build process. +8. **`gatsby-config.js`**: This is the main configuration file for a Gatsby site. This is where you can specify information about your site (metadata) like the site title and description, which Gatsby plugins you’d like to include, etc. (Check out the [config docs](https://www.gatsbyjs.org/docs/gatsby-config/) for more detail). -8. **`gatsby-ssr.js`**: This file is where Gatsby expects to find any usage of the [Gatsby server-side rendering APIs](https://www.gatsbyjs.org/docs/ssr-apis/) (if any). These allow customization of default Gatsby settings affecting server-side rendering. -9. **`LICENSE`**: Gatsby is licensed under the MIT license. +9. **`LICENSE`**: This starter is licensed under the MIT license. -10. **`package-lock.json`** (See `package.json` below, first). This is an automatically generated file based on the exact versions of your npm dependencies that were installed for your project. **(You won’t change this file directly).** +10. **`netlify.toml`**: The configuration file required for building the starter in [Netlify](https://www.netlify.com/). + +10. **`yarn.lock`** (See `package.json` below, first). Both these files are automatically generated based on the exact versions of your npm dependencies that were installed for your project. **(You won’t change this file directly).** 11. **`package.json`**: A manifest file for Node.js projects, which includes things like metadata (the project’s name, author, etc). This manifest is how npm knows which packages to install for your project. 12. **`README.md`**: A text file containing useful reference information about your project. -## πŸŽ“ Learning Gatsby +## Additional useful resources Looking for more guidance? Full documentation for Gatsby lives [on the website](https://www.gatsbyjs.org/). Here are some places to start: @@ -90,8 +127,12 @@ Looking for more guidance? Full documentation for Gatsby lives [on the website]( - **To dive straight into code samples, head [to our documentation](https://www.gatsbyjs.org/docs/).** In particular, check out the _Guides_, _API Reference_, and _Advanced Tutorials_ sections in the sidebar. -## πŸ’« Deploy +- **For a complete run down on the Square Payments documentation, head [to their developers documentation site](https://developer.squareup.com/us/en).** In there you'll find not only a well documentated usage of the API that is available, but also some examples. + +- **For a set of testing values for your site, head to [this page](https://developer.squareup.com/docs/testing/test-values).** In there you'll find a list of card values that can be used for testing purposes. + +- **A concise document on how to use the [Square Payments with Gatsby](https://www.gatsbyjs.org/docs/processing-payments-with-square/)** In here you'll be introduced on how you can integrate Square Payments nicely with Gatsby. -[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/gatsbyjs/gatsby-starter-default) +## Deploy - +Before you deploy don't forget to change your app from sandbox mode to production mode in the [Square developer portal](https://developer.squareup.com/apps) and adjust the variables and endpoints acordingly. \ No newline at end of file diff --git a/examples/using-square-payments/config/webpack.functions.js b/examples/using-square-payments/config/webpack.functions.js new file mode 100644 index 0000000000000..98c89d6afc03e --- /dev/null +++ b/examples/using-square-payments/config/webpack.functions.js @@ -0,0 +1,4 @@ +const webpack = require("webpack") +module.exports = { + plugins: [new webpack.DefinePlugin({ "global.GENTLY": false })], +} diff --git a/examples/using-square-payments/functions/processpay.js b/examples/using-square-payments/functions/processpay.js new file mode 100644 index 0000000000000..56de99e70269c --- /dev/null +++ b/examples/using-square-payments/functions/processpay.js @@ -0,0 +1,98 @@ +const crypto = require("crypto") +const squareConnect = require("square-connect") +require("dotenv").config({}) + +exports.handler = async (event, context) => { + console.log(`function method:${event.httpMethod}`) + try { + // check the method due to pre-flight options request done before the actual post by some browsers + if (event.httpMethod === "OPTIONS") { + return { + statusCode: 205, + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Headers": + "Origin, X-Requested-With, Content-Type, Accept", + }, + body: "BOOP", + } + } + + // checks the method and body to see if they are allowed + if (event.httpMethod !== "POST" || !event.body) { + return { statusCode: 405, body: "Method Not Allowed" } + } + + // fetches the token (don't forget that this might be using the sandbox one, adjust accordingly when deploying) + const token = process.env.GATSBY_SQUARE_APLLICATION_TOKEN + if (!token) { + return { + statusCode: 405, + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Headers": + "Origin, X-Requested-With, Content-Type, Accept", + }, + body: + "Something is wrong with the configuration. Check your configuration", + } + } + + // retrieves the payment data sent from the website + const data = JSON.parse(event.body) + + // Set Square Connect credentials and environment + const defaultClient = squareConnect.ApiClient.instance + + // Configure OAuth2 access token for authorization: oauth2 + const oauth2 = defaultClient.authentications["oauth2"] + oauth2.accessToken = token + + // Set 'basePath' to switch between sandbox env and production env + // sandbox: https://connect.squareupsandbox.com + // production: https://connect.squareup.com + defaultClient.basePath = "https://connect.squareupsandbox.com" + + // generate a idempotency key for the payment + const idempotency_key = crypto.randomBytes(22).toString("hex") + + // instantiates the api + const payments_api = new squareConnect.PaymentsApi() + + // generates a request object to process the payment + const request_body = { + source_id: data.cardNounce, + amount_money: { + amount: data.paymentAmmount, + currency: data.currency, + }, + idempotency_key: idempotency_key, + } + // + // calls the square payments api to process the payment issued + const response = await payments_api.createPayment(request_body) + return { + statusCode: 200, + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Headers": + "Origin, X-Requested-With, Content-Type, Accept", + }, + body:JSON.stringify({ + message: `Payment Successful`, + paymentInfo:response + }), + } + } catch (error) { + console.log(error) + return { + statusCode: 500, + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Headers": + "Origin, X-Requested-With, Content-Type, Accept", + }, + body: "Something went wrong with your request. Try again later", + } + } +} diff --git a/examples/using-square-payments/gatsby-config.js b/examples/using-square-payments/gatsby-config.js index 999bd3d349f97..dc1ad962dd625 100644 --- a/examples/using-square-payments/gatsby-config.js +++ b/examples/using-square-payments/gatsby-config.js @@ -1,20 +1,32 @@ +/** + * Configure your Gatsby site with this file. + * + * See: https://www.gatsbyjs.org/docs/gatsby-config/ + */ +const proxy= require('http-proxy-middleware'); + +require("dotenv").config({}) + module.exports = { + /* Your site config here */ siteMetadata: { - title: `Gatsby Default Starter`, - description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`, - author: `@gatsbyjs`, + title: `Gatsby Square Starter`, + description: `This barebones example ships with the minimal configuration you might need to setup Square payments in a Gatsby project`, + author: `@gatsby`, + }, + developMiddleware: app => { + app.use( + "/.netlify/functions/", + proxy({ + target: "http://localhost:9000", + pathRewrite: { + "/.netlify/functions/": "", + }, + }) + ) }, plugins: [ `gatsby-plugin-react-helmet`, - { - resolve: `gatsby-source-filesystem`, - options: { - name: `images`, - path: `${__dirname}/src/images`, - }, - }, - `gatsby-transformer-sharp`, - `gatsby-plugin-sharp`, { resolve: `gatsby-plugin-manifest`, options: { diff --git a/examples/using-square-payments/netlify.toml b/examples/using-square-payments/netlify.toml new file mode 100644 index 0000000000000..7f347c6a02c9e --- /dev/null +++ b/examples/using-square-payments/netlify.toml @@ -0,0 +1,4 @@ +[build] + Command = "yarn build" + Functions = "functions-build" + Publish = "public" \ No newline at end of file diff --git a/examples/using-square-payments/package.json b/examples/using-square-payments/package.json index a785fc918becc..d9548ed2383e3 100644 --- a/examples/using-square-payments/package.json +++ b/examples/using-square-payments/package.json @@ -5,39 +5,44 @@ "version": "0.1.0", "author": "Kyle Mathews ", "dependencies": { - "gatsby": "^2.24.41", - "gatsby-image": "^2.4.15", - "gatsby-plugin-manifest": "^2.4.22", - "gatsby-plugin-offline": "^3.2.23", - "gatsby-plugin-react-helmet": "^3.3.10", - "gatsby-plugin-sharp": "^2.6.26", - "gatsby-plugin-square-payment-form": "^1.0.3", - "gatsby-source-filesystem": "^2.3.24", - "gatsby-transformer-sharp": "^2.5.12", + "axios": "^0.19.2", + "dotenv": "^8.2.0", + "gatsby": "^2.24.67", + "gatsby-plugin-manifest": "^2.4.33", + "gatsby-plugin-offline": "^3.2.30", + "gatsby-plugin-react-helmet": "^3.3.12", "prop-types": "^15.7.2", - "react": "^16.12.0", - "react-dom": "^16.12.0", - "react-helmet": "^5.2.1" + "react": "^16.13.1", + "react-dom": "^16.13.1", + "react-helmet": "^6.1.0", + "serverless-http": "^2.3.1", + "square-connect": "^4.20200923.4" }, "devDependencies": { - "prettier": "2.0.5" + "netlify-lambda": "^2.0.1", + "npm-run-all": "^4.1.5", + "prettier": "^2.1.2" }, "keywords": [ "gatsby" ], "license": "MIT", "scripts": { - "build": "gatsby build", + "build": "run-p build:**", + "build:app": "gatsby build", + "build:lambda": "netlify-lambda -c ./config/webpack.functions.js build functions", "develop": "gatsby develop", "format": "prettier --write \"**/*.{js,jsx,json,md}\"", - "start": "npm run develop", + "start": "run-p start:**", + "start:app": "npm run develop", + "start:lambda": "netlify-lambda -c ./config/webpack.functions.js serve functions", "serve": "gatsby serve", "clean": "gatsby clean", "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1" }, "repository": { "type": "git", - "url": "https://github.com/gatsbyjs/gatsby-starter-default" + "url": "https://github.com/gatsbyjs/gatsby-starter-hello-world" }, "bugs": { "url": "https://github.com/gatsbyjs/gatsby/issues" diff --git a/examples/using-square-payments/src/components/image.js b/examples/using-square-payments/src/components/image.js deleted file mode 100644 index e61edb684de4e..0000000000000 --- a/examples/using-square-payments/src/components/image.js +++ /dev/null @@ -1,32 +0,0 @@ -import React from "react" -import { useStaticQuery, graphql } from "gatsby" -import Img from "gatsby-image" - -/* - * This component is built using `gatsby-image` to automatically serve optimized - * images with lazy loading and reduced file sizes. The image is loaded using a - * `useStaticQuery`, which allows us to load the image from directly within this - * component, rather than having to pass the image data down from pages. - * - * For more information, see the docs: - * - `gatsby-image`: https://gatsby.dev/gatsby-image - * - `useStaticQuery`: https://www.gatsbyjs.org/docs/use-static-query/ - */ - -const Image = () => { - const data = useStaticQuery(graphql` - query { - placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) { - childImageSharp { - fluid(maxWidth: 300) { - ...GatsbyImageSharpFluid - } - } - } - } - `) - - return -} - -export default Image diff --git a/examples/using-square-payments/src/components/paymentForm.js b/examples/using-square-payments/src/components/paymentForm.js index 40f512f63e2af..65113a306518f 100644 --- a/examples/using-square-payments/src/components/paymentForm.js +++ b/examples/using-square-payments/src/components/paymentForm.js @@ -1,6 +1,7 @@ import React, { Component } from "react" import "./paymentForm.css" - +import axios from 'axios' +import { navigate } from "gatsby" const styles = { name: { verticalAlign: "top", @@ -159,6 +160,20 @@ export default class PaymentForm extends Component { nonce: nonce, }) console.log(nonce) + // use axios to make a POST request to the netlify function to process the payment + axios.post(process.env.NODE_ENV==='development'?'http://localhost:9000/processpay':'https://your-website/.netlify/functions/processpay',{ + paymentAmmount:this.props.ammount*100, + currency:"USD", + cardNounce:nonce + }).then(result=>{ + // navigates to the paymentreciept page + navigate("/paymentreciept/",{ + state:result.data + }) + }).catch(error=>{ + console.log(`error in processing payment:${error}`) + this.setState({error:true}) + }) }, unsupportedBrowserDetected: () => {}, inputEventReceived: inputEvent => { diff --git a/examples/using-square-payments/src/pages/index.js b/examples/using-square-payments/src/pages/index.js index fb2cbd1d07d95..991a07db2d793 100644 --- a/examples/using-square-payments/src/pages/index.js +++ b/examples/using-square-payments/src/pages/index.js @@ -1,12 +1,10 @@ import React, { useEffect, useState } from "react" -import { Link } from "gatsby" - import Layout from "../components/layout" import SEO from "../components/seo" import PaymentForm, { loadSquareSdk } from "../components/paymentForm" const IndexPage = () => { - const [squareStatus, setSquareStatus] = useState(null) + const [squareStatus, setSquareStatus] = useState("notLoaded") useEffect(() => { loadSquareSdk() @@ -19,14 +17,22 @@ const IndexPage = () => { return ( - - {squareStatus === "ERROR" && - "Failed to load SquareSDK. Please refresh the page."} +

Thank you for purchasing

+

Awesome dog chew toy for $1

+ {squareStatus === "notLoaded" && ( + <> +

+ Please hold a moment while we're presently setting up your payment! +

+

Thank you for your patience

+ + )} + {squareStatus === "ERROR" && ( +

Failed to load SquareSDK, Please refresh the page

+ )} {squareStatus === "SUCCESS" && ( - + )} - - Go to page 2
) } diff --git a/examples/using-square-payments/src/pages/page-2.js b/examples/using-square-payments/src/pages/page-2.js deleted file mode 100644 index 666c23ef30f9d..0000000000000 --- a/examples/using-square-payments/src/pages/page-2.js +++ /dev/null @@ -1,16 +0,0 @@ -import React from "react" -import { Link } from "gatsby" - -import Layout from "../components/layout" -import SEO from "../components/seo" - -const SecondPage = () => ( - - -

Hi from the second page

-

Welcome to page 2

- Go back to the homepage -
-) - -export default SecondPage diff --git a/examples/using-square-payments/src/pages/paymentreciept.js b/examples/using-square-payments/src/pages/paymentreciept.js new file mode 100644 index 0000000000000..9ec6ae44a6cf4 --- /dev/null +++ b/examples/using-square-payments/src/pages/paymentreciept.js @@ -0,0 +1,28 @@ +import React from "react" +import Layout from "../components/layout" + +/** + * @param {Object} location is destructured from the internal gatsby navigation api + */ +const PaymentReciept = ({ location }) => { + // destructures the state passed via the payment form component + const { state } = location + return ( + + <> +

+ Your payment for Awesome dog chew toy for $1 was successful +

+

+ Here's your payment receipt information: +

+ {!state ? ( +

No payment information is present.

+ ) : ( +
{JSON.stringify(state.paymentInfo, null, 2)}
+ )} + +
+ ) +} +export default PaymentReciept