diff --git a/README.md b/README.md index 511d45b..7fcfd28 100644 --- a/README.md +++ b/README.md @@ -1,72 +1,22 @@ -# Payment service +## payment-service +- **Purpose:** Stripe integration (Checkout Session + webhooks). +- **Base path:** `/api/payments` -## Create payment database + user on mysql server +### Create product database ``` kubectl -n cloudshopt exec -it cloudshopt-mysql-0 -- bash -mysql -u root -prootpass -``` +# mysql -u root -prootpass -``` CREATE DATABASE cloudshopt_payments CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -CREATE USER 'users'@'%' IDENTIFIED BY 'userspass'; +CREATE USER 'users'@'%' IDENTIFIED BY 'CHANGE_ME_PASSWORD'; GRANT ALL PRIVILEGES ON cloudshopt_payments.* TO 'users'@'%'; FLUSH PRIVILEGES; ``` -Ustvari še bazo za *dev* okolje -``` -CREATE DATABASE cloudshopt_payments_dev CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -CREATE USER 'users_dev'@'%' IDENTIFIED BY 'userspass'; -GRANT ALL PRIVILEGES ON cloudshopt_payments_dev.* TO 'users_dev'@'%'; -FLUSH PRIVILEGES; -``` - -## Crete external secrets for prod and dev -prod: -``` -kubectl -n cloudshopt create secret generic payment-service-secrets \ - --from-literal=DB_PASSWORD="userspass" \ - --from-literal=REDIS_PASSWORD="redispass" \ - --dry-run=client -o yaml | kubectl apply -f - -``` - -dev: -``` -kubectl -n cloudshopt-dev create secret generic payment-service-secrets \ - --from-literal=DB_PASSWORD="userspass" \ - --from-literal=REDIS_PASSWORD="redispass" \ - --dry-run=client -o yaml | kubectl apply -f - -``` - -check for secrets: -``` -kubectl get secret -n cloudshopt payment-service-secrets -kubectl get secret -n cloudshopt-dev payment-service-secrets -``` - -## Install payment-service for prod and dev -prod: -``` -helm upgrade --install payment-service ./helm/payment-service \ --n cloudshopt \ --f helm/payment-service/values.yaml -``` - -dev: -``` -helm upgrade --install payment-service-dev ./helm/payment-service \ --n cloudshopt-dev \ --f helm/payment-service/values-dev.yaml -``` - +### Migrations - -## Migrations - -run migrations: ``` -kubectl exec -n cloudshopt-dev -it deploy/payment-service-dev -c app -- sh - +kubectl exec -n cloudshopt -it deploy/payment-service -c app -- sh # php artisan migrate ``` diff --git a/docs/openapi.yaml b/docs/openapi.yaml new file mode 100644 index 0000000..82e6042 --- /dev/null +++ b/docs/openapi.yaml @@ -0,0 +1,207 @@ +openapi: 3.0.3 +info: + title: CloudShopt Payment Service API + version: 1.0.0 +tags: + - name: Health + - name: Diagnostics + - name: Checkout + - name: Webhooks + +paths: + /healthz: + get: + tags: [Health] + summary: Health check + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/StatusOkBool" + + /info: + get: + tags: [Diagnostics] + summary: Service info (sha, time) + responses: + "200": + description: Info + content: + application/json: + schema: + $ref: "#/components/schemas/InfoResponse" + + /database: + get: + tags: [Diagnostics] + summary: Database connectivity check (optional) + responses: + "200": + description: DB OK (or not used) + content: + application/json: + schema: + $ref: "#/components/schemas/DatabaseOkResponse" + "500": + description: DB connection failed + content: + application/json: + schema: + $ref: "#/components/schemas/DatabaseFailResponse" + + /checkout-session: + post: + tags: [Checkout] + summary: Create Stripe Checkout Session (JWT) + description: Returns Stripe hosted checkout URL. Amount is derived from order total (cents). + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateCheckoutSessionRequest" + responses: + "200": + description: Session created + content: + application/json: + schema: + $ref: "#/components/schemas/CreateCheckoutSessionResponse" + "401": + $ref: "#/components/responses/Unauthorized" + "404": + $ref: "#/components/responses/NotFound" + "422": + $ref: "#/components/responses/ValidationError" + + /webhooks/stripe: + post: + tags: [Webhooks] + summary: Stripe webhook receiver + description: Stripe calls this endpoint. Signature is verified using STRIPE_WEBHOOK_SECRET. + requestBody: + required: true + content: + application/json: + schema: + type: object + responses: + "200": + description: Received + content: + application/json: + schema: + $ref: "#/components/schemas/WebhookReceived" + "400": + description: Invalid signature / bad request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorMessage" + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + + responses: + Unauthorized: + description: Unauthorized + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorMessage" + + NotFound: + description: Not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorMessage" + + ValidationError: + description: Validation error + content: + application/json: + schema: + $ref: "#/components/schemas/ValidationError" + + schemas: + ErrorMessage: + type: object + required: [message] + properties: + message: { type: string } + + ValidationError: + type: object + required: [message, errors] + properties: + message: { type: string } + errors: + type: object + additionalProperties: + type: array + items: { type: string } + + StatusOkBool: + type: object + required: [ok] + properties: + ok: { type: boolean, example: true } + + InfoResponse: + type: object + required: [ok, service, sha, time] + properties: + ok: { type: boolean, example: true } + service: { type: string, example: payment-service } + sha: { type: string, nullable: true, example: 0.0.1 } + time: { type: string, format: date-time, example: "2026-01-29T10:15:30.123Z" } + + DatabaseOkResponse: + type: object + required: [ok, db, time] + properties: + ok: { type: boolean, example: true } + db: + type: object + required: [connection, database, ping_ms] + properties: + connection: { type: string, example: mysql } + database: { type: string, example: cloudshopt_payments_dev } + ping_ms: { type: number, format: float, example: 1.25 } + time: { type: string, format: date-time, example: "2026-01-29T10:15:30.123Z" } + + DatabaseFailResponse: + type: object + required: [ok, error, message] + properties: + ok: { type: boolean, example: false } + error: { type: string, example: DB connection failed } + message: { type: string, nullable: true, example: "SQLSTATE[HY000] ..." } + + CreateCheckoutSessionRequest: + type: object + required: [order_id] + properties: + order_id: { type: integer, minimum: 1, example: 10 } + + CreateCheckoutSessionResponse: + type: object + required: [url, session_id] + properties: + url: { type: string, example: https://checkout.stripe.com/c/pay/cs_test_... } + session_id: { type: string, example: cs_test_a11lqwy13iFvK69o... } + + WebhookReceived: + type: object + required: [received] + properties: + received: { type: boolean, example: true } \ No newline at end of file diff --git a/resources/views/swagger.blade.php b/resources/views/swagger.blade.php new file mode 100644 index 0000000..59b1e6d --- /dev/null +++ b/resources/views/swagger.blade.php @@ -0,0 +1,22 @@ + + +
+ + +