> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tahsilat.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Kart Elementleri

> Kendi ödeme formunuzda güvenli ödeme alma

Kart Elementleri, kendi tasarladığınız ödeme formuna güvenli bir kart girişi alanı yerleştirmenizi sağlar. Hassas kart bilgileri Tahsilat'ın PCI-DSS uyumlu iframe'i içinde kalır, hiçbir zaman sizin sunucularınızdan geçmez.

<Note>
  Kart Elementleri ile ödeme formunun tamamını siz tasarlarsınız. Tahsilat.com sadece kart numarası, son kullanma tarihi ve CVV alanlarını güvenli bir iframe olarak sağlar. Taksit, bin sorgulama gibi işlemleri sizin yerinize otomatik yapar.
</Note>

## Kurulum ve Kart Elementini Oluşturma

<CodeGroup>
  ```html HTML theme={null}
  <style>
      #card-element {
          width: 100%;
          height: 44px;
          border: 1px solid #d2d2d2;
          border-radius: 8px;
      }
  </style>

  <div id="card-element"></div>
  <select id="installment-select" style="display: none;"></select>
  <button id="pay-btn" disabled>Ödemeyi Tamamla</button>

  <script src="https://js.tahsilat.com/v1/tahsilat.js"></script>
  ```
</CodeGroup>

## Kart Elementi Oluşturma

Kart elementi, güvenli kart bilgisi toplama alanını sayfanıza yerleştirir. Temel kullanımda sadece tutar ve para birimi yeterlidir. Taksit, stil, placeholder gibi ek özellikler için aşağıdaki bölümlere bakınız.

<CodeGroup>
  ```js JS theme={null}
  const tahsilat = new TahsilatSDK('pk_test_wsg...');
  const elements = tahsilat.elements();

  const cardElement = elements.create('card', {
      amount: 10000,
      currency: 'TRY'
  }).on('ready', () => {
      console.log('Kart formu hazır');
  }).on('change', (state) => {
      document.getElementById('pay-btn').disabled = !state.complete;
  }).mount('#card-element');
  ```

  ```js Debug Modu theme={null}
  const tahsilat = new TahsilatSDK('pk_test_wsg...', {
      debug: true
  });

  const elements = tahsilat.elements();

  const cardElement = elements.create('card', {
      amount: 10000,
      currency: 'TRY'
  }).on('ready', () => {
      console.log('Kart formu hazır');
  }).on('change', (state) => {
      document.getElementById('pay-btn').disabled = !state.complete;
  }).mount('#card-element');
  ```
</CodeGroup>

<Info>
  `amount` kuruş cinsindendir. 100,00 TL için `10000` olarak girilmelidir. `currency` belirtilmezse varsayılan `TRY` kullanılır.
</Info>

## Ödeme Başlatma

Kart bilgileri girildikten sonra `confirmPayment` metodu ile ödeme başlatılır. Aşağıda farklı senaryolar için örnekler bulunmaktadır.

### 1. Müşteri Bilgileri ile Ödeme

<Warning>
  Ödeme isteği oluşturulurken customer\_id gönderilmemesi durumunda her ödeme için müşteri bilgileri tekrar alınır ve yeni bir müşteri oluşturulur. Bu durumda müşteri takibi ve raporlama süreci zorlaşabilir.

  Üye işyeri arayüzünden ya da [Müşteriler](../api-reference/customers) sayfasından api aracılığı ile müşteri oluşturarak customer\_id parametresini kullanabilirsiniz.
</Warning>

