Wrapply logoWrapply Tutorials
💳 Store payments

Intégration des achats in-app : du site web à l'app Flutter

Ce guide explique comment préparer les achats in-app natifs dans une app Wrapply : produits store, product IDs, appels d’achat, restauration et validation des reçus côté backend.

Commandes bridge pour les achats in-app

Lorsque le module d'achats in-app est activé, l'app générée expose de vraies commandes JavaScript dans la WebView. Le site les appelle, puis le backend doit vérifier l'achat avant de débloquer la fonction payante.

CommandeUsagePayloadRéponse typique
window.Wrapply.iap.getProducts(payload)Lit les produits configurés dans Google Play ou App Store{ productIds: ['premium_monthly'] }{ ok, available, products, notFoundIds }
window.Wrapply.iap.purchase(payload)Lance le flux d'achat natif{ productId, consumable, applicationUserName }{ ok, purchaseStarted, product }
window.Wrapply.iap.restorePurchases(payload)Restaure les achats non consommables ou abonnements{ applicationUserName }{ ok, restoreStarted, latestPurchases }
window.Wrapply.iap.getStatus(payload)Vérifie si le billing store est disponible et lit les derniers événements{}{ ok, available, latestPurchases }

Configuration requise dans les stores

Créez les produits dans Google Play Console et App Store Connect avec les mêmes product IDs que ceux utilisés par le site. Testez sur appareils réels et validez les reçus côté serveur avant de débloquer abonnements, crédits ou contenu premium.

function onWrapplyReady(callback) {
if (window.Wrapply?.__nativeBridgeReady) return callback(window.Wrapply);
window.addEventListener('wrapplyNativeBridgeReady', () => callback(window.Wrapply), { once: true });
}

onWrapplyReady(async (Wrapply) => {
if (!Wrapply.iap) return;
const products = await Wrapply.iap.getProducts({ productIds: ['premium_monthly', 'credits_10'] });
console.log(products);
});
async function buyPremium(currentUser) {
if (!window.Wrapply?.iap) return showWebCheckoutFallback();
const result = await window.Wrapply.iap.purchase({
productId: 'premium_monthly',
consumable: false,
applicationUserName: currentUser.id
});
await fetch('/api/iap/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(result)
});
}
async function restoreNativePurchases(currentUser) {
if (!window.Wrapply?.iap) return;
const restored = await window.Wrapply.iap.restorePurchases({
applicationUserName: currentUser.id
});
await fetch('/api/iap/restore', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(restored)
});
}

Exemples d'intégration

Vous pouvez utiliser le même pattern bridge en JavaScript, React, Vue, Angular, PHP/Laravel, WordPress ou jQuery. L'important est d'attendre le bridge natif avant de l'appeler.

JavaScript

async function runNativeFeature(currentUser) {
if (!window.Wrapply?.iap) return;
const result = await window.Wrapply.iap.purchase({
productId: 'premium_monthly',
consumable: false,
applicationUserName: currentUser.id
});
await fetch('/api/wrapply-event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(result)
});
}

Hook React

import { useEffect, useState } from 'react';
export function useWrapplyBridge() {
const [ready, setReady] = useState(false);
useEffect(() => {
if (window.Wrapply?.__nativeBridgeReady) return setReady(true);
const onReady = () => setReady(true);
window.addEventListener('wrapplyNativeBridgeReady', onReady);
return () => window.removeEventListener('wrapplyNativeBridgeReady', onReady);
}, []);
return { ready, Wrapply: ready ? window.Wrapply : null };
}

Composable Vue

import { ref, onMounted } from 'vue';
export function useWrapplyBridge() {
const ready = ref(false);
onMounted(() => {
if (window.Wrapply?.__nativeBridgeReady) ready.value = true;
else window.addEventListener('wrapplyNativeBridgeReady', () => ready.value = true, { once: true });
});
return { ready };
}

Service Angular

@Injectable({ providedIn: 'root' })
export class WrapplyBridgeService {
async callNative(payload = {}) {
if (!window.Wrapply?.iap) return { ok: false, error: 'Bridge unavailable' };
return window.Wrapply.iap.getStatus(payload);
}
}

jQuery

$('#wrapply-action').on('click', async function () {
if (!window.Wrapply?.iap) return;
const result = await window.Wrapply.iap.getStatus({});
$('#wrapply-output').text(JSON.stringify(result, null, 2));
});

CMS / template backend

<button onclick="runNativeFeature(window.currentUser)">Open app feature</button>
<script>
window.addEventListener('wrapplyNativeBridgeReady', function () {
document.body.classList.add('wrapply-native-app');
});
</script>
Important : le bridge fonctionne dans la WebView de l'app générée, pas dans la version publique du site ouverte dans un navigateur.
Lorsque les fonctions natives sont activées, le ZIP généré inclut aussi WRAPPLY_NATIVE_BRIDGE_GUIDE.pdf avec modules actifs, appels exacts et notes d'implémentation.