346 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			346 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # Gift Subscriptions API Documentation
 | |
| 
 | |
| ## Overview
 | |
| 
 | |
| The Gift Subscriptions feature allows users to purchase subscription gifts that can be redeemed by other users, enabling social gifting and subscription sharing within the DysonNetwork platform.
 | |
| 
 | |
| If you use it through the gateway, the `/api` should be replaced with the `/id`
 | |
| 
 | |
| ### Key Features
 | |
| 
 | |
| - **Purchase Gifts**: Users can buy subscriptions as gifts for specific recipients or as open gifts
 | |
| - **Gift Codes**: Each gift has a unique redemption code
 | |
| - **Flexible Redemption**: Open gifts can be redeemed by anyone, while targeted gifts are recipient-specific
 | |
| - **Security**: Prevents duplicate subscriptions and enforces account level requirements
 | |
| - **Integration**: Full integration with existing subscription, coupon, and pricing systems
 | |
| - **Clean User Experience**: Unpaid gifts are hidden from users and automatically cleaned up
 | |
| - **Automatic Maintenance**: Old unpaid gifts are removed after 24 hours
 | |
| 
 | |
| ## API Endpoints
 | |
| 
 | |
| All endpoints are authenticated and require a valid user session. The base path for gift endpoints is `/api/gifts`.
 | |
| 
 | |
| ### 1. List Sent Gifts
 | |
| 
 | |
| Retrieve gifts you have purchased.
 | |
| 
 | |
| ```http
 | |
| GET /api/gifts/sent?offset=0&take=20
 | |
| Authorization: Bearer <token>
 | |
| ```
 | |
| 
 | |
| **Response**: Array of `SnWalletGift` objects
 | |
| 
 | |
| ### 2. List Received Gifts
 | |
| 
 | |
| Retrieve gifts sent to you or redeemed by you (for open gifts).
 | |
| 
 | |
| ```http
 | |
| GET /api/gifts/received?offset=0&take=20
 | |
| Authorization: Bearer <token>
 | |
| ```
 | |
| 
 | |
| **Response**: Array of `SnWalletGift` objects
 | |
| 
 | |
| ### 3. Get Specific Gift
 | |
| 
 | |
| Retrieve details for a specific gift.
 | |
| 
 | |
| ```http
 | |
| GET /api/gifts/{giftId}
 | |
| Authorization: Bearer <token>
 | |
| ```
 | |
| 
 | |
| **Parameters**:
 | |
| - `giftId`: GUID of the gift
 | |
| 
 | |
| **Response**: `SnWalletGift` object
 | |
| 
 | |
| ### 4. Check Gift Code
 | |
| 
 | |
| Validate if a gift code can be redeemed by the current user.
 | |
| 
 | |
| ```http
 | |
| GET /api/gifts/check/{giftCode}
 | |
| Authorization: Bearer <token>
 | |
| ```
 | |
| 
 | |
| **Response**:
 | |
| ```json
 | |
| {
 | |
|   "gift_code": "ABCD1234EFGH",
 | |
|   "subscription_identifier": "basic",
 | |
|   "can_redeem": true,
 | |
|   "error": null,
 | |
|   "message": "Happy birthday!"
 | |
| }
 | |
| ```
 | |
| 
 | |
| ### 5. Purchase a Gift
 | |
| 
 | |
| Create and purchase a gift subscription.
 | |
| 
 | |
| ```http
 | |
| POST /api/gifts/purchase
 | |
| Authorization: Bearer <token>
 | |
| Content-Type: application/json
 | |
| 
 | |
| {
 | |
|   "subscription_identifier": "premium",
 | |
|   "recipient_id": "550e8400-e29b-41d4-a716-446655440000",  // Optional: null for open gifts
 | |
|   "payment_method": "in_app_wallet",
 | |
|   "payment_details": {
 | |
|     "currency": "irl"
 | |
|   },
 | |
|   "message": "Enjoy your premium subscription!",  // Optional
 | |
|   "coupon": "SAVE20",  // Optional
 | |
|   "gift_duration_days": 30,  // Optional: defaults to 30
 | |
|   "subscription_duration_days": 30  // Optional: defaults to 30
 | |
| }
 | |
| ```
 | |
| 
 | |
| **Response**: `SnWalletGift` object
 | |
| 
 | |
| ### 6. Redeem a Gift
 | |
| 
 | |
| Redeem a gift code to create a subscription for yourself.
 | |
| 
 | |
| ```http
 | |
| POST /api/gifts/redeem
 | |
| Authorization: Bearer <token>
 | |
| Content-Type: application/json
 | |
| 
 | |
| {
 | |
|   "gift_code": "ABCD1234EFGH"
 | |
| }
 | |
| ```
 | |
| 
 | |
| **Response**:
 | |
| ```json
 | |
| {
 | |
|   "gift": { ... },
 | |
|   "subscription": { ... }
 | |
| }
 | |
| ```
 | |
| 
 | |
| ### 7. Mark Gift as Sent
 | |
| 
 | |
| Mark a gift as sent (ready for redemption).
 | |
| 
 | |
| ```http
 | |
| POST /api/gifts/{giftId}/send
 | |
| Authorization: Bearer <token>
 | |
| ```
 | |
| 
 | |
| **Parameters**:
 | |
| - `giftId`: GUID of the gift to mark as sent
 | |
| 
 | |
| ### 8. Cancel a Gift
 | |
| 
 | |
| Cancel a gift before it has been redeemed.
 | |
| 
 | |
| ```http
 | |
| POST /api/gifts/{giftId}/cancel
 | |
| Authorization: Bearer <token>
 | |
| ```
 | |
| 
 | |
| **Parameters**:
 | |
| - `giftId`: GUID of the gift to cancel
 | |
| 
 | |
| ## Usage Examples
 | |
| 
 | |
| ### Client Implementation
 | |
| 
 | |
| Here are examples showing how to integrate gift subscriptions into your client application.
 | |
| 
 | |
| #### Example 1: Purchase a Gift for a Specific User
 | |
| 
 | |
| ```javascript
 | |
| async function purchaseGiftForFriend(subscriptionId, friendId, message) {
 | |
|   const response = await fetch('/api/gifts/purchase', {
 | |
|     method: 'POST',
 | |
|     headers: {
 | |
|       'Authorization': `Bearer ${token}`,
 | |
|       'Content-Type': 'application/json'
 | |
|     },
 | |
|     body: JSON.stringify({
 | |
|       subscription_identifier: subscriptionId,
 | |
|       recipient_id: friendId,
 | |
|       payment_method: 'in_app_wallet',
 | |
|       payment_details: { currency: 'irl' },
 | |
|       message: message
 | |
|     })
 | |
|   });
 | |
| 
 | |
|   const gift = await response.json();
 | |
|   return gift.gift_code; // Share this code with the friend
 | |
| }
 | |
| ```
 | |
| 
 | |
| #### Example 2: Create an Open Gift
 | |
| 
 | |
| ```javascript
 | |
| async function createOpenGift(subscriptionId) {
 | |
|   const response = await fetch('/api/gifts/purchase', {
 | |
|     method: 'POST',
 | |
|     headers: {
 | |
|       'Authorization': `Bearer ${token}`,
 | |
|       'Content-Type': 'application/json'
 | |
|     },
 | |
|     body: JSON.stringify({
 | |
|       subscription_identifier: subscriptionId,
 | |
|       payment_method: 'in_app_wallet',
 | |
|       payment_details: { currency: 'irl' },
 | |
|       message: 'Redeem this anywhere!'
 | |
|       // No recipient_id makes it an open gift
 | |
|     })
 | |
|   });
 | |
| 
 | |
|   const gift = await response.json();
 | |
|   // Mark as sent to make it redeemable
 | |
|   await markGiftAsSent(gift.id);
 | |
|   return gift;
 | |
| }
 | |
| ```
 | |
| 
 | |
| #### Example 3: Redeem a Gift Code
 | |
| 
 | |
| ```javascript
 | |
| async function redeemGiftCode(giftCode) {
 | |
|   // First, check if the gift can be redeemed
 | |
|   const checkResponse = await fetch(`/api/gifts/check/${giftCode}`, {
 | |
|     headers: {
 | |
|       'Authorization': `Bearer ${token}`
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   const checkResult = await checkResponse.json();
 | |
| 
 | |
|   if (!checkResult.canRedeem) {
 | |
|     throw new Error(checkResult.error);
 | |
|   }
 | |
| 
 | |
|   // If valid, redeem it
 | |
|   const redeemResponse = await fetch('/api/gifts/redeem', {
 | |
|     method: 'POST',
 | |
|     headers: {
 | |
|       'Authorization': `Bearer ${token}`,
 | |
|       'Content-Type': 'application/json'
 | |
|     },
 | |
|     body: JSON.stringify({
 | |
|       gift_code: giftCode
 | |
|     })
 | |
|   });
 | |
| 
 | |
|   const result = await redeemResponse.json();
 | |
|   return result.subscription; // The newly created subscription
 | |
| }
 | |
| ```
 | |
| 
 | |
| #### Example 4: Display User's Gift History
 | |
| 
 | |
| ```javascript
 | |
| async function getGiftHistory() {
 | |
|   // Get gifts I sent
 | |
|   const sentResponse = await fetch('/api/gifts/sent', {
 | |
|     headers: { 'Authorization': `Bearer ${token}` }
 | |
|   });
 | |
|   const sentGifts = await sentResponse.json();
 | |
| 
 | |
|   // Get gifts I received
 | |
|   const receivedResponse = await fetch('/api/gifts/received', {
 | |
|     headers: { 'Authorization': `Bearer ${token}` }
 | |
|   });
 | |
|   const receivedGifts = await receivedResponse.json();
 | |
| 
 | |
|   return { sent: sentGifts, received: receivedGifts };
 | |
| }
 | |
| ```
 | |
| 
 | |
| ## Gift Status Lifecycle
 | |
| 
 | |
| Gifts follow this status lifecycle:
 | |
| 
 | |
| 1. **Created**: Initially purchased, can be cancelled or marked as sent
 | |
|    - **Note**: Gifts in "Created" status are not visible to users and are automatically cleaned up after 24 hours if unpaid
 | |
| 2. **Sent**: Made available for redemption, can be cancelled
 | |
| 3. **Redeemed**: Successfully redeemed, creates a subscription
 | |
| 4. **Cancelled**: Permanently cancelled, refund may be processed
 | |
| 5. **Expired**: Expired without redemption
 | |
| 
 | |
| ## Automatic Maintenance
 | |
| 
 | |
| The system includes automatic cleanup to maintain data integrity:
 | |
| 
 | |
| - **Unpaid Gift Cleanup**: Gifts that remain in "Created" status (unpaid) for more than 24 hours are automatically removed from the database
 | |
| - **User Visibility**: Only gifts that have been successfully paid and sent are visible in user gift lists
 | |
| - **Background Processing**: Cleanup runs hourly via scheduled jobs
 | |
| 
 | |
| This ensures a clean user experience while preventing accumulation of abandoned gift purchases.
 | |
| 
 | |
| ## Validation Rules
 | |
| 
 | |
| ### Purchase Validation
 | |
| - Subscription must exist and be valid
 | |
| - If coupon provided, it must be valid and applicable
 | |
| - Recipient account must exist (if specified)
 | |
| - User must meet level requirements for the subscription
 | |
| 
 | |
| ### Redemption Validation
 | |
| - Gift code must exist
 | |
| - Gift must be in "Sent" status
 | |
| - Gift must not be expired
 | |
| - User must meet level requirements
 | |
| - User must not already have an active subscription of the same type
 | |
| - For targeted gifts, user must be the specified recipient
 | |
| 
 | |
| ## Pricing & Payments
 | |
| 
 | |
| Gifts use the same pricing system as regular subscriptions:
 | |
| 
 | |
| - Base price from subscription template
 | |
| - Coupon discounts applied
 | |
| - Currency conversion as needed
 | |
| - Payment processing through existing payment methods
 | |
| 
 | |
| ## Notification Events
 | |
| 
 | |
| The system sends push notifications for:
 | |
| 
 | |
| - **gifts.redeemed**: When someone redeems your gift
 | |
| - **gifts.claimed**: When the recipient redeems your targeted gift
 | |
| 
 | |
| Notifications include gift and subscription details for rich UI updates.
 | |
| 
 | |
| ## Error Handling
 | |
| 
 | |
| Common error responses:
 | |
| 
 | |
| - `400 Bad Request`: Invalid parameters, validation failures
 | |
| - `401 Unauthorized`: Missing or invalid authentication
 | |
| - `403 Forbidden`: Insufficient permissions
 | |
| - `404 Not Found`: Gift or subscription not found
 | |
| - `409 Conflict`: Business logic violations (duplicate subscriptions, etc.)
 | |
| 
 | |
| ## Integration Notes
 | |
| 
 | |
| ### Database Schema
 | |
| The feature adds a `wallet_gifts` table with relationships to:
 | |
| - `accounts` (gifter, recipient, redeemer)
 | |
| - `wallet_subscriptions` (created subscription)
 | |
| - `wallet_coupons` (applied discounts)
 | |
| 
 | |
| ### Backwards Compatibility
 | |
| - No changes to existing subscription endpoints
 | |
| - New gift-related endpoints are additive
 | |
| - Existing payment flows remain unchanged
 | |
| 
 | |
| ### Performance Considerations
 | |
| - Gift codes are indexed for fast lookups
 | |
| - Status filters optimize database queries
 | |
| - Caching integrated with existing subscription caching
 | |
| 
 | |
| ## Support
 | |
| 
 | |
| For implementation questions or issues, refer to the DysonNetwork API documentation or contact the development team.
 |