TinyShip
TinyShip
 TinyShip
TinyShip
TinyShip Documentation
TinyShip User GuideGetting StartedBasic Configuration
Payment ConfigurationStripe ConfigurationPayPal ConfigurationWeChat Pay ConfigurationAlipay ConfigurationCreem ConfigurationPayment Testing
Credits System Configuration
Storage Service ConfigurationCaptcha Configuration
User GuidePayment

PayPal Configuration

Configure PayPal Payment

PayPal is a globally recognized payment platform supporting both one-time payments and subscriptions.

Setup Steps

  1. Visit PayPal Developer
  2. Create application and get Client ID / Client Secret
  3. Configure Webhook in Developer Dashboard
  4. Record Webhook ID for environment variables

Environment Variables

# PayPal Configuration
PAYPAL_CLIENT_ID="AYxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
PAYPAL_CLIENT_SECRET="ELxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
PAYPAL_WEBHOOK_ID="WH-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
PAYPAL_SANDBOX="true"  # Set to "false" for production

One-time vs Subscription

One-time Payment (Orders + Capture)

  • No need to create Product / Plan in PayPal Dashboard
  • Suitable for lifetime access, one-time purchases

Subscription Payment

  • Requires creating Product and Plan in PayPal Dashboard
    • Developer Dashboard → Products & Services → Subscriptions
    • Create Product → Create Plan
  • Record Plan ID and configure in config/payment.ts as paypalPlanId
  • Subscription status verified via Webhook or active query

Sandbox Testing

PayPal provides a Sandbox environment for development testing.

Enable Sandbox

  1. Set environment variable:

    PAYPAL_SANDBOX=true
  2. Sandbox API: https://api-m.sandbox.paypal.com

  3. Sandbox Accounts

    • Create Sandbox buyer/seller accounts in Developer Dashboard
    • Use Sandbox buyer account to complete payment tests

Webhook Note: Sandbox and Production webhooks are completely isolated. You must configure Webhook under Sandbox App. Sandbox webhook events may have delays (seconds to tens of seconds).

Switch to Production

  1. Set PAYPAL_SANDBOX=false
  2. Use production Client ID / Client Secret
  3. Reconfigure Webhook under production App

Webhook Events

Recommended events to monitor (covering one-time payments and subscription lifecycle):

EventDescription
PAYMENT.CAPTURE.COMPLETEDPayment captured successfully
PAYMENT.CAPTURE.DENIEDPayment capture denied
PAYMENT.CAPTURE.REFUNDEDPayment refunded
BILLING.SUBSCRIPTION.ACTIVATEDSubscription activated
BILLING.SUBSCRIPTION.UPDATEDSubscription updated
BILLING.SUBSCRIPTION.CANCELLEDSubscription cancelled
BILLING.SUBSCRIPTION.EXPIREDSubscription expired
BILLING.SUBSCRIPTION.SUSPENDEDSubscription suspended
PAYMENT.SALE.COMPLETEDSale completed

Plan Configuration Examples

Subscription Plan

config/payment.ts
monthlyPaypal: {
  provider: 'paypal',
  id: 'monthlyPaypal',
  amount: 10,
  currency: 'USD',
  duration: {
    months: 1,
    type: 'recurring'
  },
  paypalPlanId: 'P-XXXXXXXXXX', // Plan ID created in PayPal Dashboard
  i18n: {
    'en': {
      name: 'PayPal Monthly Plan',
      description: 'Monthly recurring subscription via PayPal',
      duration: 'month',
      features: ['All premium features', 'Priority support']
    },
    'zh-CN': {
      name: 'PayPal 月度订阅',
      description: '通过 PayPal 的月度循环订阅',
      duration: '月',
      features: ['所有高级功能', '优先支持']
    }
  }
}

One-time Payment (Lifetime)

config/payment.ts
lifetimePaypal: {
  provider: 'paypal',
  id: 'lifetimePaypal',
  amount: 199,
  currency: 'USD',
  duration: {
    months: 9999,
    type: 'one_time'
  },
  i18n: {
    'en': {
      name: 'Lifetime (PayPal)',
      description: 'One-time payment, lifetime access',
      duration: 'lifetime',
      features: ['All premium features', 'Priority support', 'Free lifetime updates']
    },
    'zh-CN': {
      name: '终身会员 (PayPal)',
      description: '一次付费,永久使用',
      duration: '终身',
      features: ['所有高级功能', '优先支持', '终身免费更新']
    }
  }
}

Payment Flow

One-time Payment (Orders + Capture)

User selects plan → Create order → Redirect to PayPal authorization → 
Callback /api/payment/return/paypal → Server capture → 
Update order/subscription → Redirect to success page

Subscription Payment

User selects subscription → Create subscription → Redirect to PayPal authorization → 
Callback /api/payment/return/paypal?subscription=true → 
Active query subscription status (ACTIVE) → Update subscription → Success page

Webhook serves as eventual consistency (handling delays/cancellations/refunds/renewals).

Important Notes

  • PayPal supports multi-currency (USD, EUR, GBP, etc.)
  • Supports both one-time payment and subscription
  • Subscription requires Plan ID created in PayPal Dashboard
  • Callback URL must use HTTPS
  • Sandbox and Production environments are completely isolated
  • Webhook events may have delays in Sandbox environment

Back to Payment Configuration Overview

Stripe Configuration

Configure Stripe payment

WeChat Pay Configuration

Configure WeChat Pay

On this page

Setup StepsEnvironment VariablesOne-time vs SubscriptionOne-time Payment (Orders + Capture)Subscription PaymentSandbox TestingEnable SandboxSwitch to ProductionWebhook EventsPlan Configuration ExamplesSubscription PlanOne-time Payment (Lifetime)Payment FlowOne-time Payment (Orders + Capture)Subscription PaymentImportant Notes