Ü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.

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

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.

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
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
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
// @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
{
  "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
{ "operations": [] }
tests/excluded-province.input.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
{
  "operations": [
    { "paymentMethodHide": { "paymentMethodId": "gid://shopify/PaymentCustomizationPaymentMethod/2" } }
  ]
}
tests/excluded-zip-prefix.input.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
{
  "operations": [
    { "paymentMethodHide": { "paymentMethodId": "gid://shopify/PaymentCustomizationPaymentMethod/2" } }
  ]
}
tests/no-address-yet.input.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
{ "operations": [] }

Lintel tarafından yazıldı. MIT lisansı: kendi mağazanızda da müşteri işlerinizde de ücretsiz kullanabilirsiniz.

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.

Sık sorulan 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.
  • Function API sürümü 2026-10 için yazıldı ve gösterilen tarihte Shopify’ın başvuru belgeleriyle karşılaştırıldı. Shopify her çeyrekte yeni bir sürüm yayımlar.
  • Function içeren özel (custom) uygulamalar yalnızca Shopify Plus mağazalarında çalışır. Aynı Function herkese açık bir uygulamada, sayfada aksi yazmıyorsa her planda çalışır.
  • Her örnek test verileriyle gelir ve yayımlamadan önce bu testleri çalıştırırız. Kodu değiştirdikten sonra testleri tekrar çalıştırın: shopify app function run.
  • MIT lisansı. Kodu kendi mağazanızda da müşteri işlerinizde de kullanabilirsiniz.

Mağazanız için kurulmasını, test edilmesini ve bakımını isterseniz: Shopify Functions geliştirme.

Geliştirmek istediğiniz bir şey mi var? Gelin, birlikte konuşalım.

Aynı anda sınırlı sayıda proje alıyoruz.

Gencer KarakayaShopify mühendisi

Proje özetinizi bir mühendis okur; size e-postayla yanıt veririz.