Chúng tôi có thể giúp gì?

Cho chúng tôi biết ngắn gọn về vấn đề – chúng tôi sẽ liên hệ lại qua email.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
Về trang chủ

Müşteri verileri uç noktası: siparişler, kargo ve faturalar

Müşteri verileri bağlantısının teknik referansı: reactive.chat tarafından mağazanıza gönderilen imzalı istek, yanıt şeması, sınırlar, hata nedenleri, eksiksiz PHP ve Node örnek uç noktaları ve API ile içe aktarma.

Müşteri verileri sayesinde yapay zekâ asistanı, “Kargom nerede?” veya “Faturam ödendi mi?” gibi soruları yanıtlar; bunu yalnızca doğrulanmış ziyaretçiler için ve yalnızca kendi siparişleri hakkında yapar. Bu sayfa, uç noktayı geliştiren kişi için teknik referanstır. Asistanın neleri gösterdiği ve hesabınızda hangi alanları etkinleştirebileceğiniz Sohbette müşteri verileri sayfasında açıklanır.

Ücretli planlarda kullanılabilir (deneme süresi dâhil).

Gereksinimler

  1. exp ile kimlik doğrulama. Ziyaretçinin geçerli bir userHash ve exp ile oturum açmış olması gerekir (Ziyaretçileri tanımlama). exp olmadan doğrulanmış sayılır, ancak kimliği güncel sayılmaz; bu durumda veri alınmaz.
  2. Hesabınızdaki ayar, Proje → Müşteri verileri altında: modu seçin, uç noktayı girin, alanları etkinleştirin ve oturum açmamış ziyaretçilere gösterilecek bildirimi belirleyin.

Modlar:

İstek

reactive.chat uç noktanızı POST ile çağırır:

POST /rc-kundendaten HTTP/1.1
Host: shop.your-company.com
Content-Type: application/json
Accept: application/json
User-Agent: reactive.chat-kundendaten/1
X-RC-Zeit: 1792503600
X-RC-Signatur: 5d41402abc4b2a76b9719d911017c592...

{"user_id":"4711","anliegen":"lieferung","referenz":"2026-0815","sprache":"en","nonce":"9f86d081884c7d659a2feaa0c55ad015"}

Üstbilgiler:

Gövde:

Uç noktanızın yapması gerekenler:

  1. imzayı yeniden kodlanmış JSON üzerinden değil, ham gövde üzerinden doğrulamak (sabit zamanlı karşılaştırma, örneğin hash_equals);
  2. X-RC-Zeit değeri kendi saatinizden 300 saniyeden fazla farklı olan istekleri reddetmek;
  3. her nonce değerini yalnızca bir kez kabul etmek (önerilir);
  4. yalnızca verilen user_id kimliğine ait verileri döndürmek;
  5. herkese açık bir adreste, 443 numaralı bağlantı noktasında https üzerinden erişilebilir olmak; yönlendirme ve adreste kullanıcı adı/şifre bulunmamalıdır;
  6. 3 saniye içinde eksiksiz yanıt vermek (bağlantı kurulması en fazla 2 saniye).

Yanıt

Tam olarak HTTP 200 ve bir JSON nesnesi. Eşleşme yoksa yine 200 ile {"bestellungen":[]} döndürülür.

{
  "bestellungen": [
    {
      "nummer": "2026-0815",
      "datum": "2026-09-28",
      "status": "shipped",
      "summe": "49.90",
      "waehrung": "EUR",
      "positionen": [ { "name": "Balance bike blue", "menge": 1 } ],
      "versand": { "dienst": "DHL", "sendungsnummer": "00340434161234567890", "status": "out for delivery" },
      "rechnung": { "nummer": "R-2026-1201", "status": "paid", "faellig_am": "2026-10-12" }
    }
  ]
}

Sipariş başına alanlar:

Sınırlar: en fazla 10 sipariş, sipariş başına 20 kalem, metinler en fazla 200 karakter, yanıtın tamamı en fazla 16.384 bayt. Bilinmeyen ve hesabınızda etkinleştirilmemiş alanlar hata verilmeden atılır.

