├── .gitignore ├── README.md ├── components └── Paystack.tsx ├── lib ├── index.html └── script.js ├── next-env.d.ts ├── next.config.js ├── package.json ├── pages ├── _app.tsx ├── api │ └── verify │ │ └── [reference].ts └── index.tsx ├── public ├── ads.txt ├── favicon.ico ├── logo192.png ├── logo512.png └── manifest.json ├── sass ├── App.scss └── _base.scss ├── tsconfig.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env 29 | .env.local 30 | .env.development.local 31 | .env.test.local 32 | .env.production.local 33 | 34 | # vercel 35 | .vercel -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Paystack 2 | 3 | Paystack functionality demo in Next.js with TypeScript. 4 | -------------------------------------------------------------------------------- /components/Paystack.tsx: -------------------------------------------------------------------------------- 1 | import { FormEventHandler, useEffect, useState } from "react"; 2 | import { PaystackButton } from "react-paystack"; 3 | import { PaystackProps } from "react-paystack/dist/types"; 4 | 5 | type referenceObj = { 6 | message: string; 7 | reference: string; 8 | status: "sucess" | "failure"; 9 | trans: string; 10 | transaction: string; 11 | trxref: string; 12 | }; 13 | 14 | const Paystack: React.FC = (): JSX.Element => { 15 | const [ref, setRef] = useState(""); 16 | const [email, setEmail] = useState(""); 17 | const [amount, setAmount] = useState(0); 18 | const [name, setName] = useState(""); 19 | const [surname, setSurname] = useState(""); 20 | const [success, setSuccess] = useState(false); 21 | 22 | useEffect(() => { 23 | setSuccess(false); 24 | setRef("" + Math.floor(Math.random() * 1000000000 + 1)); 25 | }, [success]); 26 | 27 | const config: PaystackProps = { 28 | reference: ref, 29 | email: email, 30 | firstname: name, 31 | lastname: surname, 32 | label: name + " " + surname, 33 | amount: (amount * 100) | 0, 34 | publicKey: process.env.PAYSTACK_PUBLIC_TEST_KEY as string, 35 | currency: "ZAR", 36 | }; 37 | 38 | 39 | 40 | const onSuccess = async (reference: referenceObj) => { 41 | const res = await fetch(`/api/verify/${reference.reference}`); 42 | const verifyData = await res.json(); 43 | 44 | if (verifyData.data.status === "success") { 45 | setSuccess(true); 46 | setEmail(""); 47 | setAmount(0); 48 | setName(""); 49 | setSurname(""); 50 | } 51 | }; 52 | 53 | const onClose = () => { 54 | alert("Payment cancelled."); 55 | }; 56 | 57 | const componentProps = { 58 | ...config, 59 | text: `Pay R${amount | 0}`, 60 | // onSuccess, 61 | onClose 62 | }; 63 | 64 | 65 | 66 | return ( 67 |
68 |
69 | 70 | setEmail(e.target.value)} 76 | /> 77 |
78 |
79 | 80 | setAmount(Number.parseFloat(e.target.value))} 88 | /> 89 |
90 |
91 | 92 | setName(e.target.value)} 97 | /> 98 |
99 |
100 | 101 | setSurname(e.target.value)} 106 | /> 107 |
108 | 109 | 110 |
111 | ); 112 | }; 113 | 114 | export default Paystack; 115 | -------------------------------------------------------------------------------- /lib/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Paystack 8 | 9 | 10 | 11 |
12 |
13 | 14 | 15 |
16 |
17 | 18 | 19 |
20 |
21 | 22 | 23 |
24 |
25 | 26 | 27 |
28 |
29 | 30 |
31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /lib/script.js: -------------------------------------------------------------------------------- 1 | const paymentForm = document.getElementById("paymentForm"); 2 | paymentForm.addEventListener("submit", payWithPaystack, false); 3 | function payWithPaystack(e) { 4 | e.preventDefault(); 5 | let handler = PaystackPop.setup({ 6 | key: process.env.PAYSTACK_PUBLIC_KEY, // Replace with your public key 7 | email: document.getElementById("email-address").value, 8 | amount: document.getElementById("amount").value * 100, 9 | currency: "ZAR", 10 | ref: "" + Math.floor(Math.random() * 1000000000 + 1), // generates a pseudo-unique reference. Please replace with a reference you generated. Or remove the line entirely so our API will generate one for you 11 | // label: "Optional string that replaces customer email" 12 | onClose: function () { 13 | alert("Window closed."); 14 | }, 15 | callback: function (response) { 16 | let message = "Payment complete! Reference: " + response.reference; 17 | alert(message); 18 | }, 19 | }); 20 | handler.openIframe(); 21 | } 22 | -------------------------------------------------------------------------------- /next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | PAYSTACK_PUBLIC_TEST_KEY: process.env.PAYSTACK_PUBLIC_TEST_KEY, 4 | PAYSTACK_SECRET_TEST_KEY: process.env.PAYSTACK_SECRET_TEST_KEY, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "paystack", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start" 9 | }, 10 | "dependencies": { 11 | "next": "latest", 12 | "node-fetch": "latest", 13 | "react": "latest", 14 | "react-dom": "latest", 15 | "react-paystack": "latest" 16 | }, 17 | "devDependencies": { 18 | "@types/node-fetch": "latest", 19 | "@types/react": "latest", 20 | "sass": "latest", 21 | "typescript": "latest" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import type { AppProps } from "next/app"; 2 | import Script from "next/script"; 3 | 4 | import "../sass/App.scss"; 5 | 6 | function MyApp({ Component, pageProps }: AppProps) { 7 | return ( 8 | <> 9 | 10 |