linepay.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import dataset
  2. import uuid
  3. from datetime import datetime
  4. from linebot.models import (
  5. MessageEvent, TextMessage, TextSendMessage, FollowEvent,
  6. TemplateSendMessage, ButtonsTemplate, URITemplateAction,
  7. )
  8. from fastapi import APIRouter
  9. from fastapi.param_functions import Depends
  10. from linepay import LinePayApi
  11. from fastapi.templating import Jinja2Templates
  12. from sqlalchemy.orm.session import Session
  13. from app import crud, schemas
  14. from app.api import deps
  15. from fastapi.encoders import jsonable_encoder
  16. import requests
  17. from app.core.config import settings
  18. baseUrl = "https://nft-api-staging.joyso.io/api/v1/"
  19. headers = {
  20. 'Authorization':
  21. 'Basic %s' % 'bmZ0OmMxOTEzOWMzYjM3YjdjZWU3ZmY3OTFiZGU3NzdjZWNl'
  22. }
  23. # template
  24. templates = Jinja2Templates(directory="templates")
  25. router = APIRouter()
  26. LINE_PAY_CHANNEL_ID = "1656387996"
  27. SECRET_KEY = "37336af5452f74ee871a9fa38d81602e"
  28. HOST_NAME = "https://api.ptt.cx:8750"
  29. # Line Pay Config
  30. LINE_PAY_CHANNEL_ID = LINE_PAY_CHANNEL_ID
  31. LINE_PAY_CHANNEL_SECRET = "37336af5452f74ee871a9fa38d81602e"
  32. # LINE_PAY_REQEST_BASE_URL = "https://{}".format(HOST_NAME)
  33. LINE_PAY_REQEST_BASE_URL = "https://api.ptt.cx:8750/api/v1/linepay"
  34. line = LinePayApi(
  35. LINE_PAY_CHANNEL_ID, LINE_PAY_CHANNEL_SECRET, is_sandbox=True
  36. )
  37. # CACHE
  38. CACHE = {}
  39. def push_text(user, message):
  40. settings.line_bot_api.push_message(
  41. user, TextSendMessage(text=message)
  42. )
  43. # Request
  44. @router.post('/request')
  45. async def pay_request(
  46. line_id:str, nft_id: str, amount: int,
  47. db: Session = Depends(deps.get_db)
  48. ):
  49. order_id = str(uuid.uuid4())
  50. currency = "TWD"
  51. nft = crud.nft.get(db=db, id=nft_id)
  52. request_options = {
  53. "amount": amount,
  54. "currency": currency,
  55. "orderId": order_id,
  56. "packages": [
  57. {
  58. "id": nft.id,
  59. "amount": amount,
  60. "products": [
  61. {
  62. "name": nft.title,
  63. "quantity": amount,
  64. "price": 1,
  65. "imageUrl": nft.imgurl
  66. }
  67. ]
  68. }
  69. ],
  70. "redirectUrls": {
  71. # "confirmUrl": LINE_PAY_REQEST_BASE_URL + "/confirm/"
  72. "confirmUrl": "https://ark.cards/confirm.html",
  73. "cancelUrl" : "https://ark.cards/confirm.html"
  74. # "cancelUrl": LINE_PAY_REQEST_BASE_URL + "/cancel/"
  75. }
  76. }
  77. response = line.request(request_options)
  78. transaction_id = int(response.get("info", {}).get("transactionId", 0))
  79. check_result = line.check_payment_status(transaction_id)
  80. response["transaction_id"] = transaction_id
  81. response["paymentStatusCheckReturnCode"] = check_result.get(
  82. "returnCode", None
  83. )
  84. response["paymentStatusCheckReturnMessage"] = check_result.get(
  85. "returnMessage", None
  86. )
  87. payment_obj = schemas.payment.PaymentBase(
  88. order_id=order_id, transaction_id=transaction_id,
  89. amount=amount, nft_id=nft_id,
  90. payment_status="establish the order", line_id=line_id
  91. )
  92. payment = crud.payment.create(db=db, obj_in=payment_obj)
  93. return {"web":response["info"]["paymentUrl"]['web'], "app":response["info"]["paymentUrl"]['web']}
  94. return response["info"]["paymentUrl"]
  95. # Confirm
  96. @router.get('/confirm')
  97. async def pay_confirm(
  98. transactionId: int = 123456789,
  99. db: Session = Depends(deps.get_db)
  100. ):
  101. db_ = dataset.connect(
  102. 'mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4'
  103. )
  104. transaction_table = db_['transaction']
  105. payment = crud.payment.get_by_transaction(db, transaction_id=transactionId)
  106. response = line.confirm(
  107. transactionId, float(payment.amount), "TWD")
  108. check_result = line.check_payment_status(transactionId)
  109. payment_details = line.payment_details(transaction_id=transactionId)
  110. response["transaction_id"] = transactionId
  111. response["paymentStatusCheckReturnCode"] = check_result.get(
  112. "returnCode", None
  113. )
  114. response["paymentStatusCheckReturnMessage"] = check_result.get(
  115. "returnMessage", None
  116. )
  117. response["payment_details"] = payment_details
  118. if(response["paymentStatusCheckReturnCode"] == '0123'):
  119. to = crud.user.get_by_lineid(db, lineid=payment.line_id).__dict__['useraddress']
  120. payload = {
  121. "txid": transactionId,
  122. # "contract": "0xe0d9102c88b09369df99b1c126fb2eebc13804f8",
  123. "contract": "0x8d5a7d8ca33fd9edca4b871cf5fb2a9cb5091505",
  124. "to": to,
  125. "uid": crud.nft.get(db, id=payment.nft_id).__dict__['uid'],
  126. "value": payment.amount
  127. }
  128. r = requests.post(baseUrl + "accounts/U9dc55544ecca3a95b170bdf2a30e3691/erc1155/transfer_by_admin",
  129. headers=headers, data=payload)
  130. payment_update = schemas.payment.PaymentUpdate(**jsonable_encoder(payment))
  131. if r.status_code == 200:
  132. title = crud.nft.get(db, id=payment.nft_id).__dict__['title']
  133. message = "您的NFT : " + title + ", 已劃轉!"
  134. push_text("U9dc55544ecca3a95b170bdf2a30e3691", message)
  135. transaction_table.insert({'txid':transactionId,'tfrom':"U9dc55544ecca3a95b170bdf2a30e3691",'to':payment.line_id,'nft':crud.nft.get(db, id=payment.nft_id).__dict__['uid'],'transaction_at':datetime.now()})
  136. from_name = settings.line_bot_api.get_profile("U9dc55544ecca3a95b170bdf2a30e3691").as_json_dict()['displayName']
  137. try:
  138. to_name = settings.line_bot_api.get_profile(payment.line_id).as_json_dict()['displayName']
  139. except:
  140. to_name = "外部"
  141. fr = "您賣給"+ to_name +"的NFT(" + title + "), 已發送,請靜待網路確認!"
  142. to_message = "您購買的NFT("+title+"), 已成功,請靜待網路確認!"
  143. push_text("U9dc55544ecca3a95b170bdf2a30e3691", fr)
  144. try:
  145. push_text(payment.line_id, to_message)
  146. except:
  147. pass
  148. payment_update.payment_status = "success"
  149. crud.payment.update(db, db_obj=payment, obj_in=payment_update)
  150. return "OK"
  151. else:
  152. # push訊息
  153. payment_update.payment_status = "success get payment, but transfer failed, error message is" + r.content
  154. crud.payment.update(db, db_obj=payment, obj_in=payment_update)
  155. message = str(transactionId) + " 收款成功,轉移失敗, error message is" + r.content
  156. to_message = str(transactionId)+ " 收款成功,轉移失敗,請洽客服"
  157. try:
  158. push_text(payment.line_id, to_message)
  159. except:
  160. pass
  161. push_text("U9dc55544ecca3a95b170bdf2a30e3691", message)
  162. return {'msg': "收款成功,轉移失敗,請洽客服"}
  163. else:
  164. payment_update = schemas.payment.PaymentUpdate(**jsonable_encoder(payment))
  165. payment_update.payment_status = "cancel"
  166. crud.payment.update(db, db_obj=payment, obj_in=payment_update)
  167. return "交易取消"