Skip to content

Commit f73a491

Browse files
authored
Add sandbox agnostic receipt verification (#1228)
1 parent 7ee92fd commit f73a491

File tree

1 file changed

+51
-16
lines changed

1 file changed

+51
-16
lines changed

index.ts

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ export const finishTransaction = (
649649
} else if (
650650
purchase.userIdAmazon ||
651651
(!purchase.isAcknowledgedAndroid &&
652-
purchase.purchaseStateAndroid === PurchaseStateAndroid.PURCHASED)
652+
purchase.purchaseStateAndroid === PurchaseStateAndroid.PURCHASED)
653653
) {
654654
return myRNIapModule.acknowledgePurchase(
655655
purchase.purchaseToken,
@@ -768,6 +768,47 @@ export const buyPromotedProductIOS = (): Promise<void> =>
768768
android: async () => Promise.resolve(),
769769
})();
770770

771+
const fetchJsonOrThrow = async (url: string, receiptBody: Record<string, unknown>,
772+
): Promise<Apple.ReceiptValidationResponse | false> => {
773+
const response = await fetch(url, {
774+
method: 'POST',
775+
headers: new Headers({
776+
Accept: 'application/json',
777+
'Content-Type': 'application/json',
778+
}),
779+
body: JSON.stringify(receiptBody),
780+
});
781+
782+
if (!response.ok) {
783+
throw Object.assign(new Error(response.statusText), {
784+
statusCode: response.status,
785+
});
786+
}
787+
788+
return response.json();
789+
};
790+
791+
const requestAgnosticReceiptValidationIos = async (receiptBody: Record<string, unknown>,
792+
): Promise<Apple.ReceiptValidationResponse | false> => {
793+
const response = await fetchJsonOrThrow(
794+
'https://buy.itunes.apple.com/verifyReceipt',
795+
receiptBody,
796+
);
797+
798+
// Best practice is to check for test receipt and check sandbox instead
799+
// https://developer.apple.com/documentation/appstorereceipts/verifyreceipt
800+
if (response && response.status === Apple.ReceiptValidationStatus.TEST_RECEIPT) {
801+
const response = await fetchJsonOrThrow(
802+
'https://sandbox.itunes.apple.com/verifyReceipt',
803+
receiptBody,
804+
);
805+
806+
return response;
807+
}
808+
809+
return response;
810+
};
811+
771812
/**
772813
* Buy products or subscriptions with offers (iOS only)
773814
*
@@ -807,26 +848,20 @@ export const validateReceiptIos = async (
807848
receiptBody: Record<string, unknown>,
808849
isTest?: boolean,
809850
): Promise<Apple.ReceiptValidationResponse | false> => {
851+
if (isTest == null) {
852+
return await requestAgnosticReceiptValidationIos(receiptBody);
853+
}
854+
810855
const url = isTest
811856
? 'https://sandbox.itunes.apple.com/verifyReceipt'
812857
: 'https://buy.itunes.apple.com/verifyReceipt';
813858

814-
const response = await fetch(url, {
815-
method: 'POST',
816-
headers: new Headers({
817-
Accept: 'application/json',
818-
'Content-Type': 'application/json',
819-
}),
820-
body: JSON.stringify(receiptBody),
821-
});
822-
823-
if (!response.ok) {
824-
throw Object.assign(new Error(response.statusText), {
825-
statusCode: response.status,
826-
});
827-
}
859+
const response = await fetchJsonOrThrow(
860+
url,
861+
receiptBody,
862+
);
828863

829-
return response.json();
864+
return response;
830865
};
831866

832867
/**

0 commit comments

Comments
 (0)