Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

9 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Payment Remaster

ๆœ€ๅฐไปฃๆ”ถไบคๆ˜“ๆตๅฏฆไฝœ - ไฝฟ็”จ Cloudflare Workersใ€PostgreSQL ๅ’Œ AWS SQS ๅปบๆง‹็š„ไบ‹ไปถ้ฉ…ๅ‹•ๆ”ฏไป˜็ณป็ตฑใ€‚

ๅฐˆๆกˆๆฆ‚่ฟฐ

ๆœฌๅฐˆๆกˆๅฏฆไฝœไธ€ๅ€‹ๆœ€ๅฐๅฏ้‹ไฝœ็š„ไปฃๆ”ถไบคๆ˜“ๆต็จ‹๏ผŒๅŒ…ๅซ๏ผš

  • ๅ•†ๆˆถ้€้Ž API ็™ผ่ตทไปฃๆ”ถไบคๆ˜“่ซ‹ๆฑ‚
  • ็ณป็ตฑๅฐ‡ไบคๆ˜“่ฝ‰็™ผ่‡ณไธŠๆธธ่™•็†
  • ๆŽฅๆ”ถไธŠๆธธๅ›ž่ชฟไธฆๆ›ดๆ–ฐ่จ‚ๅ–ฎ็‹€ๆ…‹
  • ้€้Ž Webhook ้€š็Ÿฅๅ•†ๆˆถไบคๆ˜“็ตๆžœ
  • ๅคฑๆ•—้€š็Ÿฅ้€ฒๅ…ฅๆญปไฟกไฝ‡ๅˆ—ไพ›ไบบๅทฅ่™•็†

ๆžถๆง‹ๅœ–

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                            Payment Remaster                                  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                              โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                   โ”‚
โ”‚  โ”‚ Merchant โ”‚โ”€โ”€โ”€โ–ถโ”‚ order-ingress โ”‚โ”€โ”€โ”€โ–ถโ”‚   PostgreSQL    โ”‚                   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                   โ”‚
โ”‚                          โ”‚                     โ–ฒ                             โ”‚
โ”‚                          โ–ผ                     โ”‚                             โ”‚
โ”‚                  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”             โ”‚                             โ”‚
โ”‚                  โ”‚    AWS SQS    โ”‚             โ”‚                             โ”‚
โ”‚                  โ”‚ OrderCreated  โ”‚             โ”‚                             โ”‚
โ”‚                  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜             โ”‚                             โ”‚
โ”‚                          โ”‚                     โ”‚                             โ”‚
โ”‚                          โ–ผ                     โ”‚                             โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚                      Lambda Bridge                                    โ”‚   โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”              โ”‚   โ”‚
โ”‚  โ”‚  โ”‚ gateway-router-     โ”‚    โ”‚ webhook-notifier-       โ”‚              โ”‚   โ”‚
โ”‚  โ”‚  โ”‚ trigger             โ”‚    โ”‚ trigger                 โ”‚              โ”‚   โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜              โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                โ”‚                           โ”‚                                 โ”‚
โ”‚                โ–ผ                           โ–ผ                                 โ”‚
โ”‚       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”           โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                   โ”‚
โ”‚       โ”‚gateway-router โ”‚           โ”‚merchant-webhook-    โ”‚                   โ”‚
โ”‚       โ”‚   Worker      โ”‚           โ”‚notifier Worker      โ”‚โ”€โ”€โ–ถ Merchant       โ”‚
โ”‚       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜           โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    Webhook        โ”‚
โ”‚               โ”‚                                                              โ”‚
โ”‚               โ–ผ                                                              โ”‚
โ”‚       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                            โ”‚
โ”‚       โ”‚mock-provider  โ”‚โ”€โ”€โ”€โ–ถโ”‚upstream-callback  โ”‚                            โ”‚
โ”‚       โ”‚   Worker      โ”‚    โ”‚   Worker          โ”‚                            โ”‚
โ”‚       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                            โ”‚
โ”‚                                                                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

ๆŠ€่ก“ๆฃง

ๅฑค็ดš ๆŠ€่ก“
Runtime Cloudflare Workers (Edge)
Language TypeScript 5.x
HTTP Framework Hono
Database PostgreSQL (via Hyperdrive)
Message Queue AWS SQS (Free Tier)
Lambda Bridge AWS SAM / Lambda
Testing Vitest
Package Manager pnpm (Monorepo)

ๅฐˆๆกˆ็ตๆง‹

payment-remaster/
โ”œโ”€โ”€ workers/                    # Cloudflare Workers
โ”‚   โ”œโ”€โ”€ order-ingress/         # HTTP: ๆŽฅๆ”ถๅ•†ๆˆถไธ‹ๅ–ฎ
โ”‚   โ”œโ”€โ”€ gateway-router/        # SQS Consumer: ๅ‘ผๅซไธŠๆธธ
โ”‚   โ”œโ”€โ”€ upstream-callback/     # HTTP: ๆŽฅๆ”ถไธŠๆธธๅ›ž่ชฟ
โ”‚   โ”œโ”€โ”€ merchant-webhook-notifier/  # SQS Consumer: ้€š็Ÿฅๅ•†ๆˆถ
โ”‚   โ””โ”€โ”€ mock-provider/         # HTTP: ๆจกๆ“ฌไธŠๆธธๆœๅ‹™
โ”œโ”€โ”€ shared/                     # ๅ…ฑ็”จๆจก็ต„
โ”‚   โ””โ”€โ”€ src/
โ”‚       โ”œโ”€โ”€ db/                # ่ณ‡ๆ–™ๅบซ้€ฃ็ทš่ˆ‡ Repository
โ”‚       โ”œโ”€โ”€ sqs/               # SQS ๅฎขๆˆถ็ซฏ่ˆ‡ๆถˆ่ฒป่€…
โ”‚       โ”œโ”€โ”€ events/            # ไบ‹ไปถๅฎš็พฉ
โ”‚       โ”œโ”€โ”€ domain/            # ้ ˜ๅŸŸ้‚่ผฏ
โ”‚       โ”œโ”€โ”€ http/              # HTTP ๅทฅๅ…ท
โ”‚       โ””โ”€โ”€ observability/     # ็›ฃๆŽงๆŒ‡ๆจ™
โ”œโ”€โ”€ lambda-bridge/              # AWS Lambda ๆฉ‹ๆŽฅ
โ”‚   โ”œโ”€โ”€ src/
โ”‚   โ”‚   โ”œโ”€โ”€ gateway-router-trigger.ts
โ”‚   โ”‚   โ””โ”€โ”€ webhook-notifier-trigger.ts
โ”‚   โ””โ”€โ”€ template.yaml          # SAM ๆจกๆฟ
โ”œโ”€โ”€ tests/                      # ๆธฌ่ฉฆ
โ”‚   โ”œโ”€โ”€ unit/
โ”‚   โ”œโ”€โ”€ integration/
โ”‚   โ””โ”€โ”€ contract/
โ”œโ”€โ”€ specs/                      # ่ฆๆ ผๆ–‡ไปถ
โ”‚   โ””โ”€โ”€ 001-minimal-payment-flow/
โ”œโ”€โ”€ scripts/                    # ้ƒจ็ฝฒ่…ณๆœฌ
โ”‚   โ”œโ”€โ”€ deploy-workers.sh
โ”‚   โ”œโ”€โ”€ deploy-lambda.sh
โ”‚   โ””โ”€โ”€ e2e.sh
โ””โ”€โ”€ docker-compose.yml          # ๆœฌๆฉŸ้–‹็™ผ็’ฐๅขƒ

ๅฟซ้€Ÿๅ•Ÿๅ‹•

ๅ‰็ฝฎ้œ€ๆฑ‚

  • Node.js 18+
  • pnpm 8+
  • Docker & Docker Compose
  • AWS CLI (็”จๆ–ผ Lambda ้ƒจ็ฝฒ)
  • Wrangler CLI (็”จๆ–ผ Workers ้ƒจ็ฝฒ)

