DeepLearning101 commited on
Commit
5ceee07
·
verified ·
1 Parent(s): a541218

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +69 -2
main.py CHANGED
@@ -10,6 +10,7 @@ import json
10
  import base64
11
  import hashlib
12
  import hmac
 
13
 
14
  app = FastAPI(title="Cié Cié Backend API")
15
 
@@ -38,6 +39,7 @@ RETURN_URL = "https://ciecietaipei.github.io/booking.html"
38
 
39
  supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY) if SUPABASE_URL else None
40
 
 
41
  class OrderPayload(BaseModel):
42
  service_type: str
43
  name: str
@@ -55,6 +57,12 @@ class ConfirmPayload(BaseModel):
55
  order_id: str
56
  amount: int
57
 
 
 
 
 
 
 
58
  @app.get("/")
59
  def read_root():
60
  return {"status": "online", "message": "Cié Cié FastAPI is running."}
@@ -86,7 +94,6 @@ async def submit_booking(payload: OrderPayload):
86
  "products": [{"name": "餐飲訂金與預付金", "quantity": 1, "price": final_deposit}]
87
  }],
88
  "redirectUrls": {
89
- # 這裡最關鍵:帶上 action=payment_confirm 讓前端知道要處理結帳確認
90
  "confirmUrl": f"{RETURN_URL}?action=payment_confirm&amount={final_deposit}",
91
  "cancelUrl": f"{RETURN_URL}?action=payment_cancel"
92
  }
@@ -139,7 +146,7 @@ async def submit_booking(payload: OrderPayload):
139
  return { "status": "success", "message": "訂位已成功建立!" }
140
  except Exception as e: raise HTTPException(status_code=500, detail=f"寫入資料庫失敗: {str(e)}")
141
 
142
- # 🌟 新增:確認收錢的端點 (Confirm API) 🌟
143
  @app.post("/api/linepay/confirm")
144
  async def confirm_payment(payload: ConfirmPayload):
145
  uri = f"/v3/payments/{payload.transaction_id}/confirm"
@@ -172,6 +179,66 @@ async def confirm_payment(payload: ConfirmPayload):
172
  except Exception as e:
173
  raise HTTPException(status_code=500, detail=str(e))
174
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  def notify_boss(name, tel, date, time, pax, amount):
176
  if not LINE_ACCESS_TOKEN or not BOSS_LINE_ID: return
177
  msg = f"🔔 【新訂單通知】\n姓��:{name}\n電話:{tel}\n時間:{date} {time}\n人數:{pax}位"
 
10
  import base64
11
  import hashlib
12
  import hmac
13
+ import time
14
 
15
  app = FastAPI(title="Cié Cié Backend API")
16
 
 
39
 
40
  supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY) if SUPABASE_URL else None
41
 
42
+ # --- 資料結構定義 ---
43
  class OrderPayload(BaseModel):
44
  service_type: str
45
  name: str
 
57
  order_id: str
58
  amount: int
59
 
60
+ # 🌟 新增:用來接收補付款請求的資料結構
61
+ class RepayPayload(BaseModel):
62
+ order_id: str
63
+
64
+ # --- API 端點定義 ---
65
+
66
  @app.get("/")
67
  def read_root():
68
  return {"status": "online", "message": "Cié Cié FastAPI is running."}
 
94
  "products": [{"name": "餐飲訂金與預付金", "quantity": 1, "price": final_deposit}]
95
  }],
96
  "redirectUrls": {
 
97
  "confirmUrl": f"{RETURN_URL}?action=payment_confirm&amount={final_deposit}",
98
  "cancelUrl": f"{RETURN_URL}?action=payment_cancel"
99
  }
 
146
  return { "status": "success", "message": "訂位已成功建立!" }
147
  except Exception as e: raise HTTPException(status_code=500, detail=f"寫入資料庫失敗: {str(e)}")
148
 
149
+ # 確認收錢的端點 (Confirm API)
150
  @app.post("/api/linepay/confirm")
151
  async def confirm_payment(payload: ConfirmPayload):
