> For the complete documentation index, see [llms.txt](https://docs-sdk.crypto-chief.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs-sdk.crypto-chief.com/processing/java/guides/accept-payments.md).

# Accept crypto payments

Accept incoming crypto payments in Java by creating PayIn orders (invoices).

A **PayIn** is an incoming-payment order (an invoice). Create one, show the customer the deposit address or payment link, and receive a webhook when it's paid.

There are two modes:

* **`crypto`** — fix the exact coin, network, and amount upfront.
* **`fiat`** — price the order in fiat and let the customer pick the asset at payment time.

## Crypto mode

```java
import com.cryptochief.processing.Asset;
import com.cryptochief.processing.Chain;
import com.cryptochief.processing.models.CreatePayInRequest;
import com.cryptochief.processing.models.PayInMode;

var invoice = client.payIns().create(new CreatePayInRequest(
    "invoice-1001", "u-7", PayInMode.CRYPTO,
    null, null, "https://your.app/webhooks/payin",
    null, null, null, null,
    null, null, null, null,
    "10.0", new Asset(Chain.TRON_MAINNET, "USDT")));

System.out.println("pay to: " + invoice.toAddress());
System.out.println("payment link: " + invoice.paymentLink());
```

## Fiat mode

Price in fiat; the customer chooses the coin/network when they pay.

```java
var invoice = client.payIns().create(new CreatePayInRequest(
    "invoice-1002", "u-7", PayInMode.FIAT,
    null, 3600, "https://your.app/webhooks/payin",
    null, null, null, null,
    "49.99", "USD", null, null,
    null, null));
// invoice.status() == "waiting_asset_select"
// invoice.coins() lists the offered options
```

When the customer picks an asset, commit it to get the address and final crypto amount:

```java
import com.cryptochief.processing.models.SelectAssetRequest;

var paid = client.payIns().selectAsset(
    new SelectAssetRequest(invoice.uuid(), "USDT", Chain.TRON_MAINNET));
System.out.println("pay to: " + paid.toAddress()
    + " " + paid.amountCrypto() + " " + paid.paymentCoin());
```

{% hint style="info" %}
Restrict which coins are offered in fiat mode with the `assets` allow/exclude policy. Use `accuracyPaymentPercent` to tolerate small under/over-payments and `lifetimeSec` to set an expiry.
{% endhint %}

`currency` takes any code `client.currencies().fiats()` lists — see [what the platform can put a price on](/processing/java/concepts/chains.md#what-the-platform-can-put-a-price-on).

## Mainnet or testnet

An order belongs to one environment: the real chains, or the test ones. Set `environment` to `mainnet` or `testnet` on create.

```java
import com.cryptochief.processing.models.Environment;

var inv = client.payIns().create(new CreatePayInRequest(
        "invoice-1003", "user-1", PayInMode.FIAT, null, null, null, null, null, null, null,
        "49.99", "USD", null, null, null, null)
        .withEnvironment(Environment.TESTNET));
```

It changes nothing when the request names a concrete network — that is your choice. It matters exactly where the **platform** picks the asset: fiat mode, and a network of `ANY`. Without it, an unconstrained pick could put a real payment on a test network.

Omit it and the project's own default applies. A project may be allowed one environment or both; asking for testnet on a project that does not permit it is refused with `TESTNET_NOT_ALLOWED` rather than quietly served on mainnet, and a value that is neither environment is `ENVIRONMENT_INVALID` rather than a silent fallback.

## Pin the order to a master wallet

`withMasterWallet` pins this order's transit deposit wallet to one of your project's master wallets — the address these funds are ultimately swept to. The order's chain family has to match the master wallet's; a foreign or mismatched address is refused with `400`.

```java
var inv = client.payIns().create(new CreatePayInRequest(
        "invoice-1004", "user-1", PayInMode.CRYPTO, null, null, null, null, null, null, null,
        null, null, null, null, "10.0", new Asset(Chain.TRON_MAINNET, "USDT"))
        .withMasterWallet(masterAddress));
```

`selectAsset` takes it too — the four-argument `SelectAssetRequest` — and a value there overrides one given at create:

```java
client.payIns().selectAsset(new SelectAssetRequest(
    inv.uuid(), "USDT", Chain.TRON_MAINNET, masterAddress));
```

{% hint style="info" %}
`withMasterWallet` and `withEnvironment` return a copy, so they chain. They exist because the record's two newest components are the seventeenth and eighteenth — reaching them positionally means restating sixteen nulls.
{% endhint %}

On a memo/tag family such as XRPL the "deposit wallet" is a shared tagged account rather than an address of this order's own, and pinning the master decides which account the family uses. That is also why such a wallet cannot later be re-pointed — [`shared_transit_cannot_be_rebound`](/processing/java/guides/wallets.md#re-point-a-wallet-at-another-master).

## Track the order

```java
import com.cryptochief.processing.poll.Polling;

var finalOrder = Polling.waitForPayIn(client, invoice.uuid());
if (finalOrder.succeeded()) { // status == "paid"
    // fulfill the order
}
```

You can also `cancel`, `resetAsset` (revert to asset selection), and page through `history`. Prefer reacting to the `invoice.*` [webhook](/processing/java/guides/webhooks.md) over polling.

## Order lifecycle

`waiting_asset_select` → `pending` → `processing` → **`paid`** (terminal). Terminal failures are `cancel` and `expired`. Check with `order.isTerminal()` / `order.succeeded()`.