<CodeGroup>
  ```js JS theme={null}
  document.getElementById('pay-btn').addEventListener('click', async () => {
      const btn = document.getElementById('pay-btn');
      btn.disabled = true;

      try {
          const result = await cardElement.confirmPayment({
              cardholder_name: 'Ahmet Yılmaz',
              customer_email: 'ahmet@email.com',
              customer_phone: '5551234567',
              customer_phone_code: '+90',
              customer_country: 'TR' // ISO 3166-1 alpha-2 kabul edilir.
          });

          console.log('Ödeme işlemi başarılı sonucu kontrol ediniz:', result);
      } catch (err) {
          console.error('Hata:', err);
          btn.disabled = false;
      }
  });
  ```

  ```js Debug Modu theme={null}
  // SDK'yı debug modu ile başlatın
  const tahsilat = new TahsilatSDK('pk_test_wsg...', {
      debug: true
  });

  const elements = tahsilat.elements();

  const cardElement = elements.create('card', {
      amount: 10000,
      currency: 'TRY'
  }).on('ready', () => {
      console.log('Kart formu hazır');
  }).on('change', (state) => {
      console.log('Kart durumu:', state);
      document.getElementById('pay-btn').disabled = !state.complete;
  }).on('installments', (data) => {
      console.log('Taksit seçenekleri:', data);
  }).mount('#card-element');
      // Ödeme
      document.getElementById('pay-btn').addEventListener('click', async () => {
      const btn = document.getElementById('pay-btn');
      btn.disabled = true;

      try {
          const result = await cardElement.confirmPayment({
          cardholder_name: 'Ahmet Yılmaz',
          customer_email: 'ahmet@email.com',
          customer_phone: '5551234567',
          customer_phone_code: '+90',
          customer_country: 'TR'
      });

          console.log('Ödeme sonucu:', result);
      } catch (err) {
          console.error('Hata detayı:', err);
          console.error('Hata tipi:', err.type);
          console.error('Hata kodu:', err.code);
          btn.disabled = false;
      }
  });
  ```
</CodeGroup>

### 2. Müşteri ID ile Ödeme

Mevcut bir müşteriyi `customer_id` ile ilişkilendirdiğinizde müşteri bilgileri zorunlu değildir. Müşteri, public key ile oluşturulamaz; sadece secret key ile oluşturulabilir ve JS SDK bunu desteklemez.  Bunun için [Müşteriler](../api-reference/customers) sayfasını kontrol ediniz.

<CodeGroup>
  ```js JS theme={null}
  const result = await cardElement.confirmPayment({
      cardholder_name: 'Ahmet Yılmaz',
      customer_id: 123456789,
      metadata: [
          { key: "order_id", value: "123456" },
          { key: "customer_type", value: "premium" }
      ],
  });
  ```
</CodeGroup>

### 3. Ürün ID'leri ile Ödeme

Önceden oluşturulmuş ürün ID'lerini kullanarak ödeme başlatabilirsiniz. Ürün, public key ile oluşturulamaz; sadece secret key ile oluşturulabilir ve JS SDK bunu desteklemez. Bunun için [Ürünler](../api-reference/products) sayfasını kontrol ediniz.

<CodeGroup>
  ```js JS theme={null}
  const result = await cardElement.confirmPayment({
      cardholder_name: 'Ahmet Yılmaz',
      customer_id: 123456789,
      product_ids: ['11111111111111', '2222222222222'],
      metadata: [
          { key: "order_id", value: "123456" },
          { key: "customer_type", value: "premium" }
      ],
  });
  ```
</CodeGroup>

### 4. Ürün Bilgileri İle Ödeme

<CodeGroup>
  ```js JS theme={null}
  const result = await cardElement.confirmPayment({
      cardholder_name: 'Ahmet Yılmaz',
      customer_email: 'ahmet@email.com',
      customer_phone: '5551234567',
      customer_phone_code: '+90',
      customer_country: 'TR',
      products: [
          {
              product_name: 'Premium Üyelik',
              price: 10000,
              description: 'Aylık üyelik'
          }
      ],
      metadata: [
          { key: "order_id", value: "123456" },
          { key: "customer_type", value: "premium" }
      ],
  });
  ```
</CodeGroup>

### 5. Müşteri ile İlişkilendirilmiş Ödeme

Mevcut bir müşteriyi ödeme ile ilişkilendirmek için `customer_id` parametresini kullanabilirsiniz. Bu durumda ödeme esnasında müşteri bilgileri tekrardan alınmaz:

Müşteri oluşturmak için [Müşteriler](../api-reference/customers) sayfasını ziyaret edebilirsiniz.

