--- title: "Integrate checkout" description: "Integrate our seamless checkout solution and empower your players with payment methods across APAC." source: "https://docs.tokenz.one/en/v1/checkout/get-started" api_version: "v1" locale: "en" version_status: "legacy" docs_stage: "prod" --- # Integrate checkout Integrate our seamless checkout solution and empower your players with payment methods across APAC. ## Prerequisites Before you can have a working integration, make sure you have the API credentials (secret key) from Tokenz. You can find your credentials under Developers → API keys on the Tokenz Dashboard. For more details on how Tokenz Checkout works, please see [Checkout](https://docs.tokenz.one/en/v1/). ## Set up the server #### 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}`); }); ``` ## Create a Checkout Session Add an endpoint on your server that creates a Checkout Session. A Checkout Session controls what your customer sees on the Tokenz-hosted payment page, such as line items, the order amount, currency, and available payment methods. ### Define the line items Always keep sensitive information about your product inventory, like price and availability, on your server to prevent customer manipulation from the client. Define product information when you create the Checkout Session. **Tax.** This quickstart (and its example payloads) documents the Merchant of Record (MoR) model — the default for Tokenz accounts — where Tokenz computes and collects tax automatically and you only set each item's `taxCategory`. If your account is specially configured for the Payment Gateway model, every Checkout Session must additionally include a top-level `tax` object in minor units (for example `"tax": { "amount": 0, "currency": "USD" }`); requests without it are rejected with `order.tax-required`. If you're unsure which model your account uses, check with your Tokenz contact. ### Supply success and cancel URLs Specify URLs for success and cancel pages—make sure they're publicly accessible so Tokenz can redirect customers to them. You can also handle the successful and canceled states with the same URL. ### [optional] Define available payment method(s) Specify the list of payment methods offered to your customer for this checkout. If the payment methods are not provided or an empty list is sent, all available payment methods will be displayed to the customer. ### Redirect the customer to the Tokenz checkout After creating the session, redirect your customer to the checkout page's URL returned in the response. #### 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); }); }); ``` ## Build your checkout ### Add a success page Create a success page for the URL you provided as the Checkout Session `successUrl` to display order confirmation messaging or order details to your customer. Tokenz redirects to this page after the customer successfully completes the checkout. ```html Thanks for your order!

We appreciate your business! If you have any questions, please email orders@example.com.

``` ### Add a processing payment page For asynchronous payment methods, like convenience store payment or bank transfer, the payment might be in a processing state for a few minutes up to a few days. Add a page for the `pendingUrl`. Tokenz redirects to this page after the customer closes the instructions page for asynchronous payments. ```html Thanks for your order!

Your payment is being processed! We will let you know as soon as it is completed. If you have any questions, please email orders@example.com.

``` ### Add a canceled page Add another page for `cancelUrl`. Tokenz redirects customers to this page when they click the back button during checkout. ```html Checkout canceled

Forgot to add something to your cart? Shop around then come back to pay!

``` ### Add a checkout button Finally, add a page to show customers a preview of their order. Allow them to review or modify their order—as soon as they land on the Checkout page, the order is final, and they can't modify it without creating a new Checkout Session. Add a button to your order preview page. Customers are redirected to the Tokenz-hosted payment page when they click this button. ```html Buy cool new product
ひとにぎりのエメラルド

ひとにぎりのエメラルド

1,200円
```