=== MevvPos ===
Contributors: alidayan
Tags: payment gateway, stripe, paypal, virtual pos, turkey
Requires at least: 6.0
Tested up to: 7.1
Requires PHP: 8.1
Stable tag: 4.9.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Take payments with Stripe, PayPal, Checkout.com, Razorpay, Paystack and more,
or a Turkish bank virtual POS — BIN routing and installments included.

== Description ==

MevvPos is a payment engine, not a single gateway. It talks to international
providers — **Stripe, PayPal, Mollie, Square, Authorize.Net, Checkout.com,
Razorpay and Paystack** — over their hosted checkout pages, so card details
are never typed on your site and the provider handles SCA / 3-D Secure 2 for
you. Between them they cover Europe, North America, the Middle East, India
and Africa.

It also does something the international plugins cannot: it speaks to Turkish
bank virtual POS directly.

Turkish banks do not speak a common payment protocol. Each one hands its
merchants a virtual POS account and a document describing its own signature
scheme, its own 3-D Secure return format and its own installment rules. That
is why a Turkish store cannot simply switch on a WooCommerce payment gateway
and start taking cards.

MevvPos is that layer. You enter the merchant ID, terminal ID and store key
from the agreement you signed with your bank, and your store starts taking
cards through your own POS — with 3-D Secure, with installments, and with the
bank's own decline reasons written into the order instead of a generic
failure.

= What it does =

* **Your bank's virtual POS, configured from WooCommerce.** Merchant
  credentials, endpoints, currency and test mode in one screen. The bank's
  test environment is a switch, not a second installation.
* **3-D Secure.** The customer verifies on the bank's own page. The return
  leg is checked against the signature before the order is marked paid — an
  unsigned or altered return never completes an order.
* **Installments with real rates.** Set a commission per installment count.
  What the customer sees at checkout is what reaches the bank, and the limit
  is enforced again on the server, so a modified form cannot buy more
  installments than you offer.
* **A record of every attempt.** Successes, failures and the bank's own
  decline codes, kept per order. "The card was declined" stops being a guess.
* **Turkish card recognition.** A bundled table of Turkish BIN ranges,
  rebuilt from bank sources, identifies the issuer of the card being typed
  in.
* **Pre-authorisation.** Block the amount now, take the money when the goods
  are ready. The order is held rather than completed, and the order screen
  gets a capture and a release action. Offered only where the provider really
  supports it; everywhere else the option is hidden and the reason is written
  on the settings screen.
* **Payment links.** Create a link with an amount, a description and an
  expiry, send it to the customer yourself, and they pay through your normal
  payment page. The link stops working when it expires and closes for good
  once it is paid.
* **Risk rules you can read.** Attempts per minute from one visitor or one
  card, consecutive declines, a Turkish card billed abroad, an amount
  threshold. Each rule can be switched off and its threshold changed, and you
  decide what a match does: flag, hold for review, or decline. The reason is
  always written on the order — nothing is refused silently. No IP address
  and no card number is stored.

= Institutions supported today =

İş Bankası, Akbank, Halkbank, QNB, Şekerbank, TEB and Ziraat Bankası through
the NestPay protocol; Garanti BBVA and VakıfBank through their own protocols;
and iyzico, PayTR, Craftgate and Sipay as payment institutions.

Other banks appear in the settings screen marked as not yet available. There
is a request form next to them: tell us which one you need, and if you can
send the integration document your bank gave you, that shortens the work
considerably — several Turkish banks do not publish theirs.

= Card data =

The card number is never written to the database. CVV is never stored
anywhere, in any form, including logs. Where the provider takes the card on
its own servers (PayTR), it does not reach your site at all.

= What this plugin gives you, in full =

Everything described above works in every installation, with no key, no
account, no trial period and no counter. There is **no cap on the number of
virtual POS accounts** you connect, and a store holding several merchant
agreements — the common case in Turkey, because a bank gives its best rate on
its own cards — gets BIN routing and currency routing out of the box: each
card goes to the account that is cheapest for it. Instalments go up to
**twelve**, which is the ceiling the banks themselves apply, and the revenue
report covers 7, 30 or 90 days.

Earlier releases held some of that back. They should not have, and 4.9.1
finishes removing it; a test in the suite now fails the build if a licence
branch is ever added back.

= A separate add-on =

Recurring payments and subscription billing, the mandate store, stored
payment authorisations, SCA exemption requests, the per-bank / per-instalment
/ per-decline-code breakdown with CSV export, and a weekly refresh of the BIN
table are a **separate plugin**, MevvPos Pro. That code is not in this
package — it is not disabled here, it is simply not here — and it is not
distributed through WordPress.org. Nothing on this page depends on it.

== External services ==

MevvPos is a payment engine, so it necessarily talks to the payment service
you choose. Nothing is contacted until you configure an account and a
customer pays. No analytics, telemetry or advertising service is contacted at
any time, and the free plugin never phones home on a schedule.

**1. The payment provider you configured.**

Only the provider whose account you set up is contacted, and only while a
payment, refund or status check is being made. What is sent is the payment
itself: the order number, the amount and currency, the instalment count where
the provider supports it, the return addresses on your own site, the billing
details WooCommerce already holds for that order, and — for providers that
accept card details server to server — the card number, expiry and security
code the customer typed. Card details are never stored by the plugin. This is
the plugin's purpose and it stops the moment you disable the account.

* **Stripe** (api.stripe.com) — card payments and hosted checkout worldwide.
  Terms: https://stripe.com/legal/ssa — Privacy: https://stripe.com/privacy
* **PayPal** (api-m.paypal.com, api-m.sandbox.paypal.com) — wallet and card
  payments. Terms: https://www.paypal.com/us/legalhub/useragreement-full —
  Privacy: https://www.paypal.com/us/legalhub/privacy-full
* **Mollie** (api.mollie.com) — European payment methods.
  Terms: https://www.mollie.com/user-agreement — Privacy: https://www.mollie.com/privacy
* **Square** (connect.squareup.com, connect.squareupsandbox.com) — card
  payments. Terms: https://squareup.com/us/en/legal/general/ua —
  Privacy: https://squareup.com/us/en/legal/general/privacy
* **Authorize.Net** (api.authorize.net, apitest.authorize.net,
  accept.authorize.net, test.authorize.net) — card payments in North America.
  Terms: https://www.authorize.net/about-us/terms/ —
  Privacy: https://www.authorize.net/about-us/privacy/
* **Checkout.com** (api.checkout.com, api.sandbox.checkout.com) — card
  payments. Terms: https://www.checkout.com/legal/terms-and-policies —
  Privacy: https://www.checkout.com/legal/privacy-policy
* **Razorpay** (api.razorpay.com) — payments in India.
  Terms: https://razorpay.com/terms/ — Privacy: https://razorpay.com/privacy/
* **Paystack** (api.paystack.co) — payments in Africa.
  Terms and privacy: https://paystack.com/terms
* **iyzico** (api.iyzipay.com, sandbox-api.iyzipay.com) — payments in Turkey.
  Privacy: https://www.iyzico.com/gizlilik-politikasi — the terms are the
  merchant agreement you sign with iyzico: https://www.iyzico.com/
* **Craftgate** (api.craftgate.io, sandbox-api.craftgate.io) — payment
  orchestration in Turkey. Privacy: https://craftgate.io/gizlilik-politikasi —
  the terms are the merchant agreement you sign: https://craftgate.io/
* **Sipay** (app.sipay.com.tr, provisioning.sipay.com.tr) — payments in
  Turkey. Privacy: https://www.sipay.com.tr/kvkk — the terms are the merchant
  agreement you sign: https://www.sipay.com.tr/
* **PayTR** (www.paytr.com) — payments in Turkey.
  Privacy: https://www.paytr.com/gizlilik — the terms are the merchant
  agreement you sign: https://www.paytr.com/
* **PayFlex / Innova** — VakıfBank's virtual POS, operated for the bank by
  Innova. The test endpoints are built in
  (sp-test.innova.com.tr/VAKIFBANK/MpiWeb/MPI_Enrollment.aspx for 3-D Secure
  enrolment and sp-test.innova.com.tr/VAKIFBANK_V4/VposWeb/v3/Vposreq.aspx for
  the transaction); the production address is the one VakıfBank gives you in
  your merchant agreement and you enter it in the settings. Terms: the
  merchant agreement you sign with VakıfBank — https://www.payflex.com.tr/ —
  Privacy: https://www.vakifbank.com.tr/tr/bankamiz/hakkimizda/gizlilik-kosullari-ve-kisisel-verilerin-korunmasi
  and, for the operator, https://www.innova.com.tr/kvkk-aydinlatma-metni