Gönderseniz bile asla alınmayan veriler: sokak ve diğer adres satırları, adlar, e-posta, telefon, IBAN/BIC/hesap ve kart bilgileri, doğum tarihi, şifreler/tokenlar/anahtarlar, vergi ve kimlik numaraları. En iyisi bunları hiç göndermemektir.

Yanıtın kullanımı: yalnızca asistanın o tek yanıtında kullanılır ve saklanmaz; ne sohbete ne de bilgi tabanına kaydedilir. Kayıtta yalnızca sayı ve süre tutulur. Uç noktanız zamanında yanıt vermez veya hata döndürürse asistan veri yokmuş gibi yanıtlar.

PHP ile örnek uç nokta

<?php
declare(strict_types=1);

$GEHEIMNIS = (string) getenv('RC_KD_GEHEIMNIS');   // rckd_... from the account

function antworte(int $status, array $daten): never {
    http_response_code($status);
    header('Content-Type: application/json; charset=utf-8');
    header('Cache-Control: no-store');
    echo json_encode($daten, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') { antworte(405, ['fehler' => 'POST only']); }

$body = (string) file_get_contents('php://input', false, null, 0, 4097);
if (strlen($body) > 4096) { antworte(413, ['fehler' => 'too large']); }

$zeit = (string) ($_SERVER['HTTP_X_RC_ZEIT'] ?? '');
$sig  = strtolower((string) ($_SERVER['HTTP_X_RC_SIGNATUR'] ?? ''));
if (!preg_match('/^\d{9,11}$/', $zeit) || abs(time() - (int) $zeit) > 300) {
    antworte(401, ['fehler' => 'zeit']);
}
if (!hash_equals(hash_hmac('sha256', $zeit . '.' . $body, $GEHEIMNIS), $sig)) {
    antworte(401, ['fehler' => 'signatur']);
}

$j        = json_decode($body, true);
$userId   = is_string($j['user_id'] ?? null) ? $j['user_id'] : '';
$referenz = is_string($j['referenz'] ?? null) ? trim($j['referenz']) : '';
$nonce    = is_string($j['nonce'] ?? null) ? $j['nonce'] : '';
if ($userId === '' || !preg_match('/^[0-9a-f]{32}$/', $nonce)) {
    antworte(400, ['fehler' => 'anfrage']);
}

$pdo = new PDO(getenv('SHOP_DB_DSN'), getenv('SHOP_DB_USER'), getenv('SHOP_DB_PASS'),
               [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

// nonce only once: CREATE TABLE rc_nonce (nonce CHAR(32) PRIMARY KEY, zeit INT NOT NULL);
$pdo->prepare('DELETE FROM rc_nonce WHERE zeit < ?')->execute([time() - 600]);
try {
    $pdo->prepare('INSERT INTO rc_nonce (nonce, zeit) VALUES (?, ?)')->execute([$nonce, time()]);
} catch (PDOException $e) {
    antworte(409, ['fehler' => 'nonce already used']);
}

if ($userId === 'rc-test') { antworte(200, ['bestellungen' => []]); }   // test button

// ONLY this customer; the reference is only a filter
$sql = 'SELECT id, nummer, datum, status, summe, waehrung, versand_dienst, sendungsnummer,
               versand_status, rechnung_nummer, rechnung_status, faellig_am
          FROM bestellungen WHERE kunde_id = :u';
$w = [':u' => $userId];
if ($referenz !== '') {
    $sql .= ' AND (nummer = :r1 OR rechnung_nummer = :r2 OR sendungsnummer = :r3)';
    $w += [':r1' => $referenz, ':r2' => $referenz, ':r3' => $referenz];
}
$st = $pdo->prepare($sql . ' ORDER BY datum DESC LIMIT 10');
$st->execute($w);

$pos = $pdo->prepare('SELECT name, menge FROM bestell_positionen WHERE bestellung_id = ? LIMIT 20');
$aus = [];
foreach ($st->fetchAll(PDO::FETCH_ASSOC) as $b) {
    $pos->execute([$b['id']]);
    $aus[] = [
        'nummer'     => (string) $b['nummer'],
        'datum'      => $b['datum'],
        'status'     => $b['status'],
        'summe'      => $b['summe'],
        'waehrung'   => $b['waehrung'],
        'positionen' => $pos->fetchAll(PDO::FETCH_ASSOC),
        'versand'    => ['dienst' => $b['versand_dienst'], 'sendungsnummer' => $b['sendungsnummer'],
                         'status' => $b['versand_status']],
        'rechnung'   => ['nummer' => $b['rechnung_nummer'], 'status' => $b['rechnung_status'],
                         'faellig_am' => $b['faellig_am']],
    ];
}
antworte(200, ['bestellungen' => $aus]);

Node.js (Express) ile örnek uç nokta

const crypto = require('crypto');
const express = require('express');
const app = express();
const GEHEIM = process.env.RC_KD_GEHEIMNIS;
const gesehen = new Map();   // nonce -> time; a database in production

app.post('/rc-kundendaten', express.raw({ type: 'application/json', limit: '4kb' }), async (req, res) => {
  const body = req.body.toString('utf8');          // RAW body
  const zeit = String(req.get('X-RC-Zeit') || '');
  const sig  = String(req.get('X-RC-Signatur') || '').toLowerCase();
  if (!/^\d{9,11}$/.test(zeit) || Math.abs(Date.now() / 1000 - Number(zeit)) > 300) {
    return res.status(401).json({ fehler: 'zeit' });
  }
  const soll = crypto.createHmac('sha256', GEHEIM).update(zeit + '.' + body).digest('hex');
  if (sig.length !== soll.length || !crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(soll))) {
    return res.status(401).json({ fehler: 'signatur' });
  }
  const j = JSON.parse(body);
  if (!/^[0-9a-f]{32}$/.test(j.nonce || '') || gesehen.has(j.nonce)) {
    return res.status(409).json({ fehler: 'nonce' });
  }
  gesehen.set(j.nonce, Date.now());
  if (j.user_id === 'rc-test') { return res.json({ bestellungen: [] }); }

  const bestellungen = await ladeBestellungen(j.user_id, j.referenz);   // ONLY this customer
  res.json({ bestellungen: bestellungen.slice(0, 10) });
});

Bağlantıyı test etme

Hesabınızdaki Bağlantıyı test et düğmesi, uç noktanızı user_id rc-test ve anliegen test ile çağırır. Bunun için boş bir liste veya örnek bir sipariş döndürün. Çağrı başarısız olursa hesabınızda şu nedenlerden biri belirtilir:

API ile içe aktarma

Mağazanız bir uç nokta sunamıyorsa verileri bize gönderirsiniz. Yalnızca müşteri verilerini içe aktarma (kundendaten:schreiben) kapsamına sahip bir API anahtarı ve İçe aktarma ya da İkisi de modu gerekir.

curl -X PUT "https://reactive.chat/v1/kundendaten/4711?project_id=123" \
  -H "Authorization: Bearer rc_live_..." \
  -H "Content-Type: application/json" \
  -d '{"bestellungen":[{"nummer":"2026-0815","datum":"2026-09-28","status":"shipped"}]}'

İçe aktarılan veriler şifreli saklanır (müşteri numarası yalnızca özet olarak) ve son içe aktarmadan 90 gün sonra silinir. Bu nedenle değişiklikleri düzenli gönderin; örneğin her durum değişikliğinde.

Hatalar: 402 plan_required (ücretli plan yok), 409 import_disabled (mod içe aktarmaya izin vermiyor, kd_modus ile), param (user_id, project_id, bestellungen) ile 400 bad_request, 404 (başkasının projesi). Genel hata biçimi Sunucu API’si altında açıklanır.

Oturum açmamış ziyaretçiler

Doğrulanmış kimliği olmayan biri bir sipariş hakkında soru sorarsa asistan veri almaz; bunun yerine hesabınızdaki bildirimi gösterir (dile göre metin, isteğe bağlı oturum açma bağlantısı) veya ekibinize aktarır.

Sonraki: Webhooks · Sunucu API’si

Cập nhật lần cuối: