Skip to content

Commit

Permalink
v13.12.0
Browse files Browse the repository at this point in the history
  • Loading branch information
j3k0 committed Dec 2, 2024
1 parent 6f44277 commit 6aaabd0
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 19 deletions.
30 changes: 30 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
# Release Notes - Cordova Plugin Purchase

## 13.12

### 13.12.0

#### (googleplay) Upgrade to Google Play Billing library 7.1.1

- Improved thread safety related to connection status and management.
- Added new testing response codes to BillingResult

https://developer.android.com/google/play/billing/release-notes

#### (all) Fix issue with large number of transactions

In particular, when calling "restorePurchases" in Apple and the user has more than 100 transactions.

- 5e2ad5b Delay processing of updated receipts
- 71a071c Do not retrigger "approved" for a given transaction until a minute has elapsed

#### (appstore) Fix issue with event handling when autoFinish is set

Issue #1526, approved never fires after initiating the purchase when autoFinish was set.

#### (all) Fix receipt without a transaction

Issue #1526

#### Minor changes

Logs and documentation

## 13.11

### 13.11.1
Expand Down
5 changes: 4 additions & 1 deletion api/classes/CdvPurchase.Store.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ Entry class of the plugin.

`Optional` **applicationUsername**: `string` \| () => `undefined` \| `string`

Return the identifier of the user for your application
Return the identifier of the user for your application.

**Note:** Apple AppStore requires an UUIDv4 if you want it to appear as the "appAccountToken" in
the transaction data.

___

Expand Down
2 changes: 1 addition & 1 deletion api/modules/CdvPurchase.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ ___

### PLUGIN\_VERSION

`Const` **PLUGIN\_VERSION**: ``"13.11.1"``
`Const` **PLUGIN\_VERSION**: ``"13.12.0"``

