Skip to content
This repository has been archived by the owner on Jul 8, 2024. It is now read-only.

payment: add service to dev #12

Merged
merged 13 commits into from
Aug 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .github/workflows/payment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Payment Microservice CI/CD

on:
push:
branches: [ payment ]
pull_request:
branches: [ dev, main ]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: pnpm/action-setup@v2
with:
version: latest
- uses: actions/setup-node@v3
with:
node-version: "18.x"
cache: "pnpm"
cache-dependency-path: services/payment/pnpm-lock.yaml
- name: Install dependencies
run: |
cd ./services/payment
pnpm install --frozen-lockfile
- name: Build
run: |
cd ./services/payment
pnpm build

test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: pnpm/action-setup@v2
with:
version: latest
- uses: actions/setup-node@v3
with:
node-version: "18.x"
cache: "pnpm"
cache-dependency-path: services/payment/pnpm-lock.yaml
- name: Install dependencies
run: |
cd ./services/payment
pnpm install --frozen-lockfile
- name: Execute tests
run: |
cd ./services/payment
pnpm test

publish:
runs-on: ubuntu-latest
needs: [ build, test ]
steps:
- name: Checkout code
uses: actions/checkout@master
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: ./services/
file: ./services/payment/Dockerfile
push: true
tags: floriaaan/goodfood-payment:latest
2 changes: 2 additions & 0 deletions services/payment/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
build
10 changes: 10 additions & 0 deletions services/payment/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
DATABASE_URL=postgres://postgres:password@localhost:5432/postgres
AMQP_URL=amqp://guest:guest@localhost

PORT=50003

STRIPE_API_KEY=
STRIPE_API_SECRET=
STRIPE_WEBHOOK_ENDPOINT="/webhook"
STRIPE_WEBHOOK_SECRET=
STRIPE_WEBHOOK_PORT=4242
5 changes: 5 additions & 0 deletions services/payment/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/
dist/
bin/
*.env*
!*.env.example
1 change: 1 addition & 0 deletions services/payment/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v18.12.0
41 changes: 41 additions & 0 deletions services/payment/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
FROM node:18-alpine3.17 as builder

# Set working directory
WORKDIR /app

# Copy the application code
COPY ./payment/ .

# Install dependencies
RUN npm install

# Copy the proto files
COPY ./proto ./proto/

# Generate Prisma client
RUN npx prisma generate

# Build the application
RUN npm run build


# Create a new image with the application
FROM node:18-alpine3.17 as runner

# Set working directory
WORKDIR /app

# Copy the application package
COPY --from=builder /app/dist .
COPY --from=builder /app/prisma/ .
COPY --from=builder /app/proto/ /proto/
COPY --from=builder /app/node_modules/.prisma /.prisma

# Expose the gRPC port
EXPOSE 50003

# Expose the Webhook port
EXPOSE 4242

# Start the server
CMD [ "node", "index.js"]
69 changes: 69 additions & 0 deletions services/payment/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Payment Microservice

| Informations |
| -------------------------------------------------- |
| **Port:** 50003 |
| **Developer:** @Anatole-Godard & @floriaaan |
| **Status:** In progress |
| **Last update:** 2023-08-04 |
| **Language:** NodeJS |
| **Dependencies:** TypeScript, gRPC, Postgres, AMQP |

## gRPC Methods

- `GetPayment(GetPaymentRequest) returns (Payment) {}`
This RPC function is part of the PaymentService service. It is used to retrieve information about a single payment. The client sends a request GetPaymentRequest containing the necessary information (e.g., payment ID), and the server responds with a Payment message containing the details of the requested payment.
- `GetPaymentsByUser(GetPaymentsByUserRequest) returns (GetPaymentsByUserResponse) {}`
Also part of the PaymentService service, this RPC function allows the client to get a list of payments associated with a specific user. The client sends a GetPaymentsByUserRequest, typically containing the user's ID, and the server responds with a GetPaymentsByUserResponse message containing a list of payments relevant to that user.
- `CreateCheckoutSession(CreateCheckoutSessionRequest) returns (CreateCheckoutSessionResponse) {}`
This RPC function belongs to the StripeService service. It is utilized to create a checkout session for Stripe, which typically involves setting up a payment gateway or initiating a payment process for a user. The client sends a CreateCheckoutSessionRequest with relevant information required for the session, and the server responds with a CreateCheckoutSessionResponse, which may contain details or identifiers related to the created session.

## Requirements

To run this microservice, you will need to have the following installed on your system:

- NodeJS (v18.12.0 or higher) (dev. with v18.12.0)
- Postgres (v15.2 or higher) (dev. with docker image `postgres:15.2`)

You can use the following tools to help you with the setup:

- You can use nvm to set your Node version using:
- `nvm use`.
- You can use docker to run your Postgres database using:
- `docker run --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=password -d postgres`
- You can use docker to run your RabbitMQ server using:
- `docker run --name rabbitmq -p 5672:5672 -p 15672:15672 -d rabbitmq:3-management`

## Getting started

### 1. Clone the repository and install dependencies

