This guide shows how to invoke Fluxapay contract functions locally on Stellar testnet using the Stellar CLI.
- Install Stellar CLI: stellar-cli
- Set up environment variables: Copy
.env.exampleto.envand populate with your testnet values:cp .env.example .env
- Generate test keypairs (if needed):
stellar keys generate --name test-admin stellar keys generate --name test-merchant stellar keys generate --name test-customer
- Fund test accounts on testnet via the Stellar Friendbot
# Load from .env (supported by many shells)
export $(cat .env | grep -v '#' | xargs)
# Or load manually for your shell
source .env # bash/zsh
set -a; source .env; set +a # sh# Check testnet connectivity
stellar contract info interface \
--id $PAYMENT_PROCESSOR_ID \
--network testnetRegister a new merchant on the Merchant Registry contract. The merchant must authenticate and provide KYC details.
pub fn register_merchant(
env: Env,
merchant_id: Address, // Merchant's Stellar address
business_name: String, // Legal business name
settlement_currency: String, // e.g. "USD", "EUR", "NGN"
payout_address: Option<Address>,// Optional payout wallet address
bank_account: Option<String>, // Optional bank account reference
) -> Result<(), MerchantError>stellar contract invoke \
--id $MERCHANT_REGISTRY_ID \
--network testnet \
--source $TEST_MERCHANT_ADDRESS \
-- register_merchant \
--merchant_id $TEST_MERCHANT_ADDRESS \
--business_name "TechCorp Nigeria Limited" \
--settlement_currency "NGN" \
--payout_address $ADMIN_ADDRESS \
--bank_account "0123456789"Success:
{
"status": "success"
}| Error | Cause | Solution |
|---|---|---|
MerchantAlreadyExists |
Merchant already registered | Use a different address or verify registration |
Unauthorized |
Request not signed by merchant | Ensure --source matches --merchant_id |
After registration, verify the merchant was created:
stellar contract invoke \
--id $MERCHANT_REGISTRY_ID \
--network testnet \
-- get_merchant \
--merchant_id $TEST_MERCHANT_ADDRESSCreate a payment charge that a customer must fulfill by sending USDC to the deposit address.
pub fn create_payment(
env: Env,
payment_id: String, // Unique payment identifier
merchant_id: Address, // Merchant creating the charge
amount: i128, // Amount in stroops (1 USDC = 10^7 stroops)
currency: Symbol, // e.g. "USDC"
deposit_address: Address, // Where customer sends funds
expires_at: u64, // Unix timestamp when payment expires
memo: Option<String>, // Optional memo/invoice reference
memo_type: Option<String>, // Optional memo type (e.g. "invoice_id", "order_id")
) -> Result<PaymentCharge, Error>- Merchant must be registered (see Register Merchant)
- Merchant must be verified by admin (contact operations team for testnet)
- Deposit address must be a valid Stellar address
- Expiration timestamp must be in the future
# Calculate expiration (current time + 1 hour, adjust as needed)
EXPIRES_AT=$(($(date +%s) + 3600))
stellar contract invoke \
--id $PAYMENT_PROCESSOR_ID \
--network testnet \
--source $TEST_MERCHANT_ADDRESS \
-- create_payment \
--payment_id "inv_20260329_001" \
--merchant_id $TEST_MERCHANT_ADDRESS \
--amount 1000000000 \
--currency USDC \
--deposit_address $ADMIN_ADDRESS \
--expires_at $EXPIRES_AT \
--memo "Order #12345" \
--memo_type "order_id"Success returns a PaymentCharge object:
{
"payment_id": "inv_20260329_001",
"merchant_id": "GXXXXXX...",
"amount": 1000000000,
"currency": "USDC",
"status": "Pending",
"created_at": 1711776000,
"expires_at": 1711779600,
"memo": "Order #12345",
"memo_type": "order_id"
}| Error | Cause | Solution |
|---|---|---|
Unauthorized |
Merchant not verified or role not granted | Contact admin to verify merchant |
InvalidAmount |
Amount ≤ 0 | Specify positive amount in stroops |
PaymentAlreadyExists |
Payment ID already used | Use a unique payment ID |
ContractPaused |
Contract is paused | Contact admin to unpause |
- Amount: Stellar uses stroops (1 USDC = 10^7 stroops)
- 1 USDC →
10000000stroops (7 decimal places) - 100 USDC →
1000000000stroops
- 1 USDC →
Retrieve the current status of a payment charge.
pub fn get_payment(
env: Env,
payment_id: String, // Payment identifier
) -> Result<PaymentCharge, Error>stellar contract invoke \
--id $PAYMENT_PROCESSOR_ID \
--network testnet \
-- get_payment \
--payment_id "inv_20260329_001"Returns the full PaymentCharge object with current status:
{
"payment_id": "inv_20260329_001",
"merchant_id": "GXXXXXX...",
"amount": 1000000000,
"currency": "USDC",
"status": "Confirmed",
"amount_received": 1000000000,
"created_at": 1711776000,
"expires_at": 1711779600,
"memo": "Order #12345",
"memo_type": "order_id"
}| Status | Meaning | Next Step |
|---|---|---|
Pending |
Awaiting payment | Customer sends USDC to deposit address |
Confirmed |
Payment received in full | Merchant fulfills order |
PartiallyPaid |
Underpayment received | Request additional funds or refund |
Overpaid |
Overpayment received | Refund excess or reconcile |
Expired |
Payment deadline passed | Issue new payment link |
Failed |
Payment verification failed | Troubleshoot or create new charge |
| Error | Cause | Solution |
|---|---|---|
PaymentNotFound |
Payment ID doesn't exist | Verify payment ID matches created payment |
List all payments for a specific merchant:
stellar contract invoke \
--id $PAYMENT_PROCESSOR_ID \
--network testnet \
-- get_merchant_payments \
--merchant_id $TEST_MERCHANT_ADDRESSFetch merchant payments with pagination:
stellar contract invoke \
--id $PAYMENT_PROCESSOR_ID \
--network testnet \
-- get_merchant_payments_paginated \
--merchant_id $TEST_MERCHANT_ADDRESS \
--offset 0 \
--limit 10Monitor payment verification events in real-time:
# View recent ledger entries for payment events
stellar contract invoke \
--id $PAYMENT_PROCESSOR_ID \
--network testnet \
-- --monitor-events# Error: Contract not found
# Solution: Verify contract ID is deployed and correct
stellar contract info interface \
--id $PAYMENT_PROCESSOR_ID \
--network testnet# Error: Invalid network passphrase
# Solution: Ensure you're using testnet and correct settings
export STELLAR_NETWORK=testnet# Error: Account requires minimum balance
# Solution: Fund account via Friendbot
# https://friendbot.stellar.org/?addr=<YOUR_ADDRESS># Error: Signature verification failed
# Solution: Ensure --source matches the signer for the operation
# Most operations require authentication from the affected party- Use consistent merchants: Register one test merchant and reuse its ID for multiple payments
- Generate future timestamps: Use
date +%sand add seconds for realistic expiration times - Batch operations: Chain multiple invocations in a shell script for integration testing
- Save outputs: Redirect results to JSON files for audit trails:
stellar contract invoke ... >> payment_log.json - Validate before submitting: Always check payment amounts and expiration dates before creating charges
#!/bin/bash
source .env
# Setup
EXPIRES_AT=$(($(date +%s) + 3600))
PAYMENT_ID="test_$(date +%s)"
# 1. Register merchant (one-time)
echo "Registering merchant..."
stellar contract invoke \
--id $MERCHANT_REGISTRY_ID \
--network testnet \
--source $TEST_MERCHANT_ADDRESS \
-- register_merchant \
--merchant_id $TEST_MERCHANT_ADDRESS \
--business_name "Test Shop" \
--settlement_currency "USD"
# 2. Create payment
echo "Creating payment..."
stellar contract invoke \
--id $PAYMENT_PROCESSOR_ID \
--network testnet \
--source $TEST_MERCHANT_ADDRESS \
-- create_payment \
--payment_id $PAYMENT_ID \
--merchant_id $TEST_MERCHANT_ADDRESS \
--amount 1000000000 \
--currency USDC \
--deposit_address $ADMIN_ADDRESS \
--expires_at $EXPIRES_AT
# 3. Verify payment created
echo "Verifying payment status..."
stellar contract invoke \
--id $PAYMENT_PROCESSOR_ID \
--network testnet \
-- get_payment \
--payment_id $PAYMENT_ID