Choose Your Plan

Select the perfect plan for your needs

Starter
Perfect for individuals
$9.99/month
  • Basic features
  • 2 projects
  • 5GB storage
  • Basic support
Professional
Ideal for small teams
$29.99/month
  • All Starter features
  • 10 projects
  • 25GB storage
  • Priority support
  • Advanced analytics
Enterprise
For large organizations
$99.99/month
  • All Professional features
  • Unlimited projects
  • 100GB storage
  • 24/7 phone support
  • Custom integrations
  • Dedicated account manager

Basic Payment Implementation Guide

One Item Fixed Price

Follow this step-by-step guide to implement subscription-based payments with automatic recurring billing.

Subscription Implementation
Enterprise-grade subscription system with recurring payments

1. Environment Configuration

Configure your environment variables in .env.local

NEXT_PUBLIC_ORBITA_APP_URL=https://testnet.orbita.zone
NEXT_PUBLIC_ORBITA_SHOP_URL=https://shop.orbita.zone
NEXT_PUBLIC_STARTER_MONTHLY_PAYMENT_ID=16
NEXT_PUBLIC_STARTER_YEARLY_PAYMENT_ID=18
NEXT_PUBLIC_PROFESSIONAL_MONTHLY_PAYMENT_ID=14
NEXT_PUBLIC_PROFESSIONAL_YEARLY_PAYMENT_ID=19
NEXT_PUBLIC_ENTERPRISE_MONTHLY_PAYMENT_ID=15
NEXT_PUBLIC_ENTERPRISE_YEARLY_PAYMENT_ID=20

2. Basic Checkout Implementation

Implementation of the basic checkout function in lib/payment-utils.ts

export function handleBasicCheckout(
  paymentId: string,   // ID of the subscription plan
  successURL: string   // URL to redirect after successful payment
) {
  // Encode the return URL to ensure it's properly passed in the query parameters
  const returnURL = encodeURIComponent(successURL);

  // Open the payment page in a new window/tab
  window.open(
    `${ORBITA_APP_URL}/pay?payment_id=${paymentId}&return_url=${returnURL}`
  );
}

3. Usage Example

Complete implementation with plan configuration and subscription handling

// Define the structure for subscription plans
interface Plan {
  name: string;           // Name of the plan
  description: string;    // Short description of the plan
  monthlyPrice: number;   // Price for monthly billing
  yearlyPrice: number;    // Price for yearly billing
  monthlyPaymentId: string; // Payment ID for monthly subscription
  yearlyPaymentId: string;  // Payment ID for yearly subscription
  features: string[];     // List of features included in the plan
  highlighted?: boolean;  // Whether to highlight this plan as recommended
}

// Define available subscription plans
const plans: Plan[] = [
  {
    name: "Starter",
    description: "Perfect for individuals",
    monthlyPrice: 9.99,
    yearlyPrice: 99.99,
    monthlyPaymentId: process.env.NEXT_PUBLIC_STARTER_MONTHLY_PAYMENT_ID || "16",
    yearlyPaymentId: process.env.NEXT_PUBLIC_STARTER_YEARLY_PAYMENT_ID || "18",
    features: ["Basic features", "2 projects", "5GB storage"],
  },
  // Additional plans...
];

// In your subscription component
const [yearly, setYearly] = useState(false);
const [loading, setLoading] = useState<string | null>(null);

const handleSubscribe = async (plan: Plan) => {
  // Choose the appropriate payment ID based on billing cycle
  const chosenPaymentId = yearly
    ? plan.yearlyPaymentId
    : plan.monthlyPaymentId;
  
  // Set loading state for the specific plan
  setLoading(chosenPaymentId);
  
  try {
    // Initiate the checkout process
    handleBasicCheckout(
      chosenPaymentId,
      `${ORBITA_SHOP_URL}/success` // Success URL after payment
    );
  } catch (error) {
    console.error("Subscription error:", error);
  } finally {
    // Reset loading state
    setLoading(null);
  }
};

// Subscribe button implementation
<Button
  onClick={() => handleSubscribe(plan)}
  disabled={loading === plan.monthlyPaymentId || loading === plan.yearlyPaymentId}
>
  {loading === plan.monthlyPaymentId || loading === plan.yearlyPaymentId
    ? "Processing..."
    : `Subscribe ${yearly ? "Yearly" : "Monthly"}`}
</Button>