Skip to content

Instantly share code, notes, and snippets.

@wktq
Last active Oct 19, 2021
Embed
What would you like to do?
import React, { useState, useEffect } from 'react';
import { Platform } from 'react-native';
import * as InAppPurchases from 'expo-in-app-purchases';
import * as Sentry from '@sentry/react-native';
const IAP_SKUS = Platform.select({
ios: [
'your_sku_alias',
],
android: [
'your_sku_alias',
],
});
export const IAPContext: React.Context<any> = React.createContext({
processing: false,
setProcessing: () => undefined,
getProducts: () => undefined,
});
export const useIap = (): void => React.useContext(IAPContext);
export const IAPManager = (props: any): JSX.Element => {
const [processing, setProcessing] = useState(false);
const processNewPurchase = async (purchase: InAppPurchases.InAppPurchase): Promise<void> => {
const { productId } = purchase;
// iOS
if (Platform.OS === 'ios') {
if (purchase.transactionReceipt) {
// ここにアイテム購入後のアプリ側の処理を書く(iOS)
}
}
// Android
if (Platform.OS === 'android') {
if (purchase.purchaseToken && productId) {
// ここにアイテム購入後のアプリ側の処理を書く(Android)
}
}
try {
// 購入後の処理
} catch (e) {
// 購入処理に失敗
setProcessing(false);
}
};
// 課金アイテムを取得
const getProducts = async (): Promise<InAppPurchases.IAPItemDetails[] | undefined> => {
const { responseCode, results } = await InAppPurchases.getProductsAsync(IAP_SKUS as string[]);
if (responseCode === InAppPurchases.IAPResponseCode.OK) {
return results;
}
return [];
};
// 初期化とリスナーの作成
const initIAPandEventListeners = async (): Promise<void> => {
try {
await InAppPurchases.connectAsync();
} catch (e) { /* すでにストアに接続されている場合 */ }
// 購入リスナー
InAppPurchases.setPurchaseListener(async ({ responseCode, results, errorCode }) => {
if (responseCode === InAppPurchases.IAPResponseCode.OK) {
if (results === undefined) return;
// 購入成功
await Promise.all(
results.map(async (purchase) => {
await processNewPurchase(purchase);
InAppPurchases.finishTransactionAsync(purchase, true);
}),
);
} else if (responseCode === InAppPurchases.IAPResponseCode.USER_CANCELED) {
Sentry.captureMessage('ユーザーがトランザクションを途中キャンセルしました', Sentry.Severity.Log);
} else if (responseCode === InAppPurchases.IAPResponseCode.DEFERRED) {
// iOSのみ
Sentry.captureMessage('保護者の承認が必要です', Sentry.Severity.Log);
} else {
Sentry.captureMessage(`購入中にエラーが発生しました エラーコード: ${errorCode}`, Sentry.Severity.Log);
}
setProcessing(false);
});
};
useEffect(() => {
initIAPandEventListeners();
}, []);
const { children } = props;
return (
<IAPContext.Provider value={{
processing,
setProcessing,
getProducts,
}}
>
{children}
</IAPContext.Provider>
);
};
export default IAPManager;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment