go get github.com/kvell/kvell-gopackage main
import (
"os"
"github.com/kvell/kvell-go"
)
func newKvellClient() *kvell.Client {
return kvell.NewClient(kvell.Config{
APIKey: os.Getenv("KVELL_API_KEY"),
SecretKey: os.Getenv("KVELL_SECRET_KEY"),
Environment: "sandbox", // switch to "production" when you go live
})
}
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/kvell/kvell-go"
)
func main() {
client := kvell.NewClient(kvell.Config{
APIKey: os.Getenv("KVELL_API_KEY"),
SecretKey: os.Getenv("KVELL_SECRET_KEY"),
Environment: "sandbox",
})
// Amounts are always integers in kuruş (1/100 TRY) — 15000 = 150.00 TRY
session, err := client.PaymentSessions.Create(context.Background(), kvell.CreateSessionParams{
TransactionID: "ORDER-2026-001",
Amount: 15000,
Currency: "TRY",
Description: "Order #1234",
ReturnURL: "https://merchant.example.com/return",
})
if err != nil {
log.Fatalf("create session: %v", err)
}
fmt.Println("Redirect the buyer to:", session.CheckoutURL)
}
package main
import (
"context"
"errors"
"log"
"os"
"github.com/kvell/kvell-go"
)
func main() {
client := kvell.NewClient(kvell.Config{
APIKey: os.Getenv("KVELL_API_KEY"),
SecretKey: os.Getenv("KVELL_SECRET_KEY"),
Environment: "sandbox",
})
payment, err := client.Payments.Charge(context.Background(), kvell.ChargeParams{
TransactionID: "ORDER-2026-001",
Amount: 15000, // kuruş
Currency: "TRY",
CardToken: "tok_9f8e7d6c5b4a",
})
if err != nil {
var kerr *kvell.Error
if errors.As(err, &kerr) {
switch kerr.Code {
case "KVELL-PAY-4001":
log.Fatalf("card declined (requestId=%s)", kerr.RequestID)
case "KVELL-GW-1002":
log.Fatalf("signature invalid, check your secret key (requestId=%s)", kerr.RequestID)
default:
log.Fatalf("kvell error %s (requestId=%s)", kerr.Code, kerr.RequestID)
}
}
log.Fatalf("charge failed: %v", err)
}
log.Printf("captured payment %s", payment.PaymentID)
}
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"io"
"net/http"
"os"
"github.com/kvell/kvell-go"
)
var seenEventIDs = map[string]bool{} // swap for Redis/DB in production
func kvellWebhookHandler(w http.ResponseWriter, r *http.Request) {
rawBody, _ := io.ReadAll(r.Body) // raw bytes, never the parsed JSON
signature := r.Header.Get("X-Kvell-Signature")
eventID := r.Header.Get("X-Kvell-Event-Id")
mac := hmac.New(sha256.New, []byte(os.Getenv("KVELL_WEBHOOK_SECRET")))
mac.Write(rawBody)
expected := "sha256=" + hex.EncodeToString(mac.Sum(nil))
if !hmac.Equal([]byte(signature), []byte(expected)) {
http.Error(w, "invalid signature", http.StatusUnauthorized)
return
}
if seenEventIDs[eventID] {
w.WriteHeader(http.StatusOK) // already processed, ack and stop
return
}
seenEventIDs[eventID] = true
var event kvell.Event
json.Unmarshal(rawBody, &event)
switch event.EventType {
case "payment.captured":
// Fulfil the order asynchronously; respond fast below
}
w.WriteHeader(http.StatusOK)
}