**2. Turkish banks' virtual POS gateways.**

If you pick one of the banks below, the plugin posts the payment to that
bank's own virtual POS gateway. For these eight banks the gateway address is
built in, because the bank publishes one shared address for every merchant;
what identifies your shop is the merchant number and store key from your own
merchant agreement, which you enter in the settings. Nothing is sent until you
add an account for that bank and a customer pays, and each payment goes only
to the bank you chose.

What is sent is the payment itself: the merchant number, the order number, the
amount and currency, the instalment count, the return address on your own
site, and — depending on the bank's protocol — the card number, expiry and
security code the customer typed on your checkout. The plugin stores no card
data.

For every one of these the terms are the virtual POS merchant agreement you
sign with the bank; the banks do not publish it, your own copy is the
authoritative text. The privacy policies are public:

* **İş Bankası** (sanalpos.isbank.com.tr, testsanalpos.isbank.com.tr) —
  Terms: the merchant agreement, https://www.isbank.com.tr/ —
  Privacy: https://www.isbank.com.tr/gizlilik-politikamiz
* **Akbank** (sanalpos.akbank.com, testsanalpos.akbank.com) —
  Terms: the merchant agreement, https://www.akbank.com/ —
  Privacy: https://www.akbank.com/kvkk/index.html
* **Halkbank** (sanalpos.halkbank.com.tr, testsanalpos.halkbank.com.tr) —
  Terms: the merchant agreement, https://www.halkbank.com.tr/ —
  Privacy: https://www.halkbank.com.tr/tr/dijital-bankacilik/guvenlik/sizin-icin-sunduklarimiz/kvkk
* **QNB** (sanalpos.qnbfinansbank.com, testsanalpos.qnbfinansbank.com) —
  Terms: the merchant agreement, https://www.qnb.com.tr/ —
  Privacy: https://www.qnb.com.tr/destek/gizlilik-politikasi
* **Şekerbank** (sanalpos.sekerbank.com.tr; the test address is the shared
  Asseco one, entegrasyon.asseco-see.com.tr) —
  Terms: the merchant agreement, https://www.sekerbank.com.tr/ —
  Privacy: https://www.sekerbank.com.tr/hakkimizda/kisisel-verilerin-korunmasi
* **TEB** (sanalpos.teb.com.tr; test on entegrasyon.asseco-see.com.tr) —
  Terms: the merchant agreement, https://www.teb.com.tr/ —
  Privacy: https://www.teb.com.tr/gizlilik-politikasi
* **Ziraat Bankası** (sanalpos2.ziraatbank.com.tr; test on
  entegrasyon.asseco-see.com.tr) —
  Terms: the merchant agreement, https://www.ziraatbank.com.tr/tr —
  Privacy: https://www.ziraatbank.com.tr/tr/bankamiz/gizlilik-ve-cerez-politikalari/gizlilik-politikasi
* **Garanti BBVA** (sanalposprov.garanti.com.tr,
  sanalposprovtest.garantibbva.com.tr) — its own protocol, not NestPay.
  Terms: the merchant agreement, https://www.garantibbva.com.tr/ —
  Privacy: https://www.garantibbva.com.tr/dijital-bankacilik/kisisel-verilerin-korunmasi-kanunu

The address `entegrasyon.asseco-see.com.tr` that appears above is the shared
NestPay test environment Asseco SEE runs for the banks that do not publish a
test address of their own. It is used only while test mode is on, never for a
real payment, and the terms and privacy policy that apply to it are your
bank's — the test account is issued by the bank, not by us.

For every other bank (Yapı Kredi, DenizBank, Kuveyt Türk, Albaraka,
Vakıf Katılım, Ziraat Katılım and the rest) the bank gives each
merchant its own gateway address, so nothing is built in: you type the address
from your merchant agreement into the settings and the plugin posts to that
address and to no other. The terms and privacy policy that apply are the ones
your own bank gives you.

**3. mevvsoft.com — only when you press a button in the admin.**

Two admin screens send a message to us, and only when you submit them.
Nothing is sent in the background, on a schedule, or during a payment, and no
card or payment data is ever included.

* The bank request form sends: the bank or integrator name, your site address,
  the contact name, e-mail and phone you type in, your note, and whether you
  already have the integration document.
* The support form sends: your site address, the subject, the bank concerned,
  your message, the error text you paste in, and the contact details you type
  in.

Both forms post to mevvsoft.com, on the paths `/api/v1/license/pos-request`
and `/api/v1/license/support`. These are POST-only API endpoints, not web
pages: opening them in a browser answers 404 by design, which is why they are
written here as paths rather than as links. The service's own terms and
privacy pages are linked below.

Service provided by Mev E-Ticaret Limited Şirketi (mevvsoft.com).
Terms: https://mevvsoft.com/mesafeli-satis
Privacy: https://mevvsoft.com/kvkk

== Installation ==

1. Install and activate. To take payments at a WooCommerce checkout you also
   need WooCommerce 9.0 or later; the payment engine itself, its REST surface
   and its admin screens work without WooCommerce, and another plugin can
   start a payment through them.
2. Go to Mevv → MevvPos and add your account: choose the provider or bank and
   enter the credentials from your merchant agreement. With WooCommerce
   active the same screen is reachable from WooCommerce → Settings →
   Payments → MevvPos.
3. Start in the bank's test environment. Run one payment through, confirm it
   reaches the bank's own panel, then switch to production.
4. Enter your installment rates per POS. They are what the customer sees.

== Frequently Asked Questions ==

= Do I need a merchant agreement with a bank? =

Yes. This plugin connects a virtual POS you already hold; it is not a payment
service and does not process money itself. Your bank or payment institution
gives you the credentials.

= My bank is not in the list. =

Open the settings screen and use the request form beside it. If you can send
the integration document your bank gave you, that is what decides how quickly
it can be added — several Turkish banks do not publish their documentation.

= I hold POS accounts at two banks. Can I use both? =

Not with the free plugin, which connects one. Routing a card to the right
bank by its BIN is what the paid add-on does. Extra POS accounts you have
already entered are never deleted — they are just not used until the licence
covers them, and your default POS keeps taking payments either way.

= Is the card number stored? =

No. It is passed to the bank for the payment and not written to the database.
CVV is never stored under any circumstance.

= Can a customer force more installments than I allow? =

No. The limit is applied again on the server when the order is placed, not
only in the browser.

== Screenshots ==

1. Virtual POS list.
2. Adding a POS: credentials, endpoints and test mode.
3. Installment rates.
4. Checkout with installments and 3-D Secure.
5. Attempt log with the bank's decline codes.

== Changelog ==

= 4.9.1 =
* The revenue report's date range is open in every installation. It was the
  last thing in this package still held behind a licence: the range picker was
  hidden and the query was pinned to 30 days, although the report source could
  always compute any range. 7, 30 and 90 days now work everywhere.
* The licence question is gone from this package altogether. `is_premium()`
  and the status filter behind it were removed; the two admin screens that
  mention the separate add-on now ask whether that plugin is installed, and
  nothing in this plugin behaves differently either way.
* The bank callback is split into two arrays: the untouched bytes that the
  signature check needs, and a sanitised copy that everything else uses. What
  is written to the order note, the WooCommerce log and the debug screen now
  comes from the sanitised copy.
* Every Turkish bank gateway the plugin can post to is now named in the
  readme, with its hostnames and the bank's privacy policy, alongside the
  international providers that were already listed.

= 4.9.0 =
* No feature in this plugin is locked any more. The instalment ceiling and the
  one-account limit are gone: every account you configure is used, routing by
  currency works, and the instalment table goes up to what the bank allows.
* Recurring payments moved out of this plugin into the separate MevvPos Pro
  add-on, together with the mandate store, the WooCommerce Subscriptions
  bridge, the saved-authorisation surface in My Account and the SCA exemption
  request. They are not disabled here; the code is simply not in this package.
* Every stylesheet and script is enqueued instead of printed inline, the
  provider's own 3-D Secure page is escaped before it is shown, card numbers
  are reduced to digits, and webhook header values are unslashed and stripped
  of control bytes.
* Chart.js updated to 4.5.1.

= 4.8.5 =
* Mevv menu: one row per product; tabs live in the page.

= 4.8.4 =
* MevvCore 1.0.4: licence, updates and menu now served by the shared kernel; product page under the Mevv menu.

= 4.8.3 =
* Embeds the shared MevvCore kernel.

