WP Manifestindependent plugin directory
manifest / ecommerce / ts-bnpl

TS BNPL Digipay

قیمت اقساطی محصولات و نمایش طرح ۴ قسطه دیجی‌پی روی فروشگاه تهران‌اسپیکر.

★ 0stars

Install

Download source zip No release zip yet

This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/keyvansolha/ts-bnpl/archive/refs/heads/main.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

قیمت‌گذاری اقساطی ۴ قسطه و نمایش طرح خرید اعتباری دیجی‌پی در فروشگاه تهران‌اسپیکر.

English: Installment pricing and Digipay 4-month plan display for Tehran Speaker online store.


نیازمندی‌ها / Requirements

  • WordPress 6.5+
  • PHP 7.4+
  • WooCommerce 8.0+
  • Amazing theme (optional, for tight integration)

نصب / Installation

  1. کپی کنید پوشه‌ی ts-bnpl را به wp-content/plugins/
  2. فعال کنید افزونه از پیشخوان ووکامرس
  3. برای اعلام سازگاری با HPOS، هیچ کار اضافی لازم نیست
cp -r ts-bnpl /path/to/wp-content/plugins/

تنظیمات / Configuration

قیمت‌های اقساطی

محصولات ← قیمت‌های اقساطی (Products → Installment Prices)

  • جدول همه‌ی محصولات و متغیرهایی که قیمت اقساطی دارند
  • ستون‌های نمایش: نام، SKU، قیمت نقدی، قیمت اقساطی، اختلاف
  • مرتب‌سازی بر حسب مبلغ اختلاف و درصد
  • خروجی CSV برای تطبیق با سیستم حسابداری
  • خلاصه‌ی آماری: تعداد، میانگین تفاوت، و محدوده

نمایش در صفحه‌ی محصول

محصولات ← قیمت‌های اقساطی → قسمت "نمایش در صفحه‌ی محصول"

چهار حالت نمایش:

1️⃣ حالت بازشونده (Accordion)

  • تیزر کم‌رنگ: "امکان خرید ۴ قسطه این کالا از تهران‌اسپیکر"
  • کلیک → جزئیات (مبلغ، لوگو، راهنما) همان‌جا باز می‌شود
  • پیش‌فرض

2️⃣ حالت پنل راهنما (Modal)

  • تیزر کم‌رنگ
  • کلیک → پنل راهنما باز می‌شود
  • جزئیات طرح بالای بخش "خرید اقساطی چگونه انجام می‌شود"

3️⃣ حالت صفحه‌ی فرود (Landing)

  • تیزر کم‌رنگ، اما این بار یک لینک است نه دکمه
  • کلیک → کاربر به صفحه‌ی کامل راهنمای خرید اعتباری می‌رود
  • نیازمند انتخاب یک برگه در بخش «صفحه‌ی فرود خرید اعتباری»
  • اگر برگه‌ای انتخاب نشده باشد، به‌صورت خودکار به حالت بازشونده برمی‌گردد

4️⃣ حالت صفحه‌ی فرود تصویری (Visual Landing — Experimental)

  • روی همان برگه‌ی انتخابی «صفحه‌ی فرود خرید اعتباری» فعال می‌شود
  • محتوا و تصاویر از مدیر اختصاصی محصولات ← لندینگ تصویری (آزمایشی) می‌آیند
  • محتوای دستی برگه را در این حالت جایگزین می‌کند؛ Landing قدیمی همچنان محتوای دستی را حفظ و بدنه‌ی خودش را به آن اضافه می‌کند
  • اگر برگه‌ی منتشرشده‌ای انتخاب نشده باشد، مثل Landing قدیمی به حالت بازشونده برمی‌گردد

تنظیم متن تیزر: فیلد "متن قابل کلیک"

  • خالی = پیش‌فرض: "امکان خرید ۴ قسطه این کالا از تهران‌اسپیکر"

صفحه‌ی فرود / Landing Page

یک برگه‌ی معمولی وردپرس بسازید (مثلاً «خرید اعتباری») و آن را در محصولات ← قیمت‌های اقساطی ← صفحه‌ی فرود خرید اعتباری انتخاب کنید.

افزونه محتوای کامل را روی همان یک برگه می‌سازد. لازم نیست چیزی داخل برگه بنویسید — نه گوتنبرگ، نه المنتور، نه شورت‌کد، نه HTML.

چه چیزی رندر می‌شود

  • هیرو و معرفی خرید اعتباری
  • مراحل خرید در ۴ گام
  • راهنمای تشخیص کالای واجد شرایط
  • کاروسل «محصولاتی که قابلیت خرید اعتباری دارند»
  • توضیح تفاوت مبلغ نهایی با قیمت نقدی
  • پرسش‌های پرتکرار
  • فراخوان پایانی

هدر، فوتر، بردکرامپ و <h1> از خود قالب و عنوان برگه می‌آیند؛ افزونه فقط بدنه را اضافه می‌کند و محتوای دستی خود برگه (اگر چیزی نوشته باشید) بالای آن حفظ می‌شود.

قواعد مهم

  • هیچ شناسه‌ای هاردکد نیست. با عوض کردن برگه در تنظیمات، لندینگ جابه‌جا می‌شود.
  • فقط همان یک برگه تغییر می‌کند. بقیه‌ی صفحات دست‌نخورده می‌مانند.
  • اگر برگه‌ای انتخاب نشده باشد، هیچ صفحه‌ای override نمی‌شود.
  • محتوای لندینگ عمداً provider-neutral است: نه نام ارائه‌دهنده، نه تعداد قسط، نه نرخ، نه سقف اعتبار.

کاروسل کالاهای واجد شرایط

  • منطق واجد شرایط بودن دقیقاً همان منطق صفحه‌ی محصول است: متای _bnpl_price با مقدار بزرگ‌تر از صفر. سیستم موازی و شناسه‌ی ثابت وجود ندارد.
  • کاملاً پویاست و هیچ برچسبی لازم ندارد. به محض اینکه قیمت اقساطی یک کالا ثبت شود در کاروسل می‌آید و به محض خالی شدنش حذف می‌شود. نه تگ، نه دسته، نه taxonomy، نه نگهداری دستی در پیشخوان.
  • برای کالاهای متغیر، متا روی خودِ متغیر است و کارت والد نمایش داده می‌شود.
  • کارت‌ها همان simple-card.php قالب هستند؛ کارت اختصاصی BNPL ساخته نشده.
  • استایل کارت و کاروسل هم از خود قالب صف می‌شوند (archiveModular.css یا نسخه‌ی موبایلش، به‌علاوه assets/scss/modules/product-carousel.css). قالب این فایل‌ها را فقط در آرشیو و صفحه‌های page-builder لود می‌کند، پس افزونه همان هندل‌ها را روی برگه‌ی فرود صف می‌کند. هیچ استایل کارتی بازنویسی نشده.
  • ظرف کاروسل کلاس products-carousel-panel قالب را دارد، چون CSS ماژول به همان اسکوپ شده و عرض اسلاید و اسکرول موبایل از آنجا می‌آید.
  • کارت‌های محصول در بقیه‌ی سایت (خانه، جست‌وجو، برند، آرشیو) هیچ تغییری نمی‌کنند؛ هیچ نشان یا برچسبی به آن‌ها اضافه نمی‌شود.
  • اسلایدر همان Swiper خود قالب است؛ کتابخانه‌ی جدیدی اضافه نشده.
  • روی موبایل اسکرول افقی با snap، مثل بقیه‌ی کاروسل‌های سایت.
  • اگر کالای واجد شرایطی نباشد، یک پیام تمیز نمایش داده می‌شود و چیدمان نمی‌شکند.

فهرست کامل در آرشیو فروشگاه

دکمه‌ی «مشاهده محصولات...» کاربر را به ?ts_bnpl=1 روی آرشیو فروشگاه می‌برد و همان صفحه فقط کالاهای واجد شرایط را نشان می‌دهد — با مرتب‌سازی، فیلترها، صفحه‌بندی و کارت‌های همیشگی خودش.

  • قالب آرشیو را با WC_Product_Query خودش می‌سازد و هیچ هوکی ندارد، پس به‌جای دست بردن در آن، فیلتر woocommerce_product_data_store_cpt_get_products_query ووکامرس گرفته می‌شود. فهرست، شمارش «X کالا» و بازه‌ی قیمت با هم فیلتر می‌شوند.
  • از post__in استفاده می‌شود نه meta_query، چون در کالاهای متغیر متای قیمت اقساطی روی خودِ متغیر است و کوئری روی والد پیدایش نمی‌کند.
  • صفحه‌بندی و مرتب‌سازی آرشیو از ایجکس می‌آیند و فرم را serialize می‌کنند، پس پرچم به شکل یک ورودی پنهان در همان فرم هم قرار می‌گیرد (lib/Archive/template/sample/active-filters.php در قالب، پشت class_exists).
  • بدون این پارامتر، آرشیو فروشگاه دقیقاً مثل همیشه کار می‌کند.

صفحه‌ی فرود تصویری آزمایشی / Visual Landing

