main.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. from re import U
  2. import uuid
  3. import os
  4. from typing import Optional
  5. from fastapi import FastAPI, Form, Depends, HTTPException, status
  6. from fastapi.templating import Jinja2Templates
  7. from dotenv import load_dotenv
  8. from os.path import join, dirname
  9. from linepay import LinePayApi
  10. from pydantic.networks import EmailStr
  11. from starlette.responses import HTMLResponse
  12. from sqlalchemy.orm import Session
  13. from fastapi.encoders import jsonable_encoder
  14. from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
  15. from sql.database import get_db_session
  16. from sql.crud import create_order, get_user
  17. from sql.models import order_info_linepay
  18. from sql.schemas import order_info_linepay as orderSechmas
  19. from sql.schemas import User
  20. from jose import JWTError, jwt
  21. from passlib.context import CryptContext
  22. # TBD load_env
  23. SECRET_KEY = "df2f77bd544240801a048bd4293afd8eeb7fff3cb7050e42c791db4b83ebadcd"
  24. ALGORITHM = "HS256"
  25. ACCESS_TOKEN_EXPIRE_DAYS = 5
  26. pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
  27. oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
  28. def verify_password(plain_password, hashed_password):
  29. return pwd_context.verify(plain_password, hashed_password)
  30. def get_password_hash(password):
  31. return pwd_context.hash(password)
  32. # dotenv
  33. dotenv_path = join(dirname(__file__),'./env/.env')
  34. # dotenv_path = join(dirname(__file__),'./env/test.env') ## sandbox
  35. load_dotenv(dotenv_path)
  36. # logger (TBD)
  37. # template
  38. templates = Jinja2Templates(directory="templates")
  39. # Line Pay Config
  40. LINE_PAY_CHANNEL_ID = os.environ.get("LINE_PAY_CHANNEL_ID")
  41. LINE_PAY_CHANNEL_SECRET = os.environ.get("LINE_PAY_CHANNEL_SECRET")
  42. LINE_PAY_REQEST_BASE_URL = "https://{}".format(os.environ.get("HOST_NAME"))
  43. line = LinePayApi(LINE_PAY_CHANNEL_ID, LINE_PAY_CHANNEL_SECRET, is_sandbox=False)
  44. # line = LinePayApi(LINE_PAY_CHANNEL_ID, LINE_PAY_CHANNEL_SECRET, is_sandbox=True)
  45. # CACHE
  46. CACHE = {}
  47. # Fastapi
  48. app = FastAPI()
  49. oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
  50. @app.get('/')
  51. def hello(token: str = Depends(oauth2_scheme)):
  52. index = {}
  53. index["product"] = "早鳥方案"
  54. index["amount"] = 1200
  55. index["url"] = "/request"
  56. # return {"product" : ,"amount" : 1200}
  57. return templates.TemplateResponse("index.html", {"request":index})
  58. ## Request
  59. @app.post('/request', response_class=HTMLResponse)
  60. async def pay_request(email: EmailStr= Form(...), phone: str= Form(...),full_name: str= Form(...)):
  61. order_id = str(uuid.uuid4())
  62. amount = 1200
  63. currency = "TWD"
  64. CACHE["email"] = email
  65. CACHE["phone"] = phone
  66. CACHE["full_name"] = full_name
  67. CACHE["orderid"] = order_id
  68. CACHE["amount"] = amount
  69. CACHE["currency"] = currency
  70. request_options ={
  71. "amount" : amount,
  72. "currency" : currency,
  73. "orderId" : order_id,
  74. "packages" : [
  75. {
  76. "id" : "早鳥方案",
  77. "amount" : 1200,
  78. "products" :[
  79. {
  80. # "id" : "Id_早鳥方案",
  81. "name" : "早鳥方案",
  82. "quantity" : 1,
  83. "price" : 1200,
  84. "imageUrl" : "https://kb.rspca.org.au/wp-content/uploads/2018/11/golder-retriever-puppy.jpeg"
  85. }
  86. ]
  87. }
  88. ],
  89. "redirectUrls" : {
  90. "confirmUrl" : LINE_PAY_REQEST_BASE_URL + "/confirm/",
  91. "cancelUrl" : LINE_PAY_REQEST_BASE_URL + "/cancel/"
  92. }
  93. }
  94. response = line.request(request_options)
  95. transaction_id = int(response.get("info",{}).get("transactionId",0))
  96. check_result = line.check_payment_status(transaction_id)
  97. response["transaction_id"] = transaction_id
  98. response["paymentStatusCheckReturnCode"] = check_result.get("returnCode", None)
  99. response["paymentStatusCheckReturnMessage"] = check_result.get("returnMessage", None)
  100. response["email"] = email
  101. response["phone"] = phone
  102. response["full_name"] = full_name
  103. return templates.TemplateResponse("request.html", {"request":response})
  104. # return response
  105. ## Confirm
  106. @app.get('/confirm/')
  107. async def pay_confirm(transactionId: int, orderId: Optional[str] = None, db_sesion: Session = Depends(get_db_session)):
  108. CACHE["transaction_id"] = transactionId
  109. response = line.confirm(transactionId,float(CACHE.get("amount",0)),CACHE.get("currency","TWD"))
  110. check_result = line.check_payment_status(transactionId)
  111. payment_details = line.payment_details(transaction_id=transactionId)
  112. response["transaction_id"] = transactionId
  113. response["paymentStatusCheckReturnCode"] = check_result.get("returnCode", None)
  114. response["paymentStatusCheckReturnMessage"] = check_result.get("returnMessage",None)
  115. response["payment_details"] = payment_details
  116. if(response["paymentStatusCheckReturnCode"] == '0123'):
  117. orderin = {}
  118. orderin["orderid"] = CACHE["orderid"]
  119. orderin["email"] = CACHE["email"]
  120. orderin["phone"] = CACHE["phone"]
  121. orderin["full_name"] = CACHE["full_name"]
  122. create_order(db_sesion, order_in= orderin)
  123. return templates.TemplateResponse("confirm.html", {"request":response})
  124. # return {"transactionId" : str(transactionId), "orderId" : orderId}
  125. ## Capture
  126. ## Refund
  127. ## Payment Details API
  128. @app.get('/payments')
  129. async def pay_payments(orderId : str):
  130. payment_details = line.payment_details(order_id=orderId)
  131. return payment_details
  132. ## Pay Preapproved API