# B2B alıcılar için vadeli ödeme koşulları

> B2B şirket alıcılarına 30 gün (ya da 7–90 gün) vade ve isteğe bağlı peşinat tanımlayan Shopify ödeme özelleştirme Function’ı. Shopify Plus.

Sayfa: https://lintelagency.com/tr/kaynaklar/shopify-functions/b2b-vadeli-odeme-kosullari

## Kısaca

Bu ödeme özelleştirme Function’ı, B2B şirket alıcılarına vadeli ödeme koşulu (varsayılan 30 gün) tanımlar; şirket bazında farklı vade ve isteğe bağlı peşinat da verebilirsiniz. Bireysel müşteriler etkilenmez. Payment Customization API’nin cart.payment-methods.transform.run hedefindeki paymentTermsSet işlemini kullanır (2026-10). Shopify, paymentTermsSet’e yalnızca Plus planındaki mağazalarda izin verir.

## Bilgiler

- **Function API:** Payment Customization
- **Hedef (target):** cart.payment-methods.transform.run
- **Plan:** Shopify Plus (paymentTermsSet)
- **Uygulama yetkisi:** write_payment_customizations
- **API sürümü:** 2026-10
- **Son kontrol:** 2 Kasım 2026

## Nasıl kullanılır

1. Shopify CLI ile bir uygulama oluşturun ve uzantıyı ekleyin: shopify app generate extension --template payment_customization, dil olarak JavaScript.
2. Oluşturulan shopify.extension.toml dosyasını ve src/ içindeki iki dosyayı aşağıdakilerle değiştirin.
3. Testleri çalıştırın: shopify app function run --input tests/company-default-terms.input.json.
4. shopify app deploy ile deploy edin ve Plus mağazada özelleştirmeyi paymentCustomizationCreate ile oluşturun.
5. $app:function-configuration metafield’ını ayarlayın; örneğin {"dueInDays": 30, "companyDueInDays": {"gid://shopify/Company/1234567890": 60}, "depositPercentage": 20}.

## Kod

### shopify.extension.toml

```toml
api_version = "2026-10"

[[extensions]]
name = "Net payment terms for B2B buyers"
handle = "b2b-net-payment-terms"
type = "function"

  [[extensions.targeting]]
  target = "cart.payment-methods.transform.run"
  input_query = "src/cart_payment_methods_transform_run.graphql"
  export = "cart-payment-methods-transform-run"

  [extensions.build]
  command = ""
  path = "dist/function.wasm"
```

### src/cart_payment_methods_transform_run.graphql

```graphql
query CartPaymentMethodsTransformRunInput {
  cart {
    buyerIdentity {
      purchasingCompany {
        company {
          id
        }
      }
    }
  }
  paymentCustomization {
    metafield(namespace: "$app", key: "function-configuration") {
      jsonValue
    }
  }
}
```

### src/cart_payment_methods_transform_run.js

```js
// @ts-check

/**
 * @typedef {import("../generated/api").CartPaymentMethodsTransformRunInput} CartPaymentMethodsTransformRunInput
 * @typedef {import("../generated/api").CartPaymentMethodsTransformRunResult} CartPaymentMethodsTransformRunResult
 */

/** Net terms Shopify accepts for dueInDays in API version 2026-10. */
const SUPPORTED_DUE_IN_DAYS = [7, 15, 30, 45, 60, 90];

/** Settings stored as JSON in the customization's metafield. */
const DEFAULT_CONFIG = {
  // Terms for every company buyer without an override below.
  dueInDays: 30,
  // Company ID → days, e.g. { "gid://shopify/Company/1234567890": 60 }.
  companyDueInDays: /** @type {Record<string, number>} */ ({}),
  // Optional deposit (1–99 % of the order total) paid at checkout; null for none.
  depositPercentage: /** @type {number | null} */ (null),
};

/** @type {CartPaymentMethodsTransformRunResult} */
const NO_CHANGES = { operations: [] };

/**
 * @param {CartPaymentMethodsTransformRunInput} input
 * @returns {CartPaymentMethodsTransformRunResult}
 */
export function cartPaymentMethodsTransformRun(input) {
  const company = input.cart.buyerIdentity?.purchasingCompany?.company;
  // Consumers (no purchasing company) keep paying at checkout.
  if (!company) return NO_CHANGES;

  const config = { ...DEFAULT_CONFIG, ...input.paymentCustomization?.metafield?.jsonValue };
  const dueInDays = (config.companyDueInDays ?? {})[company.id] ?? config.dueInDays;
  // An unsupported value would make Shopify reject the operation; leave the
  // company's own terms in place instead.
  if (!SUPPORTED_DUE_IN_DAYS.includes(dueInDays)) return NO_CHANGES;

  // Shopify accepts a deposit of 1–99 %; anything else is left out rather than rejected.
  const percentage = config.depositPercentage;
  const deposit = Number.isFinite(percentage) && percentage >= 1 && percentage <= 99 ? { percentage } : null;
  return {
    operations: [{ paymentTermsSet: { paymentTerms: { net: { dueInDays, deposit } } } }],
  };
}
```

## Test girdisi ve beklenen çıktı

### tests/company-default-terms.input.json

```json
{
  "cart": {
    "buyerIdentity": { "purchasingCompany": { "company": { "id": "gid://shopify/Company/1234567890" } } }
  },
  "paymentCustomization": { "metafield": null }
}
```

### tests/company-default-terms.output.json

```json
{
  "operations": [
    { "paymentTermsSet": { "paymentTerms": { "net": { "dueInDays": 30, "deposit": null } } } }
  ]
}
```

### tests/company-override-with-deposit.input.json

```json
{
  "cart": {
    "buyerIdentity": { "purchasingCompany": { "company": { "id": "gid://shopify/Company/1234567890" } } }
  },
  "paymentCustomization": {
    "metafield": {
      "jsonValue": {
        "companyDueInDays": { "gid://shopify/Company/1234567890": 60 },
        "depositPercentage": 20
      }
    }
  }
}
```

### tests/company-override-with-deposit.output.json

```json
{
  "operations": [
    { "paymentTermsSet": { "paymentTerms": { "net": { "dueInDays": 60, "deposit": { "percentage": 20 } } } } }
  ]
}
```

### tests/consumer-checkout.input.json

```json
{
  "cart": { "buyerIdentity": { "purchasingCompany": null } },
  "paymentCustomization": { "metafield": null }
}
```

### tests/consumer-checkout.output.json

```json
{ "operations": [] }
```

## Sınırlar ve özel durumlar

- Bu API sürümünde vade olarak yalnızca 7, 15, 30, 45, 60 ya da 90 gün kabul edilir; başka bir değer yok sayılır ve şirketin kendi koşulları geçerli kalır.
- Peşinat, sipariş toplamının yüzde 1 ile 99’u arasında olmalıdır.
- Sepette abonelik ürünü varsa ödeme koşulu tanımlanamaz; mağaza vitrinindeki hızlı ödeme (accelerated checkout) düğmelerinde de desteklenmez.
- Aynı işlemle olaya bağlı vade (örneğin gönderim yapıldığında ödeme) ve sabit vade tarihi de tanımlanabilir; bu örnek yalnızca gün bazlı vade (net terms) kullanır.

## Sorular

### Shopify’da toptan müşterilere 30 gün vade nasıl verilir?

Bu örnekteki gibi, şirket alıcıları için net vadeli paymentTermsSet döndüren bir ödeme özelleştirme Function’ı kullanın. Aynı Function bazı şirketlere daha uzun vade verebilir ya da peşinat isteyebilir.

### Shopify Plus olmadan çalışır mı?

Hayır. Shopify’ın referansına göre paymentTermsSet yalnızca Plus planındaki mağazalarda kullanılabilir.

### Büyük B2B siparişlerinde peşinat isteyebilir miyim?

Evet. depositPercentage’ı ayarlayın; alıcı bu oranı ödeme sırasında, kalanını vade gelince öder. Peşinatı sipariş tutarına bağlamak için input sorgusuna cart.cost.totalAmount ekleyin.

### Bazı alıcılar için ödeme koşulunu kaldırabilir miyim?

Evet. paymentTerms değeri null olan bir paymentTermsSet döndürmek o ödeme için koşulu kaldırır; alıcı peşin öder.

## Shopify belgeleri

- [Payment Customization Function API](https://shopify.dev/docs/api/functions/latest/payment-customization)

## İlgili içerikler

- [Teslimat, ödeme ya da doğrulama Function’ını etkinleştirme](https://lintelagency.com/tr/kaynaklar/graphql/function-ozellestirmesini-etkinlestirme)
- [Shopify’da B2B: plana ve özelliğe göre seçenekler](https://lintelagency.com/tr/blog/shopify-b2b-secenekleri)
- [Hangi Shopify Functions özellikleri Shopify Plus gerektirir?](https://lintelagency.com/tr/blog/hangi-shopify-functions-ozellikleri-plus-gerektirir)
- [Shopify Plus’a ihtiyacınız var mı? Gerçekten Plus gerektiren özellikler](https://lintelagency.com/tr/blog/shopify-plus-gerekli-mi)

Lisans: MIT. Kendi mağazanızda da müşteri işlerinizde de ücretsiz kullanabilirsiniz.
