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){
}
}
});