# Ülke, il ya da posta koduna göre kapıda ödemeyi gizleme

> Metafield’da listelediğiniz ülke, il ya da posta kodu öneklerinde kapıda ödemeyi gizleyen Shopify ödeme özelleştirme Function’ı; test edilmiş JavaScript.

Sayfa: https://lintelagency.com/tr/kaynaklar/shopify-functions/bolgeye-gore-kapida-odemeyi-gizleme

## Kısaca

Bu ödeme özelleştirme Function’ı, teslimat adresi hariç tuttuğunuz bir ülkede, ilde ya da posta kodu aralığındaysa kapıda ödemeyi gizler. Listeler bir JSON metafield’da durur; deploy etmeden değiştirebilirsiniz. Payment Customization API’nin cart.payment-methods.transform.run hedefini kullanır (sürüm 2026-10) ve herkese açık bir uygulamada her planda çalışır.

## Bilgiler

- **Function API:** Payment Customization
- **Hedef (target):** cart.payment-methods.transform.run
- **Plan:** Herkese açık uygulamada her plan; özel uygulamada Shopify Plus
- **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 (shopify app init), ardından 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. Test dosyalarını çalıştırın: shopify app function run --input tests/excluded-province.input.json (diğerleri için de).
4. shopify app deploy ile deploy edin, uygulamayı kurun ve özelleştirmeyi paymentCustomizationCreate ile oluşturun.
5. Bölgeleri özelleştirmenin $app:function-configuration metafield’ına yazın; örneğin {"provinces": ["US:AK", "US:HI"], "zipPrefixes": ["969"]}.

## Kod

### shopify.extension.toml

```toml
api_version = "2026-10"

[[extensions]]
name = "Hide Cash on Delivery by region"
handle = "hide-cod-by-region"
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 {
    deliveryGroups {
      deliveryAddress {
        countryCode
        provinceCode
        zip
      }
    }
  }
  paymentMethods {
    id
    name
  }
  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
 */

/**
 * Settings stored as JSON in the customization's metafield. The region lists
 * are empty by default, so nothing is hidden until the merchant sets them.
 */
const DEFAULT_CONFIG = {
  // Matched case-insensitively against the start of the payment method name.
  methodNames: ["Cash on Delivery", "Kapıda Ödeme"],
  // ISO country codes, e.g. "US".
  countries: [],
  // Country and province code joined by a colon, e.g. "US:AK" or "CA:NU".
  provinces: [],
  // ZIP or postal code prefixes, e.g. "99" or "34450". Spaces are ignored.
  zipPrefixes: [],
};

/**
 * Lowercase for matching, with Turkish dotless/dotted i folded to "i", so
 * "KAPIDA ÖDEME" and "Kapıda Ödeme" match the same configured name.
 * @param {string} text
 */
const fold = (text) => text.toLowerCase().replace(/ı/g, "i").replace(/\u0307/g, "");

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

/** @param {string | null | undefined} value */
const normalizeZip = (value) => (value ?? "").replace(/\s+/g, "").toUpperCase();

/**
 * @param {CartPaymentMethodsTransformRunInput} input
 * @returns {CartPaymentMethodsTransformRunResult}
 */
export function cartPaymentMethodsTransformRun(input) {
  const config = { ...DEFAULT_CONFIG, ...input.paymentCustomization?.metafield?.jsonValue };
  const countries = config.countries.map((code) => code.toUpperCase());
  const provinces = config.provinces.map((code) => code.toUpperCase());
  const zipPrefixes = config.zipPrefixes.map(normalizeZip).filter(Boolean);

  // A cart can ship to several addresses (split delivery); one excluded
  // address is enough, because COD applies to the whole order.
  const addresses = input.cart.deliveryGroups
    .map((group) => group.deliveryAddress)
    .filter((address) => address != null);
  const excluded = addresses.some((address) => {
    const country = (address.countryCode ?? "").toUpperCase();
    const province = `${country}:${(address.provinceCode ?? "").toUpperCase()}`;
    const zip = normalizeZip(address.zip);
    return (
      countries.includes(country) ||
      provinces.includes(province) ||
      (zip !== "" && zipPrefixes.some((prefix) => zip.startsWith(prefix)))
    );
  });
  if (!excluded) return NO_CHANGES;

  const names = config.methodNames.map(fold);
  const operations = input.paymentMethods
    .filter((method) => names.some((name) => fold(method.name).startsWith(name)))
    .map((method) => ({ paymentMethodHide: { paymentMethodId: method.id } }));

  return { operations };
}
```

## Test girdisi ve beklenen çıktı

### tests/allowed-region.input.json

```json
{
  "cart": {
    "deliveryGroups": [
      { "deliveryAddress": { "countryCode": "US", "provinceCode": "NY", "zip": "10001" } }
    ]
  },
  "paymentMethods": [
    { "id": "gid://shopify/PaymentCustomizationPaymentMethod/1", "name": "Credit card" },
    { "id": "gid://shopify/PaymentCustomizationPaymentMethod/2", "name": "Cash on Delivery (COD)" }
  ],
  "paymentCustomization": {
    "metafield": {
      "jsonValue": { "countries": ["IS"], "provinces": ["US:AK", "US:HI"], "zipPrefixes": ["969"] }
    }
  }
}
```

### tests/allowed-region.output.json

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

### tests/excluded-province.input.json

