營利是幫助專案可以長久運行的方法之一,本篇介紹以 Python 搭配 Django 進行 LINE PAY API (V3) 串接的寫法。
channel_id = settings.LINE_PAY_CLIENT_ID
channel_secret = settings.LINE_PAY_SECRET
base_url = settings.LINE_PAY_URL
LINE_PAY_URL
指的是 LINE 所提供的測試環境或是正式環境,測試環境為:https://sandbox-api-pay.line.me
;正式環境:https://api-pay.line.me
Request API
/v3/payments/request
Confirm API
/v3/payments/{transaction_id}/confirm
雖然 Request API 的結果會導向付款成功或失敗的頁面,可以初步根據跳轉判斷頁面是否成功,但仍然要使用 Confirm API 做再度確認。
了解完兩支主要 API 之後就直接進入實作環節:
需要先定義一個函式 generate_headers
,含有許多請求的 Headers,目的是做發送時的加密處理,body_json
稍後會使用到這個變數,url
指的是 Request API (/v3/payments/request
)或 Confirm API (/v3/payments/{transaction_id}/confirm
) 網址,特別注意 url
參數不包含 https://api-pay.line.me
:
import uuid
import base64
import hmac
import hashlib
import json
from django.utils import timezone, dateformat
# API Authentication
# views.py
def generate_headers(body_json, channel_secret, url):
nonce = str(uuid.uuid4())
string_to_sign = f"{channel_secret}{url}{body_json}{nonce}"
binary_message = string_to_sign.encode()
binary_secret_key = channel_secret.encode()
hash = hmac.new(binary_secret_key, binary_message, hashlib.sha256)
signature = base64.b64encode(hash.digest()).decode()
return {
"Content-Type": "application/json",
"X-LINE-ChannelId": channel_id,
"X-LINE-Authorization-Nonce": nonce,
"X-LINE-Authorization": signature,
}
範例中,消費者購買一款單價 30 元卡比巴拉鑰匙圈商品,共計一件,其中有幾個參數需要注意:
products_quantity
products_price
order_id
confirmUrl
cancelUrl
class RequestView(APIView):
def get(self, request):
url = "/v3/payments/request"
request_url = f"{base_url}{url}"
products_quantity = 1 # 購買的商品數量
products_price = 30 # 購買單價
order_id = f"{dateformat.format(timezone.now()+ timezone.timedelta(hours=8),'YmdHis')}" # 訂單編號
body = {
"amount": products_price * products_quantity, #總額
"currency": "TWD",
"orderId": order_id,
"packages": [
{
"id": "kapybara", # 系列名或分店名,像卡比巴拉周邊/臺中分鋪
"amount": products_price * products_quantity,
"products": [
{
"id": "keychain", # 商品內部名,像是卡比巴拉的鑰匙圈
"name": "卡比巴拉-鑰匙圈", # 呈現給消費者看的商品名
"imageUrl": "https://sticker.png", # 商品圖片
"quantity": products_quantity, # 商品數量
"price": products_price, # 商品單價
},
],
},
],
"options": {
"display": {"locale": "zh_TW"}
},
"redirectUrls": {
# 付款成功要跳轉的網頁
"confirmUrl": f"https://example.com.tw/line-pay/confirm/",
# 付款失敗要跳轉的網頁
"cancelUrl": f"https://example.com.tw/line-pay/cancel/",
},
}
# Convert body to JSON string
body_json = json.dumps(body)
# 呼叫剛剛所定義的 API Authentication generate_headers 函式
headers = generate_headers(body_json, channel_secret, url)
response = requests.post(request_url, headers=headers, data=body_json)
data = response.json()
if data["returnCode"] == "0000": # 成功的代碼是 0000
return Response({"paymenturl": data["info"]["paymentUrl"]}, status=200)
else:
return Response(
{"detail": f"request to LINE failed: {data['returnCode']}"},
status=500,
)
發送成功 ("returnCode" == "0000"
)的話會回傳 paymentUrl
憑著這個網址,將使用者導到 LINE PAY 付款頁面了!
{
"paymenturl": {
"web": "https://sandbox-web-pay.line.me/web/payment/wait?transactionReserveId=WjdeWQeqwqweqwYWlhqweqweA0QUqweqweV3I5MkJaeDV4c2JtTUpuSQ&locale=zh-TW_LP",
"app": "line://pay/payment/WjdySEWQEqweqwe0QUFKqwetqweqweJaeDV4c2JtTUpuSQ"
}
}
付款頁面:
當消費者進入 paymenturl
付款頁面之後若付款成功/失敗,則會根據在 Request API 所填寫的 confirmUrl
與 cancelUrl
網址跳轉至對應的頁面。
confirmUrl
頁面中可以顯示確認付款中的提醒文字,並同時呼叫 Confirm API 進行確認。cancelUrl
頁面中能顯示付款失敗,並在數秒過後重新跳轉回結帳頁面。下篇會介紹 Confirm API 實作。
在這篇文章中,我們學會了: