View Issue Details

IDProjectCategoryView StatusLast Update
0012094Talerwallet (Android App)public2026-11-11 01:50
Reporterbot-cg [agent] Assigned ToResolution deadline
ImplementerReviewer 
Release signed byDeployed by 
VerifierCommunicatorCM_7  
Data protection authority notification requiredNo  
CSIRT notification requiredNo  
Estimated effort (hours)Actual effort (hours)0 
Fast-trackNo
Work packagenone
PrioritynormalSeverityminorReproducibilityhave not tried
Status newResolutionopen 
Summary0012094: Android: the payment screen does not show that an order is age-restricted (minimum_age not even decoded); the WebExtension shows "18+" (patch attached)
DescriptionFor an age-restricted order (contract minimum_age), the WebExtension shows a "18+" badge next to the merchant on the payment screen (and "18+ This purchase is age restricted." on the pay-template form). Android and iOS show nothing; it is the only place where the user learns that the purchase is age-restricted before paying.

What the user sees (order with "minimum_age": 18, products wine and corkscrew; origin/master builds of 2026-11-11):
- WebExtension: "18+" pill at the right of the merchant row (before-web-1.png).
- Android: merchant, products, total -- no age information (before-android-1.png).
- iOS: merchant, products, amounts -- no age information (before-ios-1.png).

Reference: web screens/PaymentScreen.tsx:577-581, routes/payment-model.ts:272, screens/PaymentTemplateScreen.tsx:136-141.

Android (origin/master 4c483527): taler-kotlin-android/src/main/java/net/taler/common/ContractTerms.kt:39-160 does not decode minimum_age at all (the pay-template DTO does, PayTemplateDetails.kt:66-67,82-83); PromptPaymentComposable.kt:250-284 (MerchantSection) shows logo and name only.

Patch (android-minimum-age.patch): ContractTerms (V0 and V1) decodes minimum_age; MerchantSection shows "Age-restricted purchase: 18+" under the merchant name. One new English string. Not in the patch: the same hint on the pay-template form.
Verified: :wallet:assembleFdroidSim builds; after-android-1.png is the same order with the patch.

Related: iOS counterpart.

Assisted by LLM
Steps To Reproduce1. Create an order with "minimum_age": 18.
2. Open its taler://pay/ link: the WebExtension shows "18+", Android and iOS do not.
(Automated: wc-stack pay-uri --order-json lib/stack-examples/products-and-age.json.)
TagsNo tags attached.
Attached Files
before-web-1.png (106,404 bytes)   
before-web-1.png (106,404 bytes)   
before-android-1.png (82,461 bytes)   
before-android-1.png (82,461 bytes)   
before-ios-1.png (228,648 bytes)   
before-ios-1.png (228,648 bytes)   
after-android-1.png (90,563 bytes)   
after-android-1.png (90,563 bytes)   
android-minimum-age.patch (2,976 bytes)   
diff --git a/taler-kotlin-android/src/main/java/net/taler/common/ContractTerms.kt b/taler-kotlin-android/src/main/java/net/taler/common/ContractTerms.kt
index 1f59d332..41870125 100644
--- a/taler-kotlin-android/src/main/java/net/taler/common/ContractTerms.kt
+++ b/taler-kotlin-android/src/main/java/net/taler/common/ContractTerms.kt
@@ -53,6 +53,7 @@ sealed class ContractTerms {
     abstract val exchanges: List<Exchange>
     abstract val deliveryLocation: Location?
     abstract val deliveryDate: Timestamp?
+    abstract val minimumAge: Int?
 
     @Serializable
     @JsonClassDiscriminator("version")
@@ -98,6 +99,9 @@ sealed class ContractTerms {
         @SerialName("delivery_date")
         override val deliveryDate: Timestamp? = null,
 
+        @SerialName("minimum_age")
+        override val minimumAge: Int? = null,
+
         val amount: Amount,
 
         @SerialName("max_fee")
@@ -150,6 +154,9 @@ sealed class ContractTerms {
         @SerialName("delivery_date")
         override val deliveryDate: Timestamp? = null,
 
+        @SerialName("minimum_age")
+        override val minimumAge: Int? = null,
+
         val choices: List<ContractChoice>,
 
         @SerialName("token_families")
diff --git a/wallet/src/main/java/net/taler/wallet/payment/PromptPaymentComposable.kt b/wallet/src/main/java/net/taler/wallet/payment/PromptPaymentComposable.kt
index 3663d1d3..e5f1ca9f 100644
--- a/wallet/src/main/java/net/taler/wallet/payment/PromptPaymentComposable.kt
+++ b/wallet/src/main/java/net/taler/wallet/payment/PromptPaymentComposable.kt
@@ -270,6 +270,16 @@ fun MerchantSection(
             style = MaterialTheme.typography.titleLarge,
         )
 
+        // AGE RESTRICTION
+        contractTerms.minimumAge?.takeIf { it > 0 }?.let { age ->
+            Text(
+                stringResource(R.string.payment_minimum_age, age),
+                modifier = Modifier.padding(top = 8.dp),
+                style = MaterialTheme.typography.labelLarge,
+                color = MaterialTheme.colorScheme.error,
+            )
+        }
+
         // MERCHANT INFO BUTTON
         // TextButton(onClick = {}) {
         //     Icon(
diff --git a/wallet/src/main/res/values/strings.xml b/wallet/src/main/res/values/strings.xml
index 89750709..40f44f78 100644
--- a/wallet/src/main/res/values/strings.xml
+++ b/wallet/src/main/res/values/strings.xml
@@ -319,6 +319,7 @@ GNU Taler is immune to many types of fraud such as credit card data theft, phish
     <string name="payment_tokens_insufficient">Insufficient tokens</string>
     <string name="payment_tokens_unexpected">Unexpected merchant %1$s, your token could be stolen.</string>
     <string name="payment_tokens_untrusted">Merchant %1$s is untrusted, cannot spend this token.</string>
+    <string name="payment_minimum_age">Age-restricted purchase: %1$d+</string>
     <string name="payment_template_error">Error creating order</string>
     <string name="payment_title">Payment</string>
 
android-minimum-age.patch (2,976 bytes)   

Required notifications

Address or linkRemarkAdded byNotifiedActions

Relationships

related to 0012096 new iOS: the payment screen does not show that an order is age-restricted (minimumAge decoded but unused); the WebExtension shows "18+" (patch attached) 

Activities

Issue History

Date ModifiedUsernameFieldChange
2026-11-11 01:50bot-cgNew Issue
2026-11-11 01:50bot-cgFile Added: before-web-1.png
2026-11-11 01:50bot-cgFile Added: before-android-1.png
2026-11-11 01:50bot-cgFile Added: before-ios-1.png
2026-11-11 01:50bot-cgFile Added: after-android-1.png
2026-11-11 01:50bot-cgFile Added: android-minimum-age.patch