B2B e-ticaretin kuralları B2C’den farklıdır. Toptan müşterin pazarlık edilmiş fiyatlar, hacim indirimleri, vadeli ödeme şartları ve hızlı yeniden sipariş bekler. ERP sistemin tüm bunları zaten yönetiyor. Asıl zorluk, iş kurallarını çoğaltmadan ERP destekli fiyatlandırma mantığını WooCommerce’te görünür kılmaktır.
Açık konuşayım: bu tür projelerde gördüğüm en yaygın hata, fiyat kurallarını ERP’den WooCommerce’e “kopyalamaya” çalışmak. Kulağa mantıklı gelir, birkaç hafta işe de yarar, sonra ERP’de biri bir kademe fiyatını değiştirir ve iki sistem sessizce ayrışır. O andan itibaren müşteri bir fiyat görür, faturada başka fiyat çıkar, ve sen cuma akşamı “neden bu sipariş yanlış fiyatlanmış” diye log okursun. Ben olsam WooCommerce’i hiçbir zaman fiyatın sahibi yapmazdım — sadece gösterdiği yer olsun. Sahibi ERP. Bu yazının tamamı bu tek ilkenin etrafında dönüyor.
B2B Fiyatlandırma Sorunu
ERP sisteminde fiyatlandırma tipik olarak şöyle görünür:
Customer: ABC Corp (Tier: Gold)
├── Product: Widget A
│ ├── List Price: $100
│ ├── Gold Tier Price: $75
│ ├── Volume 10+: $70
│ ├── Volume 50+: $65
│ └── Special Contract Price: $62 (until Dec 2026)
├── Product: Widget B
│ ├── List Price: $200
│ └── Gold Tier Price: $160
WooCommerce’te bunların hiçbiri doğal olarak yok. Woo, ürün başına bir normal fiyat ve bir indirimli fiyat destekler — o kadar. Müşteriye özel kademe, hacim kırılımı, sözleşme fiyatı, geçerlilik tarihi… bunların hepsi ERP’nin dünyasında yaşar ve orada kalmalı.
Mimari: ERP, Fiyatlandırma Motoru Olarak
Fiyatlandırma mantığını WooCommerce’te çoğaltma. ERP’ni doğrudan fiyatlandırma motoru olarak kullan. Akış kabaca şöyle işler:
Customer logs into WooCommerce
→ Frontend requests prices for visible products
→ Middleware queries ERP with customer ID + product SKUs
→ ERP returns customer-specific prices
→ Prices displayed in WooCommerce
Customer adds to cart
→ Cart total calculated using ERP prices
→ At checkout, final prices verified against ERP
→ Order created with ERP-validated prices
Uygulama: Gerçek Zamanlı Fiyat Sorgulaması
Özel REST Endpoint
// WordPress plugin: ERP Price Endpoint
add_action('rest_api_init', function() {
register_rest_route('b2b/v1', '/prices', [
'methods' => 'POST',
'callback' => 'get_erp_prices',
'permission_callback' => function() {
return is_user_logged_in();
}
]);
});
function get_erp_prices($request) {
$product_ids = $request->get_param('product_ids');
$customer_id = get_user_meta(get_current_user_id(), 'erp_customer_id', true);
if (!$customer_id) {
return new WP_Error('no_erp_account', 'No ERP account linked', ['status' => 400]);
}
// Call ERP API for customer-specific prices
$erp_prices = erp_get_customer_prices($customer_id, $product_ids);
return rest_ensure_response($erp_prices);
}
Middleware Fiyat Servisi
// Price lookup service
app.post('/api/prices', authenticateCustomer, async (req, res) => {
const { productSkus } = req.body;
const erpCustomerId = req.customer.erpId;
// Cache key: customer + SKU combination
const cacheKey = prices:${erpCustomerId}:${productSkus.sort().join(',')};
const cached = await redis.get(cacheKey);
if (cached) return res.json(JSON.parse(cached));
// Fetch from ERP
const prices = await erp.getCustomerPrices(erpCustomerId, productSkus);
// Transform to WooCommerce format
const result = prices.map(p => ({
sku: p.itemCode,
price: p.customerPrice,
listPrice: p.listPrice,
discount: ((p.listPrice - p.customerPrice) / p.listPrice * 100).toFixed(0),
volumePricing: p.volumeBreaks?.map(vb => ({
minQty: vb.quantity,
price: vb.price
})) || [],
currency: p.currency
}));
// Cache for 15 minutes
await redis.setex(cacheKey, 900, JSON.stringify(result));
res.json(result);
});
Müşteri Kademeleri ve Rol Tabanlı Fiyatlandırma
ERP müşteri kademelerini WooCommerce kullanıcı rollerine eşleştir. Bunu neden yaparsın? Çünkü fiyatı her seferinde ERP’den çeksen de, “bu kullanıcı B2B mi, hangi kademede” bilgisini WordPress tarafında bir role çevirmek görünürlük ve yetki kontrolünü çok kolaylaştırır:
// Sync ERP tiers to WooCommerce roles
function sync_customer_tier($user_id, $erp_tier) {
$tier_role_map = [
'standard' => 'customer',
'silver' => 'b2b_silver',
'gold' => 'b2b_gold',
'platinum' => 'b2b_platinum'
];
$role = $tier_role_map[$erp_tier] ?? 'customer';
$user = new WP_User($user_id);
$user->set_role($role);
}
// Create B2B roles on plugin activation
function create_b2b_roles() {
add_role('b2b_silver', 'B2B Silver', ['read' => true, 'b2b_access' => true]);
add_role('b2b_gold', 'B2B Gold', ['read' => true, 'b2b_access' => true]);
add_role('b2b_platinum', 'B2B Platinum', ['read' => true, 'b2b_access' => true]);
}
Hacim İndirimlerinin Görüntülenmesi
Ürün sayfalarında hacim fiyatlandırma tablolarını göster — toptancı müşteri “50 alırsam birim fiyat ne olur” sorusunun cevabını tıklamadan görmek ister:
// React component for volume pricing
function VolumePricing({ pricing }) {
if (!pricing.volumePricing?.length) return null;
return (
Miktar
Birim Fiyat
Tasarruf
1 - {pricing.volumePricing[0].minQty - 1}
${pricing.price}
—
{pricing.volumePricing.map(vp => (
{vp.minQty}+
${vp.price}
{((pricing.price - vp.price) / pricing.price * 100).toFixed(0)}% indirim
))}
);
}
Teklif/RFQ İş Akışı
Yüksek değerli veya özel siparişler için B2B müşteriler bir teklif iş akışı bekler. Bunu atlarsan, en kârlı siparişler için müşteri telefona sarılır ve satış ekibin Excel’e döner — tam da otomatikleştirmen gereken yerde:
// Request for Quote endpoint
app.post('/api/rfq', authenticateCustomer, async (req, res) => {
const { items, notes } = req.body;
// Create RFQ in ERP
const rfq = await erp.createQuote({
customerId: req.customer.erpId,
items: items.map(i => ({
sku: i.sku,
quantity: i.quantity,
requestedPrice: i.requestedPrice || null
})),
notes,
validUntil: addDays(new Date(), 30)
});
// Notify sales team
await notify.salesTeam({
type: 'new_rfq',
customer: req.customer.name,
totalValue: rfq.estimatedTotal,
rfqId: rfq.id
});
// Create WooCommerce order with "quote" status
const wcOrder = await wooApi.post('orders', {
status: 'quote',
customer_id: req.customer.wcId,
line_items: items.map(i => ({
product_id: i.productId,
quantity: i.quantity,
total: '0' // Price TBD
})),
meta_data: [
{ key: '_rfq_id', value: rfq.id },
{ key: '_rfq_status', value: 'pending' }
]
});
res.json({ rfqId: rfq.id, orderId: wcOrder.data.id });
});
Ödeme Şartları
B2B müşteriler vadeli şartlarla (Net 30, Net 60) ödeme yapar, ödeme sayfasında kart çekerek değil. B2C kafasıyla kurulmuş bir ödeme akışını olduğu gibi B2B’ye dayatmak, ilk toptancı müşteride çöker. Bunu şöyle ele al:
- Özel ödeme gateway’i: Ödeme almadan sipariş oluşturan “Satın Alma Siparişi / Vadeli Şartlar”
- ERP fatura oluşturma: Sipariş gönderildikten sonra ERP kararlaştırılan şartlarla faturayı oluşturur
- Kredi limiti kontrolü: PO ödemesine izin vermeden önce ERP’deki müşteri kredi limitini doğrula
// Custom payment gateway: Purchase Order
class WC_Gateway_Purchase_Order extends WC_Payment_Gateway {
public function __construct() {
$this->id = 'purchase_order';
$this->title = 'Satın Alma Siparişi (Net 30)';
$this->method_title = 'Satın Alma Siparişi';
$this->has_fields = true;
}
public function payment_fields() {
echo '
PO numaranızı girin. Ödeme, gönderimden sonraki 30 gün içinde yapılmalıdır.
';
echo '';
}
public function process_payment($order_id) {
$order = wc_get_order($order_id);
$po_number = sanitize_text_field($_POST['po_number']);
// Verify credit limit with ERP
$customer_erp_id = get_user_meta($order->get_customer_id(), 'erp_customer_id', true);
$credit = erp_check_credit($customer_erp_id, $order->get_total());
if (!$credit['approved']) {
wc_add_notice('Kredi limiti aşıldı. Lütfen hesap yöneticinizle iletişime geçin.', 'error');
return ['result' => 'failure'];
}
$order->update_meta_data('_po_number', $po_number);
$order->update_status('processing', 'PO alındı: ' . $po_number);
$order->save();
return ['result' => 'success', 'redirect' => $this->get_return_url($order)];
}
}
Katalog Görünürlüğü
B2B mağazalar genellikle kimliği doğrulanmamış ziyaretçilerden fiyatları veya ürünleri gizleme ihtiyacı duyar. Rakip fiyatını görmesin, ya da pazarlık edilmiş özel fiyat herkese açık düşmesin:
// Hide prices for non-B2B users
add_filter('woocommerce_get_price_html', function($price, $product) {
if (!current_user_can('b2b_access')) {
return 'Fiyat için giriş yapın';
}
return $price;
}, 10, 2);
// Hide entire products from non-B2B users
add_action('pre_get_posts', function($query) {
if (!is_admin() && $query->is_main_query() && !current_user_can('b2b_access')) {
$query->set('meta_query', [[
'key' => '_b2b_only',
'compare' => 'NOT EXISTS'
]]);
}
});
Önbellek ve doğruluk: en çok yanılan yer
Yukarıdaki middleware fiyatı 15 dakika önbelliyor. Bu iyi bir varsayılan, ama ben olsam iki yere daha dikkat ederdim, çünkü sahada canımı en çok yakan katman burası oldu.
- Sepette gösterilen fiyat ile ödeme anındaki fiyat aynı kaynaktan gelmeli. Müşteriye önbellekten 70 dolar gösterip, ödemede ERP’den taze 65 dolar çekersen — ya da tersi — güven bir kere kırılır. Ödeme anında fiyatı ERP’ye karşı bir kez daha doğrula, ve sipariş satırına o doğrulanmış fiyatı yaz.
- Önbelleği anahtarlarken müşteriyi unutma. Yukarıdaki
cacheKeymüşteri kimliğini içeriyor, ve bu kritik. Fiyat müşteriye özel olduğunda, önbellek anahtarına müşteriyi katmayı unutan bir geliştirici, bir müşterinin özel fiyatını başka bir müşteriye sızdırır. Bu, bir fiyatlandırma hatasından çok daha kötü — bu bir gizlilik ihlali. - ERP çökerse ne oluyor? Bir yedek planın olsun: son bilinen fiyatı göster ve bir uyarı düş, ya da sepeti kibarca durdur. “ERP’ye ulaşılamıyor” senaryosunda müşteriye beyaz ekran göstermek, kaçınabileceğin en pahalı hata.
Sonuç
ERP entegrasyonlu WooCommerce B2B’nin özü tek cümlede: her sistem en iyi yaptığı işi yapsın. WooCommerce alışveriş deneyimini üstlenir — ürün gösterimi, sepet, kullanıcı arayüzü. ERP iş mantığını üstlenir — fiyatlandırma, kredi limitleri, ödeme şartları, hacim indirimleri. Middleware, ERP verilerini gerçek zamanlı olarak WooCommerce dostu formatlara çevirerek aralarındaki köprüyü kurar. ERP fiyatlandırma mantığını WooCommerce eklentilerinde çoğaltmaya kalkma. ERP’yi sorgula, sonuçları akıllıca önbelle ve gerçeğin kaynağının kaynak olarak kalmasına izin ver. Ben yirmi yıldır aynı şeyi öğreniyorum: iki sistem aynı kuralı iki yerde tuttuğu an, o kural er ya da geç iki farklı cevap verir.
Last modified: Ağustos 2, 2026
United States / English
Slovensko / Slovenčina
Canada / Français
Türkiye / Türkçe