diff --git a/with-abacate-pay/.gitignore b/with-abacate-pay/.gitignore new file mode 100644 index 00000000..54afb48b --- /dev/null +++ b/with-abacate-pay/.gitignore @@ -0,0 +1,33 @@ + +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# local env files +.env*.local + +out/ +build/ +dist/ + +# plasmo +.plasmo + +# typescript +.tsbuildinfo diff --git a/with-abacate-pay/.prettierrc.mjs b/with-abacate-pay/.prettierrc.mjs new file mode 100644 index 00000000..77f84c21 --- /dev/null +++ b/with-abacate-pay/.prettierrc.mjs @@ -0,0 +1,26 @@ +/** + * @type {import('prettier').Options} + */ +export default { + printWidth: 80, + tabWidth: 2, + useTabs: false, + semi: false, + singleQuote: false, + trailingComma: "none", + bracketSpacing: true, + bracketSameLine: true, + plugins: ["@ianvs/prettier-plugin-sort-imports"], + importOrder: [ + "", // Node.js built-in modules + "", // Imports not matched by other special words or groups. + "", // Empty line + "^@plasmo/(.*)$", + "", + "^@plasmohq/(.*)$", + "", + "^~(.*)$", + "", + "^[./]" + ] +} diff --git a/with-abacate-pay/README.md b/with-abacate-pay/README.md new file mode 100644 index 00000000..ca9c259f --- /dev/null +++ b/with-abacate-pay/README.md @@ -0,0 +1,33 @@ +This is a [Plasmo extension](https://docs.plasmo.com/) project bootstrapped with [`plasmo init`](https://www.npmjs.com/package/plasmo). + +## Getting Started + +First, run the development server: + +```bash +pnpm dev +# or +npm run dev +``` + +Open your browser and load the appropriate development build. For example, if you are developing for the chrome browser, using manifest v3, use: `build/chrome-mv3-dev`. + +You can start editing the popup by modifying `popup.tsx`. It should auto-update as you make changes. To add an options page, simply add a `options.tsx` file to the root of the project, with a react component default exported. Likewise to add a content page, add a `content.ts` file to the root of the project, importing some module and do some logic, then reload the extension on your browser. + +For further guidance, [visit our Documentation](https://docs.plasmo.com/) + +## Making production build + +Run the following: + +```bash +pnpm build +# or +npm run build +``` + +This should create a production bundle for your extension, ready to be zipped and published to the stores. + +## Submit to the webstores + +The easiest way to deploy your Plasmo extension is to use the built-in [bpp](https://bpp.browser.market) GitHub action. Prior to using this action however, make sure to build your extension and upload the first version to the store to establish the basic credentials. Then, simply follow [this setup instruction](https://docs.plasmo.com/framework/workflows/submit) and you should be on your way for automated submission! diff --git a/with-abacate-pay/assets/icon.png b/with-abacate-pay/assets/icon.png new file mode 100644 index 00000000..cfd931be Binary files /dev/null and b/with-abacate-pay/assets/icon.png differ diff --git a/with-abacate-pay/package.json b/with-abacate-pay/package.json new file mode 100644 index 00000000..4870e473 --- /dev/null +++ b/with-abacate-pay/package.json @@ -0,0 +1,37 @@ +{ + "name": "with-abacate-pay", + "displayName": "With abacate pay", + "version": "0.0.1", + "description": "A plasmo extension example using abacate pay, a brazilian payment gateway for PIX ", + "author": "VINNE7", + "scripts": { + "dev": "plasmo dev", + "build": "plasmo build", + "package": "plasmo package" + }, + "dependencies": { + "@types/cors": "^2.8.18", + "cors": "^2.8.5", + "plasmo": "0.90.3", + "react": "18.2.0", + "react-dom": "18.2.0" + }, + "devDependencies": { + "@ianvs/prettier-plugin-sort-imports": "4.1.1", + "@types/chrome": "0.0.258", + "@types/node": "20.11.5", + "@types/react": "18.2.48", + "@types/react-dom": "18.2.18", + "prettier": "3.2.4", + "typescript": "5.3.3" + }, + "manifest": { + "host_permissions": [ + "$PLASMO_PUBLIC_BACKEND_URL/*", + "https://*/*" + ], + "permissions": [ + "activeTab" + ] + } +} diff --git a/with-abacate-pay/popup.tsx b/with-abacate-pay/popup.tsx new file mode 100644 index 00000000..b2c0f0c0 --- /dev/null +++ b/with-abacate-pay/popup.tsx @@ -0,0 +1,196 @@ +import { useRef, useState } from "react" + +const BACKEND_URL = process.env.PLASMO_PUBLIC_BACKEND_URL + +const initialForm = { + name: "", + email: "", + cellphone: "", + taxId: "", + amount: 1, + description: "PIX payment via AbacatePay" +} + +function IndexPopup() { + const [form, setForm] = useState(initialForm) + const [loading, setLoading] = useState(false) + const [error, setError] = useState("") + const [payment, setPayment] = useState(null) + const [status, setStatus] = useState("") + const pollingRef = useRef(null) + + const handleChange = (e: React.ChangeEvent) => { + const { name, value } = e.target + setForm((f) => ({ ...f, [name]: value })) + } + + const handleNumber = (e: React.ChangeEvent) => { + setForm((f) => ({ ...f, amount: Number(e.target.value) })) + } + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + setLoading(true) + setError("") + setPayment(null) + setStatus("") + try { + const res = await fetch(`${BACKEND_URL}/api/create-payment`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + amount: form.amount, + expiresIn: 300, + description: form.description, + customer: { + name: form.name, + cellphone: form.cellphone, + email: form.email, + taxId: form.taxId + } + }) + }) + if (!res.ok) { + console.log(res) + throw new Error("Error creating payment") + } + const data = await res.json() + setPayment(data.data) + setStatus(data.data.status) + startPolling(data.data.id) + } catch (err: any) { + setError(err.message) + } finally { + setLoading(false) + } + } + + const startPolling = (id: string) => { + if (pollingRef.current) clearInterval(pollingRef.current) + pollingRef.current = setInterval(async () => { + try { + const res = await fetch(`${BACKEND_URL}/api/check-status/${id}`) + const data = await res.json() + setStatus(data.status || data.data?.status) + if (data.status === "paid" || data.status === "expired") { + if (pollingRef.current) clearInterval(pollingRef.current) + } + } catch (err) { + // ignore polling errors + } + }, 3000) + } + + const handleSimulate = async () => { + if (!payment?.id) return + setLoading(true) + setError("") + try { + const res = await fetch(`${BACKEND_URL}/api/simulate-payment`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ id: payment.id }) + }) + if (!res.ok) throw new Error("Error at simulate payment") + } catch (err: any) { + setError(err.message) + } finally { + setLoading(false) + } + } + + return ( +
+

AbacatePay PIX Example

+
+ + + + + + + +
+ {error &&
{error}
} + {payment && ( +
+
+ Status: {status || payment.status || "PENDING"} +
+ {payment.brCode && ( +
+ PIX QR Code +
+ {payment.brCode} +
+
+ )} + {status !== "paid" && status !== "expired" && ( + + )} +
+ )} + +
+ ) +} + +export default IndexPopup diff --git a/with-abacate-pay/tsconfig.json b/with-abacate-pay/tsconfig.json new file mode 100644 index 00000000..9c10ec49 --- /dev/null +++ b/with-abacate-pay/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "plasmo/templates/tsconfig.base", + "exclude": [ + "node_modules" + ], + "include": [ + ".plasmo/index.d.ts", + "./**/*.ts", + "./**/*.tsx" + ], + "compilerOptions": { + "paths": { + "~*": [ + "./*" + ] + }, + "baseUrl": "." + } +}