CJYen 3 年之前
父節點
當前提交
f71d2b3d6f
共有 5 個文件被更改,包括 189 次插入54 次删除
  1. 3 2
      app/api/api_v1/api.py
  2. 0 5
      app/api/api_v1/endpoints/config.py
  3. 81 46
      app/api/api_v1/endpoints/line.py
  4. 96 0
      app/api/api_v1/endpoints/linepay.py
  5. 9 1
      app/core/config.py

+ 3 - 2
app/api/api_v1/api.py

@@ -1,10 +1,11 @@
 from fastapi import APIRouter
 
-from app.api.api_v1.endpoints import login, users, nft, line, joyso
+from app.api.api_v1.endpoints import login, users, nft, line, joyso, linepay
 
 api_router = APIRouter()
 api_router.include_router(login.router, tags=["login"])
 api_router.include_router(users.router, prefix="/user", tags=["user"])
 api_router.include_router(nft.router, prefix="/nft", tags=["nft"])
 api_router.include_router(line.router, prefix="/line", tags=["line"])
-api_router.include_router(joyso.router, prefix="/joyso", tags=["joyso"])
+api_router.include_router(joyso.router, prefix="/joyso", tags=["joyso"])
+api_router.include_router(linepay.router, prefix="/linepay", tags=["linepay"])

+ 0 - 5
app/api/api_v1/endpoints/config.py

@@ -1,5 +0,0 @@
-from linebot import LineBotApi, WebhookHandler
-
-# bot config
-line_bot_api = LineBotApi("SJT7VPT4RMQFLcS27jQBy3FcC24gtDrkcwJWZ5Xzqesr5T78LOKudHEJzt0k3b2S7n4KPwf27J7DVz2c8NQ4plSaaQylEeB1cYrfejaE/RPG/lCIQBYe4iBTzo26s4i2PcmT89837per/lTyvhVIKAdB04t89/1O/w1cDnyilFU=")
-handler = WebhookHandler("411ae3ef7e766739ed2c2c27b249d010")

+ 81 - 46
app/api/api_v1/endpoints/line.py

@@ -1,54 +1,48 @@
-import pymysql
-pymysql.install_as_MySQLdb()
-import uvicorn
 import fastapi
-from fastapi.middleware.cors import CORSMiddleware
-from fastapi.responses import HTMLResponse
-from linebot import LineBotApi, WebhookHandler
 from linebot.models import (
-    MessageEvent, TextMessage, TextSendMessage, FollowEvent, TemplateSendMessage, ButtonsTemplate, URITemplateAction,
+    MessageEvent, TextMessage, TextSendMessage, FollowEvent,
+    TemplateSendMessage, ButtonsTemplate, URITemplateAction,
 )
 import dataset
 import requests
 import json
 import qrcode
-# from PIL import Image
-# import base64, io
 from random import randrange
 from app.schemas import line
+from app.core.config import settings
 import datetime as dt
 from fastapi import APIRouter
 
-router = APIRouter()
 
+router = APIRouter()
 
-# bot config
-line_bot_api = LineBotApi("SJT7VPT4RMQFLcS27jQBy3FcC24gtDrkcwJWZ5Xzqesr5T78LOKudHEJzt0k3b2S7n4KPwf27J7DVz2c8NQ4plSaaQylEeB1cYrfejaE/RPG/lCIQBYe4iBTzo26s4i2PcmT89837per/lTyvhVIKAdB04t89/1O/w1cDnyilFU=")
-handler = WebhookHandler("411ae3ef7e766739ed2c2c27b249d010")
 
 # callback event
 @router.post("/callback")
 async def callback(request: fastapi.Request):
     signature = request.headers['X-Line-Signature']
     body = await request.body()
-    handler.handle(body.decode('utf-8'), signature)
+    settings.handler.handle(body.decode('utf-8'), signature)
     return 'OK'
 
+
 # follow event
-@handler.add(FollowEvent)
+@settings.handler.add(FollowEvent)
 def handle_follow(event):
     # get user id when follow
     real_user_id = event.source.user_id
 
     # db connect and search
-    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
+    db = dataset.connect(
+        'mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4'
+    )
     table = db['users']
     result1 = table.find_one(userid=real_user_id)
 
     # 都存在db的話
     if result1:
         db.close()
