Entegrasyon kodu
Aşağıdaki kodu backend projenize tek dosya olarak ekleyin. Touchque ile tüm iletişim bu dosya üzerinden yürür. Kendi dilinizi seçin.
Bu dosya 2 bölüm içerir:
1) requireTouchque middleware ile rota korunur — onaya kadar 202 döner
2) Handler çalıştığında onayı req.touchque üzerinden okuyun
1) requireTouchque middleware ile rota korunur — onaya kadar 202 döner
2) Handler çalıştığında onayı req.touchque üzerinden okuyun
Endpoint
| Yol | İşlev |
|---|---|
POST /api/login | requireTouchque('LOGIN') ile korunur |
POST /api/transfer | requireTouchque('SEND_MONEY') ile korunur |
Onay tek bir kullanıcı + işlem + işlem detayına bağlıdır ve tam olarak bir kez tüketilebilir — token başka bir tutar, alıcı veya kullanıcı için tekrar kullanılamaz.
Express entegrasyon dosyası
const express = require('express');
const { requireTouchque } = require('@touchque/node');
const app = express();
app.use(express.json());
// ─── TQ_API_KEY / TQ_API_SECRET ortam değişkenlerinden okunur ───
// ═══════════════════════════════════════
// 1) Hassas İşlem Rotaları — Tek Satır Middleware!
// ═══════════════════════════════════════
// Giriş işlemi için 2FA onayı iste
app.post(
'/api/login',
requireTouchque('LOGIN', { user: (req) => req.session.passwordOk }),
(req, res) => {
// ✅ Buraya sadece kullanıcı telefonundan ONAYLADIKTAN sonra ulaşılır.
res.json({ success: true, assurance: req.touchque.assurance });
}
);
// Para transferi işlemi için 2FA onayı iste (işlem detaylarıyla)
app.post(
'/api/transfer',
requireTouchque('SEND_MONEY', {
user: (req) => req.session.user?.email,
details: (req) => ({ Amount: `${req.body.amount} EUR`, To: req.body.iban }),
}),
(req, res) => {
res.json({ success: true, message: 'Transfer tamamlandı!' });
}
);
// ═══════════════════════════════════════
// 2) Bu sırada gerçekte ne oluyor?
// ═══════════════════════════════════════
// a) İlk istek 202 { touchque: step, token } döner (henüz onay yok).
// b) Arayüzünüz step.number'ı (veya ilk bağlantı için step.enroll.qrCodeDataUrl) kendi
// tasarımınızla gösterir, sonra aynı isteği X-Touchque-Token başlığıyla tekrar gönderir
// (@touchque/web'in touchqueFetch()'i bu döngüyü sizin için halleder).
// c) Onaylandığında yukarıdaki handler TAM OLARAK BİR KEZ çalışır.
app.listen(3000, () => console.log('Server: http://localhost:3000'));<?php
// bootstrap/app.php (Laravel 11+)
$middleware->alias(['touchque' => \Touchque\Laravel\TouchqueMiddleware::class]);
// ─── Bir service provider içinde ───
// $this->app->singleton(\Touchque\Touchque::class, fn () => new \Touchque\Touchque());
// (TQ_API_KEY / TQ_API_SECRET ortam değişkenlerinden okunur)
// ═══════════════════════════════════════
// routes/api.php — Hassas İşlem Rotaları
// ═══════════════════════════════════════
Route::post('/login', [LoginController::class, 'store'])
->middleware('touchque:LOGIN');
Route::post('/transfer', [TransferController::class, 'store'])
->middleware('touchque:SEND_MONEY');
// TransferController@store:
//
// public function store(Request $request) {
// // Buraya sadece kullanıcı telefonundan ONAYLADIKTAN sonra ulaşılır.
// $approval = $request->attributes->get('touchque');
// return response()->json(['success' => true, 'assurance' => $approval['assurance']]);
// }
// İlk istek 202 { touchque: step, token } döner; onaylandığında controller
// tam olarak bir kez çalışır — bkz. @touchque/web ile arayüz tarafı.package main
import (
"encoding/json"
"log"
"net/http"
"github.com/Touchque/touchque-go/v5/touchque"
)
func main() {
tq, err := touchque.New() // TQ_API_KEY / TQ_API_SECRET from the environment
if err != nil {
log.Fatal(err)
}
// 1) Hassas İşlem Rotaları — tek satır sarmalayıcı!
mux := http.NewServeMux()
mux.Handle("/api/login", touchque.Require(tq, "LOGIN", http.HandlerFunc(loginHandler), touchque.RequireOptions{
User: func(r *http.Request) string { return sessionUser(r) }, // şifre adımını geçen kullanıcı
}))
mux.Handle("/api/transfer", touchque.Require(tq, "SEND_MONEY", http.HandlerFunc(transferHandler), touchque.RequireOptions{
User: func(r *http.Request) string { return sessionUser(r) },
Details: func(r *http.Request) []touchque.LoginDetail {
return []touchque.LoginDetail{{Label: "Amount", Value: amountFromRequest(r)}}
},
}))
log.Fatal(http.ListenAndServe(":3000", mux))
}
func loginHandler(w http.ResponseWriter, r *http.Request) {
// ✅ Buraya sadece kullanıcı telefonundan ONAYLADIKTAN sonra ulaşılır.
approval, _ := touchque.ApprovalFromContext(r.Context())
json.NewEncoder(w).Encode(map[string]interface{}{"success": true, "assurance": approval.Assurance})
}
func transferHandler(w http.ResponseWriter, r *http.Request) {
// Buraya sadece kullanıcı telefonundan ONAYLADIKTAN sonra ulaşılır.
approval, _ := touchque.ApprovalFromContext(r.Context())
json.NewEncoder(w).Encode(map[string]interface{}{"success": true, "assurance": approval.Assurance})
}
// sessionUser ve amountFromRequest sizin oturum ve istek yardımcılarınızdır.
// İlk istek 202 { touchque: step, token } döner; onaylandığında handler
// tam olarak bir kez çalışır — bkz. @touchque/web ile arayüz tarafı.from flask import Flask, g, jsonify, request, session
from touchque.contrib.flask import require_touchque
app = Flask(__name__)
app.secret_key = "change-me" # Flask oturumu için
# ─── TQ_API_KEY / TQ_API_SECRET ortam değişkenlerinden okunur ───
# ═══ 1) Hassas İşlem Rotaları — tek satır decorator! ═══
@app.post("/api/login")
@require_touchque("LOGIN", user=lambda: session.get("password_ok"))
def login():
# ✅ Buraya sadece kullanıcı telefonundan ONAYLADIKTAN sonra ulaşılır.
return jsonify(success=True, touchque=g.touchque)
@app.post("/api/transfer")
@require_touchque("SEND_MONEY", details=lambda: {"Amount": f'{request.json["amount"]} EUR'})
def transfer():
return jsonify(success=True, message="Transfer tamamlandı!")
# İlk istek 202 { touchque: step, token } döner; onaylandığında view
# tam olarak bir kez çalışır — bkz. @touchque/web ile arayüz tarafı.
if __name__ == "__main__":
app.run(port=3000)using Touchque.AspNetCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddTouchque(); // TQ_API_KEY / TQ_API_SECRET ortam değişkenlerinden okunur
var app = builder.Build();
// ═══════════════════════════════════════
// 1) Hassas İşlem Rotaları — uç nokta başına tek satır!
// ═══════════════════════════════════════
app.MapPost("/api/login", (HttpContext http) =>
// ✅ Buraya sadece kullanıcı telefonundan ONAYLADIKTAN sonra ulaşılır.
Results.Ok(new { success = true, assurance = http.GetTouchqueApproval()!.Assurance }))
.RequireTouchque("LOGIN", o => o.User = c => c.HttpContext.Session.GetString("password_ok"));
app.MapPost("/api/transfer", (Transfer t) => Results.Ok(new { success = true, message = "Transfer tamamlandı!" }))
.RequireAuthorization()
.RequireTouchque("SEND_MONEY", o => o.Details = c =>
[("Amount", $"{c.Argument<Transfer>()!.Amount} EUR"), ("To", c.Argument<Transfer>()!.Iban)]);
// İlk istek 202 { touchque: step, token } döner; onaylandığında uç nokta
// tam olarak bir kez çalışır — bkz. @touchque/web ile arayüz tarafı.
// Controller için: [RequireTouchque("SEND_MONEY")]
app.Run();
record Transfer(decimal Amount, string Iban);// build.gradle.kts: implementation("com.touchque:touchque-spring-boot-starter:5.2.0") (Maven Central)
// TQ_API_KEY / TQ_API_SECRET ortam değişkenlerinden (veya touchque.api-key / touchque.api-secret) okunur
// ═══════════════════════════════════════
// 1) Hassas İşlem Rotaları — metot başına tek satır!
// ═══════════════════════════════════════
@RestController
class Api {
@PostMapping("/api/login")
@RequireTouchque("LOGIN")
Map<String, Object> login(Approval approval) {
// ✅ Buraya sadece kullanıcı telefonundan ONAYLADIKTAN sonra ulaşılır.
return Map.of("success", true, "assurance", approval.assurance());
}
@PostMapping("/api/transfer")
@RequireTouchque("SEND_MONEY")
Map<String, Object> transfer(@RequestBody Transfer t) {
return Map.of("success", true, "message", "Transfer tamamlandı!");
}
}
record Transfer(BigDecimal amount, String iban) {}
// Telefonda ne görüneceği (ve giriş adımını kimin onaylayacağı):
@Bean
TouchqueGuardOptions loginGuard() {
return TouchqueGuardOptions.forAction("LOGIN")
.user(c -> (String) c.request().getSession().getAttribute("password_ok"));
}
@Bean
TouchqueGuardOptions sendMoneyGuard() {
return TouchqueGuardOptions.forAction("SEND_MONEY").details(c -> List.of(
LoginDetail.of("Amount", c.argument(Transfer.class).amount() + " EUR"),
LoginDetail.of("To", c.argument(Transfer.class).iban())));
}
// İlk istek 202 { touchque: step, token } döner; onaylandığında metot
// tam olarak bir kez çalışır — bkz. @touchque/web ile arayüz tarafı.# Gemfile: gem "touchque", "~> 5.0" (RubyGems)
# TQ_API_KEY / TQ_API_SECRET ortam değişkenlerinden (veya credentials.touchque) okunur
# ═══ 1) Hassas İşlem Rotaları — action başına tek satır! ═══
class SessionsController < ApplicationController
include Touchque::Rails::Guard
require_touchque "LOGIN", only: :create, user: -> { session[:password_ok] }
def create
# ✅ Buraya sadece kullanıcı telefonundan ONAYLADIKTAN sonra ulaşılır.
render json: { success: true, assurance: touchque_approval["assurance"] }
end
end
class TransfersController < ApplicationController
include Touchque::Rails::Guard
require_touchque "SEND_MONEY", only: :create,
details: -> { { "Amount" => "#{params.require(:amount)} EUR", "To" => params.require(:iban) } }
def create
render json: { success: true, message: "Transfer tamamlandı!" }
end
end
# İlk istek 202 { touchque: step, token } döner; onaylandığında action
# tam olarak bir kez çalışır — bkz. @touchque/web ile arayüz tarafı.