```json
{
  "cart": {
    "deliveryGroups": [
      { "deliveryAddress": { "countryCode": "US", "provinceCode": "AK", "zip": "99501" } }
    ]
  },
  "paymentMethods": [
    { "id": "gid://shopify/PaymentCustomizationPaymentMethod/1", "name": "Credit card" },
    { "id": "gid://shopify/PaymentCustomizationPaymentMethod/2", "name": "Cash on Delivery (COD)" }
  ],
  "paymentCustomization": {
    "metafield": {
      "jsonValue": { "countries": ["IS"], "provinces": ["US:AK", "US:HI"], "zipPrefixes": ["969"] }
    }
  }
}
```

### tests/excluded-province.output.json

```json
{
  "operations": [
    { "paymentMethodHide": { "paymentMethodId": "gid://shopify/PaymentCustomizationPaymentMethod/2" } }
  ]
}
```

### tests/excluded-zip-prefix.input.json

```json
{
  "cart": {
    "deliveryGroups": [
      { "deliveryAddress": { "countryCode": "US", "provinceCode": "GU", "zip": "96910" } }
    ]
  },
  "paymentMethods": [
    { "id": "gid://shopify/PaymentCustomizationPaymentMethod/1", "name": "Credit card" },
    { "id": "gid://shopify/PaymentCustomizationPaymentMethod/2", "name": "Cash on Delivery (COD)" }
  ],
  "paymentCustomization": {
    "metafield": {
      "jsonValue": { "countries": ["IS"], "provinces": ["US:AK", "US:HI"], "zipPrefixes": ["969"] }
    }
  }
}
```

### tests/excluded-zip-prefix.output.json

```json
{
  "operations": [
    { "paymentMethodHide": { "paymentMethodId": "gid://shopify/PaymentCustomizationPaymentMethod/2" } }
  ]
}
```

### tests/no-address-yet.input.json

```json
{
  "cart": { "deliveryGroups": [{ "deliveryAddress": null }] },
  "paymentMethods": [
    { "id": "gid://shopify/PaymentCustomizationPaymentMethod/1", "name": "Credit card" },
    { "id": "gid://shopify/PaymentCustomizationPaymentMethod/2", "name": "Cash on Delivery (COD)" }
  ],
  "paymentCustomization": {
    "metafield": {
      "jsonValue": { "countries": ["IS"], "provinces": ["US:AK", "US:HI"], "zipPrefixes": ["969"] }
    }
  }
}
```

### tests/no-address-yet.output.json

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

## Sınırlar ve özel durumlar

- Müşteri teslimat adresini girene kadar hiçbir şey gizlenmez; o ana kadar kontrol edilecek bir adres yoktur.
- İl kodları, Shopify’ın adreste sakladığı koddur (provinceCode). Hariç tutmak istediğiniz bölgeye bir test siparişi verip kodu siparişten kopyalayın.
- Posta kodu boşluklar silinerek önekle eşleşir; "969", 969 ile başlayan tüm kodları kapsar. Önek çok genişse tam kod yazın.
- Sepet birden fazla adrese gönderiliyorsa, tek bir hariç adres bütün sipariş için kapıda ödemeyi gizler.

## Sorular

### Shopify’da belirli posta kodlarında kapıda ödemeyi nasıl kapatırım?

Shopify’ın ödeme ayarları posta koduna göre filtreleyemiyor. Bu örnekteki gibi bir ödeme özelleştirme Function’ı teslimat adresini okur ve posta kodu listelediğiniz bir önekle başlıyorsa kapıda ödemeyi gizler.

### Kapıda ödemeyi yalnızca bir ilde gizleyebilir miyim?

Evet. Ülke ve il kodunu provinces listesine ekleyin, örneğin "US:AK". Aynı ülkenin diğer illerinde kapıda ödeme görünmeye devam eder.

### Müşteri adres girmeden kapıda ödeme neden hâlâ görünüyor?

Function bölgeyi ancak bir teslimat adresi olduğunda bilir. Adres girildikten sonra checkout Function’ı yeniden çalıştırır ve kapıda ödeme o zaman kaybolur.

### Bunu sepet tutarı sınırıyla birlikte kullanabilir miyim?

Evet. Sepet tutarı örneğini ikinci bir ödeme özelleştirmesi olarak kurun ya da oradaki tutar kontrolünü bu Function’a ekleyin. Bir mağazada en fazla 25 ödeme özelleştirmesi çalışabilir.

## Shopify belgeleri

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

## İlgili içerikler

- [Teslimat, ödeme ya da doğrulama Function’ını etkinleştirme](https://lintelagency.com/tr/kaynaklar/graphql/function-ozellestirmesini-etkinlestirme)
- [Sepet tutarı belli bir sınırı aşınca kapıda ödemeyi gizleme](https://lintelagency.com/tr/kaynaklar/shopify-functions/sepet-tutarina-gore-kapida-odemeyi-gizleme)
- [Function’ları metafield (meta alan) ile yapılandırmak: kuralı yeni sürüm yayınlamadan değiştirin](https://lintelagency.com/tr/blog/shopify-functions-metafield-ile-yapilandirma)
- [Shopify Scripts çalışmayı bıraktı. Her script’in mantığı artık nereye gidiyor?](https://lintelagency.com/tr/blog/shopify-scriptsten-functionsa-gecis)

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