Payment Service

payment-service is a Quarkus service that owns all payment processing, gateway integration, store credit, and loyalty points for ShopSTAR3. Storage is PostgreSQL with store_id as a discriminator column for multi-tenant isolation. All gateway credentials are stored in Vault — they are never written to the database.

Provider Abstraction#

All payment gateways are implemented behind a single PaymentProvider interface, which decouples the checkout flow from any specific gateway.

interface PaymentProvider {
    ChargeResult charge(ChargeRequest request);
    RefundResult refund(RefundRequest request);
    ReverseResult reverse(ReverseRequest request);
    StatusResult getStatus(String transactionId);
    WebhookEvent parseWebhook(HttpRequest request);
}

Built-in Adapters#

AdapterNotes
StripeAdapterFull charge/refund/reverse lifecycle via Stripe API
PayPalAdapterFull charge/refund/reverse lifecycle via PayPal Orders API
CodAdapterCash on Delivery — no external call; creates a PENDING transaction immediately
CCPayAdapterCharge/refund/reverse via CCPay gateway API

Each adapter reads its credentials at startup from Vault. Adding a new payment method requires only a new class implementing PaymentProvider and a corresponding Vault entry for its credentials — no database schema changes are needed.

Transactions and Refunds#

Transactions Table#

Columns: transaction_id UUID PK, store_id, order_id, provider_type, provider_transaction_id, amount, currency, status, created_at, captured_at.

The status field follows this lifecycle:

StatusMeaning
PENDINGTransaction initiated but not yet confirmed (used for COD and async gateways)
CAPTUREDPayment successfully captured
FAILEDGateway returned a failure
REVERSEDFull reversal applied after capture

Refunds Table#

Columns: refund_id UUID PK, transaction_id FK, store_id, order_id, amount, status (PENDING / COMPLETED / FAILED), destination (ORIGINAL_METHOD or STORE_CREDIT), provider_refund_id, created_at.

Refund Configuration (Per Store)#

refund_configs stores per-store refund policy flags: partial_refund_enabled BOOLEAN, refund_to_original_enabled BOOLEAN, refund_to_store_credit_enabled BOOLEAN. These settings are configurable per store; specific rules and workflows are deferred and will be defined during the refund management feature phase.

Wallet — Store Credit and Loyalty Points#

Each customer holds two independent balances per store. They are separate systems with different semantics and cannot be interchanged.

Store Credit#

Store credit is a cash-equivalent balance. It reduces the order total directly and has the same monetary value as the store’s currency.

store_credit_accounts: account_id UUID PK, customer_id, store_id, balance NUMERIC. The balance never goes negative.

store_credit_ledger: append-only ledger recording every balance movement. Each entry carries a movement_type:

Movement TypeTrigger
REFUND_CREDITA refund is issued as store credit
PROMOTION_CREDITMarketing grant applied to the account
MANUAL_GRANTStaff action via admin panel
CHECKOUT_DEBITStore credit applied at checkout
EXPIRYCredit expired (if the store has expiry enabled)

Loyalty Points#

Loyalty points are integer-valued and non-cash. They are earned on orders and redeemed at checkout via a configured exchange rate.

points_accounts: account_id UUID PK, customer_id, store_id, balance INT.

points_ledger: append-only ledger. Each entry carries a movement_type:

Movement TypeTrigger
ORDER_EARNEDPoints granted when an order is placed
ORDER_CANCELLED_REVERSALPoints reversed when the originating order is cancelled
REDEMPTIONPoints applied at checkout
EXPIRYPoints expired per store policy
MANUAL_GRANTStaff action via admin panel

points_rules (per store): earn_rate NUMERIC (points earned per currency unit spent), redeem_rate NUMERIC (points required per currency unit of discount), expiry_days INT (null = no expiry).

Checkout Integration#

The payment service participates in the checkout saga. The sequence for a payment step with wallet balances applied is:

  1. checkout-service calls GetCustomerBalances(customerId, storeId) to retrieve available store credit and points before the payment screen is displayed.
  2. The customer selects how much store credit and/or points to apply.
  3. payment-service Charge handler deducts store credit first, then deducts points (converted to a currency equivalent via redeem_rate), then charges the net remaining amount to the selected payment gateway.
  4. If the gateway charge fails, all store credit and points deductions are reversed before the failure response is returned to checkout-service.
  5. When an order.placed event is consumed, an ORDER_EARNED ledger entry is created for the customer: earn_rate × order_total.

gRPC Interface#

These methods are exposed to checkout-service only.

MethodSignaturePurpose
Charge(orderId, customerId, storeId, amount, currency, storeCredit, points, paymentMethodToken)ChargeResultExecute payment with optional wallet offsets
Reverse(transactionId, reason)ReverseResultFull reversal of a captured transaction
GetCustomerBalances(customerId, storeId)BalancesResponseReturn store credit balance, points balance, and points value equivalent in currency

Kafka Topics#

Consumed#

TopicAction
order.placedTrigger ORDER_EARNED points ledger entry
order.cancelledReverse points earned on the cancelled order if not yet consumed

Published#

TopicPayload
payment.chargedtransactionId, orderId, storeId, amount, currency, provider
payment.failedtransactionId, orderId, storeId, reason
payment.reversedtransactionId, orderId, storeId, amount
order.refundedrefundId, orderId, storeId, amount, destination
payment.points_earnedcustomerId, storeId, points, orderId

Vault Configuration#

Key pathPurpose
ss3/kv/payment-service/db.urlPostgreSQL JDBC URL
ss3/kv/payment-service/db.usernameDatabase username
ss3/kv/payment-service/db.passwordDatabase password
ss3/kv/payment-service/stripe.secret-keyStripe secret key
ss3/kv/payment-service/paypal.client-idPayPal OAuth client ID
ss3/kv/payment-service/paypal.client-secretPayPal OAuth client secret
ss3/kv/payment-service/ccpay.api-keyCCPay API key
ss3/kv/shared/Shared Kafka bootstrap and OTel config