main.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import dotenv
  2. import uuid
  3. import os
  4. import logging
  5. from typing import AsyncContextManager, Optional
  6. from fastapi import FastAPI, Request, responses
  7. from fastapi.templating import Jinja2Templates
  8. from pydantic import BaseModel
  9. from dotenv import load_dotenv
  10. from os.path import join, dirname
  11. from linepay import LinePayApi
  12. from starlette.responses import HTMLResponse
  13. # dotenv
  14. dotenv_path = join(dirname(__file__),'./env/.env')
  15. load_dotenv(dotenv_path)
  16. # logger (TBD)
  17. # template
  18. templates = Jinja2Templates(directory="templates")
  19. # Line Pay Config
  20. LINE_PAY_CHANNEL_ID = os.environ.get("LINE_PAY_CHANNEL_ID")
  21. LINE_PAY_CHANNEL_SECRET = os.environ.get("LINE_PAY_CHANNEL_SECRET")
  22. LINE_PAY_REQEST_BASE_URL = "https://{}".format(os.environ.get("HOST_NAME"))
  23. line = LinePayApi(LINE_PAY_CHANNEL_ID, LINE_PAY_CHANNEL_SECRET, is_sandbox=True)
  24. # CACHE
  25. CACHE = {}
  26. # Fastapi
  27. app = FastAPI()
  28. @app.get('/')
  29. def hellow():
  30. return {"Hello" : "World"}
  31. ## Request
  32. @app.get('/request', response_class=HTMLResponse)
  33. async def pay_request(request: Request):
  34. order_id = str(uuid.uuid4())
  35. amount = 1200
  36. currency = "TWD"
  37. CACHE["order_id"] = order_id
  38. CACHE["amount"] = amount
  39. CACHE["currency"] = currency
  40. request_options ={
  41. "amount" : amount,
  42. "currency" : currency,
  43. "orderId" : order_id,
  44. "packages" : [
  45. {
  46. "id" : "早鳥方案",
  47. "amount" : 1200,
  48. "products" :[
  49. {
  50. # "id" : "Id_早鳥方案",
  51. "name" : "早鳥方案",
  52. "quantity" : 1,
  53. "price" : 1200,
  54. "imageUrl" : "https://kb.rspca.org.au/wp-content/uploads/2018/11/golder-retriever-puppy.jpeg"
  55. }
  56. ]
  57. }
  58. ],
  59. "redirectUrls" : {
  60. "confirmUrl" : LINE_PAY_REQEST_BASE_URL + "/confirm/",
  61. "cancelUrl" : LINE_PAY_REQEST_BASE_URL + "/cancel/"
  62. }
  63. }
  64. response = line.request(request_options)
  65. transaction_id = int(response.get("info",{}).get("transactionId",0))
  66. check_result = line.check_payment_status(transaction_id)
  67. response["transaction_id"] = transaction_id
  68. response["paymentStatusCheckReturnCode"] = check_result.get("returnCode", None)
  69. response["paymentStatusCheckReturnMessage"] = check_result.get("returnMessage", None)
  70. return templates.TemplateResponse("request.html", {"request":response})
  71. # return response
  72. ## Confirm
  73. @app.get('/confirm/')
  74. async def pay_confirm(transactionId: int, orderId: Optional[str] = None):
  75. CACHE["transaction_id"] = transactionId
  76. response = line.confirm(transactionId,float(CACHE.get("amount",0)),CACHE.get("currency","TWD"))
  77. check_result = line.check_payment_status(transactionId)
  78. payment_details = line.payment_details(transaction_id=transactionId)
  79. response["transaction_id"] = transactionId
  80. response["paymentStatusCheckReturnCode"] = check_result.get("returnCode", None)
  81. response["paymentStatusCheckReturnMessage"] = check_result.get("returnMessage",None)
  82. response["payment_details"] = payment_details
  83. return templates.TemplateResponse("confirm.html", {"request":response})
  84. # return {"transactionId" : str(transactionId), "orderId" : orderId}
  85. ## Capture
  86. ## Refund
  87. ## Payment Details API
  88. @app.get('/payments')
  89. async def pay_payments(orderId : str):
  90. payment_details = line.payment_details(order_id=orderId)
  91. return payment_details
  92. ## Pay Preapproved API