<CodeGroup>
  ```js JS theme={null}
  const result = await cardElement.confirmPayment({
      cardholder_name: 'Ahmet Yılmaz',
      customer_id: 123456789,
      product_ids: ['11111111111111', '2222222222222'],
      metadata: [
          { key: "order_id", value: "123456" },
          { key: "customer_type", value: "premium" }
      ],
  });
  ```
</CodeGroup>

### Ödeme Sonuçlarını Dinleme

Tahsilat.js SDK, ödeme işlemlerinin sonuçlarını event listener'lar aracılığıyla yakalamanızı sağlar. Bu sayede ödeme başarılı, başarısız veya iptal edildiğinde kullanıcıya bilgi verebilir ve gerekli aksiyonları alabilirsiniz.

<Warning>
  Eğer ödemeyi `pre_auth: true` ile başlattıysanız, sonuç aldığınızda **is\_pre\_auth** değerini kontrol edin. `true` dönmesi durumunda ödeme başarılıdır ancak tutar karttan çekilmemiş, yalnızca bloke edilmiştir. Bloke edilen tutarı çekmek için ayrıca **ön provizyonu kapatma** işlemi yapmanız gerekmektedir.
</Warning>

<CodeGroup>
  ```js Temel Kullanım theme={null}

  const tahsilat = new TahsilatSDK('pk_test_wsg...');

  // Başarılı ödeme
  tahsilat.on('paymentSuccess', function(data) {
      console.log('Ödeme başarılı:', data);
      // Örnek: Teşekkür sayfasına yönlendir
  });

  // Başarısız ödeme
  tahsilat.on('paymentError', function(data) {
      console.log('Ödeme hatası:', data);
      // Örnek: Kullanıcıya hata mesajı göster
  });

  // İptal edilen ödeme
  tahsilat.on('paymentCancelled', function(data) {
      console.log('Ödeme iptal edildi:', data);
      // Örnek: Sepet sayfasına yönlendir
  });
  ```

  ```json Başarılı Yanıt theme={null}
  {
      "success": true,
      "transaction_id": "21325480405674",
      "payment_status": 1,
      "transaction_status": 2,
      "is_pre_auth": false,
      "amount": 50000,
      "currency": "TRY",
      "message": "İşleminiz başarılı bir şekilde tamamlanmıştır.",
      "error_code": "",
      "metadata": [
          { "key": "order_id", "value": "123456" },
          { "key": "customer_type", "value": "premium" }
      ]
  }
  ```

  ```json Başarısız Yanıt theme={null}
  {
      "success": false,
      "transaction_id": "20544083688242",
      "payment_status": 2,
      "transaction_status": 2,
      "is_pre_auth": false,
      "amount": 50000,
      "currency": "TRY",
      "message": "Hatalı test kart bilgisi.",
      "error_code": "invalid_test_card",
      "metadata": [
          { "key": "order_id", "value": "123456" },
          { "key": "customer_type", "value": "premium" }
      ]
  }
  ```
</CodeGroup>

### Yanıt Alanları

| Alan                 | Tip     | Açıklama                                  |
| -------------------- | ------- | ----------------------------------------- |
| `success`            | boolean | İşlem başarılı mı                         |
| `transaction_id`     | string  | Tahsilat işlem numarası                   |
| `payment_status`     | integer | `1`: Başarılı, `2`: Başarısız             |
| `transaction_status` | integer | `2`: Tamamlandı, `3`: Ön provizyon        |
| `is_pre_auth`        | boolean | Ön provizyon işlemi mi                    |
| `amount`             | integer | Tutar (kuruş)                             |
| `currency`           | string  | Para birimi                               |
| `message`            | string  | Durum mesajı                              |
| `error_code`         | string  | Hata kodu (başarısızsa)                   |
| `metadata`           | array   | Ödeme başlatılırken gönderilen ek veriler |

## Taksit

Kullanıcı kart numarasının ilk 6-8 hanesini girdiğinde SDK otomatik olarak BIN sorgulaması yapar ve taksit seçeneklerini döner. Bu seçenekleri kendi UI'ınızda göstermeniz gerekir.

<Warning>
  Taksit seçeneklerindeki `installment` değeri şifrelenmiş bir değerdir. Bu değeri olduğu gibi `installment_count` parametresine geçmelisiniz. Düz sayı (1, 2, 3...) göndermeyiniz.