Current release number of the plugin.

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cordova-plugin-purchase",
"version": "13.11.1",
"version": "13.12.0",
"description": "Cordova Purchase plugin for iOS, Android, Windows (AppStore, Play, UWP)",
"cordova": {
"id": "cordova-plugin-purchase",
Expand Down
2 changes: 1 addition & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ SOFTWARE.
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
id="cordova-plugin-purchase"
xmlns:android="http://schemas.android.com/apk/res/android"
version="13.11.1">
version="13.12.0">

<name>Purchase</name>
<description>Cordova Purchase plugin for iOS (AppStore), Android (PlayStore) and Windows</description>
Expand Down
4 changes: 2 additions & 2 deletions src/ts/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace CdvPurchase {
/**
* Current release number of the plugin.
*/
export const PLUGIN_VERSION = '13.11.1';
export const PLUGIN_VERSION = '13.12.0';

/**
* Entry class of the plugin.
Expand Down Expand Up @@ -82,7 +82,7 @@ namespace CdvPurchase {

/**
* Return the identifier of the user for your application.
*
*
* **Note:** Apple AppStore requires an UUIDv4 if you want it to appear as the "appAccountToken" in
* the transaction data.
*/
Expand Down
15 changes: 13 additions & 2 deletions www/store.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,8 @@ declare namespace CdvPurchase {
* Trigger the "updated" event for each product.
*/
productsUpdated(platform: Platform, products: Product[]): void;
updatedReceiptsToProcess: Receipt[];
updatedReceiptsProcessor: number | undefined;
/**
* Triggers the "approved", "pending" and "finished" events for transactions.
*
Expand All @@ -525,6 +527,7 @@ declare namespace CdvPurchase {
* @param receipts The receipts that have been updated.
*/
receiptsUpdated(platform: Platform, receipts: Receipt[]): void;
private _processUpdatedReceipts;
}
}
}
Expand Down Expand Up @@ -645,7 +648,10 @@ declare namespace CdvPurchase {
class TransactionStateMonitors {
private monitors;
private findMonitors;
private when;
private isListening;
constructor(when: When);
private startListening;
private callOnChange;
/**
* Start monitoring the provided transaction for state changes.
Expand Down Expand Up @@ -743,7 +749,7 @@ declare namespace CdvPurchase {
/**
* Current release number of the plugin.
*/
const PLUGIN_VERSION = "13.11.1";
const PLUGIN_VERSION = "13.12.0";
/**
* Entry class of the plugin.
*/
Expand Down Expand Up @@ -782,7 +788,12 @@ declare namespace CdvPurchase {
* @see {@link LogLevel}
*/
verbosity: LogLevel;
/** Return the identifier of the user for your application */
/**
* Return the identifier of the user for your application.
*
* **Note:** Apple AppStore requires an UUIDv4 if you want it to appear as the "appAccountToken" in
* the transaction data.
*/
applicationUsername?: string | (() => string | undefined);
/**
* Get the application username as a string by either calling or returning {@link Store.applicationUsername}
Expand Down
55 changes: 45 additions & 10 deletions www/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,7 @@ var CdvPurchase;
const bodyTransactionHash = CdvPurchase.Utils.md5(JSON.stringify(body.transaction));
const cached = this.cache[bodyTransactionHash];
if (cached) {
this.log.debug("validator cache hit, using cached response");
return callback({ receipt, payload: cached.payload });
}
CdvPurchase.Utils.ajax(this.log.child("Ajax"), {
Expand Down Expand Up @@ -894,6 +895,7 @@ var CdvPurchase;
this.lastTransactionState = {};
/** Store the listener's latest calling time (in ms) for a given transaction at a given state */
this.lastCallTimeForState = {};
this.updatedReceiptsToProcess = [];
this.delegate = delegate;
this.log = log.child('AdapterListener');
}
Expand Down Expand Up @@ -951,34 +953,58 @@ var CdvPurchase;
* @param receipts The receipts that have been updated.
*/
receiptsUpdated(platform, receipts) {
this.log.debug("receiptsUpdated: " + JSON.stringify(receipts.map(r => ({
platform: r.platform,
transactions: r.transactions,
}))));
for (const receipt of receipts) {
if (this.updatedReceiptsToProcess.indexOf(receipt) < 0) {
this.updatedReceiptsToProcess.push(receipt);
}
}
if (this.updatedReceiptsProcessor !== undefined) {
clearTimeout(this.updatedReceiptsProcessor);
}
this.updatedReceiptsProcessor = setTimeout(() => {
this._processUpdatedReceipts();
}, 500);
}
_processUpdatedReceipts() {
this.log.debug("processing " + this.updatedReceiptsToProcess.length + " updated receipts");
const now = +new Date();
this.log.debug("receiptsUpdated: " + JSON.stringify(receipts));
const receipts = this.updatedReceiptsToProcess;
this.updatedReceiptsToProcess = [];
receipts.forEach(receipt => {
this.delegate.updatedReceiptCallbacks.trigger(receipt, 'adapterListener_receiptsUpdated');
receipt.transactions.forEach(transaction => {
var _a;
const transactionToken = StoreAdapterListener.makeTransactionToken(transaction);
const tokenWithState = transactionToken + '@' + transaction.state;
const lastState = this.lastTransactionState[transactionToken];
// Retrigger "approved", so validation is rerun on potential update.
if (transaction.state === CdvPurchase.TransactionState.APPROVED) {
// prevent calling approved twice in a very short period (60 seconds).
if ((this.lastCallTimeForState[tokenWithState] | 0) < now - 60000) {
this.delegate.approvedCallbacks.trigger(transaction, 'adapterListener_receiptsUpdated_approved');
const lastCalled = (_a = this.lastCallTimeForState[tokenWithState]) !== null && _a !== void 0 ? _a : 0;
if (now - lastCalled > 60000) {
this.lastCallTimeForState[tokenWithState] = now;
this.delegate.approvedCallbacks.trigger(transaction, 'adapterListener_receiptsUpdated_approved');
}
else {
this.log.debug(`Skipping ${tokenWithState}, because it has been last called ${lastCalled > 0 ? Math.round(now - lastCalled) + 'ms ago (' + now + '-' + lastCalled + ')' : 'never'}`);
}
}
else if (lastState !== transaction.state) {
if (transaction.state === CdvPurchase.TransactionState.INITIATED) {
this.delegate.initiatedCallbacks.trigger(transaction, 'adapterListener_receiptsUpdated_initiated');
this.lastCallTimeForState[tokenWithState] = now;
this.delegate.initiatedCallbacks.trigger(transaction, 'adapterListener_receiptsUpdated_initiated');
}
else if (transaction.state === CdvPurchase.TransactionState.FINISHED) {
this.delegate.finishedCallbacks.trigger(transaction, 'adapterListener_receiptsUpdated_finished');
this.lastCallTimeForState[tokenWithState] = now;
this.delegate.finishedCallbacks.trigger(transaction, 'adapterListener_receiptsUpdated_finished');
}
else if (transaction.state === CdvPurchase.TransactionState.PENDING) {
this.delegate.pendingCallbacks.trigger(transaction, 'adapterListener_receiptsUpdated_pending');
this.lastCallTimeForState[tokenWithState] = now;
this.delegate.pendingCallbacks.trigger(transaction, 'adapterListener_receiptsUpdated_pending');
}
}
this.lastTransactionState[transactionToken] = transaction.state;
Expand Down Expand Up @@ -1143,14 +1169,22 @@ var CdvPurchase;
class TransactionStateMonitors {
constructor(when) {
this.monitors = [];
when
.approved(transaction => this.callOnChange(transaction), 'transactionStateMonitors_callOnChange')
.finished(transaction => this.callOnChange(transaction), 'transactionStateMonitors_callOnChange');
this.isListening = false;
this.when = when;
}
findMonitors(transaction) {
return this.monitors.filter(monitor => monitor.transaction.platform === transaction.platform
&& monitor.transaction.transactionId === transaction.transactionId);
}
startListening() {
if (this.isListening) {
return;
}
this.isListening = true;
this.when
.approved(transaction => this.callOnChange(transaction), 'transactionStateMonitors_callOnChange')
.finished(transaction => this.callOnChange(transaction), 'transactionStateMonitors_callOnChange');
}
callOnChange(transaction) {
this.findMonitors(transaction).forEach(monitor => {
if (monitor.lastChange !== transaction.state) {
Expand All @@ -1163,6 +1197,7 @@ var CdvPurchase;
* Start monitoring the provided transaction for state changes.
*/
start(transaction, onChange) {
this.startListening();
const monitorId = CdvPurchase.Utils.uuidv4();
this.monitors.push({ monitorId, transaction, onChange, lastChange: transaction.state });
setTimeout(onChange, 0, transaction.state);
Expand Down Expand Up @@ -1349,7 +1384,7 @@ var CdvPurchase;
/**
* Current release number of the plugin.
*/
CdvPurchase.PLUGIN_VERSION = '13.11.1';
CdvPurchase.PLUGIN_VERSION = '13.12.0';
/**
* Entry class of the plugin.
*/
Expand Down

0 comments on commit 6aaabd0

Please sign in to comment.