=== ROKI Connect for Gravity Forms ===
Contributors: rokiconnect
Tags: payments, payment gateway, credit card, honduras, forms
Requires at least: 6.2
Tested up to: 7.1
Requires PHP: 8.0
Stable tag: 1.0.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Take card payments on your Gravity Forms entries through ROKI Connect, the Honduran payment gateway.

== Description ==

ROKI Connect lets you charge credit and debit cards in Honduran lempiras (HNL) from any Gravity
Forms form: registrations, donations, tuition, bookings, membership dues, event tickets.

This is for the site that is not a store but still needs to get paid. A school collecting tuition,
a nonprofit taking donations, an event selling tickets - none of that is a shopping cart, and a
full e-commerce platform is far more than any of them need.

**How the payment works**

The visitor fills in your form and submits it. They are then sent to a payment page hosted by ROKI,
pay with their card, and come back to the confirmation you already wrote for that form.

The card fields are never drawn inside your own form. Gravity Forms does allow that, and this
add-on deliberately does not use it: card numbers would then travel through your web server and
drag your site into PCI obligations it has no reason to take on.

**Where the amount comes from**

Gravity Forms calculates it from the product fields on the form, on the server. The figure never
travels through the browser, so there is nothing anyone can edit in a developer console to pay
less. In the feed you choose either the form total or one specific product field.

If your form has no product field there is nothing to charge, and the add-on creates no payment.

**What decides that a payment happened**

A signed webhook from ROKI - not the visitor returning to your site. A browser coming back means a
browser came back, not that money moved. The entry is marked paid when the webhook arrives.

* Webhook signatures are verified with HMAC-SHA256 over the raw request body and compared in
  constant time. Deliveries older than five minutes are refused, so a genuinely signed request
  cannot be captured and replayed later.
* Repeated deliveries are discarded by their event id, using the deduplication Gravity Forms
  already provides, so a retried notification cannot pay the same entry twice.
* Payments belonging to a different site are ignored. If you run two WordPress installations on
  one ROKI account - a staging copy, two brands, or a migration with the old site still connected -
  both receive each other's notifications, signed with the same secret. Every reference carries a
  prefix identifying the site that created it, and it is checked before anything is credited.
* Submitting the same form again does not create a second charge. An idempotency key derived from
  the content is sent, and ROKI returns the payment that already exists.

**Optional: let the customer cover the fee**

A per-feed switch. When it is on, ROKI recalculates the total so that the amount from your form is
what reaches you.

**What this add-on does not do, said plainly**

* It does not charge subscriptions. The feed offers one-time payments only, on purpose. Charging
  without the customer present requires storing their card, and that module is enabled per merchant
  by ROKI. Offering recurring billing without it would fail at the first renewal.
* It does not put card fields inside your form, and never receives a card number.
* It does not issue refunds or voids from the WordPress admin. Those are done from the ROKI portal.

**This release is Beta.** Install it on a copy of your site first and run one complete submission
with an `sk_test_` key and a small amount. Confirm the entry is marked paid - which is the webhook's
job - before you let it take real money.

**You need a ROKI account (third-party service)**

This add-on connects your site to ROKI Connect, a third-party payment service operated by ROKI. A
merchant account is required to obtain the API keys, and the add-on will not function without one.
No payment data is sent anywhere until you configure a key and a visitor submits a form with a feed
attached to it.

When a form is submitted, the following is sent to the ROKI Connect API at `aura.roki.systems` in
order to create the charge: the amount, a reference built from your site address and the entry id,
the form title, the return addresses on your own site, the entry and form ids, and - only if you
map those fields in the feed - the customer's name, email address and phone number.

* Service website: https://roki.la
* Technical documentation: https://connect.roki.la
* Terms of service: https://roki.la/terms
* Privacy policy: https://roki.la/privacy

== Installation ==

1. Install and activate Gravity Forms 2.5 or later, with an active license. This add-on extends its
   payment framework and does nothing on its own.
2. Upload the add-on folder to `/wp-content/plugins/`, or install it from **Plugins > Add New >
   Upload Plugin**, then activate it.
