react-native-iap prorationModeAndroid DEFERRED 오류

지리·2023년 4월 17일
0

오류메세지

purchase is not suitable to be purchased

버전
react-native-iap v12.10.2

문제 상황

안드로이드 구독 변경시에 prorationModeAndroid가 DERERRED인 경우 purchase is not suitable to be purchased 란 오류 메세지가 떴다. 구글의 구매 내역을 보면 정상적으로 구독변경이 되고 있는 상태였다.

async function purchaseSubscription(purchaseTokenAndroid) {
	const sku = item.productId;
	const offerToken = item.subscriptionOfferDetails?.[0]?.offerToken;

	await requestSubscription({
	sku,
	...(offerToken && {subscriptionOffers: [{sku, offerToken}]}),
	purchaseTokenAndroid,
	prorationModeAndroid:4,

	// IMMEDIATE_WITH_TIME_PRORATION = 1,
	// IMMEDIATE_AND_CHARGE_PRORATED_PRICE = 2,
	// IMMEDIATE_WITHOUT_PRORATION = 3,
	// DEFERRED = 4,
	// IMMEDIATE_AND_CHARGE_FULL_PRICE = 5,
	// UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY = 0
	
	});
}
let purchaseUpdateSubscription = purchaseUpdatedListener(async purchase => {
	const receipt = purchase.transactionReceipt;
	
	if (receipt) {
	
		//서버로 구매 데이터 전송
		
		await finishTransaction({
			purchase,
			isConsumable: false,
		});
	}
});

finishTranscation을 보면 android에서 purchase의 purchaseToken이 없거나 !purchase.isAcknowledgedAndroid && purchase.purchaseStateAndroid === PurchaseStateAndroid.PURCHASED이 아닐 경우 이 오류를 반환한다.

//finishTransction

android: async () => {
	if (purchase?.purchaseToken) {
		if (isConsumable) {
			return getAndroidModule().consumeProduct(
			purchase.purchaseToken,
			developerPayloadAndroid,
			);
		} else if (
			purchase.userIdAmazon ||
			(!purchase.isAcknowledgedAndroid &&
			purchase.purchaseStateAndroid === PurchaseStateAndroid.PURCHASED)
		) {
			return getAndroidModule().acknowledgePurchase(
			purchase.purchaseToken,
			developerPayloadAndroid,
			);
		} else {
			return Promise.reject(
			new Error('purchase is not suitable to be purchased'),
			);
		}
	}
	return Promise.reject(
		new Error('purchase is not suitable to be purchased'),
	);
},

구글 문서를 보면 prorationModeAndroid:DEFERRED인 경우 지연된 대체 모드로 purchaseUpdatedListener에서 대체가 적용될 때까지 변경 전 요금제의 purchase를 반환한다고 되어있다.

구글에서는 권장하는 방식은linkedPurchaseToken을 이용하여 Purchases.subscriptions:acknowledge로 백엔드에서 구매 확인을 하는 방식으로 DEFERRED인경우 finishTransction으로 구매 확인을 하는게 아니라 백엔드에서 구매 확인을 하고 try/catch를 이용해 에러를 처리해주었다!

해결

let purchaseUpdateSubscription = purchaseUpdatedListener(async purchase => {
	const receipt = purchase.transactionReceipt;
	
	if (receipt) {
	
		//서버로 구매 데이터 전송
		
		try{
			await finishTransaction({
				purchase,
				isConsumable: false,
			});
		}catch(e){
		
		}
	}
});
profile
공부한것들, 경험한 것들을 기록하려 노력합니다✨

0개의 댓글