Files
awesome-cordova-plugins/src/@awesome-cordova-plugins/plugins/in-app-purchase-3/index.ts
T
gxolin b20c67bf14 feat(in-app-purchase-3) new InAppPurchase3 plugin fixed (#4873)
* fix(in-app-purchase-3) typings and doc

* update return type for initialize
2024-11-14 14:25:32 +01:00

1260 lines
36 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Cordova, CordovaProperty, AwesomeCordovaNativePlugin, Plugin } from '@awesome-cordova-plugins/core';
import { Injectable } from '@angular/core';
export interface IAPAdapter {
id: Platform;
name: string;
ready: boolean;
products: IAPProduct[];
receipts: IAPReceipt[];
isSupported: boolean;
initialize(): Promise<IAPError | undefined>;
loadProducts(products: IAPProductOptions[]): Promise<(IAPProduct | IAPError)[]>;
loadReceipts(): Promise<IAPReceipt[]>;
supportsParallelLoading: boolean;
order(offer: IAPOffer, additionalData: IAPAdditionalData): Promise<IAPError | undefined>;
finish(transaction: IAPTransaction): Promise<IAPError | undefined>;
receiptValidationBody(receipt: IAPReceipt): Promise<object | undefined>;
handleReceiptValidationResponse(receipt: IAPReceipt, response: object): Promise<void>;
requestPayment(
payment: PaymentRequest,
additionalData?: IAPAdditionalData
): Promise<IAPError | IAPTransaction | undefined>;
manageSubscriptions(): Promise<IAPError | undefined>;
manageBilling(): Promise<IAPError | undefined>;
checkSupport(functionality: string): boolean;
restorePurchases(): Promise<IAPError | undefined>;
}
export interface IAPProductOptions {
id: string;
/** @see {@link ProductType} */
type: string;
/** @see {@link Platform} */
platform: string;
group?: string;
}
/**
* Data to attach to a transaction.
* @see {@link IAPOffer.order}
* @see {@link InAppPurchase3.requestPayment}
*/
export interface IAPAdditionalData {
/** The application's user identifier, will be obfuscated with md5 to fill `accountId` if necessary */
applicationUsername?: string;
/** GooglePlay specific additional data. See cordova-plugin-purchase documentation.*/
googlePlay?: object;
/** Braintree specific additional data. See cordova-plugin-purchase documentation.*/
braintree?: object;
/** Apple AppStore specific additional data. See cordova-plugin-purchase documentation.*/
appStore?: object;
}
export type Callback<T> = (t: T) => void;
export interface IAPProduct {
platform: Platform;
type: ProductType;
id: string;
offers: IAPOffer[];
title: string;
description: string;
group?: string;
pricing: IAPPricingPhase | undefined;
canPurchase: boolean;
owned: boolean;
getOffer(id?: string): IAPOffer | undefined;
addOffer(offer: IAPOffer): this;
}
export interface IAPOffer {
id: string;
productId: string;
productType: ProductType;
productGroup: string | undefined;
platform: Platform;
pricingPhases: IAPPricingPhase[];
canPurchase: boolean;
/**
* Initiate a purchase of this offer.
*
* @example
* store.get("my-product").getOffer().order();
*/
order(additionnalData?: IAPAdditionalData): Promise<IAPError | undefined>;
}
export interface IAPPricingPhase {
price: string;
priceMicros: number;
currency: string;
billingPeriod?: number;
billingCycles?: number;
recurrenceMode?: RecurrenceMode;
paymentMode?: PaymentMode;
}
export interface IAPReceipt {
platform: Platform;
transactions: IAPTransaction[];
verify(): Promise<void>;
finish(): Promise<void>;
hasTransaction(value: IAPTransaction): boolean;
lastTransaction(): IAPTransaction | undefined;
}
export interface IAPVerifiedReceipt {
id: string;
validationDate: Date;
plaform: Platform;
sourceReceipt: IAPReceipt;
collection: IAPVerifiedPurchase[];
latestReceipt: boolean;
nativeTransactions: { type: string; data?: object }[];
warning?: string;
raw: object;
set(receipt: IAPReceipt, response: object): void;
finish(): Promise<void>;
}
export interface IAPUnverifiedReceipt {
receipt: IAPReceipt;
payload: object;
}
export interface IAPTransaction {
platform: Platform;
transactionId: string;
purchaseId?: string;
purchaseDate?: Date;
lastRenewalDate?: Date;
expirationDate?: Date;
isAcknowledged?: boolean;
isPending?: boolean;
isConsumed?: boolean;
renewalIntent?: RenewalIntent;
renewalIntentChangeDate?: Date;
state: TransactionState;
amountMicros?: number;
currency?: string;
products: { id: string; offerId?: string }[];
/**
* Finish a transaction.
*
* When the application has delivered the product, it should finalize the order.
* Only after that, money will be transferred to your account.
* This method ensures that no customers is charged for a product that couldn't be delivered.
*
* @example
* store.when()
* .approved(transaction => transaction.verify())
* .verified(receipt => receipt.finish())
*/
finish(): Promise<void>;
/**
* Verify a transaction.
*
* This will trigger a call to the receipt validation service for the attached receipt.
* Once the receipt has been verified, you can finish the transaction.
*
* @example
* store.when()
* .approved(transaction => transaction.verify())
* .verified(receipt => receipt.finish())
*/
verify(): Promise<void>;
parentReceipt: IAPReceipt;
}
export interface IAPVerifiedPurchase {
id: string;
platform?: Platform;
purchaseId?: string;
purchaseDate?: number;
expiryDate?: number;
isExpired?: boolean;
renewalIntent?: string;
renewalIntentChangeDate?: number;
cancelationReason?: CancelationReason;
isBillingRetryPeriod?: boolean;
isTrialPeriod?: boolean;
isIntroPeriod?: boolean;
discountId?: string;
priceConsentStatus?: PriceConsentStatus;
lastRenewalDate?: number;
}
export interface IAPProductEvents {
/**
* Register a function called when a product or receipt is updated.
*
* @deprecated - Use `productUpdated` or `receiptUpdated`.
*/
updated(cb: Callback<IAPProduct | IAPReceipt>, callbackName?: string): IAPProductEvents;
/** Register a function called when a receipt is updated. */
receiptUpdated(cb: Callback<IAPReceipt>, callbackName?: string): IAPProductEvents;
/** Register a function called when a product is updated. */
productUpdated(cb: Callback<IAPProduct>, callbackName?: string): IAPProductEvents;
// /** Register a function called when a product is owned. */
// owned(cb: Callback<Product>): When;
/** Register a function called when a transaction is initiated. */
initiated(cb: Callback<IAPTransaction>, callbackName?: string): IAPProductEvents;
/** Register a function called when a transaction is approved. */
approved(cb: Callback<IAPTransaction>, callbackName?: string): IAPProductEvents;
/** Register a function called when a transaction is pending. */
pending(cb: Callback<IAPTransaction>, callbackName?: string): IAPProductEvents;
/** Register a function called when a transaction is finished. */
finished(cb: Callback<IAPTransaction>, callbackName?: string): IAPProductEvents;
/** Register a function called when a receipt is verified. */
verified(cb: Callback<IAPVerifiedReceipt>, callbackName?: string): IAPProductEvents;
/** Register a function called when a receipt failed validation. */
unverified(cb: Callback<IAPUnverifiedReceipt>, callbackName?: string): IAPProductEvents;
/**
* Register a function called when all receipts have been loaded.
*
* This handler is called only once. Use this when you want to run some code at startup after
* all the local receipts have been loaded, for example to process the initial ownership status
* of your products. When you have a receipt validation server in place, a better option is to
* use the sister method "receiptsVerified".
*
* If no platforms have any receipts (the user made no purchase), this will also get called.
*/
receiptsReady(cb: Callback<void>, callbackName?: string): IAPProductEvents;
/**
* Register a function called when all receipts have been verified.
*
* If no platforms have any receipts (user made no purchase), this will also get called.
*/
receiptsVerified(cb: Callback<void>, callbackName?: string): IAPProductEvents;
}
export interface IAPPaymentRequest {
items: (
| {
id: string;
title: string;
pricing?: {
priceMicros: number;
currency?: string;
};
}
| undefined
)[];
platform: Platform;
amountMicros?: number;
currency?: string;
description?: string;
email?: string;
mobilePhoneNumber?: string;
billingAddress?: {
givenName?: string;
surname?: string;
streetAddress1?: string;
streetAddress2?: string;
streetAddress3?: string;
locality?: string;
region?: string;
postalCode?: string;
phoneNumber?: string;
countryCode?: string;
};
}
/**
* Purchase platforms supported by the plugin
*/
export enum Platform {
/** Apple AppStore */
APPLE_APPSTORE = 'ios-appstore',
/** Google Play */
GOOGLE_PLAY = 'android-playstore',
/** Windows Store */
WINDOWS_STORE = 'windows-store-transaction',
/** Braintree */
BRAINTREE = 'braintree',
// /** Stripe */
// STRIPE = 'stripe',
/** Test platform */
TEST = 'test',
}
/** Types of In-App Products */
export enum ProductType {
/** Type: An consumable product, that can be purchased multiple time */
CONSUMABLE = 'consumable',
/** Type: A non-consumable product, that can purchased only once and the user keeps forever */
NON_CONSUMABLE = 'non consumable',
/** @deprecated use PAID_SUBSCRIPTION */
FREE_SUBSCRIPTION = 'free subscription',
/** Type: An auto-renewable subscription */
PAID_SUBSCRIPTION = 'paid subscription',
/** Type: An non-renewing subscription */
NON_RENEWING_SUBSCRIPTION = 'non renewing subscription',
/** Type: The application bundle */
APPLICATION = 'application',
}
/** Mode of payment */
export enum PaymentMode {
/** Used for subscriptions, pay at the beginning of each billing period */
PAY_AS_YOU_GO = 'PayAsYouGo',
/** Pay the whole amount up front */
UP_FRONT = 'UpFront',
/** Nothing to be paid */
FREE_TRIAL = 'FreeTrial',
}
/**
* Type of recurring payment
*
* - FINITE_RECURRING: Payment recurs for a fixed number of billing period set in `paymentPhase.cycles`.
* - INFINITE_RECURRING: Payment recurs for infinite billing periods unless cancelled.
* - NON_RECURRING: A one time charge that does not repeat.
*/
export enum RecurrenceMode {
NON_RECURRING = 'NON_RECURRING',
FINITE_RECURRING = 'FINITE_RECURRING',
INFINITE_RECURRING = 'INFINITE_RECURRING',
}
/** Unit for measuring durations */
export type IPeriodUnit = 'Minute' | 'Hour' | 'Day' | 'Week' | 'Month' | 'Year';
/** Possible states of a product */
export enum TransactionState {
// REQUESTED = 'requested',
INITIATED = 'initiated',
PENDING = 'pending',
APPROVED = 'approved',
CANCELLED = 'cancelled',
FINISHED = 'finished',
// OWNED = 'owned',
// EXPIRED = 'expired',
UNKNOWN_STATE = '',
}
/** Whether or not the user was notified or agreed to a price change */
export enum PriceConsentStatus {
NOTIFIED = 'Notified',
AGREED = 'Agreed',
}
/** Whether or not the user intends to let the subscription auto-renew. */
export enum RenewalIntent {
/** The user intends to let the subscription expire without renewing. */
LAPSE = 'Lapse',
/** The user intends to renew the subscription. */
RENEW = 'Renew',
}
/** Reason why a subscription has been canceled */
export enum CancelationReason {
/** Not canceled */
NOT_CANCELED = '',
/** Subscription canceled by the developer. */
DEVELOPER = 'Developer',
/** Subscription canceled by the system for an unspecified reason. */
SYSTEM = 'System',
/** Subscription upgraded or downgraded to a new subscription. */
SYSTEM_REPLACED = 'System.Replaced',
/** Product not available for purchase at the time of renewal. */
SYSTEM_PRODUCT_UNAVAILABLE = 'System.ProductUnavailable',
/** Billing error; for example customers payment information is no longer valid. */
SYSTEM_BILLING_ERROR = 'System.BillingError',
/** Transaction is gone; It has been deleted. */
SYSTEM_DELETED = 'System.Deleted',
/** Subscription canceled by the user for an unspecified reason. */
CUSTOMER = 'Customer',
/** Customer canceled their transaction due to an actual or perceived issue within your app. */
CUSTOMER_TECHNICAL_ISSUES = 'Customer.TechnicalIssues',
/** Customer did not agree to a recent price increase. See also priceConsentStatus. */
CUSTOMER_PRICE_INCREASE = 'Customer.PriceIncrease',
/** Customer canceled for cost-related reasons. */
CUSTOMER_COST = 'Customer.Cost',
/** Customer claimed to have found a better app. */
CUSTOMER_FOUND_BETTER_APP = 'Customer.FoundBetterApp',
/** Customer did not feel he is using this service enough. */
CUSTOMER_NOT_USEFUL_ENOUGH = 'Customer.NotUsefulEnough',
/** Subscription canceled for another reason; for example, if the customer made the purchase accidentally. */
CUSTOMER_OTHER_REASON = 'Customer.OtherReason',
/** Subscription canceled for unknown reasons. */
UNKNOWN = 'Unknown',
}
export enum LogLevel {
/** Disable all logging (default) */
QUIET = 0,
/** Show only error messages */
ERROR = 1,
/** Show warnings and errors */
WARNING = 2,
/** Also show information messages */
INFO = 3,
/** Enable internal debugging messages. */
DEBUG = 4,
}
/**
* @hidden
*/
export class IAPError {
isError: true;
code: number;
message: string;
platform: Platform | null;
productId: string | null;
}
/**
* @name "In App Purchase 3"
* @description
* In-App Purchase on iOS, Android, Windows, macOS and XBox.
*
* This plugin replace the previous InAppPurchase2, due to backward compatibility issue with the wrapped
* cordova-plugin-purchase version 13.0
*
* ## Features
*
* | | ios | android | win-8 | win-10/uwp | mac |
* |--|--|--|--|--|--|
* | consumables | ✅ | ✅ | ✅ | ✅ | ✅ |
* | non consumables | ✅ | ✅ | ✅ | ✅ | ✅ |
* | subscriptions | ✅ | ✅ | ✅ | ✅ | ✅ |
* | restore purchases | ✅ | ✅ | ✅ | ✅ | ✅ |
* | receipt validations | ✅ | ✅ | | ✅ | ✅ |
* | introductory prices | ✅ | ✅ | | ✅ | ✅ |
*
* Supports:
*
* - **iOS** version 7.0 or higher.
* - **Android** version 2.2 (API level 8) or higher
* - with Google Play client version 3.9.16 or higher
* - **Windows** Store/Phone 8.1 or higher
* - **Windows 10 Mobile**
* - **macOS** version 10
* - **Xbox One**
* - (and any platform supporting Microsoft's UWP)
* - **cordova-plugin-purchase** version 13.0 or higher
* @usage
* ```typescript
* import { InAppPurchase3, Platform, ProductType } from '@awesome-cordova-plugins/in-app-purchase-3/ngx';
*
* constructor(public platform: Platform, private store: InAppPurchase3) {
* platform.ready().then(() => {
* this.store.register({
* id: "my_product_id",
* type: ProductType.NON_RENEWING_SUBSCRIPTION,
* platform: Platform.TEST
* });
* this.store.when()
* .approved(p => p.verify())
* .verified(p => p.finish());
* this.store.initialize();
* this.store.update();
* });
* }
*
* ...
*
* const product = this.store.get("my_product_id", Platform.TEST);
* store.order(product.getOffer()); // or product.getOffer().order();
* ```
*
* ## Full example
*
* ```typescript
* // After platform ready
* this.store.verbosity = this.store.DEBUG;
* this.store.register({
* id: "my_product_id",
* type: ProductType.PAID_SUBSCRIPTION,
* platform: Platform.TEST,
* });
*
* // Register event handlers for the specific product
* this.store.when().registered( (product: IAPProduct) => {
* console.log('Registered: ' + JSON.stringify(product));
* });
*
* // Updated
* this.store.when().updated( (product: IAPProduct) => {
* console.log('Updated' + JSON.stringify(product));
* });
*
* // User closed the native purchase dialog
* this.store.when().cancelled( (product) => {
* console.error('Purchase was Cancelled');
* });
*
* // Track all store errors
* this.store.error( (err) => {
* console.error('Store Error ' + JSON.stringify(err));
* });
*
* // Run some code only when the store is ready to be used
* this.store.ready(() => {
* console.log('Store is ready');
* console.log('Products: ' + JSON.stringify(this.store.products));
* console.log(JSON.stringify(this.store.get("my_product_id")));
* });
*
* // initialize the plugin
* this.store.initialize();
*
* // refresh product prices and status of purchases
* this.store.update();
*
* ...
*
* const product = this.store.get("my_product_id", Platform.TEST);
* store.order(product.getOffer()); // or product.getOffer().order();
* ```
*
* ## Philosophy
*
* The API is mostly events based. As a user of this plugin,
* you will have to register listeners to changes happening to the products
* you register.
*
* The core of the listening mechanism is the `when()` method. It allows you to
* be notified of changes to one or a set of products using a query mechanism:
* ```typescript
* this.store.when().updated(refreshScreen); // match any product
* this.store.when().owned(unlockApp); // match a specific product
* this.store.when().approved(serverCheck); // match all subscriptions
* ```
*
* The `updated` event is fired whenever one of the fields of a product is
* changed (its `owned` status for instance).
*
* This event provides a generic way to track the statuses of your purchases,
* to unlock features when needed and to refresh your views accordingly.
*
* ## Registering products
*
* The store needs to know the type and identifiers of your products before you
* can use them in your code.
*
* Use `store.register()` to define them before your first call to `store.initialize()`.
*
* Once registered, you can use `store.get()` to retrieve an `IAPProduct` object.
*
* ```typescript
* this.store.register({
* id: "my_consumable1",
* type: ProductType.CONSUMABLE
* platform: Platform.TEST,
* });
* ...
* const p = this.store.get("my_consumable1");
* ```
*
* The product `id` and `type` have to match products defined in your
* Apple, Google or Microsoft developer consoles.
*
* Learn more about it [from the wiki](https://github.com/j3k0/cordova-plugin-purchase/wiki).
*
* ## Displaying products
*
* Right after you registered your products, nothing much is known about them
* except their `id`, `type` and an optional `alias`.
*
* When you perform the initial call to `store.refresh()`, the platforms' server will
* be contacted to load informations about the registered products: human
* readable `title` and `description`, `price`, etc.
*
* This isn't an optional step, store owners require you
* to display information about a product exactly as retrieved from their server: no
* hard-coding of price and title allowed! This is also convenient for you
* as you can change the price of your items knowing that it'll be reflected instantly
* on your clients' devices.
*
* Note that the information may not be available when the first view that needs
* them appears on screen. For you, the best option is to have your view monitor
* changes made to the product.
*
* ## Purchasing
*
* #### initiate a purchase
*
* Purchases are initiated using the `store.order(offer)` method.
*
* The store will manage the internal purchase flow. It'll end:
*
* - with an `approved` event. The product enters the `APPROVED` state.
* - with a `cancelled` event. The product gets back to the `VALID` state.
* - with an `error` event. The product gets back to the `VALID` state.
*
* See the product life-cycle section for details about product states.
*
* #### finish a purchase
*
* Once the transaction is approved, the product still isn't owned: the store needs
* confirmation that the purchase was delivered before closing the transaction.
*
* To confirm delivery, you'll use the `product.finish()` method.
*
* #### example usage
*
* During initialization:
* ```typescript
* this.store.when().approved((product: IAPProduct) => {
* // download the feature
* app.downloadExtraChapter()
* .then(() => product.finish());
* });
* ```
*
* When the purchase button is clicked:
* ```typescript
* const extraChapterProduct = this.store.get("extra_chapter");
* this.store.order(extraChapterProduct.getOffer());
* ```
*
* #### un-finished purchases
*
* If your app wasn't able to deliver the content, `product.finish()` won't be called.
*
* Don't worry: the `approved` event will be re-triggered the next time you
* call `store.update()`, which can very well be the next time
* the application starts. Pending transactions are persistant.
*
* #### simple case
*
* In the most simple case, where:
*
* - delivery of purchases is only local ;
* - you don't want (or need) to implement receipt validation ;
*
* You may just want to finish all purchases automatically. You can do it this way:
* ```js
* this.store.when().approved((p: IAPProduct) => p.finish());
* ```
*
* ## Receipt validation
*
* To get the most up-to-date information about purchases (in case a purchase have been canceled, or a subscription renewed),
* you should implement server side receipt validation.
*
* This also protects you against fake "purchases", made by some users using
* "free in-app purchase" apps on their devices.
*
* When a purchase has been approved by the store, it's enriched with
* transaction information (see `product.transaction` attribute).
*
* To verify a purchase you'll have to do three things:
*
* - configure the validator.
* - call `product.verify()` from the `approved` event, before finishing the transaction.
* - finish the transaction when transaction is `verified`.
*
* Shameless Plug**: this is a feature many users struggle with, so as the author of this plugin, we can provide it to you as-a-service: https://billing.fovea.cc/
* (which is free until you start making serious money)
*
* #### example using a validation URL
*
* ```js
* this.store.validator = "https://billing.fovea.cc/";
*
* this.store.when()
* .approved((p: IAPProduct) => p.verify())
* .verified((p: IAPProduct) => p.finish());
* ```
*
* ## Subscriptions
*
* For subscription, you MUST implement remote receipt validation.
*
* When the receipt validator returns a `store.PURCHASE_EXPIRED` error code, the subscription will
* automatically loose its `owned` status.
*
* Typically, you'll enable and disable access to your content this way.
* ```typescript
* this.store.when().updated((product: IAPProduct) => {
* if (product.owned)
* app.subscriberMode();
* else
* app.guestMode();
* });
* ```
*
* ## Product life-cycle
*
* A product will change state during the application execution.
*
* Find below a diagram of the different states a product can pass by.
*
* ```
* REGISTERED +--> INVALID
* |
* +--> VALID +--> REQUESTED +--> INITIATED +-+
* |
* ^ +------------------------------+
* | |
* | |
* | |
* | +--> APPROVED +--------------------------------+--> FINISHED +--> OWNED
* | |
* +-------------------------------------------------------------+
* ```
*
* #### Notes
*
* - When finished, a consumable product will get back to the `VALID` state, while other will enter the `OWNED` state.
* - Any error in the purchase process will bring a product back to the `VALID` state.
* - During application startup, products may go instantly from `REGISTERED` to `APPROVED` or `OWNED`, for example if they are purchased non-consumables or non-expired subscriptions.
* - Non-Renewing Subscriptions are iOS products only. Please see the [iOS Non Renewing Subscriptions documentation](https://github.com/j3k0/cordova-plugin-purchase/blob/master/doc/ios.md#non-renewing) for a detailed explanation.
*
* ## events
*
* - `loaded(IAPProduct)`
* - Called when product data is loaded from the store.
* - `updated(IAPProduct)`
* - Called when any change occured to a product.
* - `error(err)`
* - Called when an order failed.
* - The `err` parameter is an error object
* - `approved(IAPProduct)`
* - Called when a product order is approved.
* - `owned(IAPProduct)`
* - Called when a non-consumable product or subscription is owned.
* - `cancelled(IAPProduct)`
* - Called when a product order is cancelled by the user.
* - `refunded(IAPProduct)`
* - Called when an order is refunded by the user.
* - Actually, all other product states have their promise
* - `registered`, `valid`, `invalid`, `requested`,
* `initiated` and `finished`
* - `verified(IAPProduct)`
* - Called when receipt validation successful
* - `unverified(IAPProduct)`
* - Called when receipt verification failed
* - `expired(IAPProduct)`
* - Called when validation find a subscription to be expired
*
* ## Learn More
*
* - [GitHub](https://github.com/j3k0/cordova-plugin-purchase)
* - [GitBook](https://purchase.cordova.fovea.cc/)
* - [Wiki](https://github.com/j3k0/cordova-plugin-purchase/wiki)
* - [API reference](https://github.com/j3k0/cordova-plugin-purchase/blob/master/doc/api.md)
*
* ## Technical Support or Questions
*
* If you have questions or need help integrating In-App Purchase, [Open an Issue on GitHub](https://github.com/j3k0/cordova-plugin-purchase/issues) or email us at _support@fovea.cc_.
*
* @interfaces
* IAPAdapter
* IAPProductOptions
* IAPProduct
* IAPOffer
* IAPPricingPhase
* IAPReceipt
* IAPVerifiedReceipt
* IAPUnverifiedReceipt
* IAPTransaction
* IAPVerifiedPurchase
* IAPProductEvents
* IAPPaymentRequest
* ```
*/
@Plugin({
pluginName: 'InAppPurchase3',
plugin: 'cordova-plugin-purchase',
pluginRef: 'CdvPurchase.store',
repo: 'https://github.com/j3k0/cordova-plugin-purchase',
platforms: ['iOS', 'Android', 'Windows'],
install: 'ionic cordova plugin add cordova-plugin-purchase --variable BILLING_KEY="<ANDROID_BILLING_KEY>"',
})
@Injectable()
export class InAppPurchase3 extends AwesomeCordovaNativePlugin {
@Cordova({ sync: true })
getAdapter(platform: Platform): IAPAdapter | undefined {
return;
}
@CordovaProperty()
log: {
error: (message: string) => void;
warn: (message: string) => void;
info: (message: string) => void;
debug: (message: string) => void;
};
/**
* Verbosity level used by the plugin logger
*
* Set to:
* - LogLevel.QUIET or 0 to disable all logging (default)
* - LogLevel.ERROR or 1 to show only error messages
* - LogLevel.WARNING or 2 to show warnings and errors
* - LogLevel.INFO or 3 to also show information messages
* - LogLevel.DEBUG or 4 to enable internal debugging messages.
*
* @see {@link LogLevel}
*/
@CordovaProperty()
verbosity: number;
/** Return the identifier of the user for your application */
@CordovaProperty()
applicationUsername: string | (() => string);
/**
* Get the application username as a string by either calling or returning {@link InAppPurchase3.applicationUsername}
*/
@Cordova({ sync: true })
getApplicationUsername(): string {
return;
}
/**
* URL or implementation of the receipt validation service
*
* @example
* Define the validator as a string
* ```ts
* InAppPurchase3.validator = "https://validator.iaptic.com/v1/validate?appName=test"
* ```
*
* @example
* Define the validator as a function
* ```ts
* InAppPurchase3.validator = (receipt, callback) => {
* callback({
* ok: true,
* data: {
* // see CdvPurchase.Validator.Response.Payload for details
* }
* })
* }
* ```
*/
@CordovaProperty()
validator:
| string
| ((receipt: object, callback: Callback<object>) => void)
| { url: string; headers?: { [token: string]: string }; timeout?: number }
| undefined;
/**
* When adding information to receipt validation requests, those can serve different functions:
* - handling support requests
* - fraud detection
* - analytics
* - tracking
*
* Make sure the value your select is in line with your application's privacy policy and your users' tracking preference.
*
* @example
* CdvPurchase.store.validator_privacy_policy = [
* 'fraud', 'support', 'analytics', 'tracking'
* ]
*/
@CordovaProperty()
validator_privacy_policy:
| 'fraud'
| 'support'
| 'analytics'
| 'tracking'
| ('fraud' | 'support' | 'analytics' | 'tracking')[]
| undefined;
/**
* Register a product.
* @example
* store.register([{
* id: 'subscription1',
* type: ProductType.PAID_SUBSCRIPTION,
* platform: Platform.APPLE_APPSTORE,
* }, {
* id: 'subscription1',
* type: ProductType.PAID_SUBSCRIPTION,
* platform: Platform.GOOGLE_PLAY,
* }, {
* id: 'consumable1',
* type: ProductType.CONSUMABLE,
* platform: Platform.BRAINTREE,
* }]);
* @param {IAPProductOptions | IAPProductOptions[]} product - one product or a list of products to register.
*/
@Cordova({ sync: true })
register(product: IAPProductOptions | IAPProductOptions[]): void {}
/**
* Call to initialize the in-app purchase plugin.
*
* @param platforms - List of payment platforms to initialize, default to Store.defaultPlatform().
* @returns {Promise<IAPError | undefined>}
*/
@Cordova({ sync: true })
initialize(platforms: (Platform | { platform: Platform; options?: object })[]): Promise<IAPError | undefined> {
return;
}
/**
* Avoid invoking store.update() if the most recent call occurred within this specific number of milliseconds.
*/
@CordovaProperty()
minTimeBetweenUpdates: number;
/** Call to refresh the price of products and status of purchases */
@Cordova({ sync: true })
update(): void {}
/**
* Register a callback to be called when the plugin is ready.
* This happens when all the platforms are initialized and their products loaded.
* @param {Callback<void>} callback called when ready
*/
@Cordova()
ready(callback: Callback<void>): void {
return;
}
@CordovaProperty()
isReady: boolean;
/**
* Setup events listener.
*
* @example
* store.when()
* .productUpdated(product => updateUI(product))
* .approved(transaction => transaction.verify())
* .verified(receipt => receipt.finish());
*/
@Cordova({ sync: true })
when(): IAPProductEvents {
return;
}
/**
* Remove a callback from any listener it might have been added to.
* @param {Callback} callback
*/
@Cordova({ sync: true })
off<T>(callback: Callback<T>): void {}
/**
* Setup a function to be notified of changes to a transaction state.
* @param {IAPTransaction} transaction The transaction to monitor.
* @param {Callback<TransactionState>} onChange Function to be called when the transaction status changes.
* @param {string} callbackName
* @returns A monitor which can be stopped with `monitor.stop()`
*
* @example
* const monitor = store.monitor(transaction, state => {
* console.log('new state: ' + state);
* if (state === TransactionState.FINISHED)
* monitor.stop();
* });
*/
@Cordova({ sync: true })
monitor(
transaction: IAPTransaction,
onChange: Callback<TransactionState>,
callbackName: string
): {
stop(): void;
transaction: IAPTransaction;
} {
return;
}
/**
* List of all active products.
* Products are active if their details have been successfully loaded from the store.
*/
@CordovaProperty()
products: IAPProduct[];
/**
* Find a product from its id and platform
* @param {string} productId Product identifier on the platform.
* @param {Platform} platform The product the product exists in. Can be omitted if you're only using a single payment platform.
*/
@Cordova({ sync: true })
get(productId: string, platform: Platform): IAPProduct {
return;
}
/** List of all receipts present on the device. */
@CordovaProperty()
localReceipts: IAPReceipt[];
/** List of all transaction from the local receipts. */
@CordovaProperty()
localTransactions: IAPTransaction[];
/**
* List of receipts verified with the receipt validation service.
* Those receipt contains more information and are generally more up-to-date than the local ones.
*/
@CordovaProperty()
verifiedReceipts: IAPVerifiedReceipt[];
/**
* List of all purchases from the verified receipts.
*/
verifiedPurchases: IAPVerifiedPurchase[];
/**
* Find the last verified purchase for a given product, from those verified by the receipt validator.
* @param {IAPProduct} product
*/
@Cordova({ sync: true })
findInVerifiedReceipts(product: IAPProduct): IAPVerifiedPurchase | undefined {
return;
}
/**
* Find the latest transaction for a given product, from those reported by the device.
* @param {IAPProduct} product
*/
@Cordova({ sync: true })
findInLocalReceipts(product: IAPProduct): IAPTransaction | undefined {
return;
}
/**
* @param product - The product object or identifier of the product.
* @returns {boolean} true if a product is owned
*/
@Cordova({ sync: true })
owned(
product:
| {
id: string;
platform?: Platform;
}
| string
): boolean {
return;
}
/**
* Place an order for a given offer.
* @param {IAPOffer} offer
* @param {IAPAdditionalData?} additionalData
*/
@Cordova({ sync: false })
order(offer: IAPOffer, additionalData?: IAPAdditionalData): Promise<IAPError | undefined> {
return;
}
/**
* Request a payment.
*
* A payment is a custom amount to charge the user. Make sure the selected payment platform
* supports Payment Requests.
*
* @param {IAPPaymentRequest} paymentRequest Parameters of the payment request
* @param {IAPAdditionalData?} additionalData Additional parameters
*/
@Cordova({ sync: false })
requestPayment(paymentRequest: IAPPaymentRequest, additionalData?: IAPAdditionalData): object {
return;
}
/**
* @returns true if a platform supports the requested functionality.
*
* @example
* store.checkSupport(Platform.APPLE_APPSTORE, 'requestPayment');
* // => false
* @param {Platform} platform
* @param {functionality} functionality
*/
@Cordova({ sync: false })
checkSupport(platform: Platform, functionality: string): boolean {
return;
}
/**
* Replay the users transactions.
*
* This method exists to cover an Apple App Store requirement.
*/
@Cordova({ sync: false })
restorePurchases(): Promise<IAPError | undefined> {
return;
}
/**
* Open the subscription management interface for the selected platform.
*
* If platform is not specified, the first available platform will be used.
*
* @example
* const activeSubscription: Purchase = // ...
* store.manageSubscriptions(activeSubscription.platform);
* @param {Platform?} platform
*/
@Cordova({ sync: false })
manageSubscriptions(platform?: Platform): Promise<IAPError | undefined> {
return;
}
/**
* Opens the billing methods page on App Store, Play, Microsoft, ...
*
* From this page, the user can update their payment methods.
* If platform is not specified, the first available platform will be used.
*
* @example
* if (purchase.isBillingRetryPeriod)
* store.manageBilling(purchase.platform);
*/
@Cordova({ sync: false })
manageBilling(): Promise<IAPError | undefined> {
return;
}
/**
* The default payment platform to use depending on the OS.
*
* - on iOS: `APPLE_APPSTORE`
* - on Android: `GOOGLE_PLAY`
*/
@Cordova({ sync: true })
defaultPlatform(): Platform {
return;
}
/**
* Register an error handler.
*
* @param {Callback<IAPError>} error An error callback that takes the error as an argument
* @example
* store.error(function(error) {
* console.error('CdvPurchase ERROR: ' + error.message);
* });
*/
@Cordova({ sync: true })
error(error: Callback<IAPError>): void {}
/**
* Version of the plugin currently installed.
*/
@CordovaProperty()
version: string;
}