--- title: "整合結帳" description: "整合我們的無縫結帳解決方案,為您的玩家提供日本本地支付方式。" source: "https://docs.tokenz.one/zh-TW/v1/checkout/get-started" api_version: "v1" locale: "zh-TW" version_status: "legacy" docs_stage: "prod" --- # 整合結帳 整合我們的無縫結帳解決方案,為您的玩家提供日本本地支付方式。 ## 必要條件 請確保您已從 Tokenz 獲取 API 憑證(金鑰)。您可以在 Tokenz Dashboard 的 Developers → API keys 找到您的憑證。 如果您想了解 Tokenz Checkout 的工作原理,請參閱 [Checkout](https://docs.tokenz.one/zh-TW/v1/) 了解更多詳細資訊。 ## 設定伺服器 #### Python ```python import os from flask import Flask, request, redirect from flask_cors import CORS import requests # Replace the keys with yours SECRET_KEY = os.environ.get("SECRET_KEY", "secret_test_YOUR_KEY_HERE") app = Flask(__name__, static_url_path="") CORS(app) root = "../client/build" @app.route("/", methods=["GET"]) def index(): return redirect("http://localhost:3080") ``` #### PHP ```php run(); ``` #### Go ```go package main import ( "encoding/json" "fmt" "io" "net/http" "os" "strings" "time" "github.com/gin-gonic/gin" ) func main() { router := gin.Default() router.StaticFile("/demo.css", "../client/build/demo.css") router.StaticFile("/", "../client/build/index.html") router.StaticFile("/payment-success", "../client/build/payment-success.html") router.StaticFile("/payment-canceled", "../client/build/payment-canceled.html") ... router.Run(":5001") } ``` #### NodeJS ```js import express from "express"; const app = express(); const port = 3000; app.get("/", (req, res) => { res.send( "
", ); }); app.listen(port, () => { console.log(`Sandbox listening on port ${port}`); }); ``` ## 創建結帳工作階段 在您的伺服器上添加一個端點來創建結帳工作階段。結帳工作階段控制您的客戶在 Tokenz 託管的支付頁面上看到的內容,例如項目、訂單金額、貨幣和可用的支付方式。 ### 定義項目(line item) 總是將您的產品庫存的敏感資訊(如價格和可用性)保存在您的伺服器上,以防止客戶從客戶端進行操作。在創建結帳工作階段時定義產品資訊。 **稅金。** 本快速入門(及其範例載荷)基於 Merchant of Record(MoR)模式——即 Tokenz 帳戶的預設模式:Tokenz 會自動計算並代收稅金,您只需為每個商品設定 `taxCategory`。如果您的帳戶被特別設定為 Payment Gateway 模式,則每個 Checkout Session 都必須額外包含頂層 `tax` 物件(以最小貨幣單位表示,例如 `"tax": { "amount": 0, "currency": "USD" }`);缺少該欄位的請求會被拒絕並回傳 `order.tax-required`。如果不確定您的帳戶使用哪種模式,請與您的 Tokenz 聯絡人確認。 ### 提供成功和取消的 URL 指定成功和取消頁面的 URL,確保它們是可公開訪問的,以便 Tokenz 可以將客戶轉址過去。您也可以使用相同的 URL 來處理成功和取消狀態。 ### [非必要] 定義可用的支付方式 指定為此結帳向您的客戶提供的支付方式列表。如果未提供支付方式或提供了空列表,則所有可用的支付方式都將顯示給客戶。 ### 將客戶轉址到 Tokenz 結帳頁面 創建工作階段後,將您的客戶轉址到回應中返回的結帳頁面的 URL。 #### Python ```python @app.route("/create-tokenz-checkout", methods=['POST']) def create_tokenz_checkout(): CALLBACK_URL_PREFIX = request.headers['referer'] headers = {"Authorization": f'Bearer {SECRET_KEY}'} print(headers) payload = { "amount": { "currency": "JPY", "amount": 5200 }, "itemDetails": [ { "product": { "label": "ひとにぎりのエメラルド", "description": "80+8", "images": [ "https://images.ctfassets.net/z82qbo7cv7ia/1dWPbk5Qx2M1Qikj6Knyuc/e37b2c26829c0d30793a348ae3adb3b0/fake-pass.webp" ], "quantity": 3, "price": { "currency": "JPY", "amount": 1200 }, "taxCategory": "DIGITAL_GOODS_AND_SERVICES" } }, { "product": { "label": "エメラルドの荷車", "description": "100+10", "images": [], "quantity": 1, "price": { "currency": "JPY", "amount": 1600 }, "taxCategory": "DIGITAL_GOODS_AND_SERVICES" } } ], "customerInfo": {}, "successUrl": "http://localhost:9000/success", "pendingUrl": "http://localhost:9000/pending", "cancelUrl": "http://localhost:9000/cancel" } res = requests.post( "https://api.tokenz.one/v1/checkoutsession", json=payload, headers=headers ) session = res.json() return redirect(session["url"], 303) ``` #### PHP ```php $app->map(['get', 'post'], '/', function ($request, $response, $args) { $fileName = trim($request->getUri()->getBasePath(), '/'); if ($request->isPost()) { $client = new \GuzzleHttp\Client(); try { $checkoutSessionResponse = $client->request('POST', 'https://api.tokenz.one/v1/checkoutsession', [ 'body' => '{ "amount": { "currency": "JPY", "amount": 5200 }, "itemDetails": [ { "product": { "label": "ひとにぎりのエメラルド", "description": "80+8", "images": [ "https://images.ctfassets.net/z82qbo7cv7ia/1dWPbk5Qx2M1Qikj6Knyuc/e37b2c26829c0d30793a348ae3adb3b0/fake-pass.webp" ], "quantity": 3, "price": { "currency": "JPY", "amount": 1200 }, "taxCategory": "DIGITAL_GOODS_AND_SERVICES" } }, { "product": { "label": "エメラルドの荷車", "description": "100+10", "images": [], "quantity": 1, "price": { "currency": "JPY", "amount": 1600 }, "taxCategory": "DIGITAL_GOODS_AND_SERVICES" } } ], "customerInfo": {}, "successUrl": "http://localhost:9000/success", "pendingUrl": "http://localhost:9000/pending", "cancelUrl": "http://localhost:9000/cancel" }', 'headers' => [ 'Content-Type' => 'application/json', 'Authorization' => 'Bearer secret_test_YOUR_KEY_HERE', ], ]); $checkoutSession = json_decode($checkoutSessionResponse->getBody()); } catch (Exception $e) { echo $e; echo \GuzzleHttp\Psr7\Message::toString($e->getResponse()); } return $response->withRedirect($checkoutSession->url, 302); } else { $filePath = __DIR__ . '/../client/build/' . $fileName; switch (pathinfo($filePath, PATHINFO_EXTENSION)) { case 'css': $mimeType = 'text/css'; break; default: $mimeType = 'text/html'; } $body = $response->getBody(); $body->write(file_get_contents($filePath)); return $response ->withHeader('Content-Type', $mimeType . '; charset=UTF-8') ->withBody($body); } }); ``` #### Go ```go router.POST("/create-tokenz-checkout", func(c *gin.Context) { url := "https://api.tokenz.one/v1/checkoutsession" payload := strings.NewReader( `{ "amount": { "currency": "JPY", "amount": 5200 }, "itemDetails": [ { "product": { "label": "ひとにぎりのエメラルド", "description": "80+8", "images": [ "https://images.ctfassets.net/z82qbo7cv7ia/1dWPbk5Qx2M1Qikj6Knyuc/e37b2c26829c0d30793a348ae3adb3b0/fake-pass.webp" ], "quantity": 3, "price": { "currency": "JPY", "amount": 1200 }, "taxCategory": "DIGITAL_GOODS_AND_SERVICES" } }, { "product": { "label": "エメラルドの荷車", "description": "100+10", "images": [], "quantity": 1, "price": { "currency": "JPY", "amount": 1600 }, "taxCategory": "DIGITAL_GOODS_AND_SERVICES" } } ], "customerInfo": {}, "successUrl": "http://localhost:9000/success", "pendingUrl": "http://localhost:9000/pending", "cancelUrl": "http://localhost:9000/cancel" }`) req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Content-Type", "application/json") req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", os.Getenv("SECRET_KEY"))) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() bodyBytes, _ := io.ReadAll(resp.Body) var result Response if err := json.Unmarshal(bodyBytes, &result); err != nil { fmt.Println("Can not unmarshal JSON") } checkoutUrl := result.URL c.Redirect(http.StatusSeeOther, checkoutUrl) }) ``` #### NodeJS ```js app.post("/create-tokenz-checkout", (req, res) => { const API_ENDPOINT = "https://api.tokenz.one/v1/checkoutsession"; const payload = { amount: { currency: "JPY", amount: 5200, }, itemDetails: [ { product: { label: "ひとにぎりのエメラルド", description: "80+8", images: [ "https://images.ctfassets.net/z82qbo7cv7ia/1dWPbk5Qx2M1Qikj6Knyuc/e37b2c26829c0d30793a348ae3adb3b0/fake-pass.webp", ], quantity: 3, price: { currency: "JPY", amount: 1200, }, taxCategory: "DIGITAL_GOODS_AND_SERVICES", }, }, { product: { label: "エメラルドの荷車", description: "100+10", images: [], quantity: 1, price: { currency: "JPY", amount: 1600, }, taxCategory: "DIGITAL_GOODS_AND_SERVICES", }, }, ], customerInfo: {}, successUrl: "http://localhost:9000/success", pendingUrl: "http://localhost:9000/pending", cancelUrl: "http://localhost:9000/cancel", }; fetch(API_ENDPOINT, { method: "POST", body: JSON.stringify(payload), headers: { "content-type": "application/json", authorization: "Bearer " + process.env.SECRET_KEY, }, }) .then((response) => response.json()) .then((session) => { console.log(session); res.redirect(303, session.url); }); }); ``` ## 建立您的結帳頁面 ### 添加成功頁面 為您提供的結帳工作階段 `successUrl` 創建一個成功頁面,向您的客戶顯示訂單確認資訊或訂單詳細資訊。客戶成功完成結帳後,Tokenz 將轉址到此頁面。 ```html感謝您的惠顧!如果您有任何問題,請發送電子郵件至 orders@example.com。
您的支付正在處理中!我們會在完成後第一時間通知您。 如果您有任何問題,請發送電子郵件至 orders@example.com.
忘記添加商品到購物車了?繼續購物,然後回來支付!