ๆญฅ้ฉŸ 1: ๅ•Ÿๅ‹•ๆœฌๆฉŸๆœๅ‹™

# ๅ•Ÿๅ‹• PostgreSQL ๅ’Œ LocalStack (SQS)
docker-compose up -d

# ็ขบ่ชๆœๅ‹™็‹€ๆ…‹
docker-compose ps

ๆญฅ้ฉŸ 2: ๅฎ‰่ฃไพ่ณด

pnpm install

ๆญฅ้ฉŸ 3: ๅŸท่กŒ่ณ‡ๆ–™ๅบซ้ท็งป

# ้€ฃ็ทšๅˆฐ PostgreSQL ๅŸท่กŒ้ท็งป
docker exec -i payment-postgres psql -U postgres -d payment < shared/src/db/migrations/001_initial_schema.sql

ๆญฅ้ฉŸ 4: ๅ•Ÿๅ‹• Workers (้–‹็™ผๆจกๅผ)

# ้–‹ๅ•Ÿๅคšๅ€‹็ต‚็ซฏๆฉŸ๏ผŒๅˆ†ๅˆฅๅ•Ÿๅ‹•ๅ„ Worker
pnpm --filter order-ingress dev
pnpm --filter gateway-router dev
pnpm --filter upstream-callback dev
pnpm --filter merchant-webhook-notifier dev
pnpm --filter mock-provider dev

ๆญฅ้ฉŸ 5: ๅŸท่กŒๆธฌ่ฉฆ

# ๅŸท่กŒๆ‰€ๆœ‰ๆธฌ่ฉฆ
pnpm vitest run

# ๅŸท่กŒ็‰นๅฎšๆธฌ่ฉฆ
pnpm vitest run tests/unit
pnpm vitest run tests/integration
pnpm vitest run tests/contract

ๆญฅ้ฉŸ 6: ๅปบ็ซ‹ๆธฌ่ฉฆ่จ‚ๅ–ฎ

# ๅปบ็ซ‹ไธ€็ญ†่จ‚ๅ–ฎ
curl -X POST http://localhost:8787/api/merchant/orders \
  -H "Content-Type: application/json" \
  -H "X-API-Key: TEST_MERCHANT_KEY" \
  -d '{
    "merchant_order_no": "MO-001",
    "amount": 100.00,
    "currency": "TWD",
    "description": "Test order"
  }'

API ๆ–‡ๆช”

POST /api/merchant/orders

ๅปบ็ซ‹ไปฃๆ”ถไบคๆ˜“่จ‚ๅ–ฎใ€‚

Request Headers:

  • X-API-Key: ๅ•†ๆˆถ API ้‡‘้‘ฐ (ๅฟ…ๅกซ)
  • Content-Type: application/json

Request Body:

{
  "merchant_order_no": "MO-001",
  "amount": 100.00,
  "currency": "TWD",
  "description": "่จ‚ๅ–ฎ่ชชๆ˜Ž"
}

Response (201 Created):

{
  "order_id": "uuid-v4",
  "status": "PENDING",
  "created_at": "2025-12-05T10:00:00.000Z"
}

GET /health

ๅฅๅบทๆชขๆŸฅ็ซฏ้ปžใ€‚

Response (200 OK):

{
  "status": "ok",
  "service": "order-ingress",
  "timestamp": "2025-12-05T10:00:00.000Z",
  "checks": {
    "worker": { "status": "ok" },
    "database": { "status": "ok", "latency_ms": 5 },
    "sqs": { "status": "ok" }
  }
}

้ƒจ็ฝฒ

้ƒจ็ฝฒ Cloudflare Workers

# ่จญๅฎš Cloudflare ๆ†‘่ญ‰
wrangler login

# ้ƒจ็ฝฒๅˆฐ staging
./scripts/deploy-workers.sh staging

# ้ƒจ็ฝฒๅˆฐ production
./scripts/deploy-workers.sh production

้ƒจ็ฝฒ Lambda Bridge

# ่จญๅฎš็’ฐๅขƒ่ฎŠๆ•ธ
export GATEWAY_ROUTER_URL="https://gateway-router.your-workers.dev"
export WEBHOOK_NOTIFIER_URL="https://webhook-notifier.your-workers.dev"