3. Go to **Forms > Settings > ROKI Connect** and paste your secret key. Keys beginning with
   `sk_test_` run against the sandbox; `sk_live_` keys take real money. Both are found in the API
   Integration tab of the ROKI portal.
4. Copy the webhook URL shown on that same screen, register it in the Webhooks tab of the ROKI
   portal, and paste the signing secret it returns back into the settings. Without this secret no
   payment is ever confirmed.
5. Make sure the form you want to charge has at least one **product** field. That is where the
   amount comes from.
6. Open that form, go to **Settings > ROKI Connect > Add New**, name the feed, choose where the
   amount comes from, and save.
7. Submit the form once with a sandbox key and a small amount, and confirm the entry is marked paid.

Your site must be served over HTTPS.

== Frequently Asked Questions ==

= Do I need Gravity Forms? =

Yes, version 2.5 or later with an active license. This is an add-on for its payment framework, not
a standalone form plugin. If Gravity Forms is missing or too old, an admin notice says so instead of
the add-on silently doing nothing.

= Which currency does it charge in? =

Honduran lempiras (HNL), which is what ROKI Connect processes. Amounts are sent with decimals, as
lempiras - never as cents.

= Can I test without taking real money? =

Yes. With an `sk_test_` key everything behaves identically against the ROKI sandbox and no money
moves. Do this before switching to a live key.

= My form has a total but nothing gets charged. Why? =

The amount comes from Gravity Forms product fields. A number field or a calculation that is not a
product field is not something Gravity Forms treats as a price. Add a product field - Single Product
for a fixed price, Drop Down or Radio Buttons for a choice of prices, User Defined Price for a free
amount such as a donation - and select it in the feed.

= The visitor paid but the entry is not marked paid. What happened? =

The entry is marked paid by the webhook, so this almost always means the webhook is not arriving or
not verifying. Check that the URL shown on the settings screen is registered in the ROKI portal and
that the signing secret pasted into the settings is the one that portal returned. Signature failures
and ignored events are written to the Gravity Forms add-on log.

= Can I charge a recurring membership? =

Not with this add-on. Only one-time payments are offered, deliberately - see the description above.

= Can I refund from WordPress? =

No. Refunds and voids are done from the ROKI portal. Note that a void and a refund are not the same
thing: while a transaction can still be voided it should be, because a void never appears on the
cardholder's statement.

== External services ==

This plugin connects to **ROKI Connect**, the payment API of ROKI Technologies S.A. de C.V., to
charge Gravity Forms submissions. A ROKI merchant account is required; the plugin does nothing
without one. ROKI is the payment processor, so this connection is what the plugin is for.

**What is sent, and when**

Every time a form entry is submitted through a ROKI feed, the plugin sends the following to
`https://aura.roki.systems/api/connect/v1`:

* the amount to charge, and a label built from the form's title;
* the entry id, the form id and your site URL, so the payment can be matched back to the entry when
  ROKI notifies your site;
* an expiry time for the payment link;
* the return address on your site, so the person comes back after paying;
* the name, email address and phone number taken from the fields you mapped in the feed, **only
  when those fields have a value**. They prefill ROKI's payment form and are used for the receipt.

The card number is never sent by the plugin and never reaches your server: it is typed on ROKI's own
page, and only the result comes back.

**Terms and privacy**

* Terms and Conditions: https://roki.la/terms
* Privacy Policy: https://roki.la/privacy

== Changelog ==

= 1.0.1 =
* A payment made on another site can no longer mark an entry paid on this one. If two WordPress
  installations are connected to the same ROKI account, each receives the other's notifications,
  signed with the same secret - and entry 4242 over there was crediting entry 4242 over here. The
  site that created a payment is now verified before anything is credited.

= 1.0.0 =
* First release. Hosted ROKI checkout from any Gravity Forms form.
* Amount taken from the form's product fields, server-side.
* Signed webhooks, verified over the raw body in constant time and deduplicated by event id.
* Idempotent submission: resubmitting the same form returns the existing payment.
* Optional customer-paid processing fee.

== Upgrade Notice ==

= 1.0.1 =
Important if you have more than one WordPress site on the same ROKI account - a staging copy counts.
Without this version, a payment on one of them can mark an entry paid on the other. With a single
site you are unaffected.
