@kchdully/react-native-iap
Version:
React Native In App Purchase Module.
197 lines (186 loc) • 6.65 kB
text/typescript
export enum ErrorCode {
E_UNKNOWN = 'E_UNKNOWN',
E_USER_CANCELLED = 'E_USER_CANCELLED',
E_USER_ERROR = 'E_USER_ERROR',
E_ITEM_UNAVAILABLE = 'E_ITEM_UNAVAILABLE',
E_REMOTE_ERROR = 'E_REMOTE_ERROR',
E_NETWORK_ERROR = 'E_NETWORK_ERROR',
E_SERVICE_ERROR = 'E_SERVICE_ERROR',
E_RECEIPT_FAILED = 'E_RECEIPT_FAILED',
E_RECEIPT_FINISHED_FAILED = 'E_RECEIPT_FINISHED_FAILED',
E_NOT_PREPARED = 'E_NOT_PREPARED',
E_NOT_ENDED = 'E_NOT_ENDED',
E_ALREADY_OWNED = 'E_ALREADY_OWNED',
E_DEVELOPER_ERROR = 'E_DEVELOPER_ERROR',
E_BILLING_RESPONSE_JSON_PARSE_ERROR = 'E_BILLING_RESPONSE_JSON_PARSE_ERROR',
E_DEFERRED_PAYMENT = 'E_DEFERRED_PAYMENT',
E_INTERRUPTED = 'E_INTERRUPTED',
E_IAP_NOT_AVAILABLE = 'E_IAP_NOT_AVAILABLE',
E_PURCHASE_ERROR = 'E_PURCHASE_ERROR',
E_SYNC_ERROR = 'E_SYNC_ERROR',
E_TRANSACTION_VALIDATION_FAILED = 'E_TRANSACTION_VALIDATION_FAILED',
E_ACTIVITY_UNAVAILABLE = 'E_ACTIVITY_UNAVAILABLE',
E_ALREADY_PREPARED = 'E_ALREADY_PREPARED',
E_PENDING = 'E_PENDING',
E_CONNECTION_CLOSED = 'E_CONNECTION_CLOSED',
}
/**
* Platform-specific error code mappings
* Maps ErrorCode enum values to platform-specific integer codes
*/
export const ErrorCodeMapping = {
ios: {
[ ]: 0,
[ ]: 1,
[ ]: 2,
[ ]: 3,
[ ]: 4,
[ ]: 5,
[ ]: 6,
[ ]: 7,
[ ]: 8,
[ ]: 9,
[ ]: 10,
[ ]: 11,
[ ]: 12,
[ ]: 13,
[ ]: 14,
[ ]: 15,
[ ]: 16,
[ ]: 17,
[ ]: 18,
[ ]: 19,
[ ]: 20,
[ ]: 21,
[ ]: 22,
[ ]: 23,
},
android: {
[ ]: 'E_UNKNOWN',
[ ]: 'E_USER_CANCELLED',
[ ]: 'E_USER_ERROR',
[ ]: 'E_ITEM_UNAVAILABLE',
[ ]: 'E_REMOTE_ERROR',
[ ]: 'E_NETWORK_ERROR',
[ ]: 'E_SERVICE_ERROR',
[ ]: 'E_RECEIPT_FAILED',
[ ]: 'E_RECEIPT_FINISHED_FAILED',
[ ]: 'E_NOT_PREPARED',
[ ]: 'E_NOT_ENDED',
[ ]: 'E_ALREADY_OWNED',
[ ]: 'E_DEVELOPER_ERROR',
[ ]:
'E_BILLING_RESPONSE_JSON_PARSE_ERROR',
[ ]: 'E_DEFERRED_PAYMENT',
[ ]: 'E_INTERRUPTED',
[ ]: 'E_IAP_NOT_AVAILABLE',
[ ]: 'E_PURCHASE_ERROR',
[ ]: 'E_SYNC_ERROR',
[ ]:
'E_TRANSACTION_VALIDATION_FAILED',
[ ]: 'E_ACTIVITY_UNAVAILABLE',
[ ]: 'E_ALREADY_PREPARED',
[ ]: 'E_PENDING',
[ ]: 'E_CONNECTION_CLOSED',
},
} as const;
export class PurchaseError implements Error {
constructor(
public name: string,
public message: string,
public responseCode?: number,
public debugMessage?: string,
public code?: ErrorCode,
public productId?: string,
public platform?: 'ios' | 'android',
) {
this.name = '[react-native-iap]: PurchaseError';
this.message = message;
this.responseCode = responseCode;
this.debugMessage = debugMessage;
this.code = code;
this.productId = productId;
this.platform = platform;
}
/**
* Creates a PurchaseError from platform-specific error data
* @param errorData Raw error data from native modules
* @param platform Platform where the error occurred
* @returns Properly typed PurchaseError instance
*/
static fromPlatformError(
errorData: any,
platform: 'ios' | 'android',
): PurchaseError {
const errorCode = errorData.code
? ErrorCodeUtils.fromPlatformCode(errorData.code, platform)
: ErrorCode.E_UNKNOWN;
return new PurchaseError(
'[react-native-iap]: PurchaseError',
errorData.message || 'Unknown error occurred',
errorData.responseCode,
errorData.debugMessage,
errorCode,
errorData.productId,
platform,
);
}
/**
* Gets the platform-specific error code for this error
* @returns Platform-specific error code
*/
getPlatformCode(): string | number | undefined {
if (!this.code || !this.platform) return undefined;
return ErrorCodeUtils.toPlatformCode(this.code, this.platform);
}
}
/**
* Utility functions for error code mapping and validation
*/
export const ErrorCodeUtils = {
/**
* Maps a platform-specific error code back to the standardized ErrorCode enum
* @param platformCode Platform-specific error code (string for Android, number for iOS)
* @param platform Target platform
* @returns Corresponding ErrorCode enum value or E_UNKNOWN if not found
*/
fromPlatformCode: (
platformCode: string | number,
platform: 'ios' | 'android',
): ErrorCode => {
const mapping = ErrorCodeMapping[platform];
for (const [errorCode, mappedCode] of Object.entries(mapping)) {
if (mappedCode === platformCode) {
return errorCode as ErrorCode;
}
}
return ErrorCode.E_UNKNOWN;
},
/**
* Maps an ErrorCode enum to platform-specific code
* @param errorCode ErrorCode enum value
* @param platform Target platform
* @returns Platform-specific error code
*/
toPlatformCode: (
errorCode: ErrorCode,
platform: 'ios' | 'android',
): string | number => {
return (
ErrorCodeMapping[platform][errorCode] ??
(platform === 'ios' ? 0 : 'E_UNKNOWN')
);
},
/**
* Checks if an error code is valid for the specified platform
* @param errorCode ErrorCode enum value
* @param platform Target platform
* @returns True if the error code is supported on the platform
*/
isValidForPlatform: (
errorCode: ErrorCode,
platform: 'ios' | 'android',
): boolean => {
return errorCode in ErrorCodeMapping[platform];
},
};