1. Clone the `goodfood` repository to your local machine.
2. Navigate to the service directory (`services/payment`) in your terminal.
3. Run `npm install` to install the necessary dependencies.
4. Create a `.env` file at the root of the project directory and add the environment variables values (see `.env.example`).
5. Run `npm run start` to start the microservice.

You can now access the microservice at `http://localhost:50003`.

NB: If you want to run the microservice in development mode, you can run `npm run dev` instead.

## Testing

How to test the microservice:

Pre-requisites:

- You need to have a Postgres database running on your machine, the migrations need to be applied.
- You need to have an internet connection.

1. Run the microservice (see [Getting started](#getting-started)).
2. Use a gRPC client (e.g. [Postman](https://www.postman.com/)) to send requests to the microservice (see [gRPC Methods](#grpc-methods)).
- Send a request to the `CreateCheckoutSession` method to create a payment.
It should return a `CreateCheckoutSessionResponse` with the created payment, and an URL by Stripe to pay the order.
The payment should be created in the database.
When the payment is paid, the order should be updated in the database using the webhook, it should also be updated in the database when the checkout has expired.
- Send a request to the `GetPayment` method to get a payment.
It should return a `GetPaymentResponse` with the payment.
- Send a request to the `GetPaymentsByUser` method to get all payments.
It should return a `GetPaymentsByUserResponse` with all payments.
15 changes: 15 additions & 0 deletions services/payment/generate_grpc_reflection.sh
floriaaan marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash

# bash list of proto files ([payment.proto])


IN_DIR="$(pwd)/../proto"
OUT_DIR="."
PROTOC="$(npm bin)/grpc_tools_node_protoc"

# Generate reflection descriptor
$PROTOC \
-I $IN_DIR \
$IN_DIR/payment.proto \
--descriptor_set_out=$OUT_DIR/reflection_descriptor.bin \

8 changes: 8 additions & 0 deletions services/payment/k8s/configmap.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: goodfood-payment-configmap
labels:
app: goodfood-payment
data:
port: "50003"
34 changes: 34 additions & 0 deletions services/payment/k8s/deployment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: goodfood-payment
labels:
app: goodfood-payment
spec:
selector:
matchLabels:
app: goodfood-payment
template:
metadata:
labels:
app: goodfood-payment
spec:
containers:
- name: goodfood-payment
image: floriaaan/goodfood-payment:1.0.0
imagePullPolicy: Always
resources:
limits:
memory: "128Mi"
cpu: "200m"
env:
- name: PORT
valueFrom:
configMapKeyRef:
name: goodfood-payment-configmap
key: port
ports:
- containerPort: 50003
name: grpc
- containerPort: 4242
name: webhook
18 changes: 18 additions & 0 deletions services/payment/k8s/hpa.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: goodfood-payment-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: goodfood-payment
minReplicas: 1
maxReplicas: 3
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
17 changes: 17 additions & 0 deletions services/payment/k8s/ingress.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: goodfood-payment
spec:
ingressClassName: nginx
rules:
- host: payment.localdev.me
http:
paths:
- pathType: Prefix
backend:
service:
name: goodfood-payment
port:
number: 50003
path: /
16 changes: 16 additions & 0 deletions services/payment/k8s/service.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: goodfood-payment
spec:
selector:
app: goodfood-payment
ports:
- name: "grpc"
port: 50003
targetPort: 50003
- name: "webook"
port: 4242
targetPort: 4242
status:
loadBalancer: {}
58 changes: 58 additions & 0 deletions services/payment/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"name": "@goodfood/payment",
"bin": "dist/index.js",
"scripts": {
"start": "node dist/index.js",
"dev": "nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/server.ts",
"build": "esbuild src/server.ts --bundle --platform=node --target=node18 --outfile=dist/index.js",
"test": "vitest",
"coverage": "vitest --coverage",
"pkg": "pkg .",
"prisma:generate": "prisma generate",
"seed": "ts-node prisma/seed.ts",
"grpc:reflection": "./generate_grpc_reflection.sh",
"postinstall": "npm run prisma:generate"
},
"dependencies": {
"@grpc/grpc-js": "1.8.14",
"@grpc/proto-loader": "0.7.6",
"@prisma/client": "5.1.1",
"amqplib": "^0.10.3",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"grpc-server-reflection": "^0.1.5",
"protobufjs": "7.2.2",
"stripe": "^12.17.0"
},
"devDependencies": {
"@types/amqplib": "^0.10.1",
"@types/express": "^4.17.17",
"@types/node": "18.15.9",
"esbuild": "^0.17.18",
"grpc-tools": "^1.12.4",
"nodemon": "^2.0.22",
"pkg": "^5.8.1",
"prisma": "5.1.1",
"ts-node": "10.9.1",
"tsconfig-paths": "^4.2.0",
"typescript": "5.0.2",
"vite-tsconfig-paths": "^4.2.0",
"vitest": "^0.29.8"
},
"prisma": {
"seed": "ts-node prisma/seed.ts"
},
"pkg": {
"scripts": "./src/dist/index.js",
"assets": [
"./prisma/**/*",
"../proto/**/*"
],
"targets": [
"node18-macos-arm64",
"node18-linux-x64",
"node18-linux-arm64"
],
"outputPath": "bin/"
}
}
Loading
Loading