Skip to content

Commit 5f551b1

Browse files
authored
Stripe initial impl (#27)
* stripe iniitial implementation
1 parent 0d82d18 commit 5f551b1

17 files changed

Lines changed: 306 additions & 55 deletions

File tree

Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ PROJECT_NAME := ${PROJECT_NAME}
1111

1212
.EXPORT_ALL_VARIABLES:
1313

14-
run: ci_setup
14+
run: ci_setup billing_setup
1515
@echo "\nDone"
1616

1717
ci_setup:
@@ -23,6 +23,11 @@ ifeq ($(CIVendor), circleci)
2323
ci_setup: circle_ci_setup
2424
endif
2525

26+
billing_setup:
27+
ifeq ($(billingEnabled), yes)
28+
sh scripts/setup-stripe-secrets.sh
29+
endif
30+
2631
circle_ci_setup:
2732
@echo "Set CIRCLECI environment variables\n"
2833
export AWS_ACCESS_KEY_ID=$(shell aws secretsmanager get-secret-value --region ${region} --secret-id=${PROJECT_NAME}-ci-user-aws-keys${randomSeed} | jq -r '.SecretString'| jq -r .access_key_id)

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ This repository is language/business-logic agnostic; mainly showcasing some univ
2121
|-- Makefile #make command triggers the initialization of repository
2222
|-- zero-module.yml #module declares required parameters and credentials
2323
| # files in templates become the repo for users
24+
| scripts/
25+
| | # these are scripts called only once during zero apply, and we don't
26+
| | # expect a need to rerun them throughout development of the repository
27+
| | # used for checking binary requires / setting up CI / secrets
28+
| | |-- check.sh
29+
| | |-- gha-setup.sh
30+
| | |-- required-bins.sh
31+
| | |-- setup-stripe-secrets.sh
2432
| templates/
2533
| | # this makefile is used both during init and
2634
| | # on-going needs/utilities for user to maintain their infrastructure

scripts/setup-stripe-secrets.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/bash
2+
3+
# This script runs only when billingEnabled = "yes", invoked from makefile
4+
# modify the kubernetes application secret and appends STRIPE_API_SECRET_KEY
5+
# the deployment by default will pick up all key-value pairs as env-vars from the secret
6+
7+
if [[ "$ENVIRONMENT" == "" ]]; then
8+
echo "Must specify \$ENVIRONMENT to create stripe secret ">&2; exit 1;
9+
elif [[ "$ENVIRONMENT" == "stage" ]]; then
10+
PUBLISHABLE_API_KEY=$stagingStripePublicApiKey
11+
SECRET_API_KEY=$stagingStripeSecretApiKey
12+
elif [[ "$ENVIRONMENT" == "prod" ]]; then
13+
PUBLISHABLE_API_KEY=$productionStripePublicApiKey
14+
SECRET_API_KEY=$productionStripeSecretApiKey
15+
fi
16+
17+
CLUSTER_NAME=${PROJECT_NAME}-${ENVIRONMENT}-${REGION}
18+
NAMESPACE=${PROJECT_NAME}
19+
20+
BASE64_TOKEN=$(printf ${SECRET_API_KEY} | base64)
21+
## Modify existing application secret to have stripe api key
22+
kubectl --context $CLUSTER_NAME -n $NAMESPACE get secret ${PROJECT_NAME} -o json | \
23+
jq --arg STRIPE_API_SECRET_KEY $BASE64_TOKEN '.data["STRIPE_API_SECRET_KEY"]=$STRIPE_API_SECRET_KEY' \
24+
| kubectl apply -f -
25+
26+
sh ${PROJECT_DIR}/scripts/stripe-example-setup.sh

templates/.env.example

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
DATABASE_ENGINE=
1+
DATABASE_ENGINE=<% index .Params `database` %>
22
DATABASE_HOST=
3-
DATABASE_PORT=
3+
DATABASE_PORT=<%if eq (index .Params `database`) "postgres" %>5432<% else if eq (index .Params `database`) "mysql" %>3306<% end %>
44
DATABASE_PASSWORD=
55
DATABASE_USERNAME=
66
DATABASE_NAME=

templates/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,26 @@ ALTER TABLE address
113113
ADD COLUMN city VARCHAR(30) AFTER street_name,
114114
ADD COLUMN province VARCHAR(30) AFTER city
115115
```
116+
<%if eq (index .Params `billingEnabled`) "yes" %>
117+
## Billing example
118+
A subscription and checkout example using [Stripe](https://stripe.com), coupled with the frontend 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.
116119

120+
### Setup
121+
The following example content has been set up in Stripe:
122+
- 1 product
123+
- 3 prices(subscriptions) [annual, monthly, daily]
124+
- 1 webhook [`charge.failed`, `charge.succeeded`, `customer.created`, `subscription_schedule.created`]
125+
See link for available webhooks: https://stripe.com/docs/api/webhook_endpoints/create?lang=curl#create_webhook_endpoint-enabled_events
126+
127+
this is setup using the script [scripts/stripe-example-setup.sh](scripts/stripe-example-setup.sh)
128+
129+
### Deployment
130+
The deployment only requires the environment variables:
131+
- STRIPE_API_SECRET_KEY (created in AWS secret then deployed via Kubernetes Secret)
132+
- FRONTEND_URL (used for sending user back to frontend upon checkouts)
133+
- BACKEND_URL (used for redirects after checkout and webhooks)
134+
135+
<% end %>
117136
<!-- Links -->
118137
[base-cronjob]: ./kubernetes/base/cronjob.yml
119138
[base-deployment]: ./kubernetes/base/deployment.yml

templates/kubernetes/base/deployment.yml

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,17 @@ spec:
4040
envFrom:
4141
- configMapRef:
4242
name: <% .Name %>-config
43+
- secretRef:
44+
name: <% .Name %>
4345
env:
4446
- name: SERVER_PORT
4547
value: "80"
4648
- name: POD_NAME
4749
valueFrom:
4850
fieldRef:
4951
fieldPath: metadata.name
50-
<% if eq (index .Params `fileUploads`) "yes" %> - name: CF_KEYPAIR_ID
52+
<%- if eq (index .Params `fileUploads`) "yes" %>
53+
- name: CF_KEYPAIR_ID
5154
valueFrom:
5255
secretKeyRef:
5356
name: cf-keypair
@@ -57,16 +60,7 @@ spec:
5760
secretKeyRef:
5861
name: cf-keypair
5962
key: private_key
60-
<% end %> - name: DATABASE_USERNAME
61-
valueFrom:
62-
secretKeyRef:
63-
name: <% .Name %>
64-
key: DATABASE_USERNAME
65-
- name: DATABASE_PASSWORD
66-
valueFrom:
67-
secretKeyRef:
68-
name: <% .Name %>
69-
key: DATABASE_PASSWORD
63+
<%- end %>
7064
---
7165
apiVersion: autoscaling/v1
7266
kind: HorizontalPodAutoscaler

templates/kubernetes/overlays/production/auth.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ metadata:
77
name: public-backend-endpoints
88
spec:
99
match:
10-
url: http://<% index .Params `productionBackendSubdomain` %><% index .Params `productionHostRoot` %>/status/<.*>
10+
url: http://<% index .Params `productionBackendSubdomain` %><% index .Params `productionHostRoot` %>/<(status|webhook)\/.*>
1111
---
1212
## Backend User-restricted endpoint
1313
# pattern: http://<proxy>/<not [/.ory/kratos and /status]>
@@ -21,5 +21,5 @@ metadata:
2121
name: authenticated-backend-endpoints
2222
spec:
2323
match:
24-
url: http://<% index .Params `productionBackendSubdomain` %><% index .Params `productionHostRoot` %>/<(?!(status|\.ory\/kratos)).*>
24+
url: http://<% index .Params `productionBackendSubdomain` %><% index .Params `productionHostRoot` %>/<(?!(status|webhook|\.ory\/kratos)).*>
2525

templates/kubernetes/overlays/production/kustomization.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,6 @@ configMapGenerator:
1818
literals:
1919
- ENVIRONMENT=production
2020
- DOMAIN=<% index .Params `productionHostRoot` %>
21+
- BACKEND_URL=https://<% index .Params `productionBackendSubdomain` %><% index .Params `productionHostRoot` %>
22+
- FRONTEND_URL=https://<% index .Params `productionFrontendSubdomain` %><% index .Params `productionHostRoot` %>
2123
- S3_BUCKET=files.<% index .Params `productionHostRoot` %>

templates/kubernetes/overlays/staging/auth.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ metadata:
77
name: public-backend-endpoints
88
spec:
99
match:
10-
url: http://<% index .Params `stagingBackendSubdomain` %><% index .Params `stagingHostRoot` %>/status/<.*>
10+
url: http://<% index .Params `stagingBackendSubdomain` %><% index .Params `stagingHostRoot` %>/<(status|webhook)\/.*>
1111
---
1212
## Backend User-restricted endpoint
1313
# pattern: http://<proxy>//api
@@ -21,4 +21,4 @@ metadata:
2121
name: authenticated-backend-endpoints
2222
spec:
2323
match:
24-
url: http://<% index .Params `stagingBackendSubdomain` %><% index .Params `stagingHostRoot` %>/<(?!(status|\.ory\/kratos)).*>
24+
url: http://<% index .Params `stagingBackendSubdomain` %><% index .Params `stagingHostRoot` %>/<(?!(status|webhook|\.ory\/kratos)).*>

templates/kubernetes/overlays/staging/kustomization.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,6 @@ configMapGenerator:
1717
literals:
1818
- ENVIRONMENT=staging
1919
- DOMAIN=<% index .Params `stagingHostRoot` %>
20+
- BACKEND_URL=https://<% index .Params `stagingBackendSubdomain` %><% index .Params `stagingHostRoot` %>
21+
- FRONTEND_URL=https://<% index .Params `stagingFrontendSubdomain` %><% index .Params `stagingHostRoot` %>
2022
- S3_BUCKET=files.<% index .Params `stagingHostRoot` %>

0 commit comments

Comments
 (0)