# ้ƒจ็ฝฒๅˆฐ staging
./scripts/deploy-lambda.sh staging

# ้ƒจ็ฝฒๅˆฐ production
./scripts/deploy-lambda.sh production

็›ฃๆŽง

ๆŒ‡ๆจ™ (Metrics)

ๆŒ‡ๆจ™ๅ็จฑ ้กžๅž‹ ่ชชๆ˜Ž
orders_created_total Counter ๅปบ็ซ‹็š„่จ‚ๅ–ฎ็ธฝๆ•ธ
orders_completed_total Counter ๅฎŒๆˆ็š„่จ‚ๅ–ฎ็ธฝๆ•ธ
webhook_attempts_total Counter Webhook ้€š็Ÿฅๅ˜—่ฉฆๆฌกๆ•ธ
webhook_failures_total Counter Webhook ้€š็Ÿฅๅคฑๆ•—ๆฌกๆ•ธ
dead_letters_total Counter ๆญปไฟก่จ˜้Œ„็ธฝๆ•ธ

ๆ—ฅ่ชŒๆฌ„ไฝ

ๆฏๅ€‹่ซ‹ๆฑ‚้ƒฝๆœƒ่จ˜้Œ„ไปฅไธ‹ๆฌ„ไฝ๏ผš

  • trace_id: ่ฟฝ่นค ID
  • order_id: ่จ‚ๅ–ฎ ID
  • merchant_id: ๅ•†ๆˆถ ID
  • Handler ๅ็จฑ

Troubleshooting

ๅธธ่ฆ‹ๅ•้กŒ

Q: ่จ‚ๅ–ฎ็‹€ๆ…‹ไธ€็›ดๆ˜ฏ PENDING๏ผŸ A: ็ขบ่ช SQS ไฝ‡ๅˆ—ๅ’Œ Lambda Bridge ๆญฃๅธธ้‹ไฝœใ€‚ๆชขๆŸฅ CloudWatch ๆ—ฅ่ชŒใ€‚

Q: Webhook ้€š็Ÿฅๅคฑๆ•—๏ผŸ A: ๆŸฅ็œ‹ dead_letter_records ่กจๆ ผ็ขบ่ชๅคฑๆ•—ๅŽŸๅ› ใ€‚ๆชขๆŸฅๅ•†ๆˆถ็ซฏ้ปžๆ˜ฏๅฆๅฏ้”ใ€‚

Q: ๆœฌๆฉŸ้–‹็™ผ Workers ็„กๆณ•้€ฃ็ทš่ณ‡ๆ–™ๅบซ๏ผŸ A: ็ขบ่ช Docker Compose ๆœๅ‹™ๆญฃๅธธ้‹ไฝœ๏ผŒPostgreSQL ็ซฏๅฃ 5432 ๅฏ้€ฃ็ทšใ€‚

ๆŸฅ็œ‹ๆญปไฟก่จ˜้Œ„

SELECT * FROM dead_letter_records
WHERE order_id = 'your-order-id'
ORDER BY last_failed_at DESC;

้–‹็™ผๆŒ‡ๅ—

ๆ–ฐๅขž Worker

  1. ๅปบ็ซ‹ workers/your-worker/ ็›ฎ้Œ„
  2. ่ค‡่ฃฝ็พๆœ‰ Worker ็š„ package.json ๅ’Œ wrangler.toml
  3. ๅฏฆไฝœ src/index.ts
  4. ๆ›ดๆ–ฐ pnpm-workspace.yaml

ๅŸท่กŒๆธฌ่ฉฆ

# ๅ–ฎๅ…ƒๆธฌ่ฉฆ
pnpm vitest run tests/unit

# ๆ•ดๅˆๆธฌ่ฉฆ
pnpm vitest run tests/integration

# ๅฅ‘็ด„ๆธฌ่ฉฆ
pnpm vitest run tests/contract

# ็›ฃ็œ‹ๆจกๅผ
pnpm vitest

License

Private - All rights reserved.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages