Package xyz.tcheeric.cashu.voucher.app
Class VoucherRedemptionService
java.lang.Object
xyz.tcheeric.cashu.voucher.app.VoucherRedemptionService
Service for secure voucher redemption with duplicate protection.
This service implements a defense-in-depth approach to prevent double redemption:
- Fingerprint check: Fast lookup in redemption tracking store
- Ledger status check: Verify voucher is in ISSUED state
- Atomic recording: Record redemption before updating ledger
- Ledger update: Mark voucher as REDEEMED
Concurrency Safety
The VoucherRedemptionPort.tryRecordRedemption(java.lang.String, java.lang.String, java.lang.String) method provides
atomic compare-and-swap semantics. If two concurrent redemption attempts
occur, only one will succeed in recording the redemption.
Model B Enforcement
This service optionally verifies that the redeeming merchant matches the voucher's issuer ID (Model B constraint).
- See Also:
-
Constructor Summary
ConstructorsConstructorDescriptionVoucherRedemptionService(@NonNull VoucherLedgerPort ledgerPort, @NonNull VoucherRedemptionPort redemptionPort) Constructs a VoucherRedemptionService with required dependencies. -
Method Summary
Modifier and TypeMethodDescriptiongetRedemptionRecord(SignedVoucher voucher) Gets redemption details for a voucher.booleanisRedeemed(SignedVoucher voucher) Checks if a voucher has been redeemed based on its fingerprint.redeem(@NonNull SignedVoucher voucher, @NonNull String merchantId, boolean verifyOnline) Attempts to redeem a voucher with duplicate protection.redeem(SignedVoucher voucher, String merchantId) Convenience method for redeeming with default online verification.
-
Constructor Details
-
VoucherRedemptionService
public VoucherRedemptionService(@NonNull @NonNull VoucherLedgerPort ledgerPort, @NonNull @NonNull VoucherRedemptionPort redemptionPort) Constructs a VoucherRedemptionService with required dependencies.- Parameters:
ledgerPort- the port for voucher status operations (must not be null)redemptionPort- the port for redemption tracking (must not be null)
-
-
Method Details
-
redeem
public RedeemVoucherResponse redeem(@NonNull @NonNull SignedVoucher voucher, @NonNull @NonNull String merchantId, boolean verifyOnline) Attempts to redeem a voucher with duplicate protection.This method performs the following steps:
- Computes fingerprint from voucher
- Checks if fingerprint already redeemed (fast path rejection)
- Optionally queries ledger for current status
- Validates voucher signature and expiry
- Optionally verifies merchant ID matches (Model B)
- Atomically records redemption
- Updates ledger status to REDEEMED
- Parameters:
voucher- the signed voucher to redeem (must not be null)merchantId- the merchant attempting redemption (must not be null)verifyOnline- whether to verify status on ledger (recommended: true)- Returns:
- redemption response with success/failure details
-
redeem
Convenience method for redeeming with default online verification.- Parameters:
voucher- the signed voucher to redeemmerchantId- the merchant attempting redemption- Returns:
- redemption response
-
isRedeemed
Checks if a voucher has been redeemed based on its fingerprint.- Parameters:
voucher- the voucher to check- Returns:
- true if the voucher has been redeemed
-
getRedemptionRecord
Gets redemption details for a voucher.- Parameters:
voucher- the voucher to look up- Returns:
- redemption record if found
-