Skip to content

Đặc tả: Payment & Marketplace Feature

Module: webmarketplace (port 8084) Status: Production

1. Tổng quan

Feature này bao phủ toàn bộ payment lifecycle: mua coin, mua NFT, presale/genesis orders và webhook confirmation từ các payment gateways.

2. Phạm vi

In-scope APIs

CoinController (/api/coin)

Endpoint Method Gateway Mô tả
/buy-by-card POST Fincode/SBPS Mua coin bằng credit card
/buy-by-apple POST Apple IAP Mua coin qua Apple In-App Purchase
/buy-by-google POST Google Play Mua coin qua Google Play Billing
/buy-by-crypto POST Slash Mua coin bằng crypto
/order-status GET - Kiểm tra trạng thái order

PaymentController (/api/payment)

Endpoint Method Mô tả
/select-payment-app POST User chọn payment app
/generate-hash POST Generate hash cho SBPS
/sbps-webhook POST SBPS webhook receiver

UserController (/api/users trong webmarketplace)

Endpoint Method Mô tả
/buy-by-card POST Mua NFT/product bằng card
/buy-by-crypto POST Mua NFT/product bằng crypto
/buy-nft/{productId} POST Mua NFT cụ thể
/confirm-buy-by-bth POST Confirm mua bằng BTH token
/buy-genesis-* POST Genesis NFT pre-order flows

WebHookController (/api/webhook)

Endpoint Method Gateway Mô tả
/confirm-card-payment POST Fincode Xác nhận thanh toán card
/confirm-crypto-payment POST Slash Xác nhận thanh toán crypto
/nft-transfer-confirm POST Node server Xác nhận NFT transfer
/nft-lock-confirm POST Node server Xác nhận NFT lock
/sell-gacha-nft-confirm POST Node server Xác nhận bán gacha NFT
/confirm-burn-nft POST Node server Xác nhận burn NFT ticket
/confirm-transfer-currency POST Node server Xác nhận transfer currency token
/nft-ownership-change POST Node server Thay đổi NFT ownership
/mint-compress-nft-confirm POST Node server Xác nhận mint compressed NFT
/transfer-compress-nft-confirm POST Node server Xác nhận transfer compressed NFT
/nft-solana-change POST Node server Solana NFT ownership change

3. User stories

ID Role Story Acceptance
PAY-US-01 User Mua coin bằng card → nhận coin ngay hoặc chờ webhook confirm Order tạo, coin credited sau confirm
PAY-US-02 User Mua coin bằng Apple IAP → hệ thống verify với Apple → coin credited Apple receipt verified
PAY-US-03 User Mua NFT bằng native token → on-chain confirm → NFT transferred Ownership updated sau confirm
PAY-US-04 User Thanh toán timeout → order tự expire, không bị trừ tiền Batch job cleanup đúng
PAY-US-05 System Webhook từ Fincode → confirm order đúng 1 lần (idempotent) Double webhook không double credit

4. Functional requirements

ID Requirement Chi tiết
PAY-F-01 Orchestration PaymentService là orchestration layer, delegate sang gateway-specific service
PAY-F-02 Gateway isolation PaymentCreditCardService, PaymentCryptoService, PaymentNativeTokenService, PaymentAppleService, PaymentGoogleService
PAY-F-03 Idempotent webhook Webhook endpoint phải check order status trước khi confirm (không double credit)
PAY-F-04 Presale/genesis Support pre-order flow với cancel/confirm lifecycle
PAY-F-05 Signature validation Fincode webhook validate Fincode-Signature header
PAY-F-06 Timeout handling Batch jobs expire pending orders: CardCheckoutExpiredConfig, CryptoCheckoutExpiredConfig, NativeTokenCheckoutExpiredConfig
PAY-F-07 NFT transfer confirm 3 types: to admin wallet, to owner, to user (switch by transferType)
PAY-F-08 Compressed NFT Support Solana compressed NFT mint/transfer confirm

5. Business rules

  • Fincode webhook: kiểm tra Fincode-Signature header match paymentFincodeSettingService.getSignature().
  • SBPS webhook: @RequestParam form-encoded payload.
  • Apple/Google: server-side receipt verification với Apple/Google servers.
  • NFT transfer types: TRANSFER_NFT_TO_ADMIN_WALLET, TRANSFER_NFT_OWNER, default TRANSFER_TO_USER.
  • Compress NFT mint fail: status=false hoặc leafIndex=Unknown → handle mint fail.

6. Data contracts

Request - buy-by-card

{
  "order_id": "<orderId>",
  "product_id": "<productId>",
  "amount": 1000,
  "card_token": "<fincodeCardToken>",
  "payment_method": "CARD"
}

Response - buy-by-card

{
  "order_id": "<orderId>",
  "status": "PENDING | SUCCESS | FAILED",
  "checkout_url": "<url>",
  "payment_id": "<paymentId>"
}

Webhook - Fincode confirm card payment (header: Fincode-Signature)

{
  "id": "<paymentId>",
  "status": "CAPTURED",
  "amount": 1000,
  "order_id": "<orderId>"
}

Response - Apple IAP

{
  "order_id": "<orderId>",
  "product_id": "<productId>"
}

7. Acceptance criteria

  • [ ] buy-by-card tạo pending order → Fincode webhook confirm → coin credited
  • [ ] buy-by-apple verify receipt với Apple → SUCCESS → coin credited
  • [ ] buy-by-google verify receipt với Google Play → coin credited
  • [ ] buy-by-crypto tạo Slash invoice → webhook confirm → coin/NFT credited
  • [ ] Fincode webhook với sai signature → FINCODE_SIGNATURE_IS_INVALID (không process)
  • [ ] Double webhook cùng paymentId → idempotent, không double credit
  • [ ] Pending order quá TTL → batch job expire, không credit
  • [ ] NFT transfer confirm với 3 transfer types đúng routing

8. Constraints

  • webmarketplace module port 8084, không có Tomcat config (minimal).
  • Webhook endpoints phải whitelist trong SecurityConfig (không cần JWT).
  • Fincode signature so sánh exact string match.

9. Code references

webmarketplace/
  controllers/
    coin/CoinController.java
    payment/PaymentController.java
    webhook/WebHookController.java
    nft_rental/NftRentalController.java
    user/UserController.java (marketplace ops)

application-core/
  service/payment/PaymentService.java
  service/payment_card/PaymentCreditCardService.java
  service/payment_crypto/PaymentCryptoService.java
  service/payment_native_token/PaymentNativeTokenService.java
  service/payment_apple/PaymentAppleService.java
  service/payment_google/PaymentGoogleService.java
  service/payment_fincode/
  service/transfer_nft/TransferNftService.java
  service/lock_nft/LockNftService.java

batch/
  job/
    card_payment_expired/CardCheckoutExpiredConfig.java
    card_payment_confirm/CardPaymentConfirmConfig.java
    crypto_payment_expired/CryptoCheckoutExpiredConfig.java
    genesis_nft/NativeTokenCheckoutExpiredConfig.java
    genesis_nft/ExpiredPreOrderGenesisNftConfig.java