Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

GameShift Payment Gateway Demo

A minimal, complete reference implementation showcasing GameShift as a payment gateway (similar to Stripe Checkout) for off-chain purchases.

This Next.js application demonstrates how to integrate GameShift's hosted checkout to accept both card and cryptocurrency payments for virtual items like in-game currency, power-ups, and other digital goods.

Overview

This demo application provides:

  • Storefront page with products dynamically loaded from GameShift SKUs
  • Dual payment flow supporting both card and cryptocurrency payments
  • GameShift hosted checkout integration with payment method selection
  • Webhook handling to process payment completion events
  • Purchase history page showing completed transactions
  • TypeScript with full type safety
  • Tailwind CSS for clean, responsive UI

Tech Stack

  • Next.js 14+ (App Router)
  • TypeScript (strict mode)
  • Tailwind CSS (styling)
  • GameShift API (payment processing)

Project Structure

off-chain-purchases/
├── app/
│   ├── api/
│   │   └── gameshift/
│   │       ├── checkout/route.ts          # Create payment endpoint (card or crypto)
│   │       ├── payments/[id]/route.ts     # Payment status lookup
│   │       └── webhook/route.ts           # Webhook handler
│   ├── orders/
│   │   └── page.tsx                       # My Purchases page
│   ├── layout.tsx                         # Root layout with navigation
│   ├── page.tsx                           # Storefront (main page)
│   └── globals.css                        # Tailwind CSS imports
├── components/
│   └── ProductCard.tsx                    # Product display with payment method selector
├── lib/
│   ├── gameshiftClient.ts                 # GameShift API wrapper
│   ├── skuMapping.ts                      # SKU fetching and product conversion
│   ├── products.ts                        # Product management (SKU-based)
│   ├── demoUser.ts                        # Hardcoded demo user
│   ├── demoOrderStore.ts                  # In-memory order tracking
│   └── types.ts                           # TypeScript type definitions
├── .env.local.example                     # Environment variable template
├── package.json                           # Dependencies and scripts
└── README.md                              # This file

Getting Started

1. Install Dependencies

npm install

2. Configure Environment Variables

Copy the example environment file:

cp .env.local.example .env.local

Edit .env.local and add your GameShift credentials:

# GameShift API Configuration
GAMESHIFT_API_BASE=https://api.gameshift.dev
GAMESHIFT_API_KEY=your_api_key_here
GAMESHIFT_ENVIRONMENT=Development
GAMESHIFT_WEBHOOK_SECRET=your_webhook_secret_here
NEXT_PUBLIC_APP_BASE_URL=http://localhost:3000

Where to Find Your GameShift Credentials

  1. API Key:

  2. Webhook Secret:

    • In GameShift Dashboard, go to Settings → Webhooks
    • Create a new webhook endpoint (use http://localhost:3000/api/gameshift/webhook for local testing or your production URL)
    • Copy the webhook secret

3. Create SKUs in GameShift Dashboard

Important: Products are dynamically loaded from GameShift SKUs. You must create at least one SKU to see products in the storefront.

  1. Log in to GameShift Dashboard

  2. Navigate to Storefront → SKUs

  3. Click Create New SKU

  4. Fill in the details:

    • Name: Product name (e.g., "Gold Pack 500")
    • Description: Product description
    • Price: Set the price (e.g., 4.99)
    • Currency: Choose USD, USDC, or SOL
    • Quantity: Set to -1 for unlimited
  5. Click Create

  6. Repeat for as many products as you want

4. Run the Development Server

npm run dev

Open http://localhost:3000 in your browser.

Your products will automatically appear in the storefront!

How the Payment Flow Works

This app supports two payment flows depending on the payment method selected:

1. Card Payment Flow (Default)

User selects "Card" payment method
        ↓
Next.js app calls POST /nx/payments
        ↓
GameShift returns checkoutUrl
        ↓
User redirected to GameShift card checkout
        ↓
User completes card payment
        ↓
GameShift sends webhook
        ↓
Order marked as paid

2. Crypto Payment Flow (SKU-based)

User selects "Crypto" payment method
        ↓
Next.js app calls GET /internal/storefront/skus/{skuId}/purchase
        ↓
GameShift returns consentUrl (storefront checkout)
        ↓
User redirected to GameShift crypto checkout
        ↓
User completes crypto payment (USDC, SOL, etc.)
        ↓
GameShift sends webhook
        ↓
Order marked as paid

Key Components

1. Creating a Payment (Checkout Flow)

When a user clicks "Purchase" on a product:

  1. Frontend calls POST /api/gameshift/checkout with the product ID and payment method

    {
      "productId": "gold-pack-small",
      "paymentMethod": "card" // or "crypto"
    }
  2. API Route (app/api/gameshift/checkout/route.ts) handles two flows:

    For Card Payments:

    • Calls POST /nx/payments to create a card payment
    • Request:
      {
        "title": "Small Gold Pack",
        "description": "500 gold coins...",
        "price": {
          "currencyId": "USD",
          "naturalAmount": "4.99"
        },
        "quantity": 1,
        "buyerId": "demo-user-1"
      }
    • Returns checkoutUrl and transactionId

    For Crypto Payments:

    • Calls GET /internal/storefront/skus/{skuId}/purchase using the product's SKU ID
    • Returns consentUrl (storefront checkout URL) and cartId
  3. Frontend redirects user to the checkout URL

  4. GameShift checkout page handles the actual payment

2. Webhook Processing

When a payment is completed, GameShift sends a webhook to your app:

  1. GameShift sends POST /api/gameshift/webhook with:

    • Headers: webhook-id, webhook-timestamp, webhook-signature
    • Body:
      {
        "data": {
          "type": "payment",
          "status": "success",
          "paymentId": "abc123...",
          "currency": "USD",
          "amount": "4.99"
        }
      }
  2. Webhook Handler (app/api/gameshift/webhook/route.ts):

    • Verifies the webhook signature using HMAC-SHA256
    • Checks if the payment type is "payment" and status is "success"
    • Updates the order status to "paid" in the order store
    • Returns HTTP 200 to acknowledge receipt

3. Webhook Signature Verification

The webhook handler uses HMAC-SHA256 to verify webhook authenticity:

signedContent = `${webhookId}.${webhookTimestamp}.${JSON.stringify(data)}`
computedSignature = HMAC-SHA256(signedContent, base64Decode(WEBHOOK_SECRET))
isValid = (webhookSignature === `v1,${base64Encode(computedSignature)}`)

This ensures the webhook actually came from GameShift and wasn't tampered with.

Payment Methods Supported

This demo supports two payment flows, and all products support both methods automatically:

Card Payments

  • Uses /nx/payments API endpoint
  • Creates a new payment charge with SKU details
  • Returns a checkoutUrl for card checkout
  • User pays with credit/debit card on GameShift's hosted page

Crypto Payments

  • Uses /internal/storefront/skus/{skuId}/purchase API endpoint
  • Generates a purchase URL for the SKU
  • Returns a consentUrl for crypto storefront checkout
  • User pays with USDC, SOL, or other Solana tokens

How It Works

  1. All products are SKUs: Products are dynamically loaded from GameShift SKUs
  2. User chooses payment method: Toggle between "Card" or "Crypto" on each product
  3. App routes to correct API:
    • Card → Creates payment with SKU details via /nx/payments
    • Crypto → Gets purchase URL via /internal/storefront/skus/{skuId}/purchase
  4. Both redirect to GameShift hosted checkout
  5. Webhooks handle completion for both payment methods

No Configuration Needed!

Since products ARE SKUs, both payment methods work automatically. Just create SKUs in the GameShift Dashboard and they'll appear with both payment options.

Demo User & Data

Hardcoded Demo User

{
  referenceId: "demo-user-1",
  email: "demo@example.com"
}

Product Catalog

Products are dynamically loaded from GameShift SKUs. The storefront will display:

  • All SKUs created in your GameShift Dashboard
  • Product name, description, and price from SKU details
  • Payment method selector (Card / Crypto) for each product
  • Real-time pricing and availability

No hardcoded products - everything comes from GameShift!

In-Memory Order Store

Orders are stored in memory using a simple Map. This means:

  • ✅ Perfect for demos and development
  • ❌ Data is lost when the server restarts
  • ❌ Not suitable for production (use a database instead)

API Endpoints

POST /api/gameshift/checkout

Create a GameShift payment and get the checkout URL. Supports both card and crypto payments.

Request:

{
  "productId": "gold-pack-small",
  "paymentMethod": "card"  // or "crypto" (optional, defaults to "card")
}

Response:

{
  "checkoutUrl": "https://app.gameshift.dev/checkout?payment=...",
  "paymentId": "abc123..."
}

Notes:

  • If paymentMethod is "crypto", the product must have a skuId configured
  • Card payments use /nx/payments API
  • Crypto payments use /internal/storefront/skus/{skuId}/purchase API

GET /api/gameshift/payments/[id]

Get the status of a payment by ID.

Response:

{
  "id": "abc123...",
  "status": "Completed",
  "purchaser": {
    "referenceId": "demo-user-1",
    "email": "demo@example.com"
  },
  "price": {
    "currencyId": "USD",
    "naturalAmount": "4.99"
  }
}

POST /api/gameshift/webhook

Webhook endpoint for GameShift events. Automatically verifies signatures and processes payment completion events.

Testing Webhooks Locally

To test webhooks during local development:

  1. Use a tunneling service like ngrok:

    ngrok http 3000
  2. Configure webhook in GameShift Dashboard:

    • URL: https://your-ngrok-url.ngrok.io/api/gameshift/webhook
    • Copy the webhook secret to your .env.local
  3. Test a payment and watch the console logs to see webhook events

Alternatively, you can use the payment status API endpoint to manually check payment status after completing a test payment.

Security Considerations

API Key Protection

  • ✅ All GameShift API calls are made from server-side only (API routes)
  • ✅ The GAMESHIFT_API_KEY is never exposed to the client
  • ✅ Environment variables are properly configured in .env.local (not committed to git)

Webhook Verification

  • ✅ Webhook signatures are verified using HMAC-SHA256
  • ✅ Invalid signatures are rejected with HTTP 401
  • ✅ Constant-time comparison prevents timing attacks

Input Validation

  • ✅ Product IDs are validated before creating payments
  • ✅ API errors are handled gracefully
  • ✅ Proper HTTP status codes are returned

Moving to Production

To use this code in production, you'll need to:

  1. Replace in-memory storage with a database (PostgreSQL, MongoDB, etc.)

    • Update lib/demoOrderStore.ts to use your database
    • Store user data, products, and orders persistently
  2. Implement real user authentication

    • Replace hardcoded demo user with actual auth (NextAuth.js, Clerk, etc.)
    • Use session/JWT to identify current user
  3. Update environment variables

    • Use production GameShift API key
    • Set production webhook URL
    • Use production base URL
  4. Add proper error handling and logging

    • Implement error monitoring (Sentry, LogRocket, etc.)
    • Add detailed logging for payment flows
  5. Implement proper order fulfillment

    • Actually grant the purchased items to the user's account
    • Send confirmation emails
    • Handle failed/refunded payments
  6. Add tests

    • Unit tests for business logic
    • Integration tests for API routes
    • E2E tests for payment flows

Troubleshooting

"API calls are failing"

  • Check that GAMESHIFT_API_KEY is set correctly in .env.local
  • Verify your API key is valid in the GameShift Dashboard
  • Check the console logs for detailed error messages

"Webhook signature verification fails"

  • Ensure GAMESHIFT_WEBHOOK_SECRET matches the secret in GameShift Dashboard
  • Check that the webhook URL is configured correctly
  • Verify the secret is base64-encoded

"Payments aren't showing in My Purchases"

  • Check if the webhook is being received (look at server logs)
  • Verify the webhook signature is passing validation
  • Check if the order exists in the in-memory store (server may have restarted)

Resources

License

This is a reference implementation for educational purposes. Feel free to use it as a starting point for your own projects.

Support

For GameShift-specific questions:

For issues with this demo:

  • Check the troubleshooting section above
  • Review the console logs for detailed error messages

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages