Open ptmkenny opened 3 years ago
+1
+1
same here, anyone got this working in React ?
I still need this, I will start implementing tomorrow probably
From my understanding, you need to install @ionic-native/core
and @ionic-native/in-app-purchase-2
in addition to the plugin, then you can import it into React like so:
Disregard, I misread the Ionic documentation. While it technically works, the code in the comment below is the advised method.
import { InAppPurchase2 } from '@ionic-native/in-app-purchase-2/ngx'
const store = new InAppPurchase2()
import { InAppPurchase2 } from '@ionic-native/in-app-purchase-2'
InAppPurchase2.register([{id: 'toto', type :'...']);
Any of you guys successfully implement it? I cannot make the store fire the ready event. Also products are not loaded and can be purchased.
I did actually get this working. I'm using Ionic React v5 with Capacitor v3.
My store sells two subscriptions (monthly and annual) as IAPs. The backend is Drupal 9.
I am just cutting and pasting the code from my actual app below, minus the stuff that is unique to my site.
Hopefully it can give people some ideas.
index.tsx
You have to initialize the store at the root of your app. I only do this on mobile because I also have a PWA on my website that uses a different payment system.
import { IAPProduct, InAppPurchase2 } from '@ionic-native/in-app-purchase-2';
const startApp = () => {
ReactDOM.render(<App />, document.getElementById('root'));
};
if (isPlatformMobile()) {
const store = InAppPurchase2;
// Needed to use IAP + cordova plugins.
// Set debug messages.
// Default.
store.verbosity = store.QUIET;
// store.verbosity = store.DEBUG;
store.register([{
id: subMonthly,
type: store.PAID_SUBSCRIPTION,
}, {
id: subAnnual,
type: store.PAID_SUBSCRIPTION,
}]);
// Register event handlers for subscriptions.
// store.when(subMonthly).updated((product: IAPProduct) => {
// console.log(`Registered: ${JSON.stringify(product)}`);
// });
// store.when(subAnnual).updated((product: IAPProduct) => {
// console.log(`Registered: ${JSON.stringify(product)}`);
// });
// Updated
// store.when(subMonthly).updated((product: IAPProduct) => {
// console.log(`Updated${JSON.stringify(product)}`);
// });
// store.when(subAnnual).updated((product: IAPProduct) => {
// console.log(`Updated${JSON.stringify(product)}`);
// });
// Upon approval, verify the receipt.
store.when(subMonthly).approved((product: IAPProduct) => {
// console.log('DOING VERIFICATION MONTHLY');
product.verify();
});
store.when(subAnnual).approved((product: IAPProduct) => {
// console.log('DOING VERIFICATION ANNUAL');
product.verify();
});
// Upon receipt validation, mark the subscription as owned.
store.when(subMonthly).verified((product: IAPProduct) => {
// console.log('DOING FINISH MONTHLY');
product.finish();
// console.log('User now owns: ', product.title);
});
store.when(subAnnual).verified((product: IAPProduct) => {
// console.log('DOING FINISH ANNUAL');
product.finish();
// console.log('User now owns: ', product.title);
});
// https://billing-dashboard.fovea.cc/setup/cordova
store.validator = mySecretCode;
store.refresh();
// console.log('store', store);
startApp();
And here's my actual store page component:
const PageStoreApp: React.VFC<MyProps> = ({ pageTitle }: MyProps) => {
const store = InAppPurchase2;
const history = useHistory();
const [isLoading, setIsLoading] = useState(false);
const [showErrorAlert, setShowErrorAlert] = useState(false);
const [showCancelledAlert, setShowCancelledAlert] = useState(false);
const [showSuccessAlert, setShowSuccessAlert] = useState(false);
const [isVerifying, setIsVerifying] = useState(false);
const { userObject } = useContext(UserContext);
const queryClient = useQueryClient();
const monthly = store.get(subMonthly);
const annual = store.get(subAnnual);
const restorePurchases = () => {
setIsLoading(true);
store.refresh().finished(() => {
queryClient.invalidateQueries(queryKeyUseUser)
.then(() => {
debugLog('restorePurchases down, shutting off loading');
setIsLoading(false);
});
});
};
const buySub = (sub: IAPProduct) => {
const productId = sub.id;
setIsLoading(true);
debugLog('attempting to purchase ', productId);
const allProducts = [subMonthly, subAnnual];
if (allProducts.includes(productId)) {
// console.log('placing order for ', productId);
// Uuid must be set for processing by drupal.
store.applicationUsername = () => (userObject.id);
debugLog('setting application username', store.applicationUsername);
store.order(productId)
.then(() => {
debugLog('order placed', store.get(productId));
})
// Drupal should receive the new sub data.
.then(() => queryClient.invalidateQueries(queryKeyUseUser))
.error((error: Error) => {
debugLog('error purchased failed', error);
setShowErrorAlert(true);
});
} else {
const error = Error(`Product is invalid: ${productId}`);
}
};
// User closed the native purchase dialog
store.when(subMonthly).cancelled((product: IAPProduct) => {
debugLog('Purchase monthly was cancelled');
setIsLoading(false);
setShowCancelledAlert(true);
});
store.when(subAnnual).cancelled((product: IAPProduct) => {
debugLog('Purchase annual was Cancelled');
setIsLoading(false);
setShowCancelledAlert(true);
});
// Upon approval, show a different message.
store.when(subMonthly).approved((product: IAPProduct) => {
debugLog('monthly approved', product);
setIsVerifying(true);
});
store.when(subAnnual).approved((product: IAPProduct) => {
debugLog('annual approved', product);
setIsVerifying(true);
});
// Upon the subscription becoming owned.
store.when(subMonthly).finished((product: IAPProduct) => {
queryClient.invalidateQueries(queryKeyUseUser)
.then(() => setShowSuccessAlert(true));
});
store.when(subAnnual).finished((product: IAPProduct) => {
queryClient.invalidateQueries(queryKeyUseUser)
.then(() => setShowSuccessAlert(true));
});
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonButtons slot="start">
<IonBackButton />
</IonButtons>
<IonTitle>
{ pageTitle === ''
? <Trans id="page.store.title">My Store</Trans>
: pageTitle}
</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent className={classesPageWithBodyText}>
<p>Choose your subscription length.</p>
<p>Subscribe yearly and get two months free.</p>
{ isLoading && !isVerifying && (
<>
<p><Trans id="store.order.please_wait_processing">Please wait while we process your order...</Trans></p>
<IonButton
size="small"
onClick={() => {
setIsLoading(false);
}}
color="danger"
>
<Trans id="button.cancel">Cancel</Trans>
</IonButton>
</>
) }
{ isLoading && isVerifying && (
<>
<p><Trans id="store.order.verifying">Verifying order...</Trans></p>
<IonButton
size="small"
onClick={() => {
setIsVerifying(false);
setIsLoading(false);
}}
color="danger"
>
<Trans id="button.cancel">Cancel</Trans>
</IonButton>
</>
) }
{ !isLoading && !isVerifying && (
<>
<IonCard>
<IonCardContent>
<IonCardTitle>
{monthly.title}
</IonCardTitle>
<p>{monthly.description}</p>
<p>{monthly.price}</p>
<IonButton
size="small"
onClick={() => {
buySub(monthly);
}}
>
<Trans id="button.store.buy.monthly">
Buy a Monthly Subscription
</Trans>
</IonButton>
</IonCardContent>
</IonCard>
<IonCard>
<IonCardContent>
<IonCardTitle>
{annual.title}
</IonCardTitle>
<p>{annual.description}</p>
<p>{annual.price}</p>
<IonButton
size="small"
onClick={() => {
buySub(annual);
}}
>
<Trans id="button.store.buy.annual">
Buy an Annual Subscription
</Trans>
</IonButton>
</IonCardContent>
</IonCard>
<IonGridTwoItems
primary={(
<ButtonContact />
)}
secondary={(
<IonButton
size="small"
onClick={() => {
restorePurchases();
}}
>
<Trans id="button.store.restore_purchases">Restore Purchases</Trans>
</IonButton>
)}
/>
</>
) }
<IonAlert
isOpen={showErrorAlert}
onDidDismiss={() => setShowErrorAlert(false)}
message={t({ id: 'alert.purchase_failed', message: 'Your purchase could not be completed. Please try again.' })}
buttons={['OK']}
/>
<IonAlert
isOpen={showCancelledAlert}
onDidDismiss={() => setShowCancelledAlert(false)}
message={t({ id: 'alert.purchase_cancelled', message: 'Your purchase was cancelled. You have not been charged.' })}
buttons={['OK']}
/>
<IonAlert
isOpen={showSuccessAlert}
onDidDismiss={() => {
history.push(routeTabWelcome);
}}
message={t({ id: 'alert.purchase_success', message: 'Thanks for purchasing!' })}
buttons={['OK']}
/>
</IonContent>
</IonPage>
);
};
PageStoreApp.defaultProps = {
pageTitle: '',
};
export default PageStoreApp;
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I'm learning React and I've built an app in Ionic / Capacitor. Now I'm trying to use this plugin in my app, but I'm having a lot of trouble figuring out how to configure it. Does anyone have an example of implementing this in React?