@mpgd/capacitor-play-billing 0.1.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +125 -0
- package/android/src/main/java/dev/mpgd/capacitor/playbilling/CapacitorPlayBillingPlugin.java +68 -10
- package/dist/commerce-provider.d.ts +68 -0
- package/dist/commerce-provider.js +91 -0
- package/dist/definitions.d.ts +60 -7
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/provider.d.ts +15 -2
- package/dist/provider.js +18 -14
- package/dist/store-sdk.d.ts +89 -0
- package/dist/store-sdk.js +613 -0
- package/package.json +11 -7
package/dist/provider.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Capacitor } from '@capacitor/core';
|
|
2
|
+
import { createGooglePlayTokenPurchaseKey } from '@mpgd/platform/commerce';
|
|
2
3
|
import { CapacitorPlayBilling } from './plugin.js';
|
|
3
4
|
const googlePlayProductPurchaseEvidenceSchema = 'google-play.product-purchase.v2';
|
|
4
5
|
class PlayPurchaseIntegrityError extends Error {
|
|
@@ -13,6 +14,12 @@ function isValidPurchaseToken(value) {
|
|
|
13
14
|
/**
|
|
14
15
|
* Resubmit owned purchases after a callback was missed or the app restarted.
|
|
15
16
|
* A native purchase is never credited locally; only the backend response grants it.
|
|
17
|
+
*
|
|
18
|
+
* @deprecated v1 recovery driver. Commerce v2 games register
|
|
19
|
+
* `createCapacitorPlayBillingServiceProvider` and let the single reconciler
|
|
20
|
+
* in `@mpgd/game-services` (PR C1) resolve unfinished purchases from
|
|
21
|
+
* `getAvailablePurchases` and `purchaseUpdated`; this driver is removed with
|
|
22
|
+
* the v1 adapter in the next major version.
|
|
16
23
|
*/
|
|
17
24
|
export async function recoverOwnedPlayPurchases(input) {
|
|
18
25
|
if (input.playerId.trim() === '') {
|
|
@@ -38,7 +45,7 @@ export async function recoverOwnedPlayPurchases(input) {
|
|
|
38
45
|
playerId: input.playerId,
|
|
39
46
|
productId,
|
|
40
47
|
platformTransactionId: result.transactionId,
|
|
41
|
-
idempotencyKey: await
|
|
48
|
+
idempotencyKey: await createGooglePlayTokenPurchaseKey(token),
|
|
42
49
|
purchasedAt: purchasedAt ?? input.now?.() ?? new Date().toISOString(),
|
|
43
50
|
evidence: result.evidence,
|
|
44
51
|
});
|
|
@@ -268,7 +275,7 @@ async function convertPurchase(purchase) {
|
|
|
268
275
|
return { status: 'pending', entitlementIds: [], evidence };
|
|
269
276
|
}
|
|
270
277
|
const transactionId = purchase.orderId?.trim()
|
|
271
|
-
|| await
|
|
278
|
+
|| await createGooglePlayTokenPurchaseKey(purchase.purchaseToken);
|
|
272
279
|
return {
|
|
273
280
|
status: 'completed',
|
|
274
281
|
transactionId,
|
|
@@ -276,18 +283,15 @@ async function convertPurchase(purchase) {
|
|
|
276
283
|
evidence,
|
|
277
284
|
};
|
|
278
285
|
}
|
|
279
|
-
/**
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
const digest = new Uint8Array(await subtle.digest('SHA-256', new TextEncoder().encode(purchaseToken)));
|
|
289
|
-
return `play-token-sha256:${[...digest].map((value) => value.toString(16).padStart(2, '0')).join('')}`;
|
|
290
|
-
}
|
|
286
|
+
/**
|
|
287
|
+
* The server's token transaction ID, computed by the one shared helper so the
|
|
288
|
+
* plugin and `@mpgd/game-services` can never drift.
|
|
289
|
+
*
|
|
290
|
+
* @deprecated Use `createGooglePlayTokenPurchaseKey` from `@mpgd/platform/commerce`;
|
|
291
|
+
* this alias is the same function (same key, same `TypeError` for an invalid
|
|
292
|
+
* token) and will be removed in the next major version.
|
|
293
|
+
*/
|
|
294
|
+
export const createGooglePlayTokenTransactionId = createGooglePlayTokenPurchaseKey;
|
|
291
295
|
function success(id, data) {
|
|
292
296
|
return { id, ok: true, data };
|
|
293
297
|
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { PlatformProviderAvailability } from '@mpgd/platform';
|
|
2
|
+
import { type StoreSdk, type StoreSdkCapabilities, type StoreSdkError, type StoreSdkErrorCodeMap, type StoreSdkPurchase } from '@mpgd/adapter-capacitor';
|
|
3
|
+
import type { CapacitorPlayBillingPlugin, PlayPurchase } from './definitions.js';
|
|
4
|
+
/** The store id of the Play Billing `StoreSdk` (RFC "Capabilities", `google-play`). */
|
|
5
|
+
export declare const googlePlayStoreId: 'google-play';
|
|
6
|
+
/**
|
|
7
|
+
* What the Play Billing plugin supports (RFC "Capabilities" profile row for
|
|
8
|
+
* `google-play`): one-time consumables and durables, no subscriptions, no
|
|
9
|
+
* multi-quantity, pending purchases, no restore call, one-time offers, and a
|
|
10
|
+
* server-owned finish (the backend acknowledges or consumes after the grant).
|
|
11
|
+
*/
|
|
12
|
+
export declare const playBillingStoreSdkCapabilities: StoreSdkCapabilities;
|
|
13
|
+
/**
|
|
14
|
+
* `defaultStoreSdkErrorCodeMap` plus every `PLAY_BILLING_*` code the plugin or
|
|
15
|
+
* this SDK emits that the default map does not already normalize.
|
|
16
|
+
*/
|
|
17
|
+
export declare const playBillingStoreSdkErrorCodeMap: StoreSdkErrorCodeMap;
|
|
18
|
+
/** One Play product the SDK sells; the provider maps it to a logical id. */
|
|
19
|
+
export interface PlayBillingStoreSdkProduct {
|
|
20
|
+
/** The Play product id (SKU). */
|
|
21
|
+
readonly sku: string;
|
|
22
|
+
readonly kind: 'consumable' | 'durable';
|
|
23
|
+
/**
|
|
24
|
+
* Default one-time offer (`offerToken`) when Play lists more than one
|
|
25
|
+
* eligible offer; a request may name another through `offerId`.
|
|
26
|
+
*/
|
|
27
|
+
readonly offerToken?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface CreateCapacitorPlayBillingStoreSdkInput {
|
|
30
|
+
readonly products: readonly PlayBillingStoreSdkProduct[];
|
|
31
|
+
/** Defaults to the registered `CapacitorPlayBilling` plugin. */
|
|
32
|
+
readonly plugin?: CapacitorPlayBillingPlugin;
|
|
33
|
+
/** Defaults to `Capacitor.getPlatform() === 'android'`. */
|
|
34
|
+
readonly isAndroid?: () => boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Diagnostics hook for a plugin purchase the SDK leaves out of
|
|
37
|
+
* `getAvailablePurchases` and events: a SKU not in `products` (for example
|
|
38
|
+
* a retired product) or a multi-line purchase. Such a purchase has no
|
|
39
|
+
* logical id for the reconciler; the backend finalizer still sees it
|
|
40
|
+
* through the Play Developer API.
|
|
41
|
+
*/
|
|
42
|
+
readonly onUnmappedPurchase?: (purchase: PlayPurchase) => void;
|
|
43
|
+
}
|
|
44
|
+
export interface CapacitorPlayBillingStoreSdk extends StoreSdk {
|
|
45
|
+
readonly store: typeof googlePlayStoreId;
|
|
46
|
+
getAvailability(): Promise<PlatformProviderAvailability>;
|
|
47
|
+
}
|
|
48
|
+
interface PlayBillingStoreSdkErrorOptions {
|
|
49
|
+
readonly retryable?: boolean;
|
|
50
|
+
readonly storeCode?: string;
|
|
51
|
+
readonly cause?: unknown;
|
|
52
|
+
}
|
|
53
|
+
/** A plugin rejection or an SDK integrity failure, carrying the plugin code. */
|
|
54
|
+
export declare class PlayBillingStoreSdkError extends Error implements StoreSdkError {
|
|
55
|
+
readonly code: string;
|
|
56
|
+
readonly retryable?: boolean;
|
|
57
|
+
readonly storeCode?: string;
|
|
58
|
+
constructor(code: string, message: string, options?: PlayBillingStoreSdkErrorOptions);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* `StoreSdk` over `@mpgd/capacitor-play-billing`'s plugin for
|
|
62
|
+
* `createStoreCommerceProvider`. It speaks Play product ids and plugin codes
|
|
63
|
+
* only: `fetchProducts` is `getProducts`, `requestPurchase` is `purchase` with
|
|
64
|
+
* the obfuscated account id from the request's account binding and the offer
|
|
65
|
+
* token from `offerId`, `getAvailablePurchases` is `getPurchases` filtered to
|
|
66
|
+
* unfinished entries (purchased and not acknowledged, plus pending on
|
|
67
|
+
* request), and `purchaseUpdated` events are the plugin's. A purchased plugin
|
|
68
|
+
* outcome is `purchased`; a pending one is `launched`, because Play resolves
|
|
69
|
+
* it later through `purchaseUpdated` or `getPurchases`; a cancelled one is
|
|
70
|
+
* `cancelled`; a plugin rejection is `failed` with the plugin code, which the
|
|
71
|
+
* provider normalizes (`PLAY_BILLING_TIMEOUT`, `PLAY_BILLING_INTERRUPTED`, and
|
|
72
|
+
* `PLAY_BILLING_EMPTY_PURCHASE` become `OUTCOME_UNKNOWN` and stay recoverable).
|
|
73
|
+
* `transactionId` is the order id or, until Play assigns one, the token key
|
|
74
|
+
* `play-token-sha256:<hex>` v1 ledgers already use. Nothing here grants, and
|
|
75
|
+
* nothing here acknowledges or consumes: the backend finalizer owns both.
|
|
76
|
+
*/
|
|
77
|
+
export declare function createCapacitorPlayBillingStoreSdk(input: CreateCapacitorPlayBillingStoreSdkInput): CapacitorPlayBillingStoreSdk;
|
|
78
|
+
/** Validates a purchase token exactly as the v1 provider does. */
|
|
79
|
+
export declare function isValidPlayPurchaseToken(value: unknown): value is string;
|
|
80
|
+
/**
|
|
81
|
+
* `StoreSdkPurchase` of one plugin purchase: `token` is the purchase token,
|
|
82
|
+
* `transactionId` is the order id or the token key when Play has not assigned
|
|
83
|
+
* one yet (the v1 rule, so ledgers written by v1 deduplicate), `purchasedAt`
|
|
84
|
+
* is `purchaseTime` as ISO 8601 when it is a valid instant, and the account
|
|
85
|
+
* binding is the obfuscated account id the purchase flow recorded. Throws
|
|
86
|
+
* `PLAY_BILLING_EVIDENCE_INVALID` for a shape the plugin never produces.
|
|
87
|
+
*/
|
|
88
|
+
export declare function toPlayBillingSdkPurchase(purchase: PlayPurchase): Promise<StoreSdkPurchase>;
|
|
89
|
+
export {};
|