= 4.8.2 =
* Prepared for submission to the WordPress Plugin Directory. Every output on the debug and instalment screens is escaped, placeholder strings carry translators comments, internal redirects use `wp_safe_redirect()` and the two that leave the site (the provider's hosted checkout page and the bank's 3-D Secure challenge) are documented as deliberate.
* The callback debug dump no longer prints raw card fields: it goes through the same masking used elsewhere, and the test-mode log writes JSON instead of `print_r()`.
* The global helper `wp_list_pluck_compat()` was renamed to `mevvpos_list_pluck()`. A plugin must not declare functions in the `wp_` namespace; the name was one core release away from colliding.
* Release packages no longer carry a stray `dist/` folder, and the packager fails if a compressed file ever slips into a zip again.

= 4.8.1 =
* PayPal tek seferlik tahsilat düzeltmesi — para hatasıydı. A one-off PayPal payment was never actually collected. The order is created with the CAPTURE intent, the customer approves it at PayPal, and the order then sits at APPROVED with the money still on their card: PayPal only moves it when a separate capture call is made, and nothing in the one-off path made that call. The plugin sat waiting for a PAYMENT.CAPTURE.COMPLETED notification that could never arrive, because the capture that would have produced it never happened. The customer believed they had paid and the merchant was never credited. The capture now runs when the provider is asked what really happened, so the return leg, the notification and subscription renewals all reach the same answer.
* Both PayPal paths now share one decision point, so they cannot drift apart again — the missing one-off capture was exactly that drift. An order already COMPLETED is never captured a second time, an ORDER_ALREADY_CAPTURED reply counts as success and the real status is read back, and a capture request that goes unanswered leaves the payment unresolved rather than marking it declined: the money may well have moved, and cancelling a paid order is the worse mistake. Renewals also make one OAuth request fewer.
* Pre-authorisation stays closed for PayPal, but the reason on the settings screen was wrong and has been rewritten. It said the integration had no capture step, which was this bug rather than a decision. What is genuinely missing is only the two-step variant: the AUTHORIZE intent, a separate authorize call, and capture at the authorisation level.

= 4.8.0 =
* Pre-authorisation. A provider account can now be switched from "sale" to "pre-authorisation": the amount is blocked on the customer's card, the order is held instead of completed, and two actions appear on the order screen — capture and release. Partial capture is offered where the provider supports it, and the rest of the block is released by the provider. Available on NestPay (Akbank, TEB, Isbank, Sekerbank, Halkbank, QNB, Ziraat), Stripe, Checkout.com and Authorize.Net. On every other provider the option is hidden and the reason is printed on the settings screen rather than left blank — none of them was given a guessed API field. NestPay needs the bank's API user and password before the option opens at all, because without them a blocked amount could never be captured.
* Payment links. Create a link from the admin with an amount, a description and an expiry, send it to the customer yourself, and they pay through your normal payment page — instalments, BIN routing, 3-D Secure and the risk rules all apply. The link identifier is 32 bytes of cryptographic randomness, the link stops working when it expires, and it closes for good once it is paid. No order is created until the customer actually opens the link, so unopened links do not clutter the order list.
* A risk layer with rules you can read. Attempts per minute from one visitor and from one card, consecutive declines, a Turkish card billed to another country, and an amount threshold. Every rule can be switched off and every threshold can be changed, and you choose what happens when one matches: flag only, hold the order for review, or decline. The default is flag only, so nothing is blocked out of the box. Whatever is decided is written on the order together with the measurement that triggered it — a silent decline is not possible. No IP address and no card number is stored: counting uses a keyed digest that cannot be reversed, and the retention window is set on screen.
* EMV 3-D Secure 2 / PSD2 strong customer authentication. The authentication outcome is now a first-class result on every payment event, with four outcomes kept apart: authenticated without a challenge (frictionless), challenge required, exempt, and refused by the issuer. This is a different protocol generation from Turkish 3-D Secure and is modelled separately; `mdStatus` handling is untouched.
* The challenge leg is handled. If the issuer still wants the customer to authenticate when they come back, they are sent to the bank once and the return is verified server-to-server — a browser landing on the return URL never completes an order. An abandoned challenge leaves the cart intact so the customer can retry.
* Liability shift is recorded on the order, read from the ECI per card scheme (Visa and Mastercard use opposite codes) and never guessed: when it cannot be determined it is left unrecorded rather than reported as "merchant".
* PSD2 exemptions (low value, transaction risk analysis, trusted beneficiary, recurring/merchant-initiated) are modelled with the RTS thresholds, and only the ones a provider genuinely accepts as a request field are sent. Requesting an exemption is a Pro feature; authentication itself is not, and payments are never blocked by the licence.
* Subscriptions: an issuer asking for authentication on a renewal is no longer treated as a declined card. The period is not consumed, the subscription is marked past due with the real reason, and a new `mevvpos_subscription_authentication_required` action fires so the customer can be asked to authenticate.
* Stripe and Mollie report the authentication outcome; PayPal, Square and Authorize.Net do not, for reasons written into each provider file. No provider is given a fabricated request field.

