26.1. Testing in the TOPS Staging Environment#
This document contains a detailled, step-by-step instructions for testing with the staging environment for the Taler Operations deployment.
The staging environment (on host rusty) is almost equivalent to the production
environment. It is, however, not connected to a real bank account.
26.1.1. Prerequisites#
An administrator needs to enable your SSH key for testing in the staging environment.
26.1.2. Withdrawals: Basic Withdrawal#
Scan the following QR code to start a withdrawal from the stage exchange:
taler://withdraw-exchange/exchange.stage.taler-ops.ch/Confirm the withdrawal in the wallet.
Run the following command to fake a wire transfer, using a randomly generated creditor IBAN. The
$AMOUNTand$SUBJECTshould be taken from the wire transfer instructions in the wallet UI.ssh -T devtesting@rusty.taler-ops.ch "fake-incoming --amount $AMOUNT --subject '$SUBJECT'"
Check that the withdrawal succeeded in the wallet.
26.1.3. Deposits: Basic Deposit#
Do a basic withdrawal.
Initiate a deposit in the wallet UI, using the receiver account known to the wallet from the withdrawal.
The deposit transaction should now ask for KYC information. Fill out the corresponding form(s).
The deposit transaction should finish.
26.1.4. Deposits: Deposit with KYC Auth#
Do a basic withdrawal.
Generate an IBAN via:
ssh -T devtesting@rusty.taler-ops.ch geniban
Initiate a deposit in the wallet UI to the randomly generated IBAN.
The deposit transaction should now ask for a KYC auth transfer. Satisfy the auth transfer by running:
ssh -T devtesting@rusty.taler-ops.ch "fake-incoming --amount $AMOUNT --subject '$SUBJECT' --debit-payto '$DEBIT_PAYTO'"
with the information shown in the wallet UI, where the
$DEBIT_PAYTOmust contain the IBAN generated in step (2).The deposit transaction should now ask for KYC information. Fill out the corresponding form(s).
The deposit transaction should finish.
26.1.5. Merchant: End-to-end onboarding (staging)#
Stage-specific glue for the merchant path already described elsewhere:
Merchant Backend Operator Manual (SPA and HTTP API) and
Merchant: Onboarding in Taler Operations Deployment (bank account → KYC auth → accept
exchange terms of service → accept payments). Authentication is
documented under Authentication. Wire faking
reuses geniban / fake-incoming from Deposits: Deposit with KYC
Auth above.
Two variants: SPA (mostly manual) below, then API (curl / scripted self-provision, login tokens, and orders).
This page is written for TOPS stage ($BASE below). Deployments
like regional currencies — overview at
https://regio.taler.net/, setup via
taler-deployment.git regional-currency/ (see the automated
setup and custom
setup manuals) — can differ.
Look at the merchant /config: if mandatory_tan_channels is
empty, MFA for self-provisioning is effectively off and
POST /instances often returns 204 (instance exists immediately,
no /challenge/… round-trip) — typical for many regio setups.
Creating orders still needs at least one active bank account (otherwise
the backend rejects with a missing-account error). Wire faking via
rusty / taler-devtesting is TOPS-stage specific (not the usual
regional-bank funding path).
Variables used below (set your own values):
BASE=https://stage.my.taler-ops.ch
INSTANCE=my-shop # instance id (slug)
INSTANCE_PASSWORD=… # password chosen at signup
EMAIL=you@example.com # inbox that can receive stage TAN mail
PHONE=+41 7x xxx xx xx # real CH mobile; must match phone_regex
# from $BASE/config *and* be accepted by
# the SMS helper (dummy numbers fail with
# TALER_EC 2132 on /challenge/$ID)
IBAN=… # from geniban
DEBIT_PAYTO=payto://iban/$IBAN
TOKEN=… # access_token from /private/token
ORDER_ID=… # from PostOrderResponse
$BASE/ redirects to $BASE/webui/. Use the
stage exchange for payments.
Check have_self_provisioning and mandatory_tan_channels on
$BASE/config.
26.1.5.2. SPA (login with password)#
Normal interactive path (Instance setup, Self-provisioning, Manually creating an order using the SPA).
Open
$BASE/webui/. Sign up or log in with$INSTANCEand$INSTANCE_PASSWORD. Confirm e-mail and SMS TAN when asked (both channels are mandatory on this backend).Complete Shared bank / KYC steps in the portal (Bank account, KYC links).
Orders → create (summary + amount). Keep the payment QR / pay link from the order status page.
Pay from the wallet (shared step 5) and confirm paid status in the SPA.
26.1.5.3. API (self-provision → password → login token → Bearer)#
Same backend via HTTP
(POST /instances, Authentication,
POST [/instances/$INSTANCE]/private/token,
POST [/instances/$INSTANCE]/private/orders).
Private endpoints need
Authorization: Bearer secret-token:… (RFC 8959).
On this stage backend, expect the MFA path below (mandatory_tan_channels
is email and sms). Where that list is empty, skip to step 3 after a
204 create.
Self-provision (
POST /instances). Example body (InstanceConfigurationRequest;auth.method=token):curl -sS -H 'Content-Type: application/json' \ -d "{ \"id\": \"$INSTANCE\", \"name\": \"Example Shop\", \"email\": \"$EMAIL\", \"phone_number\": \"$PHONE\", \"auth\": {\"method\": \"token\", \"password\": \"$INSTANCE_PASSWORD\"}, \"address\": {\"country\": \"CH\"}, \"jurisdiction\": {\"country\": \"CH\"}, \"use_stefan\": true }" \ "$BASE/instances"Typical response before MFA: HTTP 202 ChallengeResponse with
combi_and: trueand one challenge per TAN channel, e.g.:{ "combi_and": true, "challenges": [ {"tan_channel": "email", "tan_info": "…", "challenge_id": "$CHALLENGE_EMAIL"}, {"tan_channel": "sms", "tan_info": "…", "challenge_id": "$CHALLENGE_SMS"} ] }Until both TANs are solved,
$INSTANCEdoes not exist (/instances/$INSTANCE/private/…→ 404).Request and confirm each TAN on the unprefixed challenge URLs (instance path segment optional; before create, only this form works — see Solving challenges in the merchant API):
curl -sS -H 'Content-Type: application/json' -d '{}' \ "$BASE/challenge/$CHALLENGE_ID" curl -sS -H 'Content-Type: application/json' \ -d "{\"tan\":\"$TAN\"}" \ "$BASE/challenge/$CHALLENGE_ID/confirm"Repeat for every
challenge_id. A successful request returns 200; a rejected SMS/e-mail address returns 400 with code 2132 (fix$PHONE/$EMAIL). Wrong$TANon confirm returns 409.Retry the same
POST $BASE/instancesbody with:-H "Taler-Challenge-Ids: $CHALLENGE_EMAIL,$CHALLENGE_SMS"
Expect 200 / 204 when the instance is created. With unsolved challenges the retry stays at 202.
Password → login token (Basic: user
$INSTANCE, password$INSTANCE_PASSWORD; LoginTokenRequest):curl -sS -u "$INSTANCE:$INSTANCE_PASSWORD" \ -H 'Content-Type: application/json' \ -d '{"scope":"order-simple"}' \ "$BASE/instances/$INSTANCE/private/token"From LoginTokenSuccessResponse, set
TOKENtoaccess_token(already includes thesecret-token:prefix). Scopes such asspaorallwork the same way if you need broader rights.Create an order with the Bearer token:
curl -sS \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{"order":{"summary":"stage test","amount":"CHF:1"}}' \ "$BASE/instances/$INSTANCE/private/orders"Read
order_idfrom PostOrderResponse. Fetchtaler_pay_uriviaGET [/instances/$INSTANCE]/private/orders/$ORDER_ID(or the public order status URL). Finish Shared bank / KYC steps if needed, then pay from the wallet.
Note
Prefer login tokens from /private/token. Long-lived
Authorization: Bearer secret-token:$INSTANCE_PASSWORD is the
deprecated token method and will be phased out.