Skip to content

Commit 9e0c56b

Browse files
authored
stripe initial impl (#39)
* stripe initial impl
1 parent 554680a commit 9e0c56b

13 files changed

Lines changed: 262 additions & 14 deletions

File tree

templates/.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ jobs:
1818
yarn
1919
yarn test --watchAll=false
2020
- if: env.AWS_ACCESS_KEY_ID == null
21-
run: |
22-
echo "AWS Credentials not found, This is expected for the first run as the repo is provisioned then secrets are injected at a later step."
23-
exit 1
21+
run: |
22+
echo "AWS Credentials not found, This is expected for the first run as the repo is provisioned then secrets are injected at a later step."
23+
exit 1
2424
build:
2525
needs: unit-test
2626
runs-on: ubuntu-latest

templates/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,21 @@ REACT_APP_CONFIG=staging yarn build
6464
6565
serve -s build
6666
```
67+
68+
<%if eq (index .Params `billingEnabled`) "yes" %>
69+
## Billing example
70+
A subscription and checkout example using [Stripe](https://stripe.com), coupled with the backend repository to provide an end-to-end checkout example for you to customize. We also setup a webhook and an endpoint in the backend to receive webhook when events occur.
71+
72+
### Setup
73+
The following example content has been set up in Stripe:
74+
- 1 product
75+
- 3 prices(subscriptions) [annual, monthly, daily]
76+
- 1 webhook [`charge.failed`, `charge.succeeded`, `customer.created`, `subscription_schedule.created`]
77+
See link for available webhooks: https://stripe.com/docs/api/webhook_endpoints/create?lang=curl#create_webhook_endpoint-enabled_events
78+
79+
this is setup using the script [scripts/stripe-example-setup.sh](scripts/stripe-example-setup.sh)
80+
81+
### Deployment
82+
The deployment requires the publishable key in the build, per environment you will have to provide `stripePublishableKey` in `config/<env>.json` [`production`/`staging`/`development`], then when CI builds it will create a bundle with the Stripe publishable API key
83+
84+
<% end %>

templates/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6-
"@oryd/kratos-client": "^0.5.3-alpha.1",
7-
"@testing-library/jest-dom": "^4.2.4",
6+
<%if eq (index .Params `userAuth`) "yes" %>"@oryd/kratos-client": "^0.5.3-alpha.1",
7+
<% end %><%if eq (index .Params `billingEnabled`) "yes" %>"@stripe/react-stripe-js": "^1.4.0",
8+
"@stripe/stripe-js": "^1.13.2",
9+
<% end %>"@testing-library/jest-dom": "^4.2.4",
810
"@testing-library/react": "^9.3.2",
911
"@testing-library/user-event": "^7.1.2",
1012
"react": "^16.13.1",

templates/src/App.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import Home from './pages/Home'
55
<%if eq (index .Params `userAuth`) "yes" %>
66
import Auth from './pages/Auth'
77
import Logout from './pages/Logout'<% end %>
8-
8+
<%if eq (index .Params `billingEnabled`) "yes" %>
9+
import BillingRoutes from './pages/Billing/routes'
10+
<% end %>
911
import Dashboard from './pages/Dashboard'
1012
import PageNotFound from './pages/PageNotFound'
1113

@@ -57,7 +59,10 @@ function App() {
5759
<Route path="/auth/*">
5860
<AuthRoutes/>
5961
</Route>
60-
<Route path="*">
62+
<%if eq (index .Params `billingEnabled`) "yes" %><Route exact path="/billing/*">
63+
<BillingRoutes />
64+
</Route>
65+
<% end %><Route path="*">
6166
<PageNotFound />
6267
</Route>
6368
</Switch>
@@ -73,7 +78,10 @@ function App() {
7378
<Route path="/dashboard">
7479
<Dashboard />
7580
</Route>
76-
<Route path="*">
81+
<%if eq (index .Params `billingEnabled`) "yes" %><Route exact path="/billing/*">
82+
<BillingRoutes />
83+
</Route>
84+
<% end %><Route path="*">
7785
<PageNotFound />
7886
</Route>
7987
</Switch>

templates/src/components/Navigation.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ function AuthenticatedLinks() {
1414
<li>
1515
<Link to="/auth/profile">User Settings</Link>
1616
</li>
17-
<li>
17+
<%if eq (index .Params `billingEnabled`) "yes" %><li>
18+
<Link to="/billing/products">Billing</Link>
19+
</li>
20+
<% end %><li>
1821
<Link to="/auth/logout">Logout</Link>
1922
</li>
2023
</React.Fragment>
@@ -57,7 +60,10 @@ function NavLinks() {
5760
<li>
5861
<Link to="/dashboard">Dashboard</Link>
5962
</li>
60-
</ul>
63+
<%if eq (index .Params `billingEnabled`) "yes" %><li>
64+
<Link to="/billing/products">Billing</Link>
65+
</li>
66+
<% end %></ul>
6167
}
6268
<% end %>
6369
function Navigation() {
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"appName": "<% .Name %>",
33
"environment": "development",
4-
"backendURL": "http://localhost:8080"
4+
"backendURL": "http://localhost:8080"<%if eq (index .Params `billingEnabled`) "yes" %>,
5+
"stripePublishableKey": "<% index .Params `stagingStripePublicApiKey` %>"<% end %>
56
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"appName": "<% .Name %>",
33
"environment": "production",
4-
"backendURL": "https://<% index .Params `productionBackendSubdomain` %><% index .Params `productionHostRoot` %>"
4+
"backendURL": "https://<% index .Params `productionBackendSubdomain` %><% index .Params `productionHostRoot` %>"<%if eq (index .Params `billingEnabled`) "yes" %>,
5+
"stripePublishableKey": "<% index .Params `productionStripePublicApiKey` %>"<% end %>
56
}

templates/src/config/staging.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"appName": "<% .Name %>",
33
"environment": "staging",
4-
"backendURL": "https://<% index .Params `stagingBackendSubdomain` %><% index .Params `stagingHostRoot` %>"
4+
"backendURL": "https://<% index .Params `stagingBackendSubdomain` %><% index .Params `stagingHostRoot` %>"<%if eq (index .Params `billingEnabled`) "yes" %>,
5+
"stripePublishableKey": "<% index .Params `stagingStripePublicApiKey` %>"<% end %>
56
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import React from 'react'
2+
3+
import Card from '../../components/Card'
4+
5+
function Confirmation() {
6+
const queryString = decodeURIComponent(new URL(window.location).searchParams.toString());
7+
const queryParams = queryString.split("&");
8+
return (
9+
<div className="billing-container content-container">
10+
<Card header="Example Subscription Results">
11+
{ queryParams.map((param) => (<p>{ param }</p>)) }
12+
</Card>
13+
</div>
14+
)
15+
}
16+
17+
export default Confirmation
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
.billing-container .card {
2+
min-width: auto;
3+
max-width: 80%;
4+
}
5+
6+
.products {
7+
text-align: center;
8+
width: 100%;
9+
display: flex;
10+
flex-direction: row;
11+
flex-wrap: wrap;
12+
justify-content: space-around;
13+
}
14+
15+
.productInfo, .billing-container button {
16+
background: #f3f3ff;
17+
border: 1px #ccc solid;
18+
cursor: pointer;
19+
padding: 3%;
20+
}
21+
22+
.productName {
23+
font-weight: bold;
24+
}
25+
26+
.productPrice {
27+
margin-top: 1rem;
28+
}
29+
30+
.productInfo {
31+
min-width: 150px;
32+
max-width: 250px;
33+
margin: 1%;
34+
}
35+
36+
.productInfo div:not(:last-child) {
37+
padding-bottom: 0.7rem;
38+
margin-bottom: 0.7rem;
39+
border-bottom: 1px solid grey;
40+
}
41+
42+
.billing-container button{
43+
font-weight: bold;
44+
padding: 20px;
45+
width: 25%;
46+
margin: 30px auto 0;
47+
}

0 commit comments

Comments
 (0)