main.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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.params import Depends
  8. from fastapi.templating import Jinja2Templates
  9. from pydantic import BaseModel
  10. from dotenv import load_dotenv
  11. from os.path import join, dirname
  12. from linepay import LinePayApi
  13. from pydantic.errors import UrlSchemeError
  14. from starlette.responses import HTMLResponse
  15. from pydantic import BaseModel, EmailStr, validator
  16. from sqlalchemy.orm import Session
  17. from . import crud, models, schemas
  18. from .database import SessionLocal, engine
  19. # dotenv
  20. dotenv_path = join(dirname(__file__),'./env/.env')
  21. # dotenv_path = join(dirname(__file__),'./env/test.env') ## sandbox
  22. load_dotenv(dotenv_path)
  23. # logger (TBD)
  24. # template
  25. templates = Jinja2Templates(directory="templates")
  26. # Line Pay Config
  27. LINE_PAY_CHANNEL_ID = os.environ.get("LINE_PAY_CHANNEL_ID")
  28. LINE_PAY_CHANNEL_SECRET = os.environ.get("LINE_PAY_CHANNEL_SECRET")
  29. LINE_PAY_REQEST_BASE_URL = "https://{}".format(os.environ.get("HOST_NAME"))
  30. line = LinePayApi(LINE_PAY_CHANNEL_ID, LINE_PAY_CHANNEL_SECRET, is_sandbox=False)
  31. # line = LinePayApi(LINE_PAY_CHANNEL_ID, LINE_PAY_CHANNEL_SECRET, is_sandbox=True)
  32. # CACHE
  33. CACHE = {}
  34. # db
  35. models.Base.metadata.create_all(bind=engine)
  36. # Fastapi
  37. app = FastAPI()
  38. # Dependency
  39. def get_db():
  40. db = SessionLocal()
  41. try:
  42. yield db
  43. finally:
  44. db.close()
  45. @app.get('/')
  46. def hellow():
  47. return {"Hello" : "World"}
  48. ## Request
  49. @app.post('/request', response_class=HTMLResponse)
  50. async def pay_request(userinfo: schemas.UserInfo, db: Session = Depends(get_db)):
  51. order_id = str(uuid.uuid4())
  52. amount = 1200
  53. currency = "TWD"
  54. CACHE["order_id"] = order_id
  55. CACHE["amount"] = amount
  56. CACHE["currency"] = currency
  57. request_options ={
  58. "amount" : amount,
  59. "currency" : currency,
  60. "orderId" : order_id,
  61. "packages" : [
  62. {
  63. "id" : "早鳥方案",
  64. "amount" : 1200,
  65. "products" :[
  66. {
  67. # "id" : "Id_早鳥方案",
  68. "name" : "早鳥方案",
  69. "quantity" : 1,
  70. "price" : 1200,
  71. "imageUrl" : "https://kb.rspca.org.au/wp-content/uploads/2018/11/golder-retriever-puppy.jpeg"
  72. }
  73. ]
  74. }
  75. ],
  76. "redirectUrls" : {
  77. "confirmUrl" : LINE_PAY_REQEST_BASE_URL + "/confirm/",
  78. "cancelUrl" : LINE_PAY_REQEST_BASE_URL + "/cancel/"
  79. }
  80. }
  81. response = line.request(request_options)
  82. transaction_id = int(response.get("info",{}).get("transactionId",0))
  83. check_result = line.check_payment_status(transaction_id)
  84. response["transaction_id"] = transaction_id
  85. response["paymentStatusCheckReturnCode"] = check_result.get("returnCode", None)
  86. response["paymentStatusCheckReturnMessage"] = check_result.get("returnMessage", None)
  87. return templates.TemplateResponse("request.html", {"request":response})
  88. # return response
  89. ## Confirm
  90. @app.get('/confirm/')
  91. async def pay_confirm(transactionId: int, orderId: Optional[str] = None):
  92. CACHE["transaction_id"] = transactionId
  93. response = line.confirm(transactionId,float(CACHE.get("amount",0)),CACHE.get("currency","TWD"))
  94. check_result = line.check_payment_status(transactionId)
  95. payment_details = line.payment_details(transaction_id=transactionId)
  96. response["transaction_id"] = transactionId
  97. response["paymentStatusCheckReturnCode"] = check_result.get("returnCode", None)
  98. response["paymentStatusCheckReturnMessage"] = check_result.get("returnMessage",None)
  99. response["payment_details"] = payment_details
  100. return templates.TemplateResponse("confirm.html", {"request":response})
  101. # return {"transactionId" : str(transactionId), "orderId" : orderId}
  102. ## Capture
  103. ## Refund
  104. ## Payment Details API
  105. @app.get('/payments')
  106. async def pay_payments(orderId : str):
  107. payment_details = line.payment_details(order_id=orderId)
  108. return payment_details
  109. ## Pay Preapproved API