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.
| Commande | Usage | Payload | Ré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.
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);
});
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)
});
}
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
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
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
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
export class WrapplyBridgeService {
async callNative(payload = {}) {
if (!window.Wrapply?.iap) return { ok: false, error: 'Bridge unavailable' };
return window.Wrapply.iap.getStatus(payload);
}
}
jQuery
if (!window.Wrapply?.iap) return;
const result = await window.Wrapply.iap.getStatus({});
$('#wrapply-output').text(JSON.stringify(result, null, 2));
});
CMS / template backend
<script>
window.addEventListener('wrapplyNativeBridgeReady', function () {
document.body.classList.add('wrapply-native-app');
});
</script>