# StandaloneTech Documentation
Source: https://docs.standalonetech.com/index
Official documentation for StandaloneTech WooCommerce plugins: TeraWallet, TeraWallet Pro and more.
Guides, references and developer docs for our WooCommerce plugins. Pick a product to get started.
The free digital wallet for WooCommerce: top-ups, partial payments, cashback, transfers and a REST API.
Wallet withdrawals, credit expiry, wallet coupons, bulk importer and AffiliateWP payouts.
# AffiliateWP Integration
Source: https://docs.standalonetech.com/terawallet-pro/affiliatewp
Pay AffiliateWP commissions directly into the TeraWallet balance, crediting on paid referrals and reversing on refunds.
The AffiliateWP module bridges your affiliate program and your store's wallet economy: affiliates can
receive their commissions as wallet balance instead of an external payout.
This module requires the **AffiliateWP** plugin to be installed and active. Without it, the module
silently stays dormant.
## How it works
* A new **Wallet Payout** method is added to AffiliateWP (via the `affwp_payout_methods` filter).
* Affiliates **opt in** to wallet payouts from their affiliate dashboard.
* When a referral is marked **Paid**, the commission is **credited** to the affiliate's wallet.
* If a referral is later **reversed** (e.g. the order is refunded), the corresponding amount is
**debited** back out automatically, keeping balances accurate.
## Setup
1. Install and activate **AffiliateWP** and **TeraWallet Pro**.
2. The **Wallet Payout** option becomes available in AffiliateWP automatically.
3. Affiliates choose **Wallet Payout** as their preferred payout method in their dashboard.
From then on, commission crediting and reversal happen automatically as referral statuses change.
Wallet payouts pair well with [Wallet Coupons](/terawallet-pro/wallet-coupons) and
[Credit Expiry](/terawallet-pro/wallet-expiry) to build a complete affiliate-loyalty loop — reward
ambassadors with store credit they're encouraged to spend.
# Bank Transfer (BACS) Withdrawal Setup
Source: https://docs.standalonetech.com/terawallet-pro/bacs-withdrawal
Set up manual bank-transfer withdrawals in TeraWallet Pro: choose the bank fields customers fill in, review requests, pay by hand from your bank, and mark them approved.
**Bank Transfer (BACS)** is the manual payout option in the TeraWallet Pro [Wallet Withdrawal](/terawallet-pro/withdrawal)
module. There is no payment provider or API: customers give their bank details, you send the money from
your own bank, then mark the request **Approved**. It works with any currency and any country.
BACS is **never automatic**, even if **Approval Mode** is set to *Automatic (instant)*. Requests always
wait as **Pending** until you approve them.
## How it works
1. The customer saves their bank details once and requests a withdrawal. The wallet is debited the
**requested** amount straight away.
2. The request appears in **Pending** with the customer's bank details and the **Payable Amount**
(requested amount minus any fee).
3. You send that amount from your bank.
4. You click **Approve**. TeraWallet marks the request paid and emails the customer. No money moves
from TeraWallet itself.
5. If you can't pay, click **Reject**. The debit is reversed and the balance goes back to the customer.
## Step 1 — Enable the gateway
Go to **TeraWallet → Settings → Withdrawal**, turn on **Enable Withdrawal**, then turn on **Enable Bank
transfer** (the BACS gateway).
## Step 2 — Choose the bank fields
Use **Bank account fields** to pick which fields customers see. Leave it empty to show all of them.
| Field | Notes |
| - | - |
| **Account name** | Always shown and required. |
| **Account number** | Always shown and required. |
| **Sort code** | The label adapts to your store's base country: BSB (AU), Bank transit number (CA), IFSC (IN), Branch sort (IT), Bank code (NZ, SE), Routing number (US), Branch code (ZA). |
| **Bank name** | Optional. |
| **Routing number** | Optional. |
| **IBAN** | Checked for shape (15–34 letters and digits). |
| **Swift code** | Must be 8 or 11 letters and digits. |
Only pick what your bank needs to make a transfer in your region. For example, a UK store might select
sort code only, and a European store might select IBAN and SWIFT.
## Step 3 — Set limits and a fee (optional)
Set **Minimum / Maximum Withdrawal** as needed. To cover bank charges, turn on **Enable Processing Fee**
and choose **Fee Type**, **Fee Amount** and **Fixed Component**. The fee is deducted from what you pay: the
wallet is debited the requested amount and the **Payable Amount** is `requested − fee`.
## Step 4 — What customers need to do
Customers go to **My Account → Wallet → Withdrawal → Payment Settings**, choose **Bank transfer**, fill in
the fields and save. Each field is limited to 200 characters, and an invalid IBAN or SWIFT is rejected
with a message and not saved. If a customer submits a withdrawal without an account name and number, the
form asks them to set up their bank details first.
## Step 5 — Pay and approve requests
1. Go to the **Withdrawal requests** list and open a pending request.
2. Under **Payment Details**, copy the customer's bank details. **Requested Amount**, **Withdrawal Charge** and
**Payable Amount** are shown below.
3. Make the transfer in your bank.
4. Click **Approve**. For several at once, tick the requests in the list and use the **Approve** bulk action.
5. Add a note (for example the bank reference) if you want a record. Notes can be private or visible to the customer.
Only approve after the money has been sent. Approving does not send anything, it only records the
payment and notifies the customer.
## Troubleshooting
| Symptom | Likely cause |
| - | - |
| Customer sees "Click here to setup bank account details" | Account name or number is missing in their saved details. |
| "IBAN format looks invalid" / "SWIFT/BIC code must be 8 or 11 alphanumeric characters" | The customer entered the value in the wrong format. Check for typos. |
| A field customers need isn't shown | It isn't ticked in **Bank account fields**. |
| Sort code label is wrong | It follows your store's base country (WooCommerce → Settings → General). |
| Request won't go from Pending to paid automatically | By design: BACS is always manual. |
## Developer notes
* Filter `woo_wallet_withdrawal_bacs_account` changes the list of bank fields.
* Filter `woocommerce_get_bacs_locale` changes the country-specific sort-code labels.
See [Pro Hooks & REST API](/terawallet-pro/hooks) for the full reference.
# Cashfree Withdrawal Setup
Source: https://docs.standalonetech.com/terawallet-pro/cashfree-withdrawal
Step-by-step guide to paying out TeraWallet Pro withdrawals to Indian bank accounts through Cashfree Payouts: API credentials, sandbox testing, webhook and go-live checklist.
This guide connects **Cashfree Payouts** (v2 API) to the TeraWallet Pro [Wallet Withdrawal](/terawallet-pro/withdrawal)
module, so approved withdrawals are transferred to customers' Indian bank accounts.
The Cashfree gateway appears **only when your store currency is INR**. It needs a **Cashfree Payouts**
account, which is separate from a Cashfree payment-gateway account.
## How it works
1. A customer saves their bank details. TeraWallet registers them with Cashfree as a **beneficiary**
(ID `ww_user_`).
2. They request a withdrawal; the wallet is debited the **requested** amount.
3. On approval (automatic, or by you), TeraWallet creates a Cashfree **transfer** (bank transfer, INR) for
`amount − fee`.
4. If Cashfree accepts the transfer (status `SUCCESS`, `RECEIVED`, `PENDING` or `APPROVAL_PENDING`), the
request is marked **Approved** straight away.
5. Webhooks report the final result. A failed, rejected or reversed transfer cancels the request and
restores the customer's balance.
## Step 1 — Get your Cashfree credentials
In the Cashfree Payouts dashboard:
1. Open **Developers → API Keys** (the Payouts section) and generate a **Client ID** and **Client Secret**.
Sandbox and production have separate credentials.
2. If Cashfree asks you to **whitelist IP addresses** for API access, add your server's outgoing IP.
3. Make sure the Payouts balance is funded. Transfers are drawn from it.
Menu names in the Cashfree dashboard change from time to time. If you can't find an item, search the
dashboard for "API keys" or "webhooks" or check Cashfree's Payouts documentation.
## Step 2 — Configure TeraWallet
Go to **TeraWallet → Settings → Withdrawal**. Turn on **Enable Withdrawal**, choose the **Approval Mode**
(use *Manual* while testing) and turn on **Enable logging** during setup. Then, under Cashfree:
| Setting | What to do |
| - | - |
| **Enable Cashfree** | Turn on. |
| **Enable Cashfree sandbox** | Tick while using sandbox credentials. |
| **Cashfree Client ID** | From Step 1. |
| **Cashfree Client Secret** | From Step 1. Also used to verify webhooks. |
| **Enable Processing Fee**, **Fee Type**, **Fee Amount**, **Fixed Component** | Optional. The fee is deducted from the transfer: the wallet is debited the requested amount and the customer receives `amount − fee`. |
Enter the credentials **before** customers save their bank details. Beneficiary registration happens when
they save, and fails without credentials.
## Step 3 — Register the webhook
1. In the Cashfree Payouts dashboard, open the **Webhooks** settings.
2. Set the webhook URL to:
```
https://your-site.com/wp-json/terawallet/v1/cashfree/webhook
```
3. Enable the transfer events below, and save.
| Event | Effect in TeraWallet |
| - | - |
| `TRANSFER_SUCCESS` | Marks the request **Approved** (if not already), saves the bank reference (UTR) and adds a note. |
| `TRANSFER_FAILED` | Cancels the request and restores the balance. |
| `TRANSFER_REJECTED` | Cancels the request and restores the balance. |
| `TRANSFER_REVERSED` | Cancels the request and restores the balance. |
| `TRANSFER_ACKNOWLEDGED` | Adds a status note only. |
There is no separate webhook secret to copy. TeraWallet verifies each request's signature
(`x-webhook-signature`, with `x-webhook-timestamp`) using your **Client Secret**. Requests with a missing
or wrong signature are rejected.
## Step 4 — What customers need to do
Customers go to **My Account → Wallet → Withdrawal → Payment Settings**, choose **Cashfree** and enter:
| Field | Rules |
| - | - |
| **Bank account holder name** | Required. |
| **Bank account number** | Required. 8–18 digits. |
| **IFSC code** | Required. Format `ABCD0XXXXXX`. |
| **Phone** | Required. International format with 10–15 digits, such as `+919999999999`. |
Invalid values are rejected with a message. On success the customer sees "Cashfree beneficiary
registered." Without a registered beneficiary, the withdrawal form tells them to register their bank
account first.
## Step 5 — Test in sandbox
1. Tick **Enable Cashfree sandbox** and use sandbox credentials.
2. As a test customer, save bank details, add balance and submit a withdrawal.
3. Approve it in **wp-admin** (or use Automatic mode).
4. The request should show **Approved** with a note like "Cashfree transfer ww\_cf\_123 queued (status: …)".
5. Confirm the webhook updates the request when Cashfree reports the final status.
## Go live checklist
* [ ] Payouts account activated and funded for production
* [ ] Server IP whitelisted, if Cashfree requires it
* [ ] **Sandbox** unticked and production Client ID and Secret pasted
* [ ] Production webhook URL saved in Cashfree
* [ ] **Enable logging** turned off
* [ ] One small real withdrawal tested end to end
## Duplicate-payment protection
Each transfer has a fixed ID (`ww_cf_`) that is also sent as an idempotency key. TeraWallet also
saves it on the request and skips creating another transfer if one exists. Re-approving can't pay twice.
## Troubleshooting
Enable **Enable logging** and open the request to see its log. Failure reasons are also saved as notes.
| Symptom / message | Likely cause |
| - | - |
| "Cashfree" isn't in the gateway list | Store currency isn't INR. |
| "Click here to register your Cashfree bank account." | No beneficiary was registered. Credentials were missing, or registration failed. Ask the customer to save again. |
| "Invalid IFSC code" / "Invalid bank account number" / "Invalid phone number" | Details are in the wrong format. |
| "Cashfree credentials are not configured." | Client ID or Secret is empty. |
| "Cashfree transfer failed (…): …" | Cashfree's own error, such as insufficient balance, IP not whitelisted, or an invalid account. |
| Transfer stays pending | Cashfree may need approval in its dashboard (`APPROVAL_PENDING`) or the bank is processing. The webhook will update it. |
| Webhook 500 `missing_secret` / 401 `invalid_signature` | Client Secret empty, or webhook is sent by a different account or mode. |
If your host or a security plugin blocks unauthenticated REST requests, allow
`POST /wp-json/terawallet/v1/cashfree/webhook`.
See [Pro Hooks & REST API](/terawallet-pro/hooks) for the full reference.
# Pro Hooks & REST API
Source: https://docs.standalonetech.com/terawallet-pro/hooks
Developer reference for TeraWallet Pro — module hooks, withdrawal/coupon/import filters, and the Pro REST endpoints.
This page covers the developer surface added by **TeraWallet Pro**. For the core plugin's hooks and
API, see the free [Hooks Reference](/terawallet/developer-guide/hooks) and [REST API Reference](/terawallet/developer-guide/rest-api).
## Hooks
Each name below was verified against the Pro plugin source.
| Hook | Type | Module | Purpose |
| - | - | - | - |
| `woo_wallet_withdrawal_loaded` | action | Withdrawal | Fires when the withdrawal module is ready. |
| `woo_wallet_withdrawal_payment_gateways` | filter | Withdrawal | Register or remove payout gateways. |
| `woo_wallet_withdrawal_payment_gateway_settings` | filter | Withdrawal | Modify a gateway's settings fields. |
| `woo_wallet_withdrawable_amount` | filter | Withdrawal | Control how much a user is allowed to withdraw. |
| `woo_wallet_withdrawal_gateway_charge` | filter | Withdrawal | Override the calculated per-gateway processing fee. |
| `woo_wallet_coupons_loaded` | action | Coupon | Fires when the coupon system is initialized. |
| `woo_wallet_current_balance` | filter | Credit Expiry | Core filter the expiry module uses (priority 999) to exclude expired/redeemed credit. |
| `woo_wallet_import_batch_size` | filter | Importer | Adjust the number of CSV rows processed per batch. |
| `woo_wallet_rest_check_permissions` | filter | Importer | Override the capability check on Pro REST endpoints. |
| `affwp_payout_methods` | filter | AffiliateWP | Inject the "Wallet Payout" method into AffiliateWP. |
### Example: cap the withdrawable amount
```php theme={null}
add_filter( 'woo_wallet_withdrawable_amount', function( $amount, $user_id ) {
// Never allow withdrawing more than 500 at a time.
return min( (float) $amount, 500 );
}, 10, 2 );
```
## REST API
Pro adds endpoints under two namespaces. Verify exact routes/args against the plugin source before
building against them.
### Coupons — `terawallet/v1/coupons`
Full CRUD plus **bulk create** and **code generation** for wallet coupons. Used by the in-admin bulk
generator and available for your own automation. Requires the appropriate management capability.
### Importer — `woo-wallet-pro/v1/import`
| Route | Purpose |
| - | - |
| `POST /woo-wallet-pro/v1/import/upload` | Upload a CSV; returns an `import_id` (attachment id). File paths never travel through the client. |
| `POST /woo-wallet-pro/v1/import/process` | Process the next batch of rows for an import session. |
| `GET /woo-wallet-pro/v1/import/messages` | Fetch progress/result messages for a session. |
| `GET /woo-wallet-pro/v1/import/currencies` | List valid currencies for the `currency` column. |
Every import route requires `manage_options` (filterable via `woo_wallet_rest_check_permissions`),
and sessions are pinned to the uploading user.
### Withdrawal webhooks — `terawallet/v1`
Asynchronous payout webhooks for Stripe, PayPal, Razorpay, Cashfree and Paystack live under the
`terawallet/v1` namespace, with provider signature verification and replay protection. The Stripe
endpoint is `POST /wp-json/terawallet/v1/stripe/webhook` (set the webhook secret in the gateway's
settings to enable it).
# Bulk Importer
Source: https://docs.standalonetech.com/terawallet-pro/importer
Import thousands of TeraWallet credit and debit transactions from a CSV file, with batch processing, per-row currency and expiry, and error logs.
The Bulk Importer loads credit and debit transactions for many users at once from a CSV file — ideal
for migrations, mass corrections, or seeding balances.
## Opening the importer
The importer is available from either:
* **Tools → Import → WooCommerce Wallet**, or
* the **Import** action on the TeraWallet users/balances screen.
It runs as a modern admin screen and requires the `manage_options` capability.
## CSV format
Headers are matched **case- and whitespace-insensitively**.
| Column | Required | Description |
| - | - | - |
| `email` | ✅ | The user's account email. |
| `amount` | ✅ | The transaction amount. |
| `type` | ✅ | `credit` or `debit`. |
| `details` | — | A description stored on the ledger entry. |
| `expire_date` | — | Optional expiry for a credit row (works with [Credit Expiry](/terawallet-pro/wallet-expiry)). |
| `currency` | — | ISO 4217 code; validated against the store's WooCommerce currencies. |
A `sample.csv` is included with the plugin to use as a template. Missing required columns are
reported explicitly before processing starts.
## Processing & error handling
* **Batch processing** — large files are processed in batches in the background, so imports don't
time out. Developers can tune the batch size with the `woo_wallet_import_batch_size` filter.
* **Per-row currency** — each row's `currency` is forwarded to the ledger; core's currency manager
handles conversion or per-currency storage transparently.
* **Per-row expiry** — when `expire_date` is supplied on a credit row, it is applied to that exact
transaction (and takes precedence over the global Credit Expiry default).
* **Error reporting** — rows that fail (for example, a non-existent user email) are listed in a
detailed log so you can fix and re-import them.
Imports move real money in the ledger. Test with a small CSV first, and double-check the `type`
column — `debit` rows reduce balances.
# TeraWallet Pro
Source: https://docs.standalonetech.com/terawallet-pro/index
Overview of TeraWallet Pro — withdrawals, wallet coupons, credit expiry, bulk importer and AffiliateWP integration for WooCommerce.
**TeraWallet Pro** is a premium add-on for the free [TeraWallet](/terawallet/getting-started/key-features) core
plugin. It adds the money-out and lifecycle features that turn a store wallet into a full digital
economy: customer withdrawals, wallet-only coupons, automatic credit expiry, bulk balance imports,
and AffiliateWP payouts.
Pro **requires the free TeraWallet core plugin** to be installed and active — it extends core and
cannot run on its own. See [Free vs Pro](/terawallet/getting-started/pro) for a side-by-side comparison.
## What you unlock
Let customers cash out their balance to PayPal, Stripe, Razorpay, Paystack, Cashfree or bank
transfer, with admin approval and per-gateway fees.
Create coupons that credit the wallet instead of discounting the cart, with email/domain limits,
usage caps and expiry.
Expire store credit on a schedule, spend the soonest-to-expire credit first, and send reminder
and lapse emails.
Import thousands of credit/debit transactions from a CSV with batch processing and error logs.
Pay affiliate commissions straight into the wallet, crediting on paid referrals and reversing on
refunds.
Activate your license for automatic updates and support.
## Requirements
| Requirement | Version |
| - | - |
| TeraWallet (core) | Required, latest recommended |
| WordPress | 6.0 or higher |
| WooCommerce | 7.0 or higher |
| PHP | 7.4 or higher (8.2+ recommended) |
| AffiliateWP | Optional — only for affiliate payouts |
This section documents **TeraWallet Pro 1.0.6**. For core plugin features, see the
[Getting Started](/terawallet/getting-started/key-features) and [Guides](/terawallet/user-guide/wallet-dashboard)
sections.
# Installation & Licensing
Source: https://docs.standalonetech.com/terawallet-pro/installation
How to install TeraWallet Pro, activate your license for updates, and configure the Pro modules.
TeraWallet Pro installs alongside the free core plugin and adds its settings into the existing
TeraWallet admin.
## Before you start
Make sure **TeraWallet (core)** is installed and **active** first. Pro declares core as a required
plugin and none of its modules load without it.
## Install the add-on
1. Purchase TeraWallet Pro from [StandaloneTech](https://standalonetech.com/product/woocommerce-wallet-pro/)
and download the plugin ZIP.
2. In WordPress, go to **Plugins → Add New → Upload Plugin**.
3. Choose the `woo-wallet-pro` ZIP and click **Install Now**.
4. Click **Activate**.
After activation, the Pro modules appear inside **TeraWallet → Settings** (a new **Withdrawal** tab,
plus **Wallet Coupon** and **Credit Expiry** options), and an **Import** entry is added for bulk
balance management.
If you previously used the standalone add-ons (Wallet Withdrawal, Wallet Coupons, Wallet Importer,
Credit Expiry, AffiliateWP for TeraWallet), **deactivate them** after installing Pro — it bundles
all of them and will warn you if any are still active.
## Activate your license
A valid license unlocks **automatic updates** and support.
1. Go to the TeraWallet **Extensions / Go Pro** page in the admin menu.
2. Enter your **license key** from your StandaloneTech account.
3. Click **Activate**.
Once activated, plugin updates appear in **Dashboard → Updates** like any other plugin. Deactivating
the license on a site frees the activation for use elsewhere.
## Next steps
Enable payout gateways and the minimum/maximum withdrawal amounts.
Set a global expiry duration and optional per-category rules.
Build coupons that top up the wallet on redemption.
Bulk-load credits and debits from a CSV file.
# PayPal Withdrawal Setup
Source: https://docs.standalonetech.com/terawallet-pro/paypal-withdrawal
Step-by-step guide to paying out TeraWallet Pro withdrawals through PayPal Payouts: create a REST app, enable Payouts, configure credentials, register the webhook, and test in sandbox.
This guide walks through connecting **PayPal Payouts** to the TeraWallet Pro [Wallet Withdrawal](/terawallet-pro/withdrawal)
module, so approved requests are sent straight to the customer's PayPal account and final status is
reported back automatically.
Requires TeraWallet Pro with the Withdrawal module active, and a **PayPal Business** account with
**Payouts** enabled. PayPal's API calls are made server-side, so your site needs working outbound HTTPS.
## How it works
1. The customer requests a withdrawal; the wallet is debited the **requested** amount.
2. When the request is approved (automatically, or by you), TeraWallet calls the PayPal **Payouts API**
with the amount minus your processing fee.
3. If PayPal accepts the batch (status `PENDING`, `PROCESSING`, `SUCCESS` or `NEW`), the request moves to
**Approved**.
4. PayPal later sends a **webhook** with the final result. On failure, TeraWallet cancels the request and
restores the customer's balance.
## Step 1 — Create a PayPal REST app
1. Sign in to the [PayPal Developer Dashboard](https://developer.paypal.com/dashboard/applications).
2. Switch the toggle to **Sandbox** (for testing) or **Live** (for real payouts).
3. Go to **Apps & Credentials → Create App**, choose type **Merchant**, and name it (e.g. "TeraWallet Payouts").
4. Open the app and copy the **Client ID** and **Secret key**.
5. Under **Features**, tick **Payouts** and save.
Without the Payouts feature on the app (and Payouts approved on the Business account for live mode),
PayPal rejects every payout request. Sandbox and Live use **separate** credentials — never mix them.
## Step 2 — Fund the PayPal account
Payouts are drawn from the PayPal balance of the account that owns the app. Keep enough balance to cover
pending withdrawals. In sandbox, add funds to your sandbox **Business** account from the dashboard under
**Testing Tools → Sandbox Accounts**.
## Step 3 — Configure TeraWallet
Go to **TeraWallet → Settings → Withdrawal**.
**General options**
| Setting | What to do |
| - | - |
| **Enable Withdrawal** | Turn on. |
| **Approval Mode** | *Automatic (instant)* pays out as soon as a request is submitted. *Manual (admin review)* waits for you to approve. Start with Manual while testing. |
| **Minimum / Maximum Withdrawal** | Optional bounds per request. |
| **Enable logging** | Turn on while setting up (see [Troubleshooting](#troubleshooting)). Turn off afterwards — logs may contain personal data. |
**PayPal gateway options**
| Setting | What to do |
| - | - |
| **Enable PayPal** | Turn on. |
| **Mode** | *Sandbox / Test* or *Live / Production*, matching the credentials you copied. |
| **PayPal Client ID** | Paste from Step 1. |
| **PayPal Secret Key** | Paste from Step 1. |
| **PayPal Webhook ID** | Filled in during Step 4. |
| **Enable Processing Fee**, **Fee Type**, **Fee Amount**, **Fixed Component** | Optional. The fee is deducted from the payout, not added to the debit: the wallet is debited the requested amount and PayPal receives `amount − fee`. |
Save your changes.
## Step 4 — Register the webhook
Webhooks tell TeraWallet whether a payout actually succeeded or later failed.
1. In the PayPal app, scroll to **Webhooks → Add Webhook**.
2. Set the **Webhook URL** to:
```
https://your-site.com/wp-json/terawallet/v1/paypal/webhook
```
The URL must be public HTTPS. Use the **same** Sandbox/Live mode as your credentials.
3. Subscribe to these events:
| Event | Effect in TeraWallet |
| - | - |
| `PAYMENT.PAYOUTS-ITEM.SUCCEEDED` | Marks the request **Approved** and adds a "PayPal payout succeeded" note. |
| `PAYMENT.PAYOUTS-ITEM.DENIED` | Cancels the request and restores the balance. |
| `PAYMENT.PAYOUTS-ITEM.BLOCKED` | Same as above. |
| `PAYMENT.PAYOUTS-ITEM.FAILED` | Same as above. |
| `PAYMENT.PAYOUTS-ITEM.REFUNDED` | Same as above. |
| `PAYMENT.PAYOUTS-ITEM.RETURNED` | Same as above. |
| `PAYMENT.PAYOUTS-ITEM.REVERSED` | Same as above. |
| `PAYMENT.PAYOUTS-ITEM.UNCLAIMED` | Same as above. |
| `PAYMENT.PAYOUTSBATCH.DENIED` | Same as above (batch-level). |
Other event types are acknowledged and ignored.
4. Save, then copy the generated **Webhook ID** into **PayPal Webhook ID** in TeraWallet and save.
Every webhook is verified against PayPal's signature-verification API using your Webhook ID and
credentials. If the Webhook ID is empty, or the signature is invalid, the request is rejected and no
withdrawal changes. Cancelled requests have their wallet debit reversed, so the customer is made whole.
## Step 5 — What customers need to do
Customers add their PayPal email once, under **My Account → Wallet → Withdrawal → Payment Settings**
(field: **PayPal email**). If it is missing, the withdrawal form tells them to set it up before they can
submit. The payout goes to this email address, so make sure customers use the one tied to their PayPal
account.
## Step 6 — Test in sandbox
1. Set **Mode** to *Sandbox / Test* and use sandbox credentials and a sandbox webhook.
2. In the dashboard, create a sandbox **Personal** account; use its email as the test customer's PayPal email.
3. As that customer, with a wallet balance, submit a withdrawal.
4. In **wp-admin**, open the withdrawal list and **Approve** the request (or let Automatic mode do it).
5. Check the request: it should be **Approved**, with log entries showing the PayPal response.
6. Use **Webhooks → Simulate event** in the PayPal dashboard (e.g. `PAYMENT.PAYOUTS-ITEM.SUCCEEDED`, then a
failure event on a second request) to confirm status changes and notes.
7. Log in to the sandbox personal account at [sandbox.paypal.com](https://www.sandbox.paypal.com) to see the
received funds.
## Go live checklist
* [ ] Payouts approved on the live PayPal Business account and enabled on the live app
* [ ] **Mode** switched to *Live / Production*
* [ ] Live **Client ID** and **Secret Key** pasted
* [ ] A **new live webhook** created, with its Webhook ID pasted (sandbox IDs do not work live)
* [ ] PayPal balance funded
* [ ] **Enable logging** turned off
* [ ] One small real withdrawal tested end to end
## Duplicate-payment protection
Each withdrawal is sent with a stored unique batch ID (also used as PayPal's `PayPal-Request-Id`), so a
retry after a timeout is treated by PayPal as the same request and cannot pay twice.
## Troubleshooting
Enable **Enable logging**, then open the request in the withdrawal list to see its gateway log. Failure
reasons are also saved as notes on the request.
| Symptom / message | Likely cause |
| - | - |
| "Unable to approve request please check log file" | Gateway call failed. See the note on the request for the reason below. |
| "PayPal payout skipped: missing client credentials or recipient email." | Client ID/Secret empty, or the customer has no PayPal email saved. |
| "could not obtain OAuth access token" | Wrong credentials, or Sandbox/Live mode mismatch with the keys. |
| "PayPal payout rejected: …" | PayPal returned an error, commonly Payouts not enabled on the app/account, insufficient balance, or unsupported currency. The message is PayPal's own. |
| "PayPal payout transport error" | Your server could not reach `api-m.paypal.com` (firewall, DNS, cURL/SSL). |
| Request stays Approved but money never arrives | Webhook not configured; check the Webhook ID, URL and event subscriptions. |
| Webhook returns 400/500/502 | 500 `missing_webhook_id` / `missing_credentials`: fill the settings. 400 `invalid_signature`: Webhook ID belongs to a different app or mode. 502: could not verify with PayPal. |
Hosts that block unauthenticated REST requests (security plugins, WAFs, "REST API disabled" settings)
can stop PayPal from reaching the webhook URL. Allow `POST /wp-json/terawallet/v1/paypal/webhook`.
## Developer notes
* The payout uses PayPal Payouts v1, with the recipient type `EMAIL` and the withdrawal ID as the `sender_item_id`.
* Filter `woo_wallet_paypal_payouts_sync_mode` (default `false`) switches Payouts to synchronous mode.
* Filter `woo_wallet_withdrawal_payout_batch_status` changes which batch statuses count as accepted
(default `PENDING`, `PROCESSING`, `SUCCESS`, `NEW`).
See [Pro Hooks & REST API](/terawallet-pro/hooks) for the full reference.
# Paystack Withdrawal Setup
Source: https://docs.standalonetech.com/terawallet-pro/paystack-withdrawal
Step-by-step guide to paying out TeraWallet Pro withdrawals through Paystack Transfers in NGN, GHS, ZAR, KES, USD, EUR and GBP: secret key, webhook, transfer settings and testing.
This guide connects **Paystack Transfers** to the TeraWallet Pro [Wallet Withdrawal](/terawallet-pro/withdrawal)
module, so approved withdrawals are paid to customers' bank or mobile-money accounts.
The Paystack gateway appears **only when your store currency is one of NGN, GHS, ZAR, KES, USD, EUR or
GBP**. Which payout types your Paystack account can actually use depends on its country and what
Paystack has enabled for it.
## How it works
1. A customer saves their account details. TeraWallet registers them with Paystack as a **transfer
recipient** and keeps the recipient code.
2. They request a withdrawal; the wallet is debited the **requested** amount.
3. On approval (automatic, or by you), TeraWallet creates a Paystack **transfer** from your Paystack
balance for `amount − fee`.
4. If Paystack accepts the transfer, the request is marked **Approved** straight away.
5. Webhooks report the final result. A failed transfer cancels the request and restores the customer's balance.
## Step 1 — Get your Paystack secret key
1. Sign in to the [Paystack Dashboard](https://dashboard.paystack.com).
2. Go to **Settings → API Keys & Webhooks**.
3. Copy the **Secret Key**. Test keys start with `sk_test_` and live keys with `sk_live_`.
Only the secret key is needed. There is no separate sandbox switch: test or live mode is decided by the key
you paste.
## Step 2 — Allow transfers over the API
Paystack settings control whether transfers sent by API are paid automatically.
* Make sure **Transfers** are enabled on your Paystack account.
* In the dashboard's transfer settings, turn **off** the requirement to confirm transfers with an OTP, which
would otherwise hold every API transfer for manual confirmation.
* Keep enough balance in your Paystack account. Transfers are paid from it.
Menu names in the Paystack dashboard change from time to time. If you can't find an item, check
Paystack's Transfers documentation.
## Step 3 — Configure TeraWallet
Go to **TeraWallet → Settings → Withdrawal**. Turn on **Enable Withdrawal**, choose the **Approval Mode**
(use *Manual* while testing) and turn on **Enable logging** during setup. Then, under Paystack:
| Setting | What to do |
| - | - |
| **Enable Paystack** | Turn on. |
| **Secret Key** | Paste from Step 1. |
| **Enable Processing Fee**, **Fee Type**, **Fee Amount**, **Fixed Component** | Optional. The fee is deducted from the transfer: the wallet is debited the requested amount and the customer receives `amount − fee`. |
Enter the secret key **before** customers save their details. The list of banks and the recipient
registration both need it. Customers who saved details earlier will have to save them again.
## Step 4 — Register the webhook
1. In Paystack, go to **Settings → API Keys & Webhooks**.
2. Set the **Webhook URL** to:
```
https://your-site.com/wp-json/terawallet/v1/paystack/webhook
```
Paystack has one webhook URL per mode (test and live), so set it in each mode you use.
3. Save. There is no separate secret to copy: TeraWallet verifies each request's `x-paystack-signature`
using your **Secret Key**.
| Event | Effect in TeraWallet |
| - | - |
| `transfer.success` | Marks the request **Approved** (if not already) and adds a note. |
| `transfer.failed` | Cancels the request and restores the balance. |
| `transfer.reversed` | Adds a note only: **"Manual reconciliation required."** The request is not cancelled automatically. |
Other events are ignored. Paystack sends all transfer events to the one URL, so there is nothing to
subscribe to.
## Step 5 — What customers need to do
Customers go to **My Account → Wallet → Withdrawal → Payment Settings**, choose **Paystack** and enter:
| Field | Notes |
| - | - |
| **Name** | Account holder name. |
| **Number** | Bank account number, or mobile-money number depending on your currency. |
| **Bank** | Pick from the list loaded from Paystack for your currency. |
The kind of account TeraWallet registers depends on your store currency:
| Currency | Account type |
| - | - |
| NGN (and any currency not listed below) | Nigerian bank account (`nuban`) |
| GHS, KES | Mobile money |
| ZAR | South African bank account (`basa`) |
If the **Bank** list is empty, the secret key is missing or Paystack doesn't offer that payout type for
your currency. Check the key and look at the log.
## Step 6 — Test
1. Use a test secret key (`sk_test_…`) and set the webhook in Paystack's **test** mode.
2. As a test customer, save account details, add balance and submit a withdrawal.
3. Approve it in **wp-admin**.
4. The request should show **Approved** with a note like "Paystack transfer queued (transfer\_code: TRF\_…, reference: ww\_paystack\_123)".
5. Confirm the webhook adds the "Paystack confirmed transfer.success." note, or cancels the request on a failure.
## Go live checklist
* [ ] Paystack account activated for live transfers, with sufficient balance
* [ ] OTP confirmation for transfers turned off
* [ ] Live **Secret Key** (`sk_live_…`) pasted
* [ ] Live webhook URL saved in Paystack
* [ ] **Enable logging** turned off
* [ ] One small real withdrawal tested end to end
## Duplicate-payment protection
Each transfer uses a fixed reference (`ww_paystack_`). Paystack rejects a second transfer with
the same reference, so a retry can't pay twice.
## Troubleshooting
Enable **Enable logging** and open the request to see its log. Failure reasons are also saved as notes.
| Symptom / message | Likely cause |
| - | - |
| "Paystack" isn't in the gateway list | Store currency isn't supported. |
| Bank list is empty | Secret key missing or wrong, or the account type isn't offered for your currency. |
| "Unable to approve request please check log file" | The customer has no recipient code (details were saved before the key was set, or registration failed), or the secret key is empty. Ask the customer to save again, and read the log. |
| "Paystack transfer rejected (HTTP …): …" | Paystack's own error, such as insufficient balance or transfers not enabled for the account. |
| Transfer stuck at pending | OTP confirmation is on, or the bank is processing. |
| "transfer.reversed … Manual reconciliation required." | The money came back to your Paystack balance. Decide whether to refund the customer by rejecting the request. |
| Webhook 500 `missing_secret` / 401 `invalid_signature` | Secret key empty, or the webhook was sent from the other mode (test vs live). |
If your host or a security plugin blocks unauthenticated REST requests, allow
`POST /wp-json/terawallet/v1/paystack/webhook`.
See [Pro Hooks & REST API](/terawallet-pro/hooks) for the full reference.
# Razorpay (RazorpayX) Withdrawal Setup
Source: https://docs.standalonetech.com/terawallet-pro/razorpay-withdrawal
Step-by-step guide to paying out TeraWallet Pro withdrawals to Indian bank accounts through RazorpayX Payouts: API keys, account number, transfer mode, webhook and testing.
This guide connects **RazorpayX Payouts** to the TeraWallet Pro [Wallet Withdrawal](/terawallet-pro/withdrawal)
module, so approved withdrawals are paid to customers' Indian bank accounts by IMPS, NEFT or RTGS.
The Razorpay gateway appears **only when your store currency is INR**. It needs a **RazorpayX** account
(Razorpay's payouts product), not just a standard Razorpay payment-gateway account.
## How it works
1. A customer saves their bank details. TeraWallet registers them with RazorpayX as a **Contact** and a
**Fund Account** and remembers the IDs.
2. They request a withdrawal; the wallet is debited the **requested** amount.
3. On approval (automatic, or by you), TeraWallet creates a RazorpayX **payout** for `amount − fee`
from your RazorpayX account.
4. If RazorpayX accepts the payout, the request is marked **Approved** straight away. A payout that
can't be funded yet is queued by RazorpayX rather than rejected.
5. Webhooks report progress. A failed or reversed payout cancels the request and restores the
customer's balance.
## Step 1 — Get your RazorpayX details
In the RazorpayX dashboard:
1. Open **Developer Controls** (or **Settings → API Keys**) and generate an **API Key** and **Secret**.
Test keys start with `rzp_test_` and live keys with `rzp_live_`.
2. Open **My Account & Settings** and copy your **RazorpayX account number**. This is the virtual
account payouts are paid from (not your bank account number).
3. Make sure the account has funds. Payouts are drawn from this balance.
## Step 2 — Configure TeraWallet
Go to **TeraWallet → Settings → Withdrawal**. Turn on **Enable Withdrawal**, choose the **Approval Mode**
(use *Manual* while testing) and turn on **Enable logging** during setup. Then, under Razorpay:
| Setting | What to do |
| - | - |
| **Enable Razorpay** | Turn on. |
| **Enable Razorpay Test Mode** | Tick while using test keys. |
| **Razorpay API Key** | `rzp_test_…` or `rzp_live_…` from Step 1. |
| **Razorpay API Secret** | The secret for that key. |
| **RazorpayX Account Number** | From Step 1. |
| **Transfer Mode** | *IMPS* (fastest), *NEFT* or *RTGS*. One mode is used for all payouts. |
| **Razorpay Webhook Secret** | Filled in during Step 3. |
| **Enable Processing Fee**, **Fee Type**, **Fee Amount**, **Fixed Component** | Optional. The fee is deducted from the payout: the wallet is debited the requested amount and the customer receives `amount − fee`. |
Enter the API keys **before** customers save their bank details. TeraWallet registers the Contact and
Fund Account at the moment a customer saves, and skips this if the keys are missing. Customers who
saved details earlier have to save them again.
Test or live mode is decided by the API key you use. Keep the key, secret and account number all from
the same mode.
## Step 3 — Register the webhook
1. In RazorpayX, go to **Developer Controls → Webhooks → Add New Webhook**.
2. Set the **Webhook URL** to:
```
https://your-site.com/wp-json/terawallet/v1/razorpay/webhook
```
3. Choose a **Secret** and paste the same value into **Razorpay Webhook Secret** in TeraWallet.
4. Subscribe to these events:
| Event | Effect in TeraWallet |
| - | - |
| `payout.processed` | Marks the request **Approved** (if not already) and adds a note. |
| `payout.failed` | Cancels the request and restores the balance. |
| `payout.reversed` | Cancels the request and restores the balance. |
| `payout.queued`, `payout.pending`, `payout.initiated`, `payout.updated` | Adds a status note only. |
Other events are ignored.
Each request is checked against the `X-Razorpay-Signature` header using your webhook secret. A missing
secret returns an error and a wrong signature is rejected, so no withdrawal changes.
## Step 4 — What customers need to do
Customers go to **My Account → Wallet → Withdrawal → Payment Settings**, choose **Razorpay** and enter:
| Field | Rules |
| - | - |
| **Account Holder Name** | Required. |
| **IFSC Code** | Required. 11 characters, such as `HDFC0001234`. |
| **Bank Account Number** | Required. 4–26 letters and digits. |
| **Contact Phone** | Optional. |
Invalid details are rejected with a message. If a customer later changes their name, IFSC or account number,
the old RazorpayX records are dropped and new ones are created. Without a registered fund account, the
withdrawal form tells them to set up their details first.
## Step 5 — Test
1. Use test keys, tick **Enable Razorpay Test Mode** and set the test webhook.
2. As a test customer, save bank details, add balance and submit a withdrawal.
3. Approve it in **wp-admin**.
4. The request should show **Approved** with a note like "RazorpayX payout queued (payout\_id: …)".
5. Use the RazorpayX dashboard (or the test-mode payout actions) to move the payout to processed or failed
and confirm the webhook updates the request.
## Go live checklist
* [ ] RazorpayX account active and funded
* [ ] **Test Mode** unticked and live API key, secret and account number pasted
* [ ] A **live webhook** created, with the same secret saved in TeraWallet
* [ ] **Transfer Mode** suits your payout sizes (use RTGS for large amounts, and check RazorpayX's limits for each mode)
* [ ] **Enable logging** turned off
* [ ] One small real withdrawal tested end to end
## Duplicate-payment protection
Each payout is sent with a stored unique idempotency key, and the payout ID is saved on the request. A retry
after a timeout is recognised by RazorpayX as the same payout and can't pay twice.
## Troubleshooting
Enable **Enable logging** and open the request to see its log. Failure reasons are also saved as notes.
| Symptom / message | Likely cause |
| - | - |
| "Razorpay" isn't in the gateway list | Store currency isn't INR. |
| Customer is told to set up their account | No fund account was registered. Keys were missing when they saved, or registration failed. Ask them to save again. |
| "Could not register RazorpayX contact/fund account: …" | RazorpayX rejected the details or the keys. Check the keys and the message. |
| "RazorpayX payout rejected (HTTP …): …" | RazorpayX's own error, such as a wrong account number or key from another mode. |
| "Unable to approve request please check log file" | Credentials, account number or the customer's fund account is missing. See the log. |
| Request Approved but money late | The payout may be queued for low balance. Fund the account and watch the webhook notes. |
| Webhook 500 `missing_secret` / 401 `invalid_signature` | Webhook Secret is empty, or doesn't match the one set in RazorpayX. |
If your host or a security plugin blocks unauthenticated REST requests, allow
`POST /wp-json/terawallet/v1/razorpay/webhook`.
See [Pro Hooks & REST API](/terawallet-pro/hooks) for the full reference.
# Pro Settings Reference
Source: https://docs.standalonetech.com/terawallet-pro/settings
Every TeraWallet Pro setting in one place — withdrawal, wallet coupon and credit expiry options and where to find them.
TeraWallet Pro adds its settings into the existing **TeraWallet → Settings** screen. This page is a
quick reference; each setting is explained in depth on its feature page.
## Withdrawal
Found on the **Withdrawal** tab. See [Wallet Withdrawal](/terawallet-pro/withdrawal).
| Setting | Description |
| - | - |
| **Enable Withdrawal** | Master switch for the withdrawal module. |
| **Approval Mode** | Approve requests manually, or auto-approve and pay out immediately. |
| **Minimum Withdrawal** | Smallest amount a customer may request. |
| **Maximum Withdrawal** | Largest amount a customer may request. |
| **Enable logging** | Write per-gateway debug logs, surfaced on each withdrawal screen. |
| **Enable ** | Turn an individual payout gateway on, and enter its API credentials. |
| **Enable Processing Fee** | Charge a fee per gateway (deducted from the payout). |
| **Fee Type** | `percent`, `fixed`, or `percent + fixed`. |
| **Fee Amount** / **Fixed Component** | The fee value (and the flat part for `percent + fixed`). |
## Wallet Coupon
A **Wallet Coupon** toggle plus per-coupon options on the coupon editor. See
[Wallet Coupons](/terawallet-pro/wallet-coupons).
| Setting | Description |
| - | - |
| **Enable Wallet Coupon** | Allow coupons that credit the wallet instead of discounting the cart. |
| **Coupon value / currency** | The amount (and currency) credited on redemption. |
| **Email / domain restriction** | Limit redemption to addresses or domains (wildcards supported). |
| **Usage limits** | Global and per-user redemption caps. |
| **Expiry date** | Deadline after which the code can no longer be redeemed. |
## Credit Expiry
Found in the **Credit Expiry** options. See [Credit Expiry & FIFO](/terawallet-pro/wallet-expiry).
| Setting | Description |
| - | - |
| **Enable Credit Expiry** | Master switch for credit expiry and FIFO redemption. |
| **Credit Expire (default)** | Global duration after which new credit expires. |
| **Per-category durations** | Override the global default for specific transaction categories. |
## Importer
The [Bulk Importer](/terawallet-pro/importer) has no settings tab — it's an admin screen reached from
**Tools → Import → WooCommerce Wallet** or the **Import** action on the TeraWallet users screen.
## AffiliateWP
The [AffiliateWP Integration](/terawallet-pro/affiliatewp) has no settings of its own; it adds a **Wallet
Payout** method to AffiliateWP, which affiliates select in their own dashboard.
# Stripe Withdrawal Setup
Source: https://docs.standalonetech.com/terawallet-pro/stripe-withdrawal
Step-by-step guide to paying out TeraWallet Pro withdrawals through Stripe Connect transfers: enable Connect, set the OAuth redirect URI, add API keys, register the webhook, and test in test mode.
This guide connects **Stripe Connect** to the TeraWallet Pro [Wallet Withdrawal](/terawallet-pro/withdrawal)
module. Approved withdrawals are sent as Stripe **transfers** from your platform account to the
customer's own connected Stripe account.
Requires TeraWallet Pro with the Withdrawal module active and a Stripe account with **Connect**
enabled. Unlike PayPal, each customer must first **connect their own Stripe account** to your store.
If your customers won't have Stripe accounts, consider [PayPal](/terawallet-pro/paypal-withdrawal) or
bank transfer (BACS) instead.
## How it works
1. A customer connects their Stripe account once (OAuth), which stores their Stripe account ID.
2. They request a withdrawal; the wallet is debited the **requested** amount.
3. On approval (automatic, or by you), TeraWallet creates a Stripe transfer for `amount − fee` to the
customer's connected account.
4. If Stripe accepts the transfer, the request is marked **Approved** straight away.
5. If the transfer is later reversed in Stripe, the webhook cancels the request and restores the
customer's balance.
## Step 1 — Enable Stripe Connect
1. Sign in to the [Stripe Dashboard](https://dashboard.stripe.com) and switch to **Test mode** to begin.
2. Open **Settings → Connect** and complete the Connect onboarding for your platform.
3. Under **Connect settings → Onboarding options → OAuth**, turn on **OAuth for Standard accounts** (or the
equivalent OAuth option your dashboard shows).
4. Copy your **Client ID** (starts with `ca_`).
## Step 2 — Add the redirect URI
Stripe only returns customers to URLs you have allow-listed. In **Connect settings → OAuth → Redirects**, add
the URL of your customers' **Payment Settings** page:
```
https://your-site.com/my-account/my-wallet/withdraw_settings/
```
* `my-wallet` is the default wallet endpoint. If you changed it in WooCommerce settings, use yours.
* If your wallet is on a page using the `[woo-wallet]` shortcode instead of My Account, the URL is that
page with `?wallet_action=withdraw_settings`.
* Open the Payment Settings page as a customer and copy the address from the browser to be sure it matches.
If the redirect URI doesn't match exactly, Stripe shows an "invalid redirect\_uri" error when customers
try to connect.
## Step 3 — Get your API keys
In **Developers → API keys**, copy the **Publishable key** and **Secret key** for the same mode (test or
live) as the Client ID above. Test and live keys are separate.
## Step 4 — Configure TeraWallet
Go to **TeraWallet → Settings → Withdrawal**.
**General options:** turn on **Enable Withdrawal**, choose the **Approval Mode** (use *Manual* while
testing), set optional **Minimum / Maximum Withdrawal**, and turn on **Enable logging** during setup. See
[Wallet Withdrawal](/terawallet-pro/withdrawal) for details.
**Stripe gateway options**
| Setting | What to do |
| - | - |
| **Enable Stripe** | Turn on. |
| **Mode** | *Sandbox / Test* or *Live / Production*, matching the keys. |
| **Stripe client ID** | The `ca_…` ID from Step 1. |
| **Stripe publishable key** | From Step 3. |
| **Stripe secret key** | From Step 3. |
| **Stripe webhook secret** | Filled in during Step 5. |
| **Enable Processing Fee**, **Fee Type**, **Fee Amount**, **Fixed Component** | Optional. The fee is deducted from the transfer, not added to the debit: the wallet is debited the requested amount and the customer receives `amount − fee`. |
Save your changes.
## Step 5 — Register the webhook
1. In Stripe, go to **Developers → Webhooks → Add endpoint**.
2. Set the **Endpoint URL** to:
```
https://your-site.com/wp-json/terawallet/v1/stripe/webhook
```
The same URL is shown under the webhook secret field in TeraWallet.
3. Select the event **`transfer.reversed`**.
4. Save, then reveal the **Signing secret** (starts with `whsec_`) and paste it into **Stripe webhook
secret** in TeraWallet.
The only event acted on is `transfer.reversed`: the request is cancelled and the customer's balance is
restored. Because a successful transfer is approved immediately, no "success" event is needed. Other
events are acknowledged and ignored.
Each webhook's signature is verified, and requests older than five minutes or with a bad signature are
rejected. A replayed event is ignored, so a request is never cancelled twice. If the secret is empty,
the endpoint returns an error and reversals will not be picked up.
## Step 6 — Fund your platform balance
Transfers are paid out of your **Stripe platform balance** in the transfer's currency. Make sure the balance
can cover pending withdrawals. In test mode, Stripe's test card `4000 0000 0000 0077` adds available funds
to your balance.
## Step 7 — What customers need to do
Customers connect once under **My Account → Wallet → Withdrawal → Payment Settings** by clicking
**Connect with Stripe**, then signing in or creating a Stripe account and authorising it. They return to
the settings page and see "You are now connected with Stripe." The same screen has a **Disconnect stripe
account** button.
If a customer hasn't connected, the withdrawal form tells them to connect before they can submit.
## Step 8 — Test in test mode
1. Set **Mode** to *Sandbox / Test* and use test keys, test client ID and a test webhook.
2. As a test customer, click **Connect with Stripe** and finish the flow with a Stripe test account.
3. Add wallet balance, then submit a withdrawal.
4. Approve it in **wp-admin** (or use Automatic mode).
5. The request should show **Approved** with a note "Stripe transfer initiated: tr\_…". The transfer appears
in the Stripe Dashboard under **Connect → Transfers**.
6. To test reversals, reverse the transfer in the dashboard, or use the Stripe CLI:
```bash theme={null}
stripe listen --forward-to https://your-site.com/wp-json/terawallet/v1/stripe/webhook
stripe trigger transfer.reversed
```
A real reversal of an approved request should flip it to cancelled and restore the balance.
## Go live checklist
* [ ] Connect enabled and OAuth redirect URI added in **live** mode
* [ ] **Mode** switched to *Live / Production*
* [ ] Live **Client ID**, **Publishable key** and **Secret key** pasted
* [ ] A **new live webhook** created for `transfer.reversed`, and its signing secret pasted
* [ ] Platform balance funded
* [ ] **Enable logging** turned off
* [ ] One small real withdrawal tested end to end
## Duplicate-payment protection
Every transfer is sent with a fixed idempotency key based on the withdrawal ID. TeraWallet also stores the
Stripe transfer ID on the request and skips creating a second transfer if one exists, even after Stripe's
24-hour idempotency window. Re-approving a request therefore can't pay twice.
## Currencies
Amounts are converted to Stripe's smallest currency unit (for example, `10.50` becomes `1050`). Zero-decimal
currencies such as JPY and KRW are sent as whole numbers.
## Troubleshooting
Enable **Enable logging** and open the request to see its log. Failure reasons are also saved as notes.
| Symptom / message | Likely cause |
| - | - |
| "Click here to connect with Stripe" on the withdrawal form | The customer hasn't connected an account. |
| "Security check failed." after connecting | The connect link expired or was opened by a different logged-in user. Have the customer click **Connect with Stripe** again. |
| "Stripe connection failed." or an `invalid_grant` message | The OAuth code was used twice, or the secret key and client ID are from different modes. |
| Stripe says invalid `redirect_uri` | The URL isn't allow-listed in Connect → OAuth → Redirects (Step 2). |
| "Stripe secret key is not configured." | Secret key empty. |
| "Stripe transfer failed (HTTP … / code): …" | Stripe's own error: commonly insufficient platform balance, an unsupported currency for the destination account, or a disconnected account. |
| "Unable to approve request please check log file" | The transfer failed. See the note on the request. |
| Webhook returns 500 `missing_secret` | **Stripe webhook secret** is empty. |
| Webhook returns 400 `invalid_signature` | Wrong signing secret (test vs live, or another endpoint), or the server clock is more than five minutes off. |
Hosts that block unauthenticated REST requests (security plugins, WAFs) can stop Stripe reaching the
webhook. Allow `POST /wp-json/terawallet/v1/stripe/webhook`.
See [Pro Hooks & REST API](/terawallet-pro/hooks) for the full reference.
# Wallet Coupons
Source: https://docs.standalonetech.com/terawallet-pro/wallet-coupons
Create coupons that credit the TeraWallet balance instead of discounting the cart, with email/domain restrictions, usage limits and expiry.
Wallet Coupons are a dedicated coupon type that **adds balance to a customer's wallet** when
redeemed, rather than discounting their order. They're ideal for promotions, gift codes, and
goodwill credit.
## Creating a wallet coupon
1. Enable the module: in **TeraWallet → Settings**, turn on **Enable Wallet Coupon**.
2. Create a coupon as you normally would, and mark it as a **Wallet Coupon**.
3. Set the **value** that will be credited to the wallet on redemption, and the **currency**.
When a customer redeems the code, the coupon value is credited to their wallet balance instead of
reducing the cart total.
## Restrictions & limits
Each wallet coupon supports the controls you'd expect from WooCommerce coupons:
* **Email / domain restriction** — limit redemption to specific email addresses or whole domains
(wildcard supported, e.g. `*@company.com`).
* **Usage limits** — cap how many times a coupon can be used globally and per individual user.
* **Expiry date** — set a hard deadline after which the code can no longer be redeemed.
* **Per-coupon currency** — define the currency the value is credited in.
## Bulk generation
A built-in **bulk generator** creates many unique coupon codes at once (for gift-card campaigns or
mass distribution). It's backed by the coupon REST API under `terawallet/v1/coupons`, which also
supports full CRUD and code generation for programmatic workflows — see [Pro Hooks](/terawallet-pro/hooks).
Combine an email-domain restriction with a usage limit of 1-per-user to hand out one-time welcome
credit to everyone at a partner company.
# Credit Expiry & FIFO
Source: https://docs.standalonetech.com/terawallet-pro/wallet-expiry
Automatically expire TeraWallet store credit on a schedule, spend the soonest-to-expire credit first, and send reminder and lapse emails.
The Credit Expiry module gives store credit a lifecycle. Credits expire after a configurable
duration, the soonest-to-expire credit is always spent first (FIFO), and expired credit is removed
from both the spendable and the displayed balance.
## How it works
* **Expiry date per credit** — when credit is added, an expiry date is stamped on the ledger row
based on your rules.
* **FIFO redemption** — debits consume credits in **expiry-date order** (oldest/soonest-to-expire
first), so customers always use credit that is about to lapse before newer credit.
* **Currency-aware** — a debit in one currency only consumes credits in that same currency.
* **Balance filtering** — expired credit is excluded from the customer's viewable and spendable
balance (the module hooks the core `woo_wallet_current_balance` filter).
On activation, Pro adds `expire_date` and `amount_redeemed` columns to the core wallet ledger and
runs a one-time background backfill so FIFO is consistent with your existing transaction history.
## Configuration
Go to **TeraWallet → Settings** and open the **Credit Expiry** options:
* **Enable Credit Expiry** — master switch.
* **Credit Expire (default)** — the global duration after which new credit expires (e.g. 30 days).
* **Per-category durations** *(since Pro 1.0.4)* — override the global default for specific
transaction categories (for example, expire cashback faster than top-ups).
Per-transaction expiry can also be set when [importing balances](/terawallet-pro/importer) (the optional
`expire_date` CSV column) and on admin-side credits.
## Retention emails
Two automated emails keep customers informed:
* **Expiry reminder** — sent before credit is due to expire, nudging the customer to spend it.
* **Expiry notice** — sent when credit has lapsed.
A daily background task (Action Scheduler) processes expirations and reminder windows in paginated
batches, so it scales without loading every credit into memory.
Pair expiry with refunds: instead of refunding cash, issue store credit that expires in, say, 90
days to encourage a repeat purchase.
# Wallet Withdrawal
Source: https://docs.standalonetech.com/terawallet-pro/withdrawal
Let customers cash out their TeraWallet balance to PayPal, Stripe, Razorpay, Paystack, Cashfree or bank transfer, with admin approval and per-gateway fees.
The Withdrawal module turns store credit into real-world payouts. Customers request a withdrawal
from their account, and you approve or reject it — manually or automatically — paid out through one
of six gateways.
## Supported payout gateways
| Gateway | Notes |
| - | - |
| **PayPal** | Payouts API. Loads for any store currency. See the [PayPal setup guide](/terawallet-pro/paypal-withdrawal). |
| **Stripe** | Stripe Transfers. Loads for any currency. Supports asynchronous webhook updates. See the [Stripe setup guide](/terawallet-pro/stripe-withdrawal). |
| **BACS** (Bank Transfer) | Manual bank transfer; you mark requests paid after sending. Loads for any currency. See the [BACS setup guide](/terawallet-pro/bacs-withdrawal). |
| **Razorpay** (RazorpayX) | `INR` only. See the [Razorpay setup guide](/terawallet-pro/razorpay-withdrawal). |
| **Cashfree** | Payouts v2 API. `INR` only. See the [Cashfree setup guide](/terawallet-pro/cashfree-withdrawal). |
| **Paystack** | `NGN`, `GHS`, `ZAR`, `KES`, `USD`, `EUR`, `GBP`. See the [Paystack setup guide](/terawallet-pro/paystack-withdrawal). |
Currency-incompatible gateways are hidden automatically. Developers can register custom gateways via
the `woo_wallet_withdrawal_payment_gateways` filter — see [Pro Hooks](/terawallet-pro/hooks).
## Admin setup
Go to **TeraWallet → Settings → Withdrawal** and configure:
* **Enable Withdrawal** — master switch for the module.
* **Approval Mode** — approve requests manually, or auto-approve and pay out immediately.
* **Minimum / Maximum Withdrawal** — bounds for a single request.
* **Enable logging** — write per-gateway debug logs (surfaced on each withdrawal screen).
* **Per-gateway options** — enable each gateway, enter its API credentials, and set its processing
fee (see below).
### Processing fees (per gateway)
Each gateway has its own fee, configured with **Enable Processing Fee**, **Fee Type** and **Fee
Amount**:
* **Fee Type**: `percent`, `fixed`, or `percent + fixed` (a percentage plus a flat **Fixed
Component**).
* The fee is **deducted from the payout**, not added to the debit: the wallet is debited the
**requested** amount, and the gateway pays out `amount − fee`.
Fees are configured strictly per gateway. The old global "gateway charge" options were removed in
Pro 1.0.4 in favor of this per-gateway model.
## Customer experience
1. The customer opens **My Account → Wallet** and goes to the **Withdrawal** tab.
2. First time only: they save a **Payment Settings** profile (e.g. PayPal email, bank details)
for their chosen gateway.
3. They enter an amount (within your min/max and their available balance) and submit the request.
4. They receive a **request submitted** email, and **approval** or **rejection** emails as the
request progresses.
The wallet is debited the requested amount when the request is submitted. A request then moves through
**pending → approved (paid)** or **rejected**. On approval the payout is sent; on rejection the debit is
reversed and the balance is restored. Idempotency keys ensure re-approving a request can never pay twice.
## Managing requests
Withdrawal requests are stored as their own admin list. For each request you can:
* **Approve** or **Reject** it (rejection reverses the debit made at submission, restoring the customer's balance).
* Add **notes** — private (staff-only) or customer-visible, like WooCommerce order notes.
* Review **per-withdrawal gateway logs** when logging is enabled.
### Asynchronous payout webhooks
Stripe, PayPal, Razorpay, Cashfree and Paystack can report final payout status back via signed
webhooks under the `terawallet/v1` REST namespace (Stripe's endpoint is
`/wp-json/terawallet/v1/stripe/webhook`). Signatures are verified and replays are rejected. Set the
gateway's webhook secret in its settings to enable this.
Use **BACS** for manual bank transfers where you pay out by hand and simply mark the request
approved once the transfer is sent.
# Admin Settings Overview
Source: https://docs.standalonetech.com/terawallet/admin-guide/settings
A detailed guide to the TeraWallet configuration options in your WordPress admin.
The TeraWallet settings are divided into multiple tabs, each controlling specific aspects of the wallet behavior. Navigate to **TeraWallet** > **Settings** to access these options.
### General Settings
This tab controls the fundamental behavior of the wallet system.
* **Enable Partial Payment**: When active, customers can use their wallet balance for a portion of the total order.
* **Is auto deduct for partial payment**: Automatically applies the customer's wallet balance as a discount if partial payment is enabled.
* **Tax treatment** *(new in 1.6.4)*: Choose **Wallet pays goods only** (default) or **Wallet pays the whole order including tax**. See [Partial & Combined Payments](/terawallet/user-guide/partial-payments#tax-treatment).
* **Deduct wallet balance** *(new in 1.6.4)*: Deduct the wallet portion **at order placement** (default) or **when payment completes**.
* **Refund wallet on partial refunds** *(new in 1.6.4)*: Return a proportional share of the wallet payment when a partial WooCommerce refund is issued. On by default.
* **Enable Wallet Transfer**: Allow users to transfer funds to other registered customers using their email address.
* **Minimum/Maximum Transfer Amount**: Bound how much a customer can send in a single transfer.
* **Transfer Charge**: Optionally set a fixed or percentage-based charge for each fund transfer.
* **Enable Wallet Topup**: Allow customers to add funds manually via their account dashboard.
* **Minimum/Maximum Topup Amount**: Restrict the amount a customer can add to their wallet in a single transaction.
### Credit/Cashback Settings
Configure how rewards are credited to users' wallets.
* **Cashback Rule**: Choose the calculation scope:
* **Cart Wise**: Cashback based on the total cart value.
* **Product Wise**: Cashback based on specific product settings.
* **Product Category Wise**: Cashback based on the product category rules.
* **Cashback Type**: Select **Percentage** or **Fixed Amount**.
* **Cashback Amount**: The default value for the reward.
* **Max Cashback Amount**: Caps the total reward per order to a specific limit.
* **Min Cart Amount for Cashback**: The minimum total an order must reach to qualify for any cashback.
* **Max Cashback Scope** *(new in 1.6.1)*: Apply the cap **per order** (default on new installs) or **per item**.
* **Refund Clawback** *(new in 1.6.1)*: Proportionally reverse cashback when an order is refunded (off by default), with an optional **allow negative** setting.
* **Exclude Role from Cashback**: Select user roles (e.g., Administrator, Vendor) that should not receive rewards.
* **Process Cashback Status**: Define which WooCommerce order statuses trigger the reward (e.g., Completed, Processing).
See [Cashback Rules & Priority Logic](/terawallet/cashback/rules-logic) for the full calculation model.
### Transaction Descriptions
**New in 1.6.3.** A dedicated settings tab for customizing ledger entry text.
Set per-category description templates so ledger entries read the way you want. Templates support
tokens — `{order_id}`, `{amount}`, `{user_name}`, `{currency}` and `{original_details}` — and
replace the system-generated description on new transactions when configured.
### Gateway Settings
TeraWallet acts as a WooCommerce gateway. Here, you can control its visibility and fees.
* **Title/Description**: Customize what customers see at checkout.
* **Payment Method Visibility**: Hide the wallet gateway if the balance is zero or if specific products are in the cart.
* **Gateway Charges**: Apply extra fees when customers use certain gateways to top up their wallets.
### Actions Settings
Incentivize user engagement by rewarding specific site actions:
* **New User Registration**: Credit a specific amount to new users upon signing up. Since 1.6.2 this also covers users created via SSO/SAML, social login, the REST API and WP-CLI.
* **Daily Visit**: Reward users for logging in once per day.
* **Product Review**: Credit users for leaving verified reviews on your products.
* **Referrals**: Reward customers for referring visitors and sign-ups. Activity is recorded in a dedicated referrals ledger with a customer history view and an admin [Referral Report](/terawallet/admin-guide/transactions#referral-report).
* **Sell Content**: Let users sell digital content and receive the proceeds into their wallet.
When configuring rewards for actions like registrations or reviews, ensure you have set limits to prevent abuse (e.g., limit daily visit rewards to once per 24 hours).
# Transaction & Ledger Management
Source: https://docs.standalonetech.com/terawallet/admin-guide/transactions
How to manage user wallet balances and audit the transaction ledger.
TeraWallet provides a comprehensive transaction management system to view, audit, and manually adjust customer balances.
### Auditing the Ledger
Navigate to **TeraWallet** to view every balance modification recorded by the system. The ledger provides a detailed history, including:
* **User**: The customer associated with the transaction.
* **Type**: Indicates whether it was a **Credit** (funds added) or **Debit** (funds removed).
* **Amount**: The transaction value.
* **Balance**: The user's total balance *after* the transaction was recorded.
* **Details**: A system-generated or admin-provided description (e.g., "Cashback for Order #123" or "Manual credit by Admin").
* **Date**: The timestamp of the transaction.
### Manual Credit/Debit
As an administrator, you can manually adjust a user's wallet balance.
1. Go to **TeraWallet**.
2. Select the **Customer** by searching for their username or email.
3. Hover over the user and click **Edit Balance** to access edit transaction popup window.
4. Choose the **Transaction Type** (Credit or Debit).
5. Enter the **Amount**.
6. Provide a **Description** for the ledger entry.
7. Click **Save** to apply the changes and update the user's balance.
### User Balance Management
To view all customer balances in one place:
1. Navigate to **TeraWallet**.
2. This screen shows a list of all registered users and their current wallet balance.
3. You can quickly search for a specific user to check their available funds.
4. From this screen, you can click on any user to view user's transaction history.
### Locking User Accounts
In cases of suspected fraud or dispute, you can lock a user's wallet account:
1. Edit the user profile under **Users** > **All Users**.
2. Find the **Wallet Management** section.
3. Check the **Lock Wallet** box.
4. While locked, the user cannot:
* Use their wallet balance at checkout.
* Top up their wallet.
* Receive or send transfers.
Manual adjustments to the ledger should be done carefully, as they are recorded permanently in the audit trail. Always provide a clear description for future reference.
### Bulk Credit & Debit
From the **Wallet → Users** screen you can select multiple users and apply a bulk **Credit** or
**Debit**. A popup collects the amount and description, and bulk adjustments are tagged with the
`adjustment` category. Bulk operations are idempotent per user, so a retry after an interrupted run
will not double-credit anyone.
### Deleting Transaction Logs
The **Delete Logs** bulk action opens a modal where you choose:
* **Delete mode** — **Soft** (recoverable; rows are flagged `deleted`) or **Hard** (permanent removal).
* **Balance handling** — **Keep** (insert a single balancing entry so the user's balance is
unchanged) or **Wipe** (let the balance settle to `0`).
Negative balances are preserved symmetrically when **Keep** is chosen.
### Exporting Transactions
Transaction history can be exported to CSV for accounting and audits. The export includes the typed
**category** column (`topup`, `cashback`, `partial_payment`, `transfer`, `refund`, `adjustment`, etc.).
### Referral Report
**New in 1.6.2.** Available under **TeraWallet → Referral Report**.
When the Referrals earning action is enabled, the Referral Report lists every referral with the
referrer, type, status (pending / credited / rejected) and date, plus referrer/type/status and
date-range filters, a store-wide summary header, and a filtered CSV export.
# Cashback Rules & Priority Logic
Source: https://docs.standalonetech.com/terawallet/cashback/rules-logic
A deep dive into how rewards are calculated and triggered in TeraWallet.
The cashback reward program is one of the most powerful features of TeraWallet. It allows you to incentivize purchases and drive customer loyalty by offering digital balance rewards.
### Cashback Calculation Scope
TeraWallet supports three primary ways to calculate rewards:
#### 1. Cart-Wise Cashback (Global)
This rule applies to the total order value.
* **Trigger**: When an order is placed.
* **Configuration**: Set in **TeraWallet** > **Settings** > **Credit**.
* **Example**: If set to 10% and the cart total is \$1,000, the user receives \$100 cashback.
#### 2. Product-Wise Cashback (Specific)
This rule gives you granular control over individual products.
* **Configuration**: Defined on the **Product Edit** page in WooCommerce.
* **Example**: Reward \$50 for a "Premium T-shirt" but 5% for a "Luxury Watch."
* **Variable Support**: Different cashback amounts can be set for different product variations.
#### 3. Category-Wise Cashback (Taxonomy)
Apply rules to entire groups of products.
* **Configuration**: Defined in **Products** > **Categories**.
* **Conflict Handling**: If a product belongs to multiple categories with rules, you can choose whether the system should award the **Minimum** or **Maximum** available reward in the settings.
### Priority & Override Logic
When multiple rules are active, TeraWallet follows this priority:
**Product-Specific Rule > Category-Specific Rule > Global Cart Rule**.
* If a product has an individual cashback setting, that rule is used.
* If no product-level rule exists, the system checks the category rule.
* If neither exists, the global cart-wise rule is applied.
### Calculation Examples
**Example A: Percentage vs. Fixed**
* Global: 10%
* Max Cashback: \$100
* Order Total: \$2,000
* **Calculation**: 10% of \$2,000 is \$200, but since the **Max Cashback** is set to \$100, the user receives **\$100**.
**Example B: Category-Wise Override**
* Global: 5%
* "Electronics" Category: 10%
* Order Total: \$500 (Electronics items)
* **Calculation**: The user receives **\$50** (10%) instead of \$25 (5%) because the category rule has higher priority.
### When are rewards credited?
Cashback is not awarded immediately. It is triggered by order status changes.
* Go to **TeraWallet** > **Settings** > **Credit** and find **Process Cashback Status**.
* Most stores set this to **Completed** or **Processing**.
* **Flow**: Customer Pays -> Order Marked as Completed -> **Cashback Credited**.
### Cap Scope: Per Order vs Per Item
**New in 1.6.1.** Set **Max cashback scope** under **Settings → Credit**.
The **Max Cashback Amount** cap can be applied two ways:
* **Per order** *(default on new installs)* — the cap applies once to the whole cart.
* **Per item** — the cap applies to each qualifying line item.
Stores upgrading from older versions keep **per item** behavior to preserve their existing setup.
### Clawback on Refund
By default, cashback is reversed when an order is **cancelled**. You can additionally enable
**Refund clawback** under **Settings → Credit** so that cashback is clawed back **proportionally**
when an order is refunded:
* Off by default for upgrade safety — enable it explicitly.
* If the customer has already spent the credit, the default policy debits whatever balance remains
and logs the shortfall. An opt-in **allow negative** option can drive the wallet negative for an
exact reversal.
* Override the amount with the `woo_wallet_cashback_refund_clawback_amount` filter.
### Cashback Expiry
The free plugin does not enforce cashback expiry, but it exposes a seam
(`woo_wallet_cashback_expiry_timestamp`) that [TeraWallet Pro](/terawallet/getting-started/pro) and add-ons use
to expire cashback after a set period. When set, the expiry is stored on the transaction and exposed
in the REST API as `cashback_expires_at`.
### Coupons as Cashback
A unique feature where standard WooCommerce coupons can be "converted" into wallet rewards.
* Create a coupon in **Marketing** > **Coupons**.
* Check the **Is coupon cashback?** box in the TeraWallet tab.
* When the customer applies this coupon, the discount is **not deducted** from the order total. Instead, the discount value is recorded and credited to the user's wallet after checkout.
Cashback is automatically clawed back when an order is cancelled. To also reverse cashback on
**partial or full refunds**, enable **Refund clawback** in the settings (see above).
# Plugin Architecture & Internals
Source: https://docs.standalonetech.com/terawallet/developer-guide/architecture
A deep dive into how TeraWallet works under the hood for developers.
TeraWallet is built with a modular, object-oriented approach that prioritizes data integrity and extensibility.
### Core Architecture
* **Database-First Ledger**: Unlike many WordPress plugins that rely solely on user meta, TeraWallet uses a custom database table for all transaction records. This ensures that the wallet balance is always auditable and accurate.
* **MySQL Locking Mechanism**: To prevent race conditions during concurrent transactions (e.g., multiple simultaneous API calls or AJAX requests), TeraWallet employs **MySQL-level locking** (`GET_LOCK`) when performing credit or debit operations. Money-moving paths additionally serialize partial-payment debits and refunds with a **per-order lock** so concurrent gateway webhooks can't double-debit or double-refund.
* **Idempotent REST writes**: State-changing endpoints replay the cached response for a repeated `Idempotency-Key`, so retries never duplicate top-ups, transfers or bulk credits.
* **Singleton Lifecycle**: The main `Woo_Wallet` class (in `class-woo-wallet.php`) uses a singleton pattern to manage sub-modules like the Wallet, Cashback, API, and Settings.
### Folder Structure
* `/includes/`: The core PHP logic of the plugin.
* `class-woo-wallet-wallet.php`: Contains the `credit()`, `debit()`, and balance calculation logic.
* `class-woo-wallet-cashback.php`: Handles all reward calculations and rules.
* `class-woo-wallet-payment-method.php`: Implements the `WC_Payment_Gateway` for WooCommerce.
* `/actions/`: Modular classes for site-wide rewards (e.g., new registrations, daily visits).
* `/api/`: Controllers for the REST API integration.
* `/templates/`: Overridable UI components for the frontend dashboard and checkout.
* `/src/`: JavaScript (React/ES6) and SCSS source files for the admin and frontend interfaces.
* `/assets/`: Compiled CSS, JS, and image assets.
### Custom Database Tables
TeraWallet creates two primary tables during installation:
* `wp_woo_wallet_transactions`:
* `transaction_id`: Primary Key (BIGINT).
* `user_id`: The user associated with the transaction.
* `type`: Either `credit` or `debit`.
* `amount`: The transaction value.
* `balance`: The calculated balance *after* the transaction.
* `currency`: The currency code used.
* `details`: A detailed description of the entry.
* `wp_woo_wallet_transaction_meta`:
* Stores additional metadata for each transaction (e.g., associated order ID, cashback type).
* `wp_woo_wallet_referrals` *(since 1.6.2)*:
* One row per visitor or sign-up referral, with status, reward amount and the currency it was
credited in — giving referrals a full audit trail.
Since 1.6.0, the transactions table also carries per-row currency audit columns (`original_amount`,
`original_currency`, `original_rate`, `mode`), and since 1.6.3 a first-class indexed `category`
column.
### Multi-Currency
TeraWallet abstracts currency conversion behind a provider layer with first-class adapters for
**WOOCS/FOX, WPML/WCML, CURCY, Aelia and YayCurrency**, plus a generic fallback for any plugin that
filters `woocommerce_currency`. The ledger runs in one of two modes — `single_base` (one canonical
balance in the shop base currency) or `per_currency` (separate sub-balances), the latter gated by
the `woo_wallet_enable_per_currency_mode` filter. Inspect the active provider and mode at runtime via
`GET /terawallet/v1/system/multicurrency`.
### Core Transaction Flow
1. **Initiation**: A module calls `woo_wallet()->wallet->credit()` or `debit()`.
2. **Locking**: The system acquires a MySQL lock for the specific user.
3. **Calculation**: It fetches the most recent balance from the ledger.
4. **Validation**: For debits, it ensures the user has sufficient funds (unless negative transactions are allowed via filter).
5. **Recording**: A new entry is inserted into the `transactions` table.
6. **Syncing**: The `_current_woo_wallet_balance` user meta key is updated for fast read access.
7. **Hooks**: Actions like `woo_wallet_transaction_recorded` are fired.
8. **Release**: The MySQL lock is released.
The `_current_woo_wallet_balance` user meta is essentially a cache of the value in the ledger. Always use the `get_wallet_balance()` method to ensure accuracy.
# Hooks Reference (Actions & Filters)
Source: https://docs.standalonetech.com/terawallet/developer-guide/hooks
A comprehensive guide to extending TeraWallet using WordPress hooks.
TeraWallet is highly extensible, offering numerous actions and filters to customize its behavior.
### Essential Filters
#### `woo_wallet_current_balance`
Modify the current wallet balance before it is returned.
* **Parameters**: `(float) $balance`, `(int) $user_id`.
* **Example**: Add a temporary 5% bonus to all balance displays.
```php theme={null}
add_filter( 'woo_wallet_current_balance', function( $balance, $user_id ) {
return $balance * 1.05;
}, 10, 2 );
```
#### `woo_wallet_payment_is_available`
Programmatically toggle the wallet payment gateway visibility.
* **Parameters**: `(bool) $is_available`.
* **Example**: Disable wallet payment for a specific product category.
#### `woo_wallet_cashback_amount`
Adjust the calculated cashback amount before it's stored.
* **Parameters**: `(float) $cashback_amount`, `(int) $order_id`.
#### `woo_wallet_disallow_negative_transaction`
Allow or disallow negative transactions for specific scenarios.
* **Parameters**: `(bool) $disallow`, `(float) $amount`, `(float) $balance`.
* **Example**: Allow a "Credit Limit" for trusted users.
```php theme={null}
add_filter( 'woo_wallet_disallow_negative_transaction', function( $disallow, $amount, $balance ) {
if ( current_user_can( 'manage_options' ) ) {
return false; // Allow admins to go negative
}
return $disallow;
}, 10, 3 );
```
### Essential Actions
#### `woo_wallet_transaction_recorded`
Fires after any successful credit or debit to the ledger.
* **Parameters**: `(int) $transaction_id`, `(int) $user_id`, `(float) $amount`, `(string) $type`.
* **Example**: Send a custom SMS notification when balance is updated.
#### `woo_wallet_payment_processed`
Fires after a successful wallet purchase.
* **Parameters**: `(int) $order_id`, `(int) $transaction_id`.
#### `woo_wallet_admin_adjust_balance`
Fires when an administrator manually edits a user's balance.
* **Parameters**: `(int) $user_id`, `(float) $amount`, `(string) $payment_type`.
#### `woo_wallet_credit_purchase_completed`
Fires when a customer completes a "Wallet Topup" order.
* **Parameters**: `(int) $transaction_id`, `(object) $order`.
### Customizing Partial Payments
#### `woo_wallet_partial_payment_amount`
Modify the amount applied as a partial payment.
* **Parameters**: `(float) $amount`.
* **Example**: Always cap partial payments to 50% of the total order.
```php theme={null}
add_filter( 'woo_wallet_partial_payment_amount', function( $amount ) {
$cart_total = WC()->cart->get_total('edit');
return min( $amount, $cart_total / 2 );
} );
```
### Recently Added Hooks (1.6.1–1.6.4)
These hooks were introduced in recent releases. Each name below was verified against the plugin
source.
| Hook | Type | Since | Purpose |
| - | - | - | - |
| `woo_wallet_dashboard_stat_cards` | filter | 1.6.4 | Register custom summary cards on the customer dashboard (e.g. "Total withdrawn"). |
| `woo_wallet_partial_payment_max_amount` | filter | 1.6.4 | Cap the wallet amount that can be applied to an order at checkout. |
| `woo_wallet_partial_payment_refund_amount` | filter | 1.6.4 | Override the wallet amount refunded on a partial WooCommerce refund. |
| `woo_wallet_partial_payment_debit_failed` | action | 1.6.4 | Fires when a deferred partial-payment debit fails because the balance was spent before payment completed. |
| `woo_wallet_allowed_dashboard_actions` | filter | 1.6.4 | Allow-list of dashboard tabs the `wallet_action` parameter may dispatch. |
| `woo_wallet_cashback_refund_clawback_amount` | filter | 1.6.1 | Override the cashback amount clawed back on a refund. |
| `woo_wallet_cashback_expiry_timestamp` | filter | 1.6.1 | Mark a cashback row as expiring at a given timestamp (Pro/add-on seam). |
| `woo_wallet_transaction_types` | filter | 1.6.3 | Register custom transaction categories. |
| `woo_wallet_user_transactions_purged` | action | 1.6.1 | Fires after a Delete Logs purge completes. |
| `woo_wallet_enable_per_currency_mode` | filter | 1.6.0 | Enable the per-currency ledger mode. |
#### Example: add a dashboard summary card
```php theme={null}
add_filter( 'woo_wallet_dashboard_stat_cards', function( $cards, $user_id ) {
$cards['withdrawn'] = array(
'id' => 'withdrawn',
'priority' => 80,
'tone' => 'neutral',
'icon' => 'wallet',
'label' => __( 'Total withdrawn', 'your-textdomain' ),
'value' => your_get_total_withdrawn( $user_id ),
);
return $cards;
}, 10, 2 );
```
When using hooks that modify balance or payment eligibility, always test with a non-admin user to ensure correct front-end behavior.
# REST API Reference
Source: https://docs.standalonetech.com/terawallet/developer-guide/rest-api
Programmatic access to wallet balances, transactions, top-ups, transfers and admin tools via the terawallet/v1 REST API.
TeraWallet ships a first-class REST API under the **`terawallet/v1`** namespace. It powers the
plugin's own React dashboard and admin screens, and is fully available to your own apps and
integrations.
The older `wc/v3/wallet/*` routes still exist as a **deprecated** back-compatibility layer and
will be removed in a future major release. New integrations should target **`terawallet/v1`**.
## Base URL
```
https://your-store.com/wp-json/terawallet/v1/
```
## Authentication
Endpoints are grouped by who may call them, and each group uses the matching auth method:
| Group | Path prefix | Who | Authentication |
| - | - | - | - |
| Customer | `me/*` | The logged-in customer (acts on their own wallet) | WordPress cookie + REST nonce (same-origin), e.g. an `X-WP-Nonce` header |
| Admin | `admin/*` | Users with the `manage_woocommerce` capability | Cookie + nonce, or WooCommerce **Consumer Key / Secret** (Basic Auth) |
| Settings / System | `settings/*`, `system/*` | `manage_woocommerce` | Cookie + nonce, or Consumer Key / Secret |
| Public | `public/*`, `settings/public` | Anyone | None |
For external/server-to-server calls, generate keys under **WooCommerce → Settings → Advanced →
REST API** and send them as HTTP Basic Auth.
### Idempotency
State-changing customer endpoints (`POST me/topup`, `POST me/transfer`) and admin bulk
operations honor an **`Idempotency-Key`** request header. Send a unique key (e.g. a UUID) per
logical action; a retry with the same key replays the original response instead of creating a
duplicate top-up, transfer, or credit. Keys are scoped per user with a 24-hour TTL.
***
## Customer endpoints (`me/*`)
### Get balance
```
GET /terawallet/v1/me/balance
```
Returns the current user's balance. The response is multi-currency aware: `amount` is in the
active storefront currency, while `base_*` fields are always normalized to the shop base currency.
```json theme={null}
{
"amount": 250.00,
"currency": "USD",
"formatted": "$250.00",
"base_currency": "USD",
"base_amount": 250.00,
"base_formatted": "$250.00",
"mode": "single_base",
"balances": [
{ "currency": "USD", "amount": 250.00, "formatted": "$250.00" }
]
}
```
| Field | Description |
| - | - |
| `amount` / `currency` / `formatted` | Balance in the active storefront currency. |
| `base_amount` / `base_currency` | Total wallet value normalized to the shop base currency. |
| `mode` | `single_base` or `per_currency` (see [multi-currency](#system-endpoints)). |
| `balances[]` | Per-currency sub-balances; always at least one entry. |
### List transactions
```
GET /terawallet/v1/me/transactions
GET /terawallet/v1/me/transactions/{id}
```
Paginated ledger history for the current user.
| Query arg | Type | Notes |
| - | - | - |
| `page`, `per_page` | integer | Standard pagination. |
| `orderby` | string | `date`, `amount`, or `transaction_id`. |
| `order` | string | `asc` or `desc`. |
| `type` | string | Filter by `credit` or `debit`. |
| `category` | string | Filter by transaction category (see below). |
Each row exposes a typed **`category`**, one of: `topup`, `cashback`, `cashback_adjustment`,
`cashback_refund`, `partial_payment`, `transfer`, `refund`, `adjustment`, `other`.
### Create a top-up
```
POST /terawallet/v1/me/topup
```
Creates a top-up order and returns a payment URL to redirect the customer to.
| Body field | Type | Required | Notes |
| - | - | - | - |
| `amount` | number | Yes | Minimum `0.01`. |
| `payment_method` | string | No | A WooCommerce gateway id (e.g. `stripe`). |
| `currency` | string | No | ISO 4217 code; charges the top-up in that currency. |
```json theme={null}
{
"order_id": 1234,
"amount": 50.00,
"currency": "USD",
"payment_url": "https://your-store.com/checkout/order-pay/1234/?pay_for_order=true&key=wc_order_..."
}
```
Send an `Idempotency-Key` header so a double-submit (or a network retry) returns the original
order instead of creating a second top-up.
### Transfer funds
```
POST /terawallet/v1/me/transfer
GET /terawallet/v1/me/transfer/recipients
```
Send wallet balance to another registered user. Provide **either** `recipient_id` **or**
`recipient_email`.
| Body field | Type | Required | Notes |
| - | - | - | - |
| `recipient_id` | integer | One of id/email | Recipient user id. |
| `recipient_email` | string | One of id/email | Recipient account email. |
| `amount` | number | Yes | Subject to the configured min/max and transfer charge. |
| `note` | string | No | Optional message stored on both ledger legs. |
| `currency` | string | No | Optional ISO 4217 code. |
The `recipients` route returns a lookup list for an autocomplete picker (gated by a filter).
### Other customer reads
| Endpoint | Returns |
| - | - |
| `GET /terawallet/v1/me` | Profile snapshot with wallet summary and related links. |
| `GET /terawallet/v1/me/referrals` | The customer's referral share URL, visitor/signup counts and earnings. |
| `GET /terawallet/v1/me/cashback-rules` | The cashback rules currently active for this customer/cart. |
***
## Admin endpoints (`admin/*`)
Require the `manage_woocommerce` capability.
### Transactions
```
GET /terawallet/v1/admin/transactions
POST /terawallet/v1/admin/transactions
GET /terawallet/v1/admin/transactions/{id}
PATCH /terawallet/v1/admin/transactions/{id}
DELETE /terawallet/v1/admin/transactions/{id}?force=true
POST /terawallet/v1/admin/transactions/bulk
```
List supports `page`, `per_page`, `orderby` (`id`, `transaction_id`, `date`, `amount`,
`currency`, `type`, `user_id`), `order`, and `type` filters.
Create a manual credit or debit:
```json theme={null}
{
"user_id": 42,
"type": "credit",
"amount": 10.00,
"details": "Goodwill credit"
}
```
`DELETE` performs a soft delete by default; pass `?force=true` for a permanent delete. The
`bulk` route accepts an `action` of `credit`, `debit`, or `delete` and is idempotent per user.
### Users
```
GET /terawallet/v1/admin/users
GET /terawallet/v1/admin/users/{id}
POST /terawallet/v1/admin/users/{id}/lock
POST /terawallet/v1/admin/users/{id}/unlock
```
List users with their balances, read a single user, and lock/unlock a wallet to block further
spending (useful for fraud holds).
### Admin transfer
```
POST /terawallet/v1/admin/transfer
```
Move balance between two users on the customer's behalf.
***
## Settings & system endpoints
| Endpoint | Description |
| - | - |
| `GET /terawallet/v1/settings` | Fetch all plugin settings. |
| `POST /terawallet/v1/settings/section` | Save a settings section (`section_id` + fields). |
| `POST /terawallet/v1/settings/js-section` | Save a JS-registered settings tab (sanitized per server whitelist). |
| `GET /terawallet/v1/system/multicurrency` | Active currency provider, base/active currencies and ledger mode. |
| `GET /terawallet/v1/settings/public` | Unauthenticated public settings (e.g. cashback rules). |
All responses are JSON. Send `Content-Type: application/json` on requests with a body, and an
`Idempotency-Key` header on top-ups, transfers and bulk operations.
## Legacy namespace (deprecated)
The `wc/v3/wallet/*` routes from earlier versions remain as thin proxies for back-compatibility
and emit the same row shapes as their `terawallet/v1` equivalents. **Do not build new
integrations against them** — migrate to `terawallet/v1`.
# Troubleshooting & FAQ
Source: https://docs.standalonetech.com/terawallet/faq/troubleshooting
Common issues and solutions for TeraWallet.
### Common Issues
#### Wallet Payment Method is Not Visible at Checkout
If the "Wallet" payment method doesn't appear for customers:
1. **Low Balance**: The wallet method is hidden by default if the customer's balance is lower than the order total (unless partial payment is enabled).
2. **Settings**: Go to **WooCommerce** > **Settings** > **Payments** and ensure "TeraWallet" is enabled.
3. **Guest Checkout**: Wallet payments require a registered account. It will not show for guests unless they log in or create an account.
4. **Top-up Item**: The wallet gateway is disabled if the customer is purchasing a "Wallet Topup" product.
#### Cashback Not Applying to Orders
If cashback is not credited after a purchase:
1. **Order Status**: Check the "Process Cashback Status" in **TeraWallet** > **Settings** > **Credit**. The reward is only credited when the order reaches that specific status (e.g., Completed).
2. **User Role**: Ensure the customer's role is not in the "Exclude Role" list in settings.
3. **Product Rule**: If you're using product-wise rules, verify that the individual product has a cashback amount set.
4. **Rechargeable Order**: Cashback is never awarded for "Wallet Topup" purchases.
#### Partial Payment Option is Missing
1. **Enable Setting**: Ensure "Enable Partial Payment" is checked in **TeraWallet** > **Settings** > **General**.
2. **Zero Balance**: The option won't appear if the customer has a \$0 balance.
3. **Full Balance**: If the customer has enough balance to cover the *entire* order, they should use the "Wallet" gateway instead of partial payment.
#### Tax Stays on the Full Order with Partial Payment
By default the wallet pays for **goods only**, so tax is still charged on the order — this is correct
when wallet top-ups are not taxed when loaded. If your top-ups *are* taxed at load and you want the
wallet to cover tax too, set **Tax treatment** to **Wallet pays the whole order including tax** under
**Settings → General → Partial Payment**. See [Partial & Combined Payments](/terawallet/user-guide/partial-payments#tax-treatment).
#### Balance Shows Funds but Checkout Says "Insufficient"
On single-currency stores that previously ran in multi-currency mode, the displayed balance and the
spendable balance could diverge. TeraWallet 1.6.4 ships a **one-time upgrade** that normalizes any
leftover non-base ledger rows into the store base currency, so the two figures agree again. If you
just upgraded, reload the wallet page once to let the upgrade run.
### Frequently Asked Questions
#### Can I delete the "Wallet Topup" product?
**No**. This product is required for the top-up feature to work. Deleting it will break the ability for customers to add funds. If deleted by mistake, deactivate and reactivate the plugin to recreate it.
#### Does TeraWallet support multi-currency?
Yes, TeraWallet is compatible with popular multi-currency plugins like **WOOCS** and **WPML Multi-currency**. It records transactions in the site's default currency and handles conversions automatically during checkout.
#### Can I manually edit a user's balance?
Yes. Go to **TeraWallet** > **Transactions** and click **Add New** to manually credit or debit any user's account.
#### Is there a limit to how much a user can store?
By default, there is no limit to the maximum balance a user can hold. However, you can set limits on how much they can **top up** in a single transaction in the settings.
Still having issues? Visit our [Community Support Forum](https://standalonetech.com/forums/forum/terawallet/) or check the WordPress.org support threads.
# Initial Configuration
Source: https://docs.standalonetech.com/terawallet/getting-started/configuration
Setting up TeraWallet for the first time.
After activating the TeraWallet plugin, you need to configure it to suit your store's requirements.
### Accessing Settings
Navigate to **TeraWallet** > **Settings** in your WordPress dashboard to access all configuration options.
### General Setup
In the **General** tab, you can manage core features:
* **Enable Partial Payment**: When enabled, customers can use their wallet balance to pay for part of an order and use another payment method for the remainder.
* **Enable Wallet Transfer**: Allow customers to send wallet balance to other registered users.
* **Top-up Minimum/Maximum**: Set limits for how much a customer can add to their wallet at once.
### Required WooCommerce Settings
To ensure the wallet functions correctly as a payment method:
1. Go to **WooCommerce** > **Settings** > **Payments**.
2. Locate **TeraWallet** in the list of payment methods.
3. Toggle the switch to **Enable** it.
4. Click **Finish set up** to customize the title and description seen by customers at checkout.
### Wallet Recharge Product
TeraWallet automatically creates a hidden "Wallet Topup" product used for adding funds.
* **Do not delete** this product.
* The product is set as **Virtual** and **Private** so it doesn't appear in your shop catalog.
* You can find it under **Products** > **All Products** if you need to troubleshoot top-up issues.
If you delete the "Wallet Topup" product, customers will not be able to add funds to their wallet. The plugin will attempt to recreate it upon the next activation.
# Installation
Source: https://docs.standalonetech.com/terawallet/getting-started/installation
How to install and activate the TeraWallet plugin on your WordPress site.
TeraWallet (formerly WooWallet) is a digital wallet system for WooCommerce. It allows customers to store funds, earn rewards, and use their balance for checkouts.
### Requirements
Before installing TeraWallet, ensure your environment meets these minimums:
* **WordPress** 6.4 or higher
* **WooCommerce** 7.2 or higher (latest recommended)
* **PHP** 7.4 or higher
### Automatic Installation
The easiest way to install TeraWallet is through the WordPress admin dashboard:
1. Log in to your WordPress dashboard.
2. Navigate to **Plugins** > **Add New**.
3. In the search bar, type `TeraWallet`.
4. Find **TeraWallet** by StandaloneTech and click **Install Now**.
5. Once the installation is complete, click **Activate**.
### Manual Installation
If you prefer manual installation:
1. Download the plugin ZIP file from the [WordPress Plugin Repository](https://wordpress.org/plugins/woo-wallet/).
2. Log in to your WordPress dashboard.
3. Navigate to **Plugins** > **Add New** > **Upload Plugin**.
4. Choose the downloaded ZIP file and click **Install Now**.
5. After installation, click **Activate Plugin**.
### Verification
Once activated, you will see a new **TeraWallet** menu item in your WordPress admin sidebar.
If you don't see the TeraWallet menu, ensure that WooCommerce is installed and active.
# Key Features
Source: https://docs.standalonetech.com/terawallet/getting-started/key-features
An at-a-glance tour of everything TeraWallet can do — wallet top-ups, partial payments, cashback, transfers, earning actions and more.
TeraWallet turns WooCommerce into a full digital-wallet platform. Here's the complete picture,
with links to the deep-dive guide for each capability.
## Money in, money out
Customers add funds through any WooCommerce payment gateway. Set min/max amounts and optional
per-gateway charges.
Pay part of an order from the wallet and the rest with another gateway, with full control over
tax treatment, refund behavior and debit timing.
Customers send balance to other registered users, with configurable minimums and transfer fees.
Native WooCommerce refunds credit the wallet automatically — full cancellations and proportional
partial refunds alike.
## Rewards & engagement
Reward customers cart-wise, product-wise or category-wise, with per-order or per-item caps and
optional clawback on refund.
Credit the wallet for daily visits, new registrations, product reviews, referrals, and selling
content.
A dedicated referrals ledger with customer history and an admin Referral Report.
Convert standard WooCommerce coupons into wallet rewards instead of direct discounts.
## Operations & platform
An append-only, SQL-locked transaction ledger that stays accurate under heavy concurrency.
Adapters for WOOCS/FOX, WPML/WCML, CURCY, Aelia and YayCurrency, with per-row currency audit
columns.
The `terawallet/v1` API for balances, transactions, top-ups, transfers and admin tooling.
A rich set of actions and filters for deep customization and marketplace integrations.
Looking for withdrawals, wallet expiry, importers or AffiliateWP integration? Those live in
[TeraWallet Pro](/terawallet/getting-started/pro).
# TeraWallet Free vs Pro
Source: https://docs.standalonetech.com/terawallet/getting-started/pro
Compare the free TeraWallet plugin with TeraWallet Pro — withdrawals, wallet expiry, wallet coupons, the importer and AffiliateWP integration.
The free TeraWallet plugin is a complete wallet system on its own. **TeraWallet Pro** is an
optional add-on that unlocks advanced money-out and lifecycle features.
## Feature comparison
| Capability | Free | Pro |
| - | :-: | :-: |
| Wallet top-ups via WooCommerce gateways | ✅ | ✅ |
| Partial & combined payments | ✅ | ✅ |
| Cashback (cart / product / category) | ✅ | ✅ |
| Peer-to-peer transfers | ✅ | ✅ |
| Earning actions & referrals | ✅ | ✅ |
| Multi-currency support | ✅ | ✅ |
| REST API & developer hooks | ✅ | ✅ |
| **[Wallet Withdrawal](/terawallet-pro/withdrawal)** — customers cash out to bank/payment methods | — | ✅ |
| **[Credit Expiry & FIFO](/terawallet-pro/wallet-expiry)** — expire credit on a schedule, spend oldest first | — | ✅ |
| **[Wallet Coupons](/terawallet-pro/wallet-coupons)** — coupons redeemable directly into the wallet | — | ✅ |
| **[Bulk Importer](/terawallet-pro/importer)** — bulk-import balances & history from CSV | — | ✅ |
| **[AffiliateWP Integration](/terawallet-pro/affiliatewp)** — pay affiliate commissions to the wallet | — | ✅ |
## Activating Pro
When the TeraWallet Pro plugin is installed and activated, a **Go Pro / Extensions** page appears
in the TeraWallet admin menu. Enter and activate your license key there to receive updates and
unlock the Pro features. See [Installation & Licensing](/terawallet-pro/installation) for the full walkthrough.
Full documentation for every Pro feature.
See pricing and buy on StandaloneTech.
# TeraWallet (WooWallet) Documentation
Source: https://docs.standalonetech.com/terawallet/index
The official developer and user documentation for the leading WooCommerce wallet system.
TeraWallet is a powerful, digital wallet system for WooCommerce that allows customers to store funds, earn rewards through various site activities, and use their balance for fast, secure checkouts.
### Core Features
Secure transaction history with atomic credits and debits for every user.
Reward customers based on cart total, product categories, or specific products.
Allow customers to combine wallet funds with other payment gateways at checkout.
Extensible architecture with a rich set of actions and filters for deep integration.
### Navigation
To get started with TeraWallet, choose the guide most relevant to your role:
* **[Administrators](/terawallet/admin-guide/settings)**: Learn how to configure rules, manage user balances, and audit transactions.
* **[Customers](/terawallet/user-guide/wallet-dashboard)**: Understand how to top up, transfer, and pay with your wallet.
* **[Developers](/terawallet/developer-guide/architecture)**: Dive into the plugin internals, hooks reference, and REST API endpoints.
### Quick Links
# Release Notes
Source: https://docs.standalonetech.com/terawallet/releases/changelog
What's new in TeraWallet — a release-by-release summary of features, improvements, fixes and security hardening.
A user-friendly summary of recent TeraWallet releases. For the complete, verbatim developer
changelog, see `changelog.txt` in the plugin package.
**New**
* **Dashboard summary cards.** The customer wallet dashboard now shows a row of cards above the
transaction list — **Total top-ups**, **Total spent** (full wallet payments *and* partial
payments), **Cashback earned** (only when the cashback program is enabled) and **Available
balance**. Add-ons can register their own cards (e.g. "Total withdrawn") via the new
`woo_wallet_dashboard_stat_cards` filter.
* **Partial payment tax treatment.** A new setting lets you choose **Wallet pays goods only**
(default) or **Wallet pays the whole order including tax**, resolving long-standing reports of
tax staying on the full order. See [Partial & Combined Payments](/terawallet/user-guide/partial-payments).
* **Proportional partial refunds.** Partial wallet payments are now refunded proportionally when
you issue a *partial* WooCommerce refund (previously only full cancellations refunded the
wallet). Opt out per store, or override the amount with `woo_wallet_partial_payment_refund_amount`.
* **"Deduct wallet balance" timing.** Choose to deduct at order placement (default) or **when
payment completes**, so abandoned or failed orders never leave the wallet debited.
* **Better wallet emails.** Both wallet emails support WooCommerce's **Additional content** box,
are grouped under **Payments** in WooCommerce 10.3+, and now include action buttons ("View your
wallet" / "Recharge your wallet now").
**Improvements**
* Partial-payment refunds reverse the exact base-currency amount originally debited — no more
phantom FX gain/loss on multi-currency stores.
* The partial-payment debit is serialized by a per-order lock so concurrent gateway webhooks can't
double-debit.
* The transaction table's **Details** column now wraps instead of truncating, staying readable on
mobile.
**Fixes**
* Closed a silent over-cap where the displayed wallet amount and the actual debit could disagree.
* Fixed the plain-text transaction email showing the balance instead of the transacted amount.
* The low-balance email now fires once when the threshold is crossed, instead of on every debit.
* Corrected a typo in the low-balance email.
* Single-currency stores: a one-time upgrade normalizes leftover non-base ledger rows so the
spendable balance and the displayed balance always agree.
**Security**
* The My Account `wallet_action` parameter is now sanitized and allow-listed before dispatch
(filterable via `woo_wallet_allowed_dashboard_actions`).
* **Transaction category** is now a first-class, indexed column for cheap admin filters and
aggregations.
* New **Transaction descriptions** settings tab with per-category templates and tokens
(`{order_id}`, `{amount}`, `{user_name}`, `{currency}`, `{original_details}`).
* A filterable PHP registry of canonical categories so add-ons can register their own kinds.
* CSV export now includes the `category` column.
* Hardening: category templates are HTML-stripped (no stored XSS), and unknown category slugs
collapse to `other`.
* **Referrals** activity now lives in a dedicated `woo_wallet_referrals` table with a full audit
trail, a customer referral history view, and a new admin **Referral Report** (filters, summary,
CSV export).
* Signup and referral bonuses are now credited for users created via SSO/SAML, social login, the
REST API, WP-CLI and programmatic `wp_insert_user()`.
* Referral bonuses are credited in the store base currency; the "Minimum Order Amount" setting was
clarified to **Minimum Spend**.
* Concurrency and idempotency hardening across bulk admin credit/debit and signup capture.
* New **cashback cap scope** setting: apply the cap **per order** or **per item**.
* New **cashback clawback on refund** (off by default) with an allow-negative option and override
filters.
* A **cashback expiry seam** (`woo_wallet_cashback_expiry_timestamp`) for Pro/add-ons.
* REST transactions expose a typed `category` field and accept a `category=` filter.
* The **Delete Logs** admin action now opens a modal to choose delete mode (soft/hard) and balance
handling (keep/wipe).
* The React **Actions** tab was unified with the standard settings flow.
* A brand-new **React settings interface** with a typed field registry and REST-backed save/load.
* First-class **multi-currency** support with adapters for WOOCS/FOX, WPML/WCML, CURCY, Aelia and
YayCurrency, plus a generic fallback — with per-row currency audit columns for accurate
historical reporting.
# Partial & Combined Payments
Source: https://docs.standalonetech.com/terawallet/user-guide/partial-payments
How to use wallet balance along with other payment methods at checkout.
Partial payment is a powerful feature that allows customers to use their existing wallet balance to pay for part of an order, while paying the remainder with another gateway (e.g., Stripe, PayPal, or Bank Transfer).
### How It Works
When partial payment is enabled, TeraWallet calculates the available balance and applies it as a **negative fee** to the WooCommerce cart. This effectively reduces the "Total" that needs to be collected by other payment methods.
### Checkout Flow Example
Here is a step-by-step example of how a partial payment transaction works:
1. **User Balance**: The customer has **\$100** in their wallet.
2. **Cart Total**: The customer adds items worth **\$300** to their cart.
3. **Applying Balance**: On the checkout page, the user chooses to use their wallet balance.
4. **Calculated Totals**:
* Subtotal: \$300
* **Wallet Deduction (Via Wallet): -\$100**
* **New Total to Pay: \$200**
5. **Final Payment**: The customer pays the remaining **\$200** using their preferred gateway (e.g., Credit Card).
6. **Post-Payment**:
* WooCommerce marks the order as paid.
* TeraWallet debits \$100 from the customer's wallet ledger.
* The ledger entry will show: "For order payment #1234 (Partial)".
### Auto-Deduct Feature
Administrators can enable **Auto-Deduct** in the settings. When active:
* The maximum available wallet balance is **automatically applied** as a discount when the customer reaches the checkout page.
* The customer doesn't need to manually toggle the option.
### Tax Treatment
**New in 1.6.4.** Set this under **TeraWallet → Settings → General → Partial Payment**.
Because WooCommerce clamps negative fees to the *ex-tax* subtotal, a non-taxable wallet fee can't
pay the tax portion of an order. The **Tax treatment** setting lets you decide how the wallet fee
interacts with tax:
* **Wallet pays goods only** *(default)* — the wallet fee is clamped to the ex-tax subtotal and tax
is charged on the order. Correct when wallet top-ups are **not** taxed at load.
* **Wallet pays the whole order including tax** — the wallet fee is taxable, so the wallet can cover
the tax line too. Use this only when top-ups **are** taxed when the customer loads them.
### When the Wallet is Debited
**New in 1.6.4.** "Deduct wallet balance" timing, under **Settings → General → Partial Payment**.
* **At order placement** *(default)* — the wallet portion is debited immediately when the order is
created.
* **When payment completes** — the wallet is debited only once the order reaches a paid status, so
abandoned or failed orders never leave the wallet debited. If the balance was already spent
elsewhere before payment cleared, the order is placed **on-hold** and the
`woo_wallet_partial_payment_debit_failed` action fires instead of overdrafting the wallet.
### Refund Logic for Partial Payments
If an order paid partially is **cancelled**, the full wallet portion is credited back automatically.
Since 1.6.4, **partial** WooCommerce refunds are also handled: TeraWallet returns a **proportional**
share of the wallet payment to the customer's balance — capped so the cumulative refund can never
exceed the original wallet debit, and idempotent per refund.
* Refunds reverse the exact base-currency amount originally debited, so multi-currency stores see no
phantom FX gain or loss.
* You can opt out per store with **Refund wallet on partial refunds**, or override the amount with
the `woo_wallet_partial_payment_refund_amount` filter.
* The remaining amount (paid via the secondary gateway) must still be refunded separately by the
administrator within that gateway's interface.
### Important Notes
* **Insufficient Balance**: If the wallet balance is zero, the partial payment option will not appear.
* **Full Payment**: If the wallet balance is *greater than or equal to* the order total, the user can pay for the entire order using the **Wallet Gateway** directly, and no other payment method is required.
* **Top-up Conflict**: Partial payments **cannot be used** if the customer is currently attempting to buy a "Wallet Topup" product.
Partial payments are implemented as a non-taxable negative fee in WooCommerce, ensuring that tax calculations on the remaining items are not affected.
# Customer Wallet Dashboard
Source: https://docs.standalonetech.com/terawallet/user-guide/wallet-dashboard
How customers can manage their balance, view history, and perform transfers.
Customers can manage their wallet balance directly from their WooCommerce account page. TeraWallet seamlessly integrates a "My Wallet" tab into the customer dashboard.
### Dashboard Summary Cards
**New in 1.6.4.** A row of summary cards appears above the recent transactions list.
When a customer opens **My Account → My Wallet**, they first see four at-a-glance cards:
* **Total top-ups** — everything the customer has added to their wallet.
* **Total spent** — both full wallet payments and partial payments.
* **Cashback earned** — shown only when the cashback reward program is enabled.
* **Available balance** — current spendable funds.
These figures share the same helper used by the admin user report, so the customer dashboard and the
admin screen always agree. Add-ons can register their own cards (for example "Total withdrawn") via
the `woo_wallet_dashboard_stat_cards` filter.
### Viewing Balance & Transactions
Customers can navigate to **My Account** > **My Wallet** to:
* **Check Current Balance**: The total available funds are displayed prominently.
* **View Transaction History**: A detailed table showing every credit and debit, along with dates and descriptions. The **Details** column wraps onto multiple lines so long descriptions stay readable on mobile.
* **Filter History**: Customers can use date range filters to audit their transaction history.
### Adding Funds (Top-up)
If the administrator has enabled top-ups, customers can add funds manually:
1. Go to the **My Wallet** tab.
2. Navigate to the **Top-up** sub-tab.
3. Enter the amount you wish to add.
4. Click **Add Balance**.
5. You will be redirected to the WooCommerce checkout page.
6. Complete the payment using any available gateway (e.g., Credit Card, PayPal).
7. Once the payment is processed, the funds are instantly credited to your wallet.
### Sending Funds (Transfer)
Customers can send funds to other registered users if transfers are enabled:
1. Navigate to the **Transfer** sub-tab within **My Wallet**.
2. Enter the recipient's **email address** (the email must be associated with a registered account on the site).
3. Specify the **amount** you want to send.
4. Add an optional **note** for the recipient.
5. Click **Transfer Now**.
6. The amount is instantly debited from your wallet and credited to the recipient's ledger.
### Shortcodes
You can display wallet information anywhere on your site using these shortcodes:
* `[woo-wallet]`: Displays the full wallet dashboard (recommended for a dedicated "My Wallet" page).
* `[mini-wallet]`: Shows a simple widget with the user's current balance, ideal for headers or sidebars.
* `[tw-sell-content]`: Renders the Sell Content action UI (when the Sell Content earning action is enabled).
If you're using a page builder like Elementor or Gutenberg, you can insert the `[mini-wallet]` shortcode into your navigation menu for a personalized user experience.