</Warning>

### Taksit Akışı

1. Kullanıcı kart numarasını girer
2. SDK otomatik BIN lookup yapar
3. `installments` eventi tetiklenir
4. Siz taksit seçeneklerini gösterirsiniz
5. Seçilen taksitin **şifreli** `installment` değerini `installment_count` olarak göndermelisiniz.

### Tam Örnek

Aşağıda taksit seçimi dahil uçtan uca bir ödeme akışı gösterilmektedir. Bu örneği kendi projenize uygun şekilde özelleştirebilirsiniz.

<CodeGroup>
  ```js JS theme={null}
  let selectedInstallment = null;

  const cardElement = elements.create('card', {
      amount: 10000,
      currency: 'TRY'
  }).on('installments', (data) => {
      const select = document.getElementById('installment-select');

      if (!data.installments) {
          selectedInstallment = null;
          select.style.display = 'none';

          return;
      }

      selectedInstallment = data.installments[0].installment;
      select.style.display = 'block';
      select.innerHTML = data.installments.map(item =>
      `<option value="${item.installment}">
              ${item.installment_text} - ₺${item.total_amount}
          </option>`
      ).join('');

      select.addEventListener('change', (e) => {
          selectedInstallment = e.target.value;
      });
  }).on('change', (state) => {
      document.getElementById('pay-btn').disabled = !state.complete;
  }).mount('#card-element');

  // Ödeme
  document.getElementById('pay-btn').addEventListener('click', async () => {
      try {
          const result = await cardElement.confirmPayment({
              cardholder_name: 'Ahmet Yılmaz',
              installment_count: selectedInstallment,
              customer_email: 'ahmet@email.com',
              customer_phone: '5551234567',
              customer_phone_code: '+90',
              customer_country: 'TR',
              products: [
                  { product_name: 'Ürün', price: 10000 }
              ]
          });

          console.log('Ödeme işlemi başarılı sonucu kontrol ediniz:', result);
      } catch (err) {
          console.error('Hata:', err);
      }
  });
  ```
</CodeGroup>

### Installments Event Verisi

<CodeGroup>
  ```json Örnek theme={null}
  {
      "installments": [
          {
              "installment": "eyJpdiI6Ij...",
              "installment_count": 1,
              "installment_text": "Tek çekim",
              "total_amount": "100.00",
              "installment_amount": "100.00",
              "commission_rate": "0.00",
              "commission_by": "1",
              "commission_by_text": "company",
          },
          {
              "installment": "eyJpdiI6Ik...",
              "installment_count": 3,
              "installment_text": "3 Taksit",
              "total_amount": "105.00",
              "installment_amount": "35.00",
              "commission_rate": "5.00",
              "commission_by": "2",
              "commission_by_text": "customer",
          }
      ],
      "binDetail": {
          "brand": "mastercard",
          "type": "credit",
          "bank_name": "Yapı Kredi"
      }
  }
  ```
</CodeGroup>

| Alan                 | Tip     | Açıklama                                                                    |
| -------------------- | ------- | --------------------------------------------------------------------------- |
| `installment`        | string  | Şifreli taksit değeri. `installment_count` parametresine bu değeri geçirin. |
| `installment_count`  | integer | Taksit sayısı (görüntüleme amaçlı).                                         |
| `installment_text`   | string  | Görüntüleme metni.                                                          |
| `total_amount`       | string  | Komisyon dahil toplam tutar.                                                |
| `installment_amount` | string  | Taksit başına tutar.                                                        |
| `commission_rate`    | string  | Komisyon oranı (%).                                                         |

## Özelleştirme

Ödeme parametrelerini önceden tanımlayarak `confirmPayment()` çağrısını basitleştirebilirsiniz:

