The Payment That Could Never Work
I was testing my SaaS payment flow end-to-end. PayPal business account approved, subscription plans created, webhook registered, buttons on the website. Everything looked perfect. Time to test a real payment: I clicked "Subscribe," logged into my personal PayPal, selected a payment method, clicked "Pay Now" — and got an error. Not a declined card. Not a technical error. Just a flat refusal.
After digging through PayPal's documentation and community forums, I found the answer: Chinese PayPal accounts cannot send payments to other Chinese PayPal business accounts. It's a regulatory restriction, not a bug. My test was doomed from the start — I was a Chinese account holder trying to pay another Chinese account holder, and PayPal's rules for China simply don't allow it.
The PayPal China Restriction Explained
PayPal operates in China under a specific set of rules imposed by Chinese financial regulations. One of the most impactful restrictions for SaaS founders and indie hackers is:
PayPal accounts registered with a Chinese billing address cannot make payments to PayPal business accounts that are also registered in China.
This means:
- ✅ Chinese buyer → US seller: Works
- ✅ US buyer → Chinese seller: Works
- ❌ Chinese buyer → Chinese seller: Blocked
This isn't about currency or language settings. It's about the billing address registered on the PayPal account. If both sender and recipient have Chinese billing addresses, the transaction is refused regardless of the currency or amount.
Why This Matters for SaaS Founders
If you're a Chinese developer building a SaaS product and you set up a Chinese PayPal business account to receive payments, you face a fundamental problem:
- You can't test your own payment flow. Your personal PayPal (Chinese) can't pay your business PayPal (Chinese). Ever. There's no workaround within PayPal's system.
- You lose the entire Chinese domestic market. Chinese customers can't pay you through PayPal, period.
- Your target market must be overseas. The only people who can pay you are non-Chinese PayPal users.
This actually has a silver lining: it forces you to build for the global market from day one, which is often a better strategy for SaaS anyway. But it's crucial to understand this constraint before you waste time trying to test payments that will never work.
How to Test Your Payment Flow Without a Real Payment
Since you can't test with real money, here are the approaches that work:
Method 1: PayPal Sandbox (Recommended for Development)
PayPal provides a full sandbox environment at developer.paypal.com:
- Go to PayPal Developer Dashboard → Sandbox → Accounts
- Create a sandbox Personal account (buyer) and Business account (seller)
- Set both sandbox accounts to US billing addresses
- Use sandbox API credentials in your app
- Test the full payment flow — sandbox transactions behave exactly like real ones
Method 2: Simulated Webhook Testing
You can simulate PayPal webhook events to test your payment processing logic without any actual payment:
import json, requests
# Simulate a PAYMENT.SALE.COMPLETED webhook
webhook_payload = {
"id": "WH-TEST-12345",
"event_type": "PAYMENT.SALE.COMPLETED",
"resource": {
"id": "SALE-TEST-001",
"amount": {"total": "23.99", "currency": "USD"},
"custom": json.dumps({"username": "testuser", "plan": "monthly"}),
"create_time": "2026-07-18T00:00:00Z"
}
}
# Send to your webhook endpoint
response = requests.post(
"https://your-server.com/webhook",
json=webhook_payload,
headers={"Content-Type": "application/json"}
)
print(f"Webhook response: {response.status_code}")
This lets you verify that your webhook handler correctly processes payments, creates accounts, and sends notifications — all without real money changing hands.
Method 3: Ask a Non-Chinese Friend
If you know someone outside China with a PayPal account, ask them to make a small test payment ($1). You can refund it immediately. This is the only way to test the real live payment flow with actual PayPal infrastructure.
Browser Issues: The Incognito Trap
Even when testing with sandbox or a friend's account, there's another gotcha: browser cookies.
If you've ever logged into your Chinese PayPal account in your browser, PayPal remembers. When you try to test a payment (even with a different account), PayPal may auto-fill your Chinese account or apply China-specific restrictions based on your cookies. This leads to confusing situations where:
- The payment button works in one browser but not another
- You see different payment options than expected
- PayPal shows your Chinese account as the default, which then gets blocked
Solution: Always test in an incognito/private window. This ensures a clean session with no cached PayPal cookies.
Setting Up PayPal Subscriptions: The Complete Flow
For reference, here's the complete subscription setup that works (for non-Chinese customers):
Step 1: Create a Subscription Plan
curl -X POST https://api-m.paypal.com/v1/billing/plans \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ACCESS_TOKEN" \
-d '{
"product_id": "YOUR_PRODUCT_ID",
"name": "Monthly Plan",
"billing_cycles": [{
"frequency": {"interval_unit": "MONTH", "interval_count": 1},
"tenure_type": "REGULAR",
"sequence": 1,
"total_cycles": 0,
"pricing_scheme": {
"fixed_price": {"value": "23.99", "currency_code": "USD"}
}
}],
"payment_preferences": {
"auto_bill_outstanding": true,
"payment_failure_threshold": 3
}
}'
Step 2: Create Subscribe Buttons
Use the direct plan link instead of the JavaScript SDK (which can be blocked by ad blockers or in certain regions):
<!-- Direct plan link (always works) -->
<a href="https://www.paypal.com/webapps/billing/plans/subscribe?plan_id=YOUR_PLAN_ID"
style="display:inline-block;background:#0070ba;color:#fff;padding:12px 30px;
border-radius:6px;text-decoration:none;font-weight:600;">
Subscribe
</a>
Step 3: Register Webhook
curl -X POST https://api-m.paypal.com/v1/notifications/webhooks \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ACCESS_TOKEN" \
-d '{
"url": "https://your-server.com/webhook",
"event_types": [
{"name": "PAYMENT.SALE.COMPLETED"},
{"name": "BILLING.SUBSCRIPTION.ACTIVATED"},
{"name": "BILLING.SUBSCRIPTION.CANCELLED"}
]
}'
Step 4: Handle Webhook in Your Application
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def paypal_webhook():
event = request.json
event_type = event.get('event_type')
if event_type == 'PAYMENT.SALE.COMPLETED':
custom = json.loads(event['resource'].get('custom', '{}'))
username = custom.get('username')
plan = custom.get('plan')
# Provision the customer's account
provision_customer(username, plan)
# Send welcome email
send_welcome_email(username, plan)
elif event_type == 'BILLING.SUBSCRIPTION.CANCELLED':
custom = json.loads(event['resource'].get('custom', '{}'))
username = custom.get('username')
suspend_customer(username)
return jsonify({"status": "ok"}), 200
Alternative Payment Methods for Chinese SaaS Founders
If PayPal's China restriction is a dealbreaker, consider these alternatives:
| Platform | Pros | Cons |
|---|---|---|
| Stripe | Best developer experience, supports subscriptions | Not available in China — need a US/HK entity |
| Paddle | Handles tax compliance, supports China sellers | 5% + $0.50 per transaction, approval process |
| Lemon Squeezy | Easy setup, good for digital products | Tax verification can be slow for Chinese businesses |
| Gumroad | Simple, no monthly fee | 8.5% fee, limited subscription features |
| Cryptocurrency | No geographic restrictions | Volatility, limited mainstream adoption |
My approach: PayPal works fine as long as your customers are outside China. For a SaaS targeting global developers, PayPal covers 80%+ of your potential market. Don't let the China restriction stop you — it actually forces you to think globally, which is where the real money is.
Conclusion
The PayPal China restriction is a hard wall: Chinese buyers can't pay Chinese sellers, period. There's no workaround within PayPal. Accept this constraint early, build for the global market, and use sandbox or simulated webhooks for testing. And always test in incognito mode — PayPal's cookies will mess with your results.