Bu sayfada
Kimlik Doğrulama
Her Merchant API isteğini HMAC-SHA256 ile doğrulayın: zorunlu başlıklar, kanonik yük oluşturma, zaman damgaları ve tekrar koruması.
Her Paymos API isteği, kanonik bir dize üzerinden hesaplanan HMAC-SHA256 imzası taşır. Kimlik bilgilerini panelde üretirsiniz — kimlik türleri, kapsamlar ve yaşam döngüsü için API Anahtarları bölümüne bakın.
İmzalama şeması
Her API isteği iki zorunlu ve bir isteğe bağlı başlık taşır:
| Başlık | Açıklama |
|---|---|
Authorization |
HMAC-SHA256 {apiKeyId}:{base64signature} — API anahtarı ID'niz (örn. pk_live_...) ve imza |
X-Request-Timestamp |
Geçerli Unix zaman damgası (saniye) |
X-Correlation-Id |
(isteğe bağlı) İstek takibi için kendi korelasyon ID'niz |
İmzalama yükü
İmza Base64(HMAC-SHA256(api_secret, string_to_sign)) şeklindedir; burada:
string_to_sign = timestamp + "\n" + METHOD + "\n" + path + "\n" + query + "\n" + bodyHash
| Bileşen | Açıklama |
|---|---|
timestamp |
X-Request-Timestamp ile aynı değer |
METHOD |
Büyük harfle HTTP metodu (POST, GET) |
path |
URL-decode edilmiş istek yolu, sorgu dizesi olmadan (/v1/invoices) |
query |
? dahil sorgu dizesi (yoksa boş dize) |
bodyHash |
İstek gövdesinin hex kodlu SHA-256'sı (küçük harf). Gövde yoksa boş dize — boş dizeyi hash'lemeYİN |
Gövde olmadığında bodyHash boş dizedir. Boş dizeyi hash'lemeyin: SHA-256("") sabit, boş olmayan bir özet döndürür; bu durumda sunucu sizinkinden farklı bir string_to_sign hesaplar ve imzayı reddeder.
İmza oluşturma
Örnek: JSON gövdeli POST /v1/invoices
1709000000\nPOST\n/v1/invoices\n\n<sha256hex of body>
Burada query bileşeni boştur (sorgu parametresi yok) ve bodyHash, istek gövdesinin küçük harfli hex SHA-256 özetidir.
Örnek: GET /v1/invoices/inv_74BPZFhr9qy9Uz2fbRkdJX
1709000000\nGET\n/v1/invoices/inv_74BPZFhr9qy9Uz2fbRkdJX\n\n
Sorgu dizesi ve istek gövdesi olmadığı için son iki bileşen boş dizedir.
Tekrar (replay) koruması
X-Request-Timestamp, sunucu saatinin kabul edilebilir zaman penceresi içinde olmalıdır (varsayılan ±5 dakika). Pencere dışındaki istekler yetkisiz olarak reddedilir (timestamp_expired).
Sunucu saatiniz kayıyorsa, kimlik doğrulaması gerektirmeyen time uç noktasından sunucu saatini okuyun ve imzalamadan önce ofsetinizi düzeltin:
GET /v1/time
{ "server_time": 1739280600 }
server_time, Unix saniyesi cinsinden geçerli sunucu saatidir. Kimlik doğrulama gerekmez. Kendi saatinizle karşılaştırın ve gönderdiğiniz X-Request-Timestamp değerini buna göre ayarlayın.
Secret rotasyonu ek süresi
API secret'ınızı rotasyona aldığınızda, önceki secret bir ek süre boyunca geçerli kalır. Bu pencere içinde, mevcut veya önceki secret ile hesaplanan imzaların ikisi de kabul edilir. Mevcut ek süre dolmadan yeni bir rotasyon başlatılamaz.
SDK örneği
Resmî SDK, kanonik dizeyi kurar ve her isteği imzalar. Uygulama kodu yalnızca kimlik bilgilerini ve tiplenmiş istek alanlarını sağlar.
API_KEY_ID="pk_live_xxxxxxxxxxxx"
API_SECRET="sk_live_xxxxxxxxxxxx"
BODY='{"project_id":"prj_xxxxxxxxxxxx","amount":"100.00","currency":"USD","external_order_id":"order-123","client_id":"customer-456"}'
TS=$(date +%s)
BODY_HASH=$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | sed 's/^.* //')
SIGNATURE=$(printf '%s\n%s\n%s\n%s\n%s' "$TS" POST /v1/invoices '' "$BODY_HASH" \
| openssl dgst -sha256 -hmac "$API_SECRET" -binary | base64)
curl -sS https://api.paymos.io/v1/invoices \
-H "Authorization: HMAC-SHA256 $API_KEY_ID:$SIGNATURE" \
-H "X-Request-Timestamp: $TS" \
-H "Content-Type: application/json" \
-d "$BODY"
import { Paymos, externalOrderId } from '@paymos/sdk';
const paymos = new Paymos({
apiKey: process.env.PAYMOS_API_KEY,
apiSecret: process.env.PAYMOS_API_SECRET,
});
const invoice = await paymos.invoices.create({
projectId: 'prj_xxxxxxxxxxxx',
amount: '100.00',
currency: 'USD',
externalOrderId: externalOrderId('order'),
clientId: 'customer-456',
});
console.log(invoice.invoiceId, invoice.paymentUrl);
import os
from paymos import Paymos
paymos = Paymos(
api_key=os.environ["PAYMOS_API_KEY"],
api_secret=os.environ["PAYMOS_API_SECRET"],
)
invoice = paymos.invoices.create(
project_id="prj_xxxxxxxxxxxx",
amount="100.00",
currency="USD",
external_order_id="order-123",
client_id="customer-456",
)
print(invoice["invoice_id"], invoice["payment_url"])
<?php
use Paymos\Client;
use Paymos\ClientConfig;
use Paymos\IdempotencyKey;
$paymos = new Client(new ClientConfig(
getenv('PAYMOS_API_KEY'),
getenv('PAYMOS_API_SECRET')
));
$invoice = $paymos->invoices()->create(array(
'project_id' => 'prj_xxxxxxxxxxxx',
'amount' => '100.00',
'currency' => 'USD',
'external_order_id' => IdempotencyKey::externalOrderId('order'),
'client_id' => 'customer-456',
));
echo $invoice['invoice_id'] . ' ' . $invoice['payment_url'];
package main
import (
"context"
"fmt"
"os"
paymos "github.com/Paymos-labs/go-sdk/v2"
)
func main() {
client, err := paymos.NewClient(os.Getenv("PAYMOS_API_KEY"), os.Getenv("PAYMOS_API_SECRET"))
if err != nil {
panic(err)
}
invoice, err := client.Invoices.Create(context.Background(), paymos.CreateInvoiceParams{
ProjectID: "prj_xxxxxxxxxxxx",
Amount: "100.00",
Currency: "USD",
ExternalOrderID: "order-123",
ClientID: stringPointer("customer-456"),
})
if err != nil {
panic(err)
}
fmt.Println(invoice.InvoiceID, invoice.PaymentURL)
}
func stringPointer(value string) *string { return &value }
using Paymos;
using var paymos = new PaymosClient(
Environment.GetEnvironmentVariable("PAYMOS_API_KEY")!,
Environment.GetEnvironmentVariable("PAYMOS_API_SECRET")!);
var invoice = await paymos.Invoices.CreateAsync(new CreateInvoiceRequest(
ProjectId: "prj_xxxxxxxxxxxx",
Amount: "100.00",
Currency: "USD",
ExternalOrderId: "order-123",
ClientId: "customer-456"));
Console.WriteLine($"{invoice.InvoiceId} {invoice.PaymentUrl}");
import io.paymos.CreateInvoiceRequest;
import io.paymos.Invoice;
import io.paymos.PaymosClient;
PaymosClient paymos = new PaymosClient(
System.getenv("PAYMOS_API_KEY"),
System.getenv("PAYMOS_API_SECRET"));
Invoice invoice = paymos.invoices.create(
CreateInvoiceRequest.builder()
.projectId("prj_xxxxxxxxxxxx")
.amount("100.00")
.currency("USD")
.externalOrderId("order-123")
.clientId("customer-456")
.build());
System.out.println(invoice.invoiceId() + " " + invoice.paymentUrl());
require 'paymos'
paymos = Paymos::Client.new(
api_key: ENV.fetch('PAYMOS_API_KEY'),
api_secret: ENV.fetch('PAYMOS_API_SECRET')
)
invoice = paymos.invoices.create(
project_id: 'prj_xxxxxxxxxxxx',
amount: '100.00',
currency: 'USD',
external_order_id: 'order-123',
client_id: 'customer-456'
)
puts "#{invoice.invoice_id} #{invoice.payment_url}"
use paymos::{CreateInvoiceRequest, PaymosClient};
let paymos = PaymosClient::new(
std::env::var("PAYMOS_API_KEY")?,
std::env::var("PAYMOS_API_SECRET")?,
)?;
let invoice = paymos
.invoices()
.create(&CreateInvoiceRequest {
project_id: "prj_xxxxxxxxxxxx".to_owned(),
amount: "100.00".to_owned(),
currency: "USD".to_owned(),
external_order_id: "order-123".to_owned(),
network: None,
allow_multiple_payments: None,
customer_fee_percent: None,
client_id: Some("customer-456".to_owned()),
})
.await?;
println!("{} {}", invoice.invoice_id, invoice.payment_url);