152
  uri = f"/v3/payments/{payload.transaction_id}/confirm"
 
179
  except Exception as e:
180
  raise HTTPException(status_code=500, detail=str(e))
181
 
182
+ # 🌟 新增:處理重新產生付款連結的 API 🌟
183
+ @app.post("/api/linepay/repay")
184
+ async def repay_payment(payload: RepayPayload):
185
+ if not supabase: raise HTTPException(status_code=500, detail="資料庫未連線")
186
+
187
+ try:
188
+ # 1. 找回原本的訂單
189
+ res = supabase.table("bookings").select("*").ilike("remarks", f"%{payload.order_id}%").execute()
190
+ if not res.data: raise HTTPException(status_code=404, detail="找不到該筆訂單")
191
+
192
+ booking = res.data[0]
193
+ # 防呆:如果客人其實已經付過錢了,阻止他重複刷卡
194
+ if "已付" in booking.get("status", "") or "確認" in booking.get("status", ""):
195
+ raise HTTPException(status_code=400, detail="此訂單已完成付款或確認,無需重新結帳")
196
+
197
+ # 2. 獲取要收取的金額 (PoC 階段先以防護訂金的 1000 元作為補收預設值)
198
+ # 備註:在最終版的 orders 表格中,我們會直接從資料庫精準讀取 deposit_amount
199
+ amount = 1000
200
+
201
+ # 3. 重新向 LINE Pay 申請新的交易連結
202
+ # 技巧:在原本的 order_id 後面加上時間戳記,繞過 LINE Pay 「同訂單號不可重複請求」的限制
203
+ new_order_id = f"{payload.order_id}-R{int(time.time())}"
204
+
205
+ request_body = {
206
+ "amount": amount,
207
+ "currency": "TWD",
208
+ "orderId": new_order_id,
209
+ "packages": [{
210
+ "id": "pkg_repay", "amount": amount, "name": "Cié Cié Taipei 補繳訂金",
211
+ "products": [{"name": "餐飲訂金", "quantity": 1, "price": amount}]
212
+ }],
213
+ "redirectUrls": {
214
+ # 付款成功後,一樣帶回前端進行確認
215
+ "confirmUrl": f"{RETURN_URL}?action=payment_confirm&amount={amount}&orderId={payload.order_id}",
216
+ "cancelUrl": f"{RETURN_URL}?action=payment_cancel"
217
+ }
218
+ }
219
+
220
+ uri = "/v3/payments/request"
221
+ nonce = str(uuid.uuid4())
222
+ body_str = json.dumps(request_body)
223
+ message = LINE_PAY_CHANNEL_SECRET + uri + body_str + nonce
224
+ signature = base64.b64encode(hmac.new(LINE_PAY_CHANNEL_SECRET.encode(), message.encode(), hashlib.sha256).digest()).decode()
225
+
226
+ headers = {
227
+ "Content-Type": "application/json", "X-LINE-ChannelId": LINE_PAY_CHANNEL_ID,
228
+ "X-LINE-Authorization-Nonce": nonce, "X-LINE-Authorization": signature
229
+ }
230
+
231
+ line_pay_res = requests.post(f"{LINE_PAY_BASE_URL}{uri}", headers=headers, data=body_str)
232
+ res_data = line_pay_res.json()
233
+
234
+ if res_data.get("returnCode") == "0000":
235
+ return {"payment_url": res_data["info"]["paymentUrl"]["web"]}
236
+ else:
237
+ raise HTTPException(status_code=500, detail=f"LINE Pay 錯誤: {res_data.get('returnMessage')}")
238
+
239
+ except Exception as e:
240
+ raise HTTPException(status_code=500, detail=str(e))
241
+
242
  def notify_boss(name, tel, date, time, pax, amount):
243
  if not LINE_ACCESS_TOKEN or not BOSS_LINE_ID: return
244
  msg = f"🔔 【新訂單通知】\n姓��:{name}\n電話:{tel}\n時間:{date} {time}\n人數:{pax}位"