Skip to content

Feature: Gift Cards & Store Credit (Purchase, Redeem, Refund-to-Credit) #30

@hoangsonww

Description

@hoangsonww

Summary

Enable customers to buy digital gift cards, redeem them into account store credit, and allow admins/support to refund orders to store credit. Provide balance tracking, partial redemptions, audit logs, and secure one-time redemption codes.

Motivation

  • New revenue stream (gift cards) and improved retention (store credit keeps value on-platform).
  • Faster, cheaper refunds; fewer payment gateway fees on reversals.
  • Better UX for gifting and exchanges.

Goals

  1. Sell gift cards in preset or custom amounts.
  2. Email delivery with secure, single-use redemption code and optional recipient note/scheduled send.
  3. Redeem code → converts to store credit tied to the user.
  4. Store credit can be used at checkout (partial/combined with card).
  5. Admin can issue manual credit (goodwill) and refund to credit.
  6. Full audit trail and anti-fraud checks.

Non-Goals

  • Physical gift cards and printing.
  • Multi-currency beyond one configured store currency (follow-up).

Data Model (MongoDB)

GiftCard {
  _id, codeHash, amount, currency, remaining, status: 'active'|'redeemed'|'void',
  purchaserUserId?, recipientEmail, message?, scheduledSendAt?, issuedAt, redeemedAt?
}

StoreCreditLedger {
  _id, userId, delta, balanceAfter, reason: 'redeem'|'refund'|'goodwill'|'adjustment',
  ref?: { type: 'order'|'giftcard'|'admin', id: string }, createdAt
}

API (Express)

POST   /api/giftcards/purchase            // creates pending gift card (after payment success -> activate & send)
POST   /api/giftcards/redeem              // body: { code } -> adds to StoreCreditLedger
GET    /api/credits/balance               // current user balance
POST   /api/credits/apply                 // body: { cartId, amount } -> reserve credit for checkout
POST   /api/credits/release               // release reservation (on cancel/expire)
POST   /api/admin/credits/grant           // admin-only goodwill credit
POST   /api/admin/orders/:id/refundCredit // refund order total/partial to credit

Checkout Flow

  • Show Store Credit line with available balance; user chooses amount to apply.
  • On order success, convert reserved credit → consumed; on failure, release.
  • Combine credit with existing payment method to cover remainder.

Email & UX

  • Gift Card Email: design with amount, code, personal message, CTA to redeem.
  • Account → Wallet: balance, ledger, redeem form, “copy code” and QR (optional).
  • Admin: search gift cards, void, resend email; ledger viewer per user.

Security & Fraud

  • Store only hashed codes (codeHash); compare with bcrypt/scrypt.
  • Rate-limit redeem attempts; lock after N failures; log IP/user-agent.
  • Mark suspicious orders (e.g., multiple gift cards with new account) for review.
  • Codes are single-use; partially redeemed gift cards track remaining.

Config

  • MIN/MAX gift card amounts; allowed presets.
  • Email provider keys (SendGrid/Resend/Mailgun); templates.
  • Toggle scheduled delivery and timezone handling.

Acceptance Criteria

  • Purchase flow creates active gift cards post-payment; emails sent (can resend).
  • Redeem consumes code, credits user balance; partial redemption updates remaining.
  • Checkout can apply/release credit and handle mixed payments.
  • Admin can grant credit and refund orders to credit.
  • Robust audit trail via StoreCreditLedger (balance is derivable).
  • Rate limiting and hashed codes in place; unit/integration tests pass.
  • README/docs updated (setup, env, flows).

Implementation Notes

  • Use a 12–16 char human-friendly code (e.g., grouped XXXX-XXXX-XXXX) + internal random salt before hashing.
  • Keep a lightweight reservation collection or field to prevent double-spend during checkout race conditions.
  • Consider idempotency keys on purchase/redeem/apply endpoints.

Metadata

Metadata

Assignees

Labels

dependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationduplicateThis issue or pull request already existsenhancementNew feature or requestgood first issueGood for newcomershelp wantedExtra attention is neededquestionFurther information is requested

Projects

Status

Backlog

Relationships

None yet

Development

No branches or pull requests

Issue actions