پس از انتخاب همان برگه‌ی Landing، حالت Visual Landing (Experimental) / لندینگ تصویری (آزمایشی) را در محصولات ← قیمت‌های اقساطی ← نمایش در صفحه‌ی محصول انتخاب کنید. محتوای این نسخه از محصولات ← لندینگ تصویری (آزمایشی) مدیریت می‌شود و شش تب دارد: Top Banners، Hero، Providers، Eligibility، Conditions و Final CTA.

  • بنرها قابل افزودن، حذف و مرتب‌سازی‌اند. یک بنر ثابت است؛ از دو بنر به بالا همان Swiper موجود سایت با دکمه و pagination فعال می‌شود.
  • هر تصویر محتوایی source جداگانه‌ی AVIF و WebP برای دسکتاپ و موبایل دارد. اولین بنر اولویت LCP می‌گیرد و بقیه‌ی تصاویر lazy هستند.
  • ارائه‌دهنده وقتی عمومی می‌شود که به یک درگاه اقساطی واقعی و ثبت‌شده وصل باشد، نمایش آن در مدیر لندینگ روشن باشد و خود درگاه ووکامرس نیز فعال و خارج از حالت تست باشد. در دسترس‌بودن برای سبد جاری در checkout بررسی می‌شود.
  • کارت محصولات، منطق واجد شرایط بودن، FAQ، کاروسل و لوگوی متحرک از پیاده‌سازی موجود قالب/افزونه استفاده می‌شوند؛ نمونه‌ی بخش Eligibility نیز همان تیزر واقعی صفحه محصول است و checkout و داده‌های مالی مسیر جدا ندارند.
  • breadcrumb، عنوان قالب و محتوای ویرایشگر فقط روی برگه‌ی انتخابی و فقط در این mode پنهان/جایگزین می‌شوند.
  • اندازه‌ها، نسبت‌ها، حجم فایل، safe area، نام‌گذاری و محل دقیق آپلود در راهنمای تحویل تصویر آمده است.

رابط کاربری / UI

صفحه‌ی محصول / Product Page

قیمت نقدی همیشه CTA اصلی می‌ماند.

خرید اعتباری یک گزینه‌ی ثانویه و جمع:

  • تا کاربر کلیک نکند، مبلغ قسط و نام دیجی‌پی دیده نمی‌شود
  • موبایل و دسکتاپ با طراحی تطبیقی پشتیبانی می‌شوند

متغیرهای متحرک: با تعویض رنگ/ویژگی:

  • مبلغ قسط به‌روز می‌شود
  • در حالت مودال، جزئیات در داخل پنل جایی دارد

تسویه‌حساب / Checkout

  • درگاه دیجی‌پی وقتی فعال است، نمایش دارد
  • انتخاب درگاه → مبالغ بازمحاسبه می‌شود
  • کیف پول جزئی خودکار غیرفعال می‌شود تا تضاد مبالغ رخ ندهد

توسعه / Development

بازنویسی تنظیمات

برای override حالت یا متن تیزر در کد:

// تغییر حالت جهانی
add_filter( 'ts_bnpl_display_mode', function () {
    return 'modal'; // accordion، modal، landing یا visual_landing
} );

// تغییر صفحه‌ی فرود
add_filter( 'ts_bnpl_landing_page_id', function () {
    return 123;
} );

// دستکاری فهرست کالاهای کاروسل
add_filter( 'ts_bnpl_eligible_product_ids', function ( $ids ) {
    return $ids;
} );

// تغییر متن تیزر
add_filter( 'ts_bnpl_teaser_text', function () {
    return 'خرید اقساطی دسترس‌پذیر است';
} );

قیمت اقساطی محصول

// دریافت
$teaser_html = TS_BNPL_Display::teaser_html( $total );

// در variation:
$variation['bnpl_html'] = TS_BNPL_Display::teaser_html( $total );

داده‌های متادیتا

  • محصول: _bnpl_price (قیمت اقساطی)
  • سفارش: _is_bnpl (آیا اقساط است)
  • سفارش: _bnpl_months (تعداد اقساط، مثلاً ۴)

اختبار / Testing

لندینگ تصویری

php tests/mode-routing.test.php
php tests/legacy-landing-routing.test.php
php tests/visual-settings.test.php
php tests/responsive-media.test.php
php tests/providers.test.php
php tests/visual-admin.test.php
php tests/visual-render.test.php
node --test tests/*.test.mjs

صفحه‌ی محصول

# متغیرهای متحرک و تیزرهای دو حالت
npm test -- tests/product-variation.test.mjs

تسویه‌حساب

# بازمحاسبه هنگام تعویض درگاه
npm test -- tests/checkout-experience.test.mjs

حق‌الاستفاده / License

تمام کد در این افزونه برای تهران‌اسپیکر اختصاصی است.


پشتیبانی / Support

برای مسائل یا بهبود‌های پیشنهادی، درخواست pull یا issue را باز کنید.