= 4.7.1 =
* WooCommerce block checkout (Cart and Checkout blocks) support. MevvPos was invisible on the block-based checkout because it only rendered through the classic `payment_fields()` hook; it now registers a payment method type with WooCommerce Blocks. Card details and the instalment table are collected in the block exactly as in the classic form, the fields reach the server under the same names, and the instalment surcharge is applied to the block cart through the Store API. Installs without WooCommerce Blocks are untouched.

= 4.7.0 =
* MevvPos can now be used by something other than WooCommerce. A new external surface lets another plugin start a payment, verify the provider's callback and issue a refund, and it keeps its own session record so a provider that rewrites the order number does not break the caller.
* The surface answers honestly about what each provider can do: a provider that cannot query a payment's status, or cannot refund, says so instead of failing later.
* Removed a stray 33 KB file from the language folder that was shipping in every package. A new check keeps the folder to its expected contents.

= 4.6.0 =
* Fixed a serious bug: a subscription whose card was declined once was finished for good. Only active subscriptions were picked up for renewal, so a past-due row was terminal. Failed periods are now retried on a schedule (day 1, 3 and 7) and the subscription is only cancelled when the schedule is exhausted.
* The retry time is kept separately from the billing date, so a period paid three days late no longer pushes every future charge three days later.
* Subscriptions can now be cancelled from the admin screen and by the customer from their own order page. Cancelling closes the authorisation at the provider as well — writing "cancelled" in our own table while the provider keeps charging is not a cancellation.
* Saved payment methods appear under My Account. Deleting one cancels the subscriptions that depend on it and revokes the authorisation at the provider. No card data is stored: the entry holds the provider's reference and a masked label.

= 4.5.0 =
* Local payment methods: iDEAL, Bancontact, SEPA Direct Debit, Klarna, EPS, Przelewy24, BLIK, TWINT, Multibanco and wallets, each through the provider's own field. Mollie, Stripe, Checkout.com, Square, Paystack and Razorpay.
* A method is only offered when the order's currency matches it; the merchant chooses which methods to enable per account, and an unpicked method is never sent.
* Recurring: an iDEAL, Bancontact or EPS first payment leaves a SEPA mandate behind, so a subscription started with iDEAL renews by direct debit. Methods that cannot carry a mandate are withheld from a first payment rather than failing a month later.

= 4.4.0 =
* Three new international providers: Checkout.com (global, full 3-D Secure 2 reporting and recurring), Razorpay (India, with a signed browser return leg) and Paystack (Nigeria, Ghana, South Africa, Kenya, with recurring).
* Eight international providers in total, alongside the thirteen Turkish institutions.

= 4.3.0 =
* EMV 3-D Secure 2 / PSD2 strong customer authentication: authentication status, challenge flow, exemption model and chargeback liability from the ECI, kept separate from Turkish 3-D Secure.
* Fixed: Stripe's authentication_required answer was treated as a card decline, so subscription renewals went past due for the wrong reason and the customer never saw the challenge.
* All 18 locales now cover the full catalogue; a coverage gate keeps a new string from shipping untranslated.

= 4.2.0 =
* Security: the update signature's public key can no longer be swapped by a filter in production. Any other plugin on the same site could previously supply its own key and serve a forged, validly-signed update.
* Subscriptions can now be set up from a WooCommerce Subscriptions product without writing PHP.
* A failed recurring charge is now written to the order; previously the subscription went past due in silence.