<CodeGroup>
  ```js Stil theme={null}
  const cardElement = elements.create('card', {
      amount: 10000,
      currency: 'TRY',
      style: {
          fontSize: '16px',
          fontFamily: 'Arial, sans-serif',
          color: '#333333',
          '::placeholder': {
              color: '#aaaaaa'
          }
      },
      placeholder: {
          cardNumber: '0000 0000 0000 0000',
          expiry: 'AA/YY',
          cvv: 'CVV'
      }
  });

  cardElement.mount('#card-element');
  ```

  ```js Event'ler theme={null}
  const cardElement = elements.create('card', {
      amount: 10000,
      currency: 'TRY'
  }).on('ready', () => {
      console.log('Kart formu hazır');
  })
  .on('change', (state) => {
      // state.complete - tüm alanlar geçerli mi
      // state.brand   - kart markası (visa, mastercard, troy...)
      // state.error   - hata mesajı (varsa)
      // state.empty   - form boş mu
      document.getElementById('pay-btn').disabled = !state.complete;
  })
  .on('installments', (data) => {
      // data.installments - taksit listesi
      // data.binDetail    - kart BIN bilgisi
  })
  .on('focus', (data) => {
      // data.field - odaklanan alan
  })
  .on('blur', (data) => {
      // data.field - odaktan çıkan alan
  });
  ```
</CodeGroup>

## Event'ler

| Event          | Açıklama                                                                                   |
| -------------- | ------------------------------------------------------------------------------------------ |
| `ready`        | Kart elementi yüklendi ve kullanıma hazır.                                                 |
| `change`       | Kart bilgisi değişti. `state.complete`, `state.brand`, `state.error`, `state.empty` döner. |
| `installments` | BIN lookup sonucu taksit seçenekleri geldi.                                                |
| `focus`        | Bir alan odaklandı. `data.field` ile hangi alan olduğu döner.                              |
| `blur`         | Bir alan odaktan çıktı.                                                                    |

## confirmPayment() Parametreleri

| Parametre             | Tip     | Zorunlu | Açıklama                                                               |
| --------------------- | ------- | ------- | ---------------------------------------------------------------------- |
| `cardholder_name`     | string  | ✓       | Kart sahibinin adı ve soyadı.                                          |
| `installment_count`   | string  |         | Şifreli taksit değeri. Gönderilmezse tek çekim uygulanır.              |
| `customer_id`         | integer |         | Mevcut müşteri ID. Gönderildiğinde müşteri bilgileri zorunlu değildir. |
| `customer_email`      | string  | \*      | Müşteri e-posta. `customer_id` yoksa zorunlu.                          |
| `customer_phone`      | string  | \*      | Müşteri telefon. `customer_id` yoksa zorunlu.                          |
| `customer_phone_code` | string  | \*      | Telefon ülke kodu (örn. `+90`). `customer_id` yoksa zorunlu.           |
| `customer_country`    | string  | \*      | Ülke kodu (örn. `TR`). `customer_id` yoksa zorunlu.                    |
| `products`            | array   |         | Ürün bilgileri. `product_ids` gönderilmiyorsa kullanılabilir.          |
| `product_ids`         | array   |         | Önceden oluşturulmuş ürün ID'leri.                                     |
| `metadata`            | array   |         | Ek veriler. `[{ key: "...", value: "..." }]` formatında.               |
| `description`         | string  |         | Ödeme açıklaması.                                                      |

## elements.create() Parametreleri

| Parametre     | Tip     | Zorunlu | Açıklama                                              |
| ------------- | ------- | ------- | ----------------------------------------------------- |
| `amount`      | integer | ✓       | Ödeme tutarı, kuruş cinsinden.                        |
| `currency`    | string  |         | Para birimi. Varsayılan: `TRY`.                       |
| `locale`      | string  |         | Dil. Varsayılan: `tr`.                                |
| `style`       | object  |         | Kart elementinin stil ayarları.                       |
| `placeholder` | object  |         | Placeholder metinleri: `{ cardNumber, expiry, cvv }`. |
| `hideErrors`  | boolean |         | Hata mesajlarını gizle. Varsayılan: `false`.          |

<Info>
  Ödeme tutarı ile ürünlerin toplam tutarı eşleşmelidir. Aksi takdirde ödeme reddedilir.
</Info>

<Warning>
  Ödeme sonuçlarını almak için `confirmPayment` promise sonucunu dinleyebilir veya backend tarafında webhook entegrasyonu yapabilirsiniz. Webhook en güvenilir yöntemdir.
</Warning>
