# Web APIs Bridge

> Which standard browser APIs work inside the app, and which need the native bridge instead.

- **Applies to:** AppMint and Appwright
- **Source:** the Integration Guide shipped inside the app; this page is generated from it.
- **HTML:** https://freewebtoapk.com/docs/web-apis-bridge

Native Polyfills for Notifications, Share, Clipboard & More

### 1. What are Web API Bridges?

Android WebView doesn't support several modern Web APIs that Chrome does. Your generated app automatically polyfills these APIs so websites work just like they do in Chrome:

✅ Web Notifications (Notification API)  
✅ Web Share (navigator.share)  
✅ Clipboard (navigator.clipboard)  
✅ window.close()  
✅ target="_blank" links & window.open()

No setup needed - these work automatically in every generated app.

### 2. Web Notifications

Websites that use Notification.requestPermission() and new Notification() will show real Android notifications.

- On Android 13+, the user gets a system permission dialog
- On Android 12 and below, notifications are allowed by default
- Tapping a notification opens the app
- The 'tag' option replaces previous notifications (matches Web spec)

```
// Your website JS — works the same as in Chrome:
Notification.requestPermission().then(function(result) {
  if (result === 'granted') {
    new Notification('Hello!', {
      body: 'This is a native Android notification',
      tag: 'my-notif'
    });
  }
});
```

### 3. Web Share API

navigator.share() opens the Android native share sheet, letting users share content to WhatsApp, Telegram, email, etc.

- Supports title, text, and url
- navigator.canShare() returns true
- Works exactly like Chrome's share dialog

```
// Share content from your website:
navigator.share({
  title: 'Check this out',
  text: 'Amazing content!',
  url: 'https://example.com/page'
});
```

### 4. Clipboard API

navigator.clipboard.writeText() and readText() are bridged to Android's native clipboard.

- writeText() copies text to system clipboard
- readText() reads from system clipboard
- Both return Promises (matching the Web spec)

```
// Copy to clipboard:
await navigator.clipboard.writeText('Hello World');

// Read from clipboard:
const text = await navigator.clipboard.readText();
```

### 5. window.close() & target="_blank"

Two common WebView gaps are also fixed:

- window.close() - closes/finishes the app activity (useful for payment/auth callback pages)
- target="_blank" links - load inside the WebView instead of being silently dropped
- window.open() calls - handled the same way

No website changes needed - these just work.

### 6. Domain Matching for External Links

When 'External Links → Open in Browser' is set, the app intelligently matches domains:

- google.com and www.google.com are treated as the same domain
- Only truly different domains open in Chrome
- Redirects within the same site stay in the WebView

This prevents the issue where a site like google.com redirects to www.google.com and accidentally opens in Chrome.

### 7. UPI & Payment App Links (Razorpay, GPay, PhonePe, Paytm)

Any link whose scheme isn't a web page automatically opens the Android app that owns it - no setup, no scheme list to configure:

- upi://pay - generic UPI intent (the user picks their UPI app)
- paytmmp:// (Paytm), phonepe://, tez:// (Google Pay), gpay://
- tel:, mailto:, sms:, whatsapp://, tg://, intent://

This works everywhere a page can navigate:  
✅ A tapped <a href="upi://pay?..."> link  
✅ A JS redirect (window.location.href = 'upi://...')  
✅ A popup - window.open('paytmmp://...') - which is how Razorpay Checkout hands off to UPI apps

So Razorpay / Cashfree / PhonePe checkout pages work as-is: the customer taps a UPI option, the payment app opens, they approve, and your page's success handler fires when they return. If no app on the phone can handle the scheme, the user sees a clear toast instead of a blank error page.

⚠️ Selling DIGITAL goods in a Play Store app? Google requires Play Billing for those - use the IAP guide instead. UPI/card checkout is for physical goods, services, and apps distributed outside Play.

```
<!-- Simplest form — a plain UPI intent link. The user's phone
     shows every installed UPI app (GPay/PhonePe/Paytm/BHIM): -->
<a href="upi://pay?pa=merchant@bank&pn=MyStore&am=99.00&cu=INR&tn=Order%20123">
  Pay ₹99 via UPI
</a>
```

### 8. Complete Example - Razorpay Checkout with UPI, End to End

A full, copy-pasteable flow using Razorpay Checkout. What happens on the phone:

1. Customer taps 'Pay ₹499' → Razorpay Checkout opens in the page
2. Customer picks UPI → their UPI app opens automatically (this is the paytmmp:// / phonepe:// hand-off the app handles for you)
3. Customer approves in the UPI app and returns - Android brings your app back on its own
4. The handler function fires with a payment ID → show your success screen
5. dismiss fires if they cancel → let them retry

Replace rzp_test_XXXXXXXX with your key from dashboard.razorpay.com. Test with a key_test key first - Razorpay's test mode simulates UPI approval.

⚠️ For a real store, confirm the payment server-side (Razorpay webhook or Orders API + signature check) before shipping goods - the browser-side handler alone can be faked.

```
<!doctype html>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>

<h2>Premium Plan — ₹499</h2>
<button id="payBtn">Pay ₹499</button>
<p id="result"></p>

<script>
document.getElementById('payBtn').onclick = function () {
  var rzp = new Razorpay({
    key: 'rzp_test_XXXXXXXX',      // your Razorpay Key ID
    amount: 49900,                  // paise — ₹499.00
    currency: 'INR',
    name: 'My Store',
    description: 'Premium Plan',
    prefill: { contact: '', email: '' },
    theme: { color: '#2563eb' },

    // Fires after the customer returns from their UPI app
    handler: function (response) {
      document.getElementById('result').textContent =
        '✅ Paid! Payment ID: ' + response.razorpay_payment_id;
      // Real store: send response.razorpay_payment_id to your
      // server / webhook flow and verify before unlocking anything.
    },

    modal: {
      ondismiss: function () {
        document.getElementById('result').textContent =
          'Payment cancelled — tap Pay to try again.';
      }
    }
  });
  rzp.open();
};
</script>
```