= 4.1.0 =
* Para birimine göre yönlendirme: birden çok sağlayıcı hesabı varken ödeme, para birimi için yazılmış hesaba gider. Kural sırası para birimi → kart BIN → varsayılan hesap; para birimi bir kısıt, BIN bir iyileştirme.
* Abonelik ve tekrarlayan ödeme. Yetki (mandate) kart jetonu, hesap kasası ve SEPA yetkisi olarak üç biçimde tutuluyor; kart bilgisi sağlayıcıda kalıyor. Yenileme dönem başına idempotent ve lisans dolsa bile durmuyor — kapanan şey yalnız YENİ abonelik açmak.
* Stripe, PayPal, Mollie ve Authorize.Net abonelik destekliyor. Square ve yedi Türk sanal POS'u desteklemiyor; onlarda seçenek hiç gösterilmiyor ve lisans da sorulmuyor.
* Ücretsiz sürüme imzalı güncelleme istemcisi eklendi. İmzasız yanıt uygulanmıyor ve paket adresi yalnız kendi alan adımızdan kabul ediliyor.
* On yedi dil 4.0.0 dizgeleriyle tamamlandı; varyantlar gerçekten ayrıldı (de_DE "du" / de_DE_formal "Sie", nl_BE "u", es_AR voseo, pt_PT Avrupa Portekizcesi).
* Düzeltme: `MevvPos_Http::json()` nesne gövdeyi dizeye çevirmeye çalışıp ölümcül hata veriyordu. PayPal tahsilat isteği boş bir JSON nesnesi gönderdiği için PAYPAL TAHSİLATI ÜRETİMDE KIRIKTI.
* Düzeltme: taksit tablosunun BIN listesi geçit ayarındaki bankadan değil, etkin POS kayıtlarından üretiliyor. İkisi ayrışınca müşterinin kartı hiçbir listede eşleşmiyor ve taksit sessizce hiç açılmıyordu.

= 4.0.0 =
* **International providers**: Stripe (Payment Intents), PayPal (Orders v2),
  Mollie, Square and Authorize.Net. All of them use the provider's own hosted
  page, so card details never reach your server and SCA / 3-D Secure 2 is the
  provider's responsibility.
* **WooCommerce is no longer required.** The payment engine loads on its own
  and can be driven by another plugin — a form plugin, for example. Install
  WooCommerce and the checkout gateway registers itself as before.
* **Provider contract no longer depends on WooCommerce.** Providers now
  receive a plain payment intent (amount as an integer in minor units)
  instead of a WC_Order. The seven Turkish providers produce byte-identical
  requests and signatures; this is verified against the previous release.
* **Refunds**: the gateway now declares refund support and refunds through the
  international providers from the order screen. Refunds are not limited by
  the licence.
* Signed webhooks with replay protection and idempotency: the same event
  delivered twice has no second effect.
* Money is handled as integer minor units end to end; no floating-point
  arithmetic on amounts.
* Free / Pro boundary redrawn: one provider account, wallets (Apple Pay /
  Google Pay) and multi-currency are free. Several accounts at once, routing
  between them, provider-independent recurring payments, advanced reports and
  the Türkiye-specific features (12 instalments, per-instalment commission,
  live BIN updates) are Pro. When a licence lapses the first configured
  account keeps collecting and existing recurring authorisations keep
  renewing — payments never stop.

= 2.0.4 =
* The free plan's limits now say what they are and where to go: adding a
  second virtual POS explains the Pro routing instead of a dead warning,
  and the installment grid marks the rates the free plan does not show yet.
* Rates you enter above the free installment cap are kept, not cleared.

= 2.0.3 =
* Garanti BBVA, VakıfBank, iyzico, PayTR, Craftgate and Sipay added.
* Card BIN table rebuilt from bank sources; earlier ranges were wrong for
  several banks and could route a card to the wrong POS.
* Installment limit enforced on the server as well as in the browser.
* Bank request and support forms added to the settings screen.
* Licensing and the BIN refresh moved out into a separate paid plugin.

= 1.0.0 =
* First release: NestPay banks, BIN routing, installments, 3-D Secure.

== Upgrade Notice ==

= 4.0.0 =
The provider contract changed: custom providers registered through the
`mevvpos_providers` filter must accept a MevvPos_Payment_Intent instead of a
WC_Order. Bank requests and signatures are unchanged, so existing Turkish POS
setups keep working untouched.

= 2.0.3 =
Corrects card BIN ranges that could send a card to the wrong POS. Check your
bank-to-POS mapping after updating.