-        line_bot_api.reply_message(
+        settings.line_bot_api.reply_message(
             event.reply_token,
             TextSendMessage(text='很高興再見到您!'))
 
@@ -56,7 +50,10 @@ def handle_follow(event):
     else:
         # create user account api
         url = 'https://nft-api-staging.joyso.io/api/v1/accounts'
-        headers = {'Authorization': 'Basic bmZ0OmMxOTEzOWMzYjM3YjdjZWU3ZmY3OTFiZGU3NzdjZWNl'}
+        headers = {
+            'Authorization':
+            'Basic bmZ0OmMxOTEzOWMzYjM3YjdjZWU3ZmY3OTFiZGU3NzdjZWNl'
+        }
 
         # setup for temp use (unique id)
         rand_num = str(randrange(99999))
@@ -77,8 +74,9 @@ def handle_follow(event):
         qr.add_data(user_address)
         qr.make(fit=True)
         img_qr = qr.make_image(fill='black', back_color='white')
-        filename = "/var/www/ArkCard-Linebot/ArkCard-web/qrcode/" + real_user_id + '.png'
-        img_save = img_qr.save(filename)
+        filename = "/var/www/ArkCard-Linebot/ArkCard-web/qrcode/" + \
+                   real_user_id + '.png'
+        img_qr.save(filename)
 
         # add to db
         data = dict(userid=real_user_id, useraddress=user_address)
@@ -86,12 +84,13 @@ def handle_follow(event):
 
         db.close()
 
-        line_bot_api.reply_message(
+        settings.line_bot_api.reply_message(
             event.reply_token,
             TextSendMessage(text='歡迎加入好友'))
 
+
 # message handler
-@handler.add(MessageEvent, message=TextMessage)
+@settings.handler.add(MessageEvent, message=TextMessage)
 def message(event):
     if '我要發送' in event.message.text:
         button_template_message = ButtonsTemplate(
@@ -100,22 +99,24 @@ def message(event):
             actions=[
                 URITemplateAction(
                     label='打開發送頁',
-                    uri='https://ark.cards/collect.html?' + event.source.user_id),])
-        line_bot_api.reply_message(
+                    uri='https://ark.cards/collect.html?'
+                        + event.source.user_id)])
+        settings.line_bot_api.reply_message(
             event.reply_token,
             TemplateSendMessage(
                 alt_text="Receive",
                 template=button_template_message))
 
-    elif '我要接收' in  event.message.text:
+    elif '我要接收' in event.message.text:
         button_template_message = ButtonsTemplate(
             title=' ',
             text='點擊並打開接收頁面,即可分享接收地址給對方!',
             actions=[
                 URITemplateAction(
                     label='打開接收頁',
-                    uri='https://ark.cards/qr-code.html?' + event.source.user_id),])
-        line_bot_api.reply_message(
+                    uri='https://ark.cards/qr-code.html?' +
+                        event.source.user_id)])
+        settings.line_bot_api.reply_message(
             event.reply_token,
             TemplateSendMessage(
                 alt_text="Receive",
@@ -128,8 +129,9 @@ def message(event):
             actions=[
                 URITemplateAction(
                     label='打開NFT商品頁',
-                    uri='https://ark.cards/shop.html?' + event.source.user_id),])
-        line_bot_api.reply_message(
+                    uri='https://ark.cards/shop.html?' +
+                        event.source.user_id)])
+        settings.line_bot_api.reply_message(
             event.reply_token,
             TemplateSendMessage(
                 alt_text="Receive",
@@ -142,8 +144,9 @@ def message(event):
             actions=[
                 URITemplateAction(
                     label='打開收藏頁',
-                    uri='https://ark.cards/collect.html?' + event.source.user_id), ])
-        line_bot_api.reply_message(
+                    uri='https://ark.cards/collect.html?' +
+                        event.source.user_id), ])
+        settings.line_bot_api.reply_message(
             event.reply_token,
             TemplateSendMessage(
                 alt_text="Receive",
@@ -155,22 +158,28 @@ def message(event):
             actions=[
                 URITemplateAction(
                     label='ArkCard的官網',
-                    uri='https://ark.cards'),])
-        line_bot_api.reply_message(
+                    uri='https://ark.cards')])
+        settings.line_bot_api.reply_message(
             event.reply_token,
             TemplateSendMessage(
                 alt_text="Receive",
                 template=button_template_message))
 
