[web] Complete integration of payments code (#1233)
Next step - deploy from here.
This commit is contained in:
commit
e4ce144bd4
23 changed files with 139 additions and 163 deletions
43
.github/workflows/web-deploy-payments.yml
vendored
Normal file
43
.github/workflows/web-deploy-payments.yml
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
name: "Deploy (payments)"
|
||||
|
||||
on:
|
||||
push:
|
||||
# Run workflow on pushes to the deploy/payments
|
||||
branches: [deploy/payments]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: web
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup node and enable yarn caching
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "yarn"
|
||||
cache-dependency-path: "docs/yarn.lock"
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install
|
||||
|
||||
- name: Build payments
|
||||
run: yarn build:payments
|
||||
|
||||
- name: Publish payments
|
||||
uses: cloudflare/pages-action@1
|
||||
with:
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
projectName: ente
|
||||
branch: deploy/payments
|
||||
directory: web/apps/payments/out
|
||||
wranglerVersion: "3"
|
13
.github/workflows/web-nightly.yml
vendored
13
.github/workflows/web-nightly.yml
vendored
|
@ -78,6 +78,19 @@ jobs:
|
|||
directory: web/apps/cast/out
|
||||
wranglerVersion: "3"
|
||||
|
||||
- name: Build payments
|
||||
run: yarn build:payments
|
||||
|
||||
- name: Publish payments
|
||||
uses: cloudflare/pages-action@1
|
||||
with:
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
projectName: ente
|
||||
branch: n-payments
|
||||
directory: web/apps/payments/out
|
||||
wranglerVersion: "3"
|
||||
|
||||
- name: Build photos
|
||||
run: yarn build:photos
|
||||
env:
|
||||
|
|
1
.github/workflows/web-preview.yml
vendored
1
.github/workflows/web-preview.yml
vendored
|
@ -12,6 +12,7 @@ on:
|
|||
- "accounts"
|
||||
- "auth"
|
||||
- "cast"
|
||||
- "payments"
|
||||
- "photos"
|
||||
|
||||
jobs:
|
||||
|
|
|
@ -17,6 +17,7 @@ services:
|
|||
- custom-logs:/var/logs
|
||||
- ./museum.yaml:/museum.yaml:ro
|
||||
- ./scripts/compose/credentials.yaml:/credentials.yaml:ro
|
||||
- ./data:/data:ro
|
||||
networks:
|
||||
- internal
|
||||
|
||||
|
|
|
@ -3,28 +3,55 @@ Stripe's API for payments.
|
|||
|
||||
## Development
|
||||
|
||||
If you're running this to test out the payment flows end-to-end, please do a
|
||||
`yarn build`, that will place the output within the `out` folder.
|
||||
There are three pieces that need to be connected to have a working local setup:
|
||||
|
||||
Then use any tool to serve this over HTTP. For example, `python3 -m http.server
|
||||
3001` will serve this directory over port `3001`.
|
||||
- A client app
|
||||
- This web app
|
||||
- Museum
|
||||
|
||||
Aside that, these are the necessary configuration changes.
|
||||
### Client app
|
||||
|
||||
### Local configuration
|
||||
For the client, let us consider the Photos web app (similar configuration can be
|
||||
done in the mobile client too).
|
||||
|
||||
Create an `.env` in this directory to point to the local museum instance, and to
|
||||
define the necessary Stripe keys that can be fetched from [Stripe's developer
|
||||
Add the following to `web/apps/photos/.env.local`:
|
||||
|
||||
```env
|
||||
NEXT_PUBLIC_ENTE_ENDPOINT = http://localhost:8080
|
||||
NEXT_PUBLIC_ENTE_PAYMENTS_ENDPOINT = http://localhost:3001
|
||||
```
|
||||
Then start it locally
|
||||
|
||||
```sh
|
||||
yarn dev:photos
|
||||
```
|
||||
|
||||
This tells it to connect to the museum and payments app running on localhost.
|
||||
|
||||
> For connecting from the mobile app, you'll need to run museum on a local IP
|
||||
> instead localhost. If so, just replace "http://localhost:8080" with (say)
|
||||
> "http://192.168.1.2:8080" wherever mentioned.
|
||||
|
||||
### Payments app
|
||||
|
||||
For this (payments) web app, configure it to connect to the local museum, and
|
||||
use a set of (development) Stripe keys which can be found in [Stripe's developer
|
||||
dashboard](https://dashboard.stripe.com).
|
||||
|
||||
Assuming that your local museum instance is running on `192.168.1.2:8080`, your
|
||||
`.env` should look as follows.
|
||||
Add the following to
|
||||
`web/apps/payments/.env.local`
|
||||
|
||||
```
|
||||
NEXT_PUBLIC_ENTE_ENDPOINT = http://192.168.1.2:8080
|
||||
```env
|
||||
NEXT_PUBLIC_ENTE_ENDPOINT = http://localhost:8080
|
||||
NEXT_PUBLIC_STRIPE_US_PUBLISHABLE_KEY = stripe_publishable_key
|
||||
```
|
||||
|
||||
Then start it locally
|
||||
|
||||
```sh
|
||||
yarn dev:payments
|
||||
```
|
||||
|
||||
### Museum
|
||||
|
||||
1. Install the [stripe-cli](https://docs.stripe.com/stripe-cli) and capture the
|
||||
|
@ -33,18 +60,32 @@ NEXT_PUBLIC_STRIPE_US_PUBLISHABLE_KEY = stripe_publishable_key
|
|||
2. Define this secret within your `musuem.yaml`
|
||||
|
||||
3. Update the `whitelisted-redirect-urls` so that it supports redirecting to
|
||||
this locally running project.
|
||||
the locally running payments app.
|
||||
|
||||
Assuming that your local payments app is running on `192.168.1.2:3001`, your
|
||||
`museum.yaml` should look as follows.
|
||||
Assuming that your local payments app is running on `localhost:3001`, your
|
||||
`server/museum.yaml` should look as follows.
|
||||
|
||||
```yaml
|
||||
stripe:
|
||||
us:
|
||||
key: stripe_dev_key
|
||||
webhook-secret: stripe_dev_webhook_secret
|
||||
whitelisted-redirect-urls: ["http://192.168.1.2:3001/frameRedirect"]
|
||||
whitelisted-redirect-urls: ["http://localhost:3000/gallery", "http://192.168.1.2:3001/frameRedirect"]
|
||||
path:
|
||||
success: ?status=success&session_id={CHECKOUT_SESSION_ID}
|
||||
cancel: ?status=fail&reason=canceled
|
||||
```
|
||||
|
||||
Make sure you have test plans available for museum to use, by placing them in
|
||||
(say) `server/data/billing/us-testing.json`.
|
||||
|
||||
Finally, start museum, for example:
|
||||
|
||||
```
|
||||
docker compose up
|
||||
```
|
||||
|
||||
Now if you try to purchase a plan from your locally running photos web client,
|
||||
it should redirect to the locally running payments app, and from there to
|
||||
Stripe. Once the test purchase completes it should redirect back to the local
|
||||
web client.
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
-------------------------------
|
||||
UBUNTU FONT LICENCE Version 1.0
|
||||
-------------------------------
|
||||
|
||||
PREAMBLE
|
||||
This licence allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely. The fonts, including any derivative works, can be
|
||||
bundled, embedded, and redistributed provided the terms of this licence
|
||||
are met. The fonts and derivatives, however, cannot be released under
|
||||
any other licence. The requirement for fonts to remain under this
|
||||
licence does not require any document created using the fonts or their
|
||||
derivatives to be published under this licence, as long as the primary
|
||||
purpose of the document is not to be a vehicle for the distribution of
|
||||
the fonts.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this licence and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Original Version" refers to the collection of Font Software components
|
||||
as received under this licence.
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to
|
||||
a new environment.
|
||||
|
||||
"Copyright Holder(s)" refers to all individuals and companies who have a
|
||||
copyright ownership of the Font Software.
|
||||
|
||||
"Substantially Changed" refers to Modified Versions which can be easily
|
||||
identified as dissimilar to the Font Software by users of the Font
|
||||
Software comparing the Original Version with the Modified Version.
|
||||
|
||||
To "Propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification and with or without charging
|
||||
a redistribution fee), making available to the public, and in some
|
||||
countries other activities as well.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
This licence does not grant any rights under trademark law and all such
|
||||
rights are reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of the Font Software, to propagate the Font Software, subject to
|
||||
the below conditions:
|
||||
|
||||
1) Each copy of the Font Software must contain the above copyright
|
||||
notice and this licence. These can be included either as stand-alone
|
||||
text files, human-readable headers or in the appropriate machine-
|
||||
readable metadata fields within text or binary files as long as those
|
||||
fields can be easily viewed by the user.
|
||||
|
||||
2) The font name complies with the following:
|
||||
(a) The Original Version must retain its name, unmodified.
|
||||
(b) Modified Versions which are Substantially Changed must be renamed to
|
||||
avoid use of the name of the Original Version or similar names entirely.
|
||||
(c) Modified Versions which are not Substantially Changed must be
|
||||
renamed to both (i) retain the name of the Original Version and (ii) add
|
||||
additional naming elements to distinguish the Modified Version from the
|
||||
Original Version. The name of such Modified Versions must be the name of
|
||||
the Original Version, with "derivative X" where X represents the name of
|
||||
the new work, appended to that name.
|
||||
|
||||
3) The name(s) of the Copyright Holder(s) and any contributor to the
|
||||
Font Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except (i) as required by this licence, (ii) to
|
||||
acknowledge the contribution(s) of the Copyright Holder(s) or (iii) with
|
||||
their explicit written permission.
|
||||
|
||||
4) The Font Software, modified or unmodified, in part or in whole, must
|
||||
be distributed entirely under this licence, and must not be distributed
|
||||
under any other licence. The requirement for fonts to remain under this
|
||||
licence does not affect any document created using the Font Software,
|
||||
except any version of the Font Software extracted from a document
|
||||
created using the Font Software may only be distributed under this
|
||||
licence.
|
||||
|
||||
TERMINATION
|
||||
This licence becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
|
||||
DEALINGS IN THE FONT SOFTWARE.
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,10 +1,10 @@
|
|||
import * as React from "react";
|
||||
import { Spinner } from "react-bootstrap";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export default function EnteSpinner(props: any) {
|
||||
export const EnteSpinner: React.FC = () => {
|
||||
return (
|
||||
<Spinner {...props} animation="border" variant="success" role="status">
|
||||
<Spinner animation="border" variant="success" role="status">
|
||||
<span className="sr-only">Loading...</span>
|
||||
</Spinner>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Container } from "components/Container";
|
||||
import constants from "utils/strings/constants";
|
||||
import constants from "utils/strings";
|
||||
|
||||
export default function Home() {
|
||||
return <Container>{constants.NOT_FOUND}</Container>;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import "bootstrap/dist/css/bootstrap.min.css";
|
||||
import type { AppProps } from "next/app";
|
||||
import Head from "next/head";
|
||||
import constants from "utils/strings/constants";
|
||||
import constants from "utils/strings";
|
||||
import "../styles/globals.css";
|
||||
|
||||
function MyApp({ Component, pageProps }: AppProps) {
|
||||
|
@ -14,4 +14,5 @@ function MyApp({ Component, pageProps }: AppProps) {
|
|||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default MyApp;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Container } from "components/Container";
|
||||
import EnteSpinner from "components/EnteSpinner";
|
||||
import { EnteSpinner } from "components/EnteSpinner";
|
||||
import * as React from "react";
|
||||
|
||||
export default function DesktopRedirect() {
|
||||
|
@ -12,7 +12,7 @@ export default function DesktopRedirect() {
|
|||
|
||||
return (
|
||||
<Container>
|
||||
<EnteSpinner animation="border" />
|
||||
<EnteSpinner />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import { Container } from "components/Container";
|
||||
import EnteSpinner from "components/EnteSpinner";
|
||||
import { EnteSpinner } from "components/EnteSpinner";
|
||||
import * as React from "react";
|
||||
import { parseAndHandleRequest } from "services/billingService";
|
||||
import { CUSTOM_ERROR } from "utils/error";
|
||||
import constants from "utils/strings/constants";
|
||||
import constants from "utils/strings";
|
||||
|
||||
export default function Home() {
|
||||
const [errorMessageView, setErrorMessageView] = React.useState(false);
|
||||
const [loading, setLoading] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
async function main() {
|
||||
try {
|
||||
|
@ -34,7 +35,7 @@ export default function Home() {
|
|||
{errorMessageView ? (
|
||||
<div>{constants.SOMETHING_WENT_WRONG}</div>
|
||||
) : (
|
||||
loading && <EnteSpinner animation="border" />
|
||||
loading && <EnteSpinner />
|
||||
)}
|
||||
</Container>
|
||||
);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import { loadStripe } from "@stripe/stripe-js";
|
||||
import { CUSTOM_ERROR } from "utils/error";
|
||||
import { logError } from "utils/sentry";
|
||||
import { logError } from "utils/log";
|
||||
import HTTPService from "./HTTPService";
|
||||
|
||||
const getStripePublishableKey = (stripeAccount: StripeAccountCountry) => {
|
||||
|
|
|
@ -1,39 +1,16 @@
|
|||
/* ubuntu-regular - latin */
|
||||
@font-face {
|
||||
font-family: "Ubuntu";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src:
|
||||
local(""),
|
||||
url("/fonts/ubuntu-v15-latin-regular.woff2") format("woff2"),
|
||||
/* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url("/fonts/ubuntu-v15-latin-regular.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
}
|
||||
|
||||
/* ubuntu-700 - latin */
|
||||
@font-face {
|
||||
font-family: "Ubuntu";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src:
|
||||
local(""),
|
||||
url("/fonts/ubuntu-v15-latin-700.woff2") format("woff2"),
|
||||
/* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url("/fonts/ubuntu-v15-latin-700.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
}
|
||||
html,
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-family: system-ui, sans-serif;
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #191919 !important;
|
||||
color: #aaa !important;
|
||||
font-family: Ubuntu, Arial, sans-serif !important;
|
||||
}
|
||||
|
||||
:is(h1, h2, h3, h4, h5, h6) {
|
||||
color: #d7d7d7;
|
||||
}
|
||||
|
@ -43,11 +20,3 @@ body {
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.ente-container {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
export function runningInBrowser() {
|
||||
return typeof window !== "undefined";
|
||||
}
|
|
@ -3,4 +3,5 @@ const englishConstants = {
|
|||
SOMETHING_WENT_WRONG: "Oops, something went wrong.",
|
||||
NOT_FOUND: "404 | This page could not be found.",
|
||||
};
|
||||
|
||||
export default englishConstants;
|
|
@ -486,7 +486,9 @@ export default function App(props: EnteAppProps) {
|
|||
<EnteSpinner />
|
||||
</Overlay>
|
||||
)}
|
||||
<Component setLoading={setLoading} {...pageProps} />
|
||||
{isI18nReady && (
|
||||
<Component setLoading={setLoading} {...pageProps} />
|
||||
)}
|
||||
</AppContext.Provider>
|
||||
</ThemeProvider>
|
||||
</CacheProvider>
|
||||
|
|
|
@ -36,10 +36,12 @@ deployments, and the action that triggers them:
|
|||
| [auth.ente.io](https://auth.ente.io) | Production | Push to `deploy/auth` |
|
||||
| [accounts.ente.io](https://accounts.ente.io) | Production | Push to `deploy/accounts` |
|
||||
| [cast.ente.io](https://cast.ente.io) | Production | Push to `deploy/cast` |
|
||||
| [payments.ente.io](https://payments.ente.io) | Production | Push to `deploy/payments` |
|
||||
| [help.ente.io](https://help.ente.io) | Production | Push to `main` + changes in `docs/` |
|
||||
| [accounts.ente.sh](https://accounts.ente.sh) | Preview | Nightly deploy of `main` |
|
||||
| [auth.ente.sh](https://auth.ente.sh) | Preview | Nightly deploy of `main` |
|
||||
| [cast.ente.sh](https://cast.ente.sh) | Preview | Nightly deploy of `main` |
|
||||
| [payments.ente.sh](https://payments.ente.sh) | Preview | Nightly deploy of `main` |
|
||||
| [photos.ente.sh](https://photos.ente.sh) | Preview | Nightly deploy of `main` |
|
||||
| [preview.ente.sh](https://preview.ente.sh) | Preview | Manually triggered |
|
||||
|
||||
|
@ -52,8 +54,8 @@ Apart from this, there are also some other deployments:
|
|||
`albums.ente.io`, it redirects to the `/shared-albums` page (Enhancement:
|
||||
serve it as a separate app with a smaller bundle size).
|
||||
|
||||
- `payments.ente.io` and `family.ente.io` are currently in a separate
|
||||
repositories (Enhancement: bring them in here).
|
||||
- `family.ente.io` is currently in a separate repositories (Enhancement: bring
|
||||
them in here).
|
||||
|
||||
### Preview deployments
|
||||
|
||||
|
|
Loading…
Reference in a new issue