+
 @router.post("/push/")
 def push_text(user, message):
-    line_bot_api.push_message(user, TextSendMessage(text=message))
+    settings.line_bot_api.push_message(
+        user, TextSendMessage(text=message)
+    )
+
 
 # nft collection api
 @router.get("/collection/{userid}")
 def collection(userid):
     # db connect
-    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
+    db = dataset.connect(
+        'mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4'
+    )
     table3 = db['nftdrops']
     table2 = db['nft']
     nftdrops = {}
@@ -199,11 +208,14 @@ def collection(userid):
         return nfts_all
         db.close()
 
+
 # receive handler
 @router.get("/receive/{userid}")
 def receive(userid):
     # db connect
-    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
+    db = dataset.connect(
+        'mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4'
+    )
     table = db['users']
 
     table.find_one(userid=userid)
@@ -212,14 +224,19 @@ def receive(userid):
         return "ERROR: User Not Found"
     else:
         result = table.find_one(userid=userid)
-        return {"userid": result['userid'], "useraddress": result['useraddress']}
+        return {
+            "userid": result['userid'], "useraddress": result['useraddress']
+        }
     db.close()
 
+
 # send handler
 @router.post("/send")
-async def receive(userModel : line.TransactionNft):
+async def send(userModel: line.TransactionNft):
     # db connect
-    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
+    db = dataset.connect(
+        'mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4'
+    )
     table = db['users']
     table2 = db['nft']
     table3 = db['nftdrops']
@@ -274,13 +291,17 @@ async def receive(userModel : line.TransactionNft):
         return {'msg': 'nft not found'}
     return {'msg': 'OK'}
 
+
 # shop handler
 @router.get("/shop/{userid}")
 def shop(userid):
     # db connect
-    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
+    db = dataset.connect(
+        'mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4'
+    )
 
-    sql = 'SELECT DISTINCT(title), id, imgurl, userid FROM arkcard.nft  WHERE id<1001 and userid IS NULL GROUP BY title LIMIT 5'
+    sql = 'SELECT DISTINCT(title), id, imgurl, userid FROM arkcard.nft  ' \
+          'WHERE id<1001 and userid IS NULL GROUP BY title LIMIT 5'
     result = db.query(sql)
     rows = {}
     i = 0
@@ -290,10 +311,13 @@ def shop(userid):
     return rows
     db.close()
 
+
 @router.post("/buy")
 async def buy(userModel: line.BuyNft):
     # db connect
-    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
+    db = dataset.connect(
+        'mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4'
+    )
     table2 = db['nft']
 
     # input
@@ -320,10 +344,13 @@ async def buy(userModel: line.BuyNft):
         db.close()
     return "您已購買成功!"
 
+
 @router.post("/event")
-async def nftdrops(userModel : line.NftDrops):
+async def nftdrops(userModel: line.NftDrops):
     # db connect
-    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
+    db = dataset.connect(
+        'mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4'
+    )
     table3 = db['nftdrops']
 
     # input對應
@@ -337,8 +364,16 @@ async def nftdrops(userModel : line.NftDrops):
     # 如果userid不在db, 寫入到一個空值nft
     if not table3.find_one(userid=userid):
         # 新增資料
-        table3.insert(dict(eventid=eventid, nftid=nftid, userid=userid, email=email, time=now))
-        table3.insert(dict(eventid=eventid, nftid=nftid2, userid=userid, email=email, time=now))
+        table3.insert(
+            dict(
+                eventid=eventid, nftid=nftid,
+                userid=userid, email=email, time=now
+            ))
+        table3.insert(
+            dict(
+                eventid=eventid, nftid=nftid2,
+                userid=userid, email=email, time=now
+            ))
         db.close()
         # push訊息
         message = "已為您登記活動!"

+ 96 - 0
app/api/api_v1/endpoints/linepay.py

@@ -0,0 +1,96 @@
+from fastapi import APIRouter
+from linepay import LinePayApi
+from fastapi.templating import Jinja2Templates
+
+# template
+templates = Jinja2Templates(directory="templates")
+
+router = APIRouter()
+
+LINE_PAY_CHANNEL_ID = "1656387996"
+SECRET_KEY = \
+    "df2f77bd544240801a048bd4293afd8eeb7fff3cb7050e42c791db4b83ebadcd"
+
+HOST_NAME = "https://f516-42-74-70-95.ngrok.io"
+# Line Pay Config
+LINE_PAY_CHANNEL_ID = LINE_PAY_CHANNEL_ID
+LINE_PAY_CHANNEL_SECRET = SECRET_KEY
+# LINE_PAY_REQEST_BASE_URL = "https://{}".format(HOST_NAME)
+LINE_PAY_REQEST_BASE_URL = "https://f516-42-74-70-95.ngrok.io"
+line = LinePayApi(
+    LINE_PAY_CHANNEL_ID, LINE_PAY_CHANNEL_SECRET, is_sandbox=True
+)
+
+# CACHE
+CACHE = {}
+
+
+# Request
+@router.post('/request')
+async def pay_request():
+    order_id = "20211227011"
+    amount = "1"
+    currency = "TWD"
+
+    request_options = {
+        "amount": amount,
+        "currency": currency,
+        "orderId": order_id,
+        "packages": [
+            {
+                "id": "NFT",
+                "amount": 1,
+                "products": [
+                    {
+                        "name": "NFT Box 1",
+                        "quantity": 1,
+                        "price": 1,
+                        "imageUrl": "https://i.imgur.com/3rFHRVz.jpg"
+                    }
+                ]
+            }
+
+        ],
+        "redirectUrls": {
+            "confirmUrl": LINE_PAY_REQEST_BASE_URL + "/confirm/"
+            # "cancelUrl": LINE_PAY_REQEST_BASE_URL + "/cancel/"
+        }
+    }
+    response = line.request(request_options)
+    transaction_id = int(response.get("info", {}).get("transactionId", 0))
+    check_result = line.check_payment_status(transaction_id)
+    response["transaction_id"] = transaction_id
+    response["paymentStatusCheckReturnCode"] = check_result.get(
+        "returnCode", None
+    )
+    response["paymentStatusCheckReturnMessage"] = check_result.get(
+        "returnMessage", None
+    )
+    # return response
+    return response
+
+
+# Confirm
+@router.get('/confirm/')
+async def pay_confirm(
+    transactionId: int = "transactionId",
+):
+    CACHE["transaction_id"] = transactionId
+    response = line.confirm(
+        transactionId, float(CACHE.get("amount", 0)),
+        CACHE.get("currency", "TWD"))
+    check_result = line.check_payment_status(transactionId)
+    payment_details = line.payment_details(transaction_id=transactionId)
+    response["transaction_id"] = transactionId
+    response["paymentStatusCheckReturnCode"] = check_result.get(
+        "returnCode", None
+    )
+    response["paymentStatusCheckReturnMessage"] = check_result.get(
+        "returnMessage", None
+    )
+    response["payment_details"] = payment_details
+    if(response["paymentStatusCheckReturnCode"] == '0123'):
+        # return response
+        return "confirm.html", {"request": response}
+    else:
+        return "Not found"

+ 9 - 1
app/core/config.py

@@ -2,7 +2,7 @@ import secrets
 from typing import Any, Dict, List, Optional, Union
 
 from pydantic import AnyHttpUrl, BaseSettings, EmailStr, HttpUrl, PostgresDsn, validator
-
+from linebot import LineBotApi, WebhookHandler
 
 class Settings(BaseSettings):
     API_V1_STR: str = "/api/v1"
@@ -29,6 +29,14 @@ class Settings(BaseSettings):
     IMG_PATH: str = "/var/www/ArkCard-Linebot/ArkCard-web/img/nft/"
     IMG_HOST: AnyHttpUrl = "https://ark.cards/img/nft/"
 
+    # # bot config
+    line_bot_api = LineBotApi(
+        "SJT7VPT4RMQFLcS27jQBy3FcC24gtDrkcwJWZ5Xzqesr5T78LOKudHEJzt0k3b2S7"
+        "n4KPwf27J7DVz2c8NQ4plSaaQylEeB1cYrfejaE/RPG/lCIQBYe4iBTzo26s4i2Pcm"
+        "T89837per/lTyvhVIKAdB04t89/1O/w1cDnyilFU=")
+    handler = WebhookHandler("411ae3ef7e766739ed2c2c27b249d010")
+
+
     @validator("SENTRY_DSN", pre=True)
     def sentry_dsn_can_be_blank(cls, v: str) -> Optional[str]:
         if len(v) == 0: