@capgo/capacitor-pay 8.0.12 → 8.1.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.
@@ -1,5 +1,5 @@
1
1
  export type PayPlatform = 'ios' | 'android' | 'web';
2
- export type ApplePayNetwork = 'AmEx' | 'Bancomat' | 'Bancontact' | 'PagoBancomat' | 'CarteBancaire' | 'CarteBancaires' | 'CartesBancaires' | 'ChinaUnionPay' | 'Dankort' | 'Discover' | 'Eftpos' | 'Electron' | 'Elo' | 'girocard' | 'Himyan' | 'Interac' | 'iD' | 'Jaywan' | 'JCB' | 'mada' | 'Maestro' | 'MasterCard' | 'Meeza' | 'Mir' | 'MyDebit' | 'NAPAS' | 'BankAxept' | 'PostFinanceAG' | 'PrivateLabel' | 'QUICPay' | 'Suica' | 'Visa' | 'VPay';
2
+ export type ApplePayNetwork = 'AmEx' | 'amex' | 'Bancomat' | 'Bancontact' | 'PagoBancomat' | 'CarteBancaire' | 'CarteBancaires' | 'CartesBancaires' | 'ChinaUnionPay' | 'Dankort' | 'Discover' | 'discover' | 'Eftpos' | 'Electron' | 'Elo' | 'girocard' | 'Himyan' | 'Interac' | 'iD' | 'Jaywan' | 'JCB' | 'jcb' | 'mada' | 'Maestro' | 'maestro' | 'MasterCard' | 'masterCard' | 'Meeza' | 'Mir' | 'MyDebit' | 'NAPAS' | 'BankAxept' | 'PostFinanceAG' | 'PrivateLabel' | 'QUICPay' | 'Suica' | 'Visa' | 'visa' | 'VPay' | 'vPay';
3
3
  export type ApplePayMerchantCapability = '3DS' | 'credit' | 'debit' | 'emv';
4
4
  export type ApplePaySummaryItemType = 'final' | 'pending';
5
5
  export type ApplePayContactField = 'emailAddress' | 'name' | 'phoneNumber' | 'postalAddress';
@@ -9,6 +9,61 @@ export interface ApplePaySummaryItem {
9
9
  amount: string;
10
10
  type?: ApplePaySummaryItemType;
11
11
  }
12
+ export type ApplePayRecurringPaymentIntervalUnit = 'day' | 'week' | 'month' | 'year';
13
+ export interface ApplePayRecurringPaymentSummaryItem extends ApplePaySummaryItem {
14
+ /**
15
+ * Unit of time between recurring payments.
16
+ */
17
+ intervalUnit: ApplePayRecurringPaymentIntervalUnit;
18
+ /**
19
+ * Number of `intervalUnit` units between recurring payments (for example `1` month, `2` weeks).
20
+ */
21
+ intervalCount: number;
22
+ /**
23
+ * Start date of the recurring period.
24
+ *
25
+ * On supported platforms this may be either:
26
+ * - a `number` representing milliseconds since Unix epoch, or
27
+ * - a `string` in a date format accepted by the native implementation
28
+ * (for example an ISO 8601 date-time string or a `yyyy-MM-dd` date string).
29
+ */
30
+ startDate?: number | string;
31
+ /**
32
+ * End date of the recurring period.
33
+ *
34
+ * On supported platforms this may be either:
35
+ * - a `number` representing milliseconds since Unix epoch, or
36
+ * - a `string` in a date format accepted by the native implementation
37
+ * (for example an ISO 8601 date-time string or a `yyyy-MM-dd` date string).
38
+ */
39
+ endDate?: number | string;
40
+ }
41
+ export interface ApplePayRecurringPaymentRequest {
42
+ /**
43
+ * A description for the recurring payment shown in the Apple Pay sheet.
44
+ */
45
+ paymentDescription: string;
46
+ /**
47
+ * The recurring billing item (for example your subscription).
48
+ */
49
+ regularBilling: ApplePayRecurringPaymentSummaryItem;
50
+ /**
51
+ * URL where the user can manage the recurring payment (cancel, update, etc).
52
+ */
53
+ managementURL: string;
54
+ /**
55
+ * Optional billing agreement text shown to the user.
56
+ */
57
+ billingAgreement?: string;
58
+ /**
59
+ * Optional URL where Apple can send token update notifications.
60
+ */
61
+ tokenNotificationURL?: string;
62
+ /**
63
+ * Optional trial billing item (for example a free trial period).
64
+ */
65
+ trialBilling?: ApplePayRecurringPaymentSummaryItem;
66
+ }
12
67
  export interface ApplePayAvailabilityOptions {
13
68
  /**
14
69
  * Optional list of payment networks you intend to use.
@@ -71,6 +126,10 @@ export interface ApplePayPaymentOptions {
71
126
  * Optional opaque application data passed back in the payment token.
72
127
  */
73
128
  applicationData?: string;
129
+ /**
130
+ * Recurring payment configuration (iOS 16+).
131
+ */
132
+ recurringPaymentRequest?: ApplePayRecurringPaymentRequest;
74
133
  }
75
134
  export interface ApplePayContact {
76
135
  name?: {
@@ -116,6 +175,82 @@ export interface ApplePayPaymentResult {
116
175
  billingContact?: ApplePayContact;
117
176
  }
118
177
  export type GooglePayEnvironment = 'test' | 'production';
178
+ export type GooglePayCardNetwork = 'AMEX' | 'DISCOVER' | 'JCB' | 'MASTERCARD' | 'VISA' | (string & Record<never, never>);
179
+ export type GooglePayAuthMethod = 'PAN_ONLY' | 'CRYPTOGRAM_3DS' | (string & Record<never, never>);
180
+ export type GooglePayTotalPriceStatus = 'NOT_CURRENTLY_KNOWN' | 'ESTIMATED' | 'FINAL' | (string & Record<never, never>);
181
+ export interface GooglePayBillingAddressParameters {
182
+ format?: 'MIN' | 'FULL' | (string & Record<never, never>);
183
+ phoneNumberRequired?: boolean;
184
+ }
185
+ export interface GooglePayCardPaymentMethodParameters {
186
+ allowedAuthMethods?: GooglePayAuthMethod[];
187
+ allowedCardNetworks?: GooglePayCardNetwork[];
188
+ billingAddressRequired?: boolean;
189
+ billingAddressParameters?: GooglePayBillingAddressParameters;
190
+ }
191
+ export interface GooglePayTokenizationSpecification {
192
+ type?: 'PAYMENT_GATEWAY' | 'DIRECT' | (string & Record<never, never>);
193
+ parameters?: Record<string, string>;
194
+ }
195
+ export interface GooglePayAllowedPaymentMethod {
196
+ type?: 'CARD' | (string & Record<never, never>);
197
+ parameters?: GooglePayCardPaymentMethodParameters;
198
+ tokenizationSpecification?: GooglePayTokenizationSpecification;
199
+ }
200
+ export interface GooglePayMerchantInfo {
201
+ merchantId?: string;
202
+ merchantName?: string;
203
+ }
204
+ export interface GooglePayTransactionInfo {
205
+ totalPriceStatus?: GooglePayTotalPriceStatus;
206
+ totalPrice?: string;
207
+ currencyCode?: string;
208
+ countryCode?: string;
209
+ }
210
+ /**
211
+ * Typed helper for the Google Pay `IsReadyToPayRequest` JSON.
212
+ * The native Android implementation still accepts arbitrary JSON (forward compatible).
213
+ */
214
+ export interface GooglePayIsReadyToPayRequest {
215
+ /**
216
+ * The list of payment methods you want to check for readiness.
217
+ */
218
+ allowedPaymentMethods?: GooglePayAllowedPaymentMethod[];
219
+ /**
220
+ * Forward-compatible escape hatch for additional fields supported by Google Pay.
221
+ */
222
+ [key: string]: unknown;
223
+ }
224
+ /**
225
+ * Typed helper for the Google Pay `PaymentDataRequest` JSON.
226
+ * The native Android implementation still accepts arbitrary JSON (forward compatible).
227
+ */
228
+ export interface GooglePayPaymentDataRequest {
229
+ /**
230
+ * Google Pay API version, typically `2`.
231
+ */
232
+ apiVersion?: number;
233
+ /**
234
+ * Google Pay API minor version, typically `0`.
235
+ */
236
+ apiVersionMinor?: number;
237
+ /**
238
+ * Allowed payment method configurations.
239
+ */
240
+ allowedPaymentMethods?: GooglePayAllowedPaymentMethod[];
241
+ /**
242
+ * Merchant information displayed in the Google Pay sheet.
243
+ */
244
+ merchantInfo?: GooglePayMerchantInfo;
245
+ /**
246
+ * Transaction details (amount, currency, etc).
247
+ */
248
+ transactionInfo?: GooglePayTransactionInfo;
249
+ /**
250
+ * Forward-compatible escape hatch for additional fields supported by Google Pay.
251
+ */
252
+ [key: string]: unknown;
253
+ }
119
254
  export interface GooglePayAvailabilityOptions {
120
255
  /**
121
256
  * Environment used to construct the Google Payments client. Defaults to `'test'`.
@@ -125,7 +260,7 @@ export interface GooglePayAvailabilityOptions {
125
260
  * Raw `IsReadyToPayRequest` JSON as defined by the Google Pay API.
126
261
  * Supply the card networks and auth methods you intend to support at runtime.
127
262
  */
128
- isReadyToPayRequest?: Record<string, unknown>;
263
+ isReadyToPayRequest?: GooglePayIsReadyToPayRequest;
129
264
  }
130
265
  export interface GooglePayAvailabilityResult {
131
266
  /**
@@ -142,7 +277,7 @@ export interface GooglePayPaymentOptions {
142
277
  * Raw `PaymentDataRequest` JSON as defined by the Google Pay API.
143
278
  * Provide transaction details, merchant info, and tokenization parameters.
144
279
  */
145
- paymentDataRequest: Record<string, unknown>;
280
+ paymentDataRequest: GooglePayPaymentDataRequest;
146
281
  }
147
282
  export interface GooglePayPaymentResult {
148
283
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["export type PayPlatform = 'ios' | 'android' | 'web';\n\nexport type ApplePayNetwork =\n | 'AmEx'\n | 'Bancomat'\n | 'Bancontact'\n | 'PagoBancomat'\n | 'CarteBancaire'\n | 'CarteBancaires'\n | 'CartesBancaires'\n | 'ChinaUnionPay'\n | 'Dankort'\n | 'Discover'\n | 'Eftpos'\n | 'Electron'\n | 'Elo'\n | 'girocard'\n | 'Himyan'\n | 'Interac'\n | 'iD'\n | 'Jaywan'\n | 'JCB'\n | 'mada'\n | 'Maestro'\n | 'MasterCard'\n | 'Meeza'\n | 'Mir'\n | 'MyDebit'\n | 'NAPAS'\n | 'BankAxept'\n | 'PostFinanceAG'\n | 'PrivateLabel'\n | 'QUICPay'\n | 'Suica'\n | 'Visa'\n | 'VPay';\n\nexport type ApplePayMerchantCapability = '3DS' | 'credit' | 'debit' | 'emv';\n\nexport type ApplePaySummaryItemType = 'final' | 'pending';\n\nexport type ApplePayContactField = 'emailAddress' | 'name' | 'phoneNumber' | 'postalAddress';\n\nexport type ApplePayShippingType = 'shipping' | 'delivery' | 'servicePickup' | 'storePickup';\n\nexport interface ApplePaySummaryItem {\n label: string;\n amount: string;\n type?: ApplePaySummaryItemType;\n}\n\nexport interface ApplePayAvailabilityOptions {\n /**\n * Optional list of payment networks you intend to use.\n * Passing networks determines the return value of `canMakePaymentsUsingNetworks`.\n */\n supportedNetworks?: ApplePayNetwork[];\n}\n\nexport interface ApplePayAvailabilityResult {\n /**\n * Indicates whether the device can make Apple Pay payments in general.\n */\n canMakePayments: boolean;\n /**\n * Indicates whether the device can make Apple Pay payments with the supplied networks.\n */\n canMakePaymentsUsingNetworks: boolean;\n}\n\nexport interface ApplePayPaymentOptions {\n /**\n * Merchant identifier created in the Apple Developer portal.\n */\n merchantIdentifier: string;\n /**\n * Two-letter ISO 3166 country code.\n */\n countryCode: string;\n /**\n * Three-letter ISO 4217 currency code.\n */\n currencyCode: string;\n /**\n * Payment summary items displayed in the Apple Pay sheet.\n */\n paymentSummaryItems: ApplePaySummaryItem[];\n /**\n * Card networks to support.\n */\n supportedNetworks: ApplePayNetwork[];\n /**\n * Merchant payment capabilities. Defaults to ['3DS'] when omitted.\n */\n merchantCapabilities?: ApplePayMerchantCapability[];\n /**\n * Contact fields that must be supplied for shipping.\n */\n requiredShippingContactFields?: ApplePayContactField[];\n /**\n * Contact fields that must be supplied for billing.\n */\n requiredBillingContactFields?: ApplePayContactField[];\n /**\n * Controls the shipping flow presented to the user.\n */\n shippingType?: ApplePayShippingType;\n /**\n * Optional ISO 3166 country codes where the merchant is supported.\n */\n supportedCountries?: string[];\n /**\n * Optional opaque application data passed back in the payment token.\n */\n applicationData?: string;\n}\n\nexport interface ApplePayContact {\n name?: {\n givenName?: string;\n familyName?: string;\n middleName?: string;\n namePrefix?: string;\n nameSuffix?: string;\n nickname?: string;\n };\n emailAddress?: string;\n phoneNumber?: string;\n postalAddress?: {\n street?: string;\n city?: string;\n state?: string;\n postalCode?: string;\n country?: string;\n isoCountryCode?: string;\n subAdministrativeArea?: string;\n subLocality?: string;\n };\n}\n\nexport interface ApplePayPaymentResult {\n /**\n * Raw payment token encoded as base64 string.\n */\n paymentData: string;\n /**\n * Raw payment token JSON string, useful for debugging.\n */\n paymentString: string;\n /**\n * Payment transaction identifier.\n */\n transactionIdentifier: string;\n paymentMethod: {\n displayName?: string;\n network?: ApplePayNetwork;\n type: 'debit' | 'credit' | 'prepaid' | 'store';\n };\n shippingContact?: ApplePayContact;\n billingContact?: ApplePayContact;\n}\n\nexport type GooglePayEnvironment = 'test' | 'production';\n\nexport interface GooglePayAvailabilityOptions {\n /**\n * Environment used to construct the Google Payments client. Defaults to `'test'`.\n */\n environment?: GooglePayEnvironment;\n /**\n * Raw `IsReadyToPayRequest` JSON as defined by the Google Pay API.\n * Supply the card networks and auth methods you intend to support at runtime.\n */\n isReadyToPayRequest?: Record<string, unknown>;\n}\n\nexport interface GooglePayAvailabilityResult {\n /**\n * Indicates whether the Google Pay API is available for the supplied parameters.\n */\n isReady: boolean;\n}\n\nexport interface GooglePayPaymentOptions {\n /**\n * Environment used to construct the Google Payments client. Defaults to `'test'`.\n */\n environment?: GooglePayEnvironment;\n /**\n * Raw `PaymentDataRequest` JSON as defined by the Google Pay API.\n * Provide transaction details, merchant info, and tokenization parameters.\n */\n paymentDataRequest: Record<string, unknown>;\n}\n\nexport interface GooglePayPaymentResult {\n /**\n * Payment data returned by Google Pay.\n */\n paymentData: Record<string, unknown>;\n}\n\nexport interface PayAvailabilityOptions {\n apple?: ApplePayAvailabilityOptions;\n google?: GooglePayAvailabilityOptions;\n}\n\nexport interface PayAvailabilityResult {\n available: boolean;\n platform: PayPlatform;\n apple?: ApplePayAvailabilityResult;\n google?: GooglePayAvailabilityResult;\n}\n\nexport interface PayPaymentOptions {\n apple?: ApplePayPaymentOptions;\n google?: GooglePayPaymentOptions;\n}\n\nexport interface PayPaymentResult {\n platform: Exclude<PayPlatform, 'web'>;\n apple?: ApplePayPaymentResult;\n google?: GooglePayPaymentResult;\n}\n\nexport interface PayPlugin {\n /**\n * Checks whether native pay is available on the current platform.\n * On iOS this evaluates Apple Pay, on Android it evaluates Google Pay.\n */\n isPayAvailable(options?: PayAvailabilityOptions): Promise<PayAvailabilityResult>;\n /**\n * Presents the native pay sheet for the current platform.\n * Provide the Apple Pay configuration on iOS and the Google Pay configuration on Android.\n */\n requestPayment(options: PayPaymentOptions): Promise<PayPaymentResult>;\n\n /**\n * Get the native Capacitor plugin version\n *\n * @returns {Promise<{ id: string }>} an Promise with version for this device\n * @throws An error if the something went wrong\n */\n getPluginVersion(): Promise<{ version: string }>;\n}\n"]}
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["export type PayPlatform = 'ios' | 'android' | 'web';\n\nexport type ApplePayNetwork =\n | 'AmEx'\n | 'amex'\n | 'Bancomat'\n | 'Bancontact'\n | 'PagoBancomat'\n | 'CarteBancaire'\n | 'CarteBancaires'\n | 'CartesBancaires'\n | 'ChinaUnionPay'\n | 'Dankort'\n | 'Discover'\n | 'discover'\n | 'Eftpos'\n | 'Electron'\n | 'Elo'\n | 'girocard'\n | 'Himyan'\n | 'Interac'\n | 'iD'\n | 'Jaywan'\n | 'JCB'\n | 'jcb'\n | 'mada'\n | 'Maestro'\n | 'maestro'\n | 'MasterCard'\n | 'masterCard'\n | 'Meeza'\n | 'Mir'\n | 'MyDebit'\n | 'NAPAS'\n | 'BankAxept'\n | 'PostFinanceAG'\n | 'PrivateLabel'\n | 'QUICPay'\n | 'Suica'\n | 'Visa'\n | 'visa'\n | 'VPay'\n | 'vPay';\n\nexport type ApplePayMerchantCapability = '3DS' | 'credit' | 'debit' | 'emv';\n\nexport type ApplePaySummaryItemType = 'final' | 'pending';\n\nexport type ApplePayContactField = 'emailAddress' | 'name' | 'phoneNumber' | 'postalAddress';\n\nexport type ApplePayShippingType = 'shipping' | 'delivery' | 'servicePickup' | 'storePickup';\n\nexport interface ApplePaySummaryItem {\n label: string;\n amount: string;\n type?: ApplePaySummaryItemType;\n}\n\nexport type ApplePayRecurringPaymentIntervalUnit = 'day' | 'week' | 'month' | 'year';\n\nexport interface ApplePayRecurringPaymentSummaryItem extends ApplePaySummaryItem {\n /**\n * Unit of time between recurring payments.\n */\n intervalUnit: ApplePayRecurringPaymentIntervalUnit;\n /**\n * Number of `intervalUnit` units between recurring payments (for example `1` month, `2` weeks).\n */\n intervalCount: number;\n /**\n * Start date of the recurring period.\n *\n * On supported platforms this may be either:\n * - a `number` representing milliseconds since Unix epoch, or\n * - a `string` in a date format accepted by the native implementation\n * (for example an ISO 8601 date-time string or a `yyyy-MM-dd` date string).\n */\n startDate?: number | string;\n /**\n * End date of the recurring period.\n *\n * On supported platforms this may be either:\n * - a `number` representing milliseconds since Unix epoch, or\n * - a `string` in a date format accepted by the native implementation\n * (for example an ISO 8601 date-time string or a `yyyy-MM-dd` date string).\n */\n endDate?: number | string;\n}\n\nexport interface ApplePayRecurringPaymentRequest {\n /**\n * A description for the recurring payment shown in the Apple Pay sheet.\n */\n paymentDescription: string;\n /**\n * The recurring billing item (for example your subscription).\n */\n regularBilling: ApplePayRecurringPaymentSummaryItem;\n /**\n * URL where the user can manage the recurring payment (cancel, update, etc).\n */\n managementURL: string;\n /**\n * Optional billing agreement text shown to the user.\n */\n billingAgreement?: string;\n /**\n * Optional URL where Apple can send token update notifications.\n */\n tokenNotificationURL?: string;\n /**\n * Optional trial billing item (for example a free trial period).\n */\n trialBilling?: ApplePayRecurringPaymentSummaryItem;\n}\n\nexport interface ApplePayAvailabilityOptions {\n /**\n * Optional list of payment networks you intend to use.\n * Passing networks determines the return value of `canMakePaymentsUsingNetworks`.\n */\n supportedNetworks?: ApplePayNetwork[];\n}\n\nexport interface ApplePayAvailabilityResult {\n /**\n * Indicates whether the device can make Apple Pay payments in general.\n */\n canMakePayments: boolean;\n /**\n * Indicates whether the device can make Apple Pay payments with the supplied networks.\n */\n canMakePaymentsUsingNetworks: boolean;\n}\n\nexport interface ApplePayPaymentOptions {\n /**\n * Merchant identifier created in the Apple Developer portal.\n */\n merchantIdentifier: string;\n /**\n * Two-letter ISO 3166 country code.\n */\n countryCode: string;\n /**\n * Three-letter ISO 4217 currency code.\n */\n currencyCode: string;\n /**\n * Payment summary items displayed in the Apple Pay sheet.\n */\n paymentSummaryItems: ApplePaySummaryItem[];\n /**\n * Card networks to support.\n */\n supportedNetworks: ApplePayNetwork[];\n /**\n * Merchant payment capabilities. Defaults to ['3DS'] when omitted.\n */\n merchantCapabilities?: ApplePayMerchantCapability[];\n /**\n * Contact fields that must be supplied for shipping.\n */\n requiredShippingContactFields?: ApplePayContactField[];\n /**\n * Contact fields that must be supplied for billing.\n */\n requiredBillingContactFields?: ApplePayContactField[];\n /**\n * Controls the shipping flow presented to the user.\n */\n shippingType?: ApplePayShippingType;\n /**\n * Optional ISO 3166 country codes where the merchant is supported.\n */\n supportedCountries?: string[];\n /**\n * Optional opaque application data passed back in the payment token.\n */\n applicationData?: string;\n\n /**\n * Recurring payment configuration (iOS 16+).\n */\n recurringPaymentRequest?: ApplePayRecurringPaymentRequest;\n}\n\nexport interface ApplePayContact {\n name?: {\n givenName?: string;\n familyName?: string;\n middleName?: string;\n namePrefix?: string;\n nameSuffix?: string;\n nickname?: string;\n };\n emailAddress?: string;\n phoneNumber?: string;\n postalAddress?: {\n street?: string;\n city?: string;\n state?: string;\n postalCode?: string;\n country?: string;\n isoCountryCode?: string;\n subAdministrativeArea?: string;\n subLocality?: string;\n };\n}\n\nexport interface ApplePayPaymentResult {\n /**\n * Raw payment token encoded as base64 string.\n */\n paymentData: string;\n /**\n * Raw payment token JSON string, useful for debugging.\n */\n paymentString: string;\n /**\n * Payment transaction identifier.\n */\n transactionIdentifier: string;\n paymentMethod: {\n displayName?: string;\n network?: ApplePayNetwork;\n type: 'debit' | 'credit' | 'prepaid' | 'store';\n };\n shippingContact?: ApplePayContact;\n billingContact?: ApplePayContact;\n}\n\nexport type GooglePayEnvironment = 'test' | 'production';\n\nexport type GooglePayCardNetwork =\n | 'AMEX'\n | 'DISCOVER'\n | 'JCB'\n | 'MASTERCARD'\n | 'VISA'\n // Keep this open-ended so users can pass new/region-specific networks without waiting for a release.\n | (string & Record<never, never>);\n\nexport type GooglePayAuthMethod =\n | 'PAN_ONLY'\n | 'CRYPTOGRAM_3DS'\n // Keep this open-ended for forward compatibility.\n | (string & Record<never, never>);\n\nexport type GooglePayTotalPriceStatus = 'NOT_CURRENTLY_KNOWN' | 'ESTIMATED' | 'FINAL' | (string & Record<never, never>);\n\nexport interface GooglePayBillingAddressParameters {\n format?: 'MIN' | 'FULL' | (string & Record<never, never>);\n phoneNumberRequired?: boolean;\n}\n\nexport interface GooglePayCardPaymentMethodParameters {\n allowedAuthMethods?: GooglePayAuthMethod[];\n allowedCardNetworks?: GooglePayCardNetwork[];\n billingAddressRequired?: boolean;\n billingAddressParameters?: GooglePayBillingAddressParameters;\n}\n\nexport interface GooglePayTokenizationSpecification {\n type?: 'PAYMENT_GATEWAY' | 'DIRECT' | (string & Record<never, never>);\n parameters?: Record<string, string>;\n}\n\nexport interface GooglePayAllowedPaymentMethod {\n type?: 'CARD' | (string & Record<never, never>);\n parameters?: GooglePayCardPaymentMethodParameters;\n tokenizationSpecification?: GooglePayTokenizationSpecification;\n}\n\nexport interface GooglePayMerchantInfo {\n merchantId?: string;\n merchantName?: string;\n}\n\nexport interface GooglePayTransactionInfo {\n totalPriceStatus?: GooglePayTotalPriceStatus;\n totalPrice?: string;\n currencyCode?: string;\n countryCode?: string;\n}\n\n/**\n * Typed helper for the Google Pay `IsReadyToPayRequest` JSON.\n * The native Android implementation still accepts arbitrary JSON (forward compatible).\n */\nexport interface GooglePayIsReadyToPayRequest {\n /**\n * The list of payment methods you want to check for readiness.\n */\n allowedPaymentMethods?: GooglePayAllowedPaymentMethod[];\n /**\n * Forward-compatible escape hatch for additional fields supported by Google Pay.\n */\n [key: string]: unknown;\n}\n\n/**\n * Typed helper for the Google Pay `PaymentDataRequest` JSON.\n * The native Android implementation still accepts arbitrary JSON (forward compatible).\n */\nexport interface GooglePayPaymentDataRequest {\n /**\n * Google Pay API version, typically `2`.\n */\n apiVersion?: number;\n /**\n * Google Pay API minor version, typically `0`.\n */\n apiVersionMinor?: number;\n /**\n * Allowed payment method configurations.\n */\n allowedPaymentMethods?: GooglePayAllowedPaymentMethod[];\n /**\n * Merchant information displayed in the Google Pay sheet.\n */\n merchantInfo?: GooglePayMerchantInfo;\n /**\n * Transaction details (amount, currency, etc).\n */\n transactionInfo?: GooglePayTransactionInfo;\n /**\n * Forward-compatible escape hatch for additional fields supported by Google Pay.\n */\n [key: string]: unknown;\n}\n\nexport interface GooglePayAvailabilityOptions {\n /**\n * Environment used to construct the Google Payments client. Defaults to `'test'`.\n */\n environment?: GooglePayEnvironment;\n /**\n * Raw `IsReadyToPayRequest` JSON as defined by the Google Pay API.\n * Supply the card networks and auth methods you intend to support at runtime.\n */\n isReadyToPayRequest?: GooglePayIsReadyToPayRequest;\n}\n\nexport interface GooglePayAvailabilityResult {\n /**\n * Indicates whether the Google Pay API is available for the supplied parameters.\n */\n isReady: boolean;\n}\n\nexport interface GooglePayPaymentOptions {\n /**\n * Environment used to construct the Google Payments client. Defaults to `'test'`.\n */\n environment?: GooglePayEnvironment;\n /**\n * Raw `PaymentDataRequest` JSON as defined by the Google Pay API.\n * Provide transaction details, merchant info, and tokenization parameters.\n */\n paymentDataRequest: GooglePayPaymentDataRequest;\n}\n\nexport interface GooglePayPaymentResult {\n /**\n * Payment data returned by Google Pay.\n */\n paymentData: Record<string, unknown>;\n}\n\nexport interface PayAvailabilityOptions {\n apple?: ApplePayAvailabilityOptions;\n google?: GooglePayAvailabilityOptions;\n}\n\nexport interface PayAvailabilityResult {\n available: boolean;\n platform: PayPlatform;\n apple?: ApplePayAvailabilityResult;\n google?: GooglePayAvailabilityResult;\n}\n\nexport interface PayPaymentOptions {\n apple?: ApplePayPaymentOptions;\n google?: GooglePayPaymentOptions;\n}\n\nexport interface PayPaymentResult {\n platform: Exclude<PayPlatform, 'web'>;\n apple?: ApplePayPaymentResult;\n google?: GooglePayPaymentResult;\n}\n\nexport interface PayPlugin {\n /**\n * Checks whether native pay is available on the current platform.\n * On iOS this evaluates Apple Pay, on Android it evaluates Google Pay.\n */\n isPayAvailable(options?: PayAvailabilityOptions): Promise<PayAvailabilityResult>;\n /**\n * Presents the native pay sheet for the current platform.\n * Provide the Apple Pay configuration on iOS and the Google Pay configuration on Android.\n */\n requestPayment(options: PayPaymentOptions): Promise<PayPaymentResult>;\n\n /**\n * Get the native Capacitor plugin version\n *\n * @returns {Promise<{ id: string }>} an Promise with version for this device\n * @throws An error if the something went wrong\n */\n getPluginVersion(): Promise<{ version: string }>;\n}\n"]}
@@ -72,6 +72,46 @@ Your server must broker the merchant validation handshake before the device can
72
72
  - Provide a list of networks (`supportedNetworks`) that matches the networks approved by your processor.
73
73
  - Include realistic summary items and ensure the total is a final amount.
74
74
 
75
+ ## Recurring payments (subscriptions)
76
+
77
+ This plugin supports Apple Pay recurring payments on **iOS 16+** via `recurringPaymentRequest`.
78
+
79
+ Key points:
80
+
81
+ - You still provide `paymentSummaryItems` (what’s shown in the sheet).
82
+ - The recurring metadata is provided via `recurringPaymentRequest`.
83
+ - If you pass `recurringPaymentRequest` on iOS 15 or earlier, the plugin rejects the call.
84
+
85
+ Example:
86
+
87
+ ```ts
88
+ import { Pay } from '@capgo/capacitor-pay';
89
+
90
+ await Pay.requestPayment({
91
+ apple: {
92
+ merchantIdentifier: 'merchant.com.example.app',
93
+ countryCode: 'US',
94
+ currencyCode: 'USD',
95
+ supportedNetworks: ['visa', 'masterCard'],
96
+ paymentSummaryItems: [
97
+ { label: 'Pro Plan', amount: '9.99' },
98
+ { label: 'Example Store', amount: '9.99' },
99
+ ],
100
+ recurringPaymentRequest: {
101
+ paymentDescription: 'Pro Plan Subscription',
102
+ managementURL: 'https://example.com/account/subscription',
103
+ regularBilling: {
104
+ label: 'Pro Plan',
105
+ amount: '9.99',
106
+ intervalUnit: 'month',
107
+ intervalCount: 1,
108
+ startDate: Date.now(),
109
+ },
110
+ },
111
+ },
112
+ });
113
+ ```
114
+
75
115
  ## 9. Build and test on device
76
116
 
77
117
  - Apple Pay is unavailable on the iOS simulator. Use a real device signed into an Apple ID with a supported card in Wallet.
@@ -61,6 +61,60 @@ Handle the encrypted payment data server-side before charging the customer:
61
61
  - `merchantInfo` for user-facing display
62
62
  3. Provide this JSON to `Pay.requestPayment({ google: { ... } })`.
63
63
 
64
+ ## Subscriptions / recurring charges
65
+
66
+ Google Pay itself returns a **payment token** (or gateway payload). Subscriptions are typically implemented by:
67
+
68
+ 1. Collecting a token once using `Pay.requestPayment`.
69
+ 2. Sending the token to your backend.
70
+ 3. Creating and managing recurring charges with your PSP/gateway (Stripe/Adyen/Braintree/etc).
71
+
72
+ Example `paymentDataRequest` (gateway tokenization):
73
+
74
+ ```ts
75
+ import { Pay, type GooglePayPaymentDataRequest } from '@capgo/capacitor-pay';
76
+
77
+ const paymentDataRequest: GooglePayPaymentDataRequest = {
78
+ apiVersion: 2,
79
+ apiVersionMinor: 0,
80
+ allowedPaymentMethods: [
81
+ {
82
+ type: 'CARD',
83
+ parameters: {
84
+ allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
85
+ allowedCardNetworks: ['AMEX', 'DISCOVER', 'MASTERCARD', 'VISA'],
86
+ },
87
+ tokenizationSpecification: {
88
+ type: 'PAYMENT_GATEWAY',
89
+ parameters: {
90
+ gateway: 'example',
91
+ gatewayMerchantId: 'exampleGatewayMerchantId',
92
+ },
93
+ },
94
+ },
95
+ ],
96
+ merchantInfo: {
97
+ merchantId: '01234567890123456789',
98
+ merchantName: 'Example Merchant',
99
+ },
100
+ transactionInfo: {
101
+ totalPriceStatus: 'FINAL',
102
+ totalPrice: '9.99',
103
+ currencyCode: 'USD',
104
+ countryCode: 'US',
105
+ },
106
+ };
107
+
108
+ const result = await Pay.requestPayment({
109
+ google: {
110
+ environment: 'test',
111
+ paymentDataRequest,
112
+ },
113
+ });
114
+
115
+ // Send `result.google?.paymentData` to your backend and use your PSP to start the subscription.
116
+ ```
117
+
64
118
  ## 8. Use the correct environment
65
119
 
66
120
  - During development, set `environment: 'test'` and rely on test card numbers.
@@ -5,7 +5,7 @@ import PassKit
5
5
 
6
6
  @objc(PayPlugin)
7
7
  public class PayPlugin: CAPPlugin, CAPBridgedPlugin, PKPaymentAuthorizationControllerDelegate {
8
- private let pluginVersion: String = "8.0.12"
8
+ private let pluginVersion: String = "8.1.0"
9
9
  public let identifier = "PayPlugin"
10
10
  public let jsName = "Pay"
11
11
  public let pluginMethods: [CAPPluginMethod] = [
@@ -192,9 +192,196 @@ public class PayPlugin: CAPPlugin, CAPBridgedPlugin, PKPaymentAuthorizationContr
192
192
  }
193
193
  }
194
194
 
195
+ if let recurringOptions = options["recurringPaymentRequest"] as? [String: Any] {
196
+ if #available(iOS 16.0, *) {
197
+ paymentRequest.recurringPaymentRequest = try buildRecurringPaymentRequest(from: recurringOptions)
198
+ } else {
199
+ throw PayPluginError.invalidConfiguration("`recurringPaymentRequest` requires iOS 16 or later.")
200
+ }
201
+ }
202
+
195
203
  return paymentRequest
196
204
  }
197
205
 
206
+ @available(iOS 16.0, *)
207
+ /// Builds a PassKit recurring payment request (`PKRecurringPaymentRequest`) from the JS options object.
208
+ private func buildRecurringPaymentRequest(from options: [String: Any]) throws -> PKRecurringPaymentRequest {
209
+ guard let paymentDescription = options["paymentDescription"] as? String, !paymentDescription.isEmpty else {
210
+ throw PayPluginError.invalidConfiguration("`recurringPaymentRequest.paymentDescription` is required.")
211
+ }
212
+
213
+ let regularBilling = try recurringPaymentSummaryItem(from: options["regularBilling"], fieldName: "recurringPaymentRequest.regularBilling")
214
+
215
+ guard let managementURLString = options["managementURL"] as? String,
216
+ let managementURL = URL(string: managementURLString) else {
217
+ throw PayPluginError.invalidConfiguration("`recurringPaymentRequest.managementURL` must be a valid URL string.")
218
+ }
219
+
220
+ let recurringRequest = PKRecurringPaymentRequest(
221
+ paymentDescription: paymentDescription,
222
+ regularBilling: regularBilling,
223
+ managementURL: managementURL
224
+ )
225
+
226
+ if let billingAgreement = options["billingAgreement"] as? String, !billingAgreement.isEmpty {
227
+ recurringRequest.billingAgreement = billingAgreement
228
+ }
229
+
230
+ if let tokenNotificationURLValue = options["tokenNotificationURL"] {
231
+ guard let tokenNotificationURLString = tokenNotificationURLValue as? String,
232
+ let tokenNotificationURL = URL(string: tokenNotificationURLString) else {
233
+ throw PayPluginError.invalidConfiguration(
234
+ "`recurringPaymentRequest.tokenNotificationURL` must be a valid URL string when provided."
235
+ )
236
+ }
237
+ recurringRequest.tokenNotificationURL = tokenNotificationURL
238
+ }
239
+
240
+ if let trialBillingRaw = options["trialBilling"] {
241
+ recurringRequest.trialBilling = try recurringPaymentSummaryItem(
242
+ from: trialBillingRaw,
243
+ fieldName: "recurringPaymentRequest.trialBilling"
244
+ )
245
+ }
246
+
247
+ return recurringRequest
248
+ }
249
+
250
+ @available(iOS 16.0, *)
251
+ /// Parses and validates a recurring payment summary item (regular or trial billing).
252
+ private func recurringPaymentSummaryItem(from value: Any?, fieldName: String) throws -> PKRecurringPaymentSummaryItem {
253
+ guard let rawItem = value as? [String: Any],
254
+ let label = rawItem["label"] as? String,
255
+ let amountString = rawItem["amount"] as? String else {
256
+ throw PayPluginError.invalidConfiguration("`\(fieldName)` must include `label` and `amount`.")
257
+ }
258
+
259
+ let amount = NSDecimalNumber(string: amountString)
260
+ if amount == NSDecimalNumber.notANumber {
261
+ throw PayPluginError.invalidConfiguration("`\(fieldName).amount` must be a valid decimal string.")
262
+ }
263
+
264
+ let item = PKRecurringPaymentSummaryItem(label: label, amount: amount)
265
+
266
+ if let typeString = rawItem["type"] as? String {
267
+ switch typeString.lowercased() {
268
+ case "pending":
269
+ item.type = .pending
270
+ default:
271
+ item.type = .final
272
+ }
273
+ }
274
+
275
+ if let intervalUnitRaw = rawItem["intervalUnit"] ?? rawItem["recurringPaymentIntervalUnit"],
276
+ let intervalUnit = parseRecurringIntervalUnit(from: intervalUnitRaw) {
277
+ item.intervalUnit = intervalUnit
278
+ } else {
279
+ throw PayPluginError.invalidConfiguration("`\(fieldName).intervalUnit` is required.")
280
+ }
281
+
282
+ if let intervalCountRaw = rawItem["intervalCount"] ?? rawItem["recurringPaymentIntervalCount"] {
283
+ if let intervalCount = parseInt(from: intervalCountRaw), intervalCount > 0 {
284
+ item.intervalCount = intervalCount
285
+ } else {
286
+ throw PayPluginError.invalidConfiguration("`\(fieldName).intervalCount` must be a positive integer.")
287
+ }
288
+ } else {
289
+ throw PayPluginError.invalidConfiguration("`\(fieldName).intervalCount` is required.")
290
+ }
291
+
292
+ if let startDateRaw = rawItem["startDate"] ?? rawItem["recurringPaymentStartDate"] {
293
+ guard let startDate = parseDate(from: startDateRaw) else {
294
+ throw PayPluginError.invalidConfiguration("`\(fieldName).startDate` must be a valid date.")
295
+ }
296
+ item.startDate = startDate
297
+ }
298
+
299
+ if let endDateRaw = rawItem["endDate"] ?? rawItem["recurringPaymentEndDate"] {
300
+ guard let endDate = parseDate(from: endDateRaw) else {
301
+ throw PayPluginError.invalidConfiguration("`\(fieldName).endDate` must be a valid date.")
302
+ }
303
+ item.endDate = endDate
304
+ }
305
+
306
+ return item
307
+ }
308
+
309
+ @available(iOS 16.0, *)
310
+ /// Maps string values used by Apple Pay on the Web to `NSCalendar.Unit` values required by PassKit.
311
+ private func parseRecurringIntervalUnit(from value: Any) -> NSCalendar.Unit? {
312
+ guard let stringValue = value as? String else {
313
+ return nil
314
+ }
315
+
316
+ switch stringValue.lowercased() {
317
+ case "day":
318
+ return .day
319
+ case "week":
320
+ return .weekOfYear
321
+ case "month":
322
+ return .month
323
+ case "year":
324
+ return .year
325
+ default:
326
+ return nil
327
+ }
328
+ }
329
+
330
+ /// Parses a positive integer from common JS number representations.
331
+ private func parseInt(from value: Any) -> Int? {
332
+ if let intValue = value as? Int {
333
+ return intValue
334
+ }
335
+ if let doubleValue = value as? Double {
336
+ guard doubleValue.isFinite,
337
+ doubleValue.rounded() == doubleValue,
338
+ doubleValue >= Double(Int.min),
339
+ doubleValue <= Double(Int.max) else {
340
+ return nil
341
+ }
342
+ return Int(doubleValue)
343
+ }
344
+ if let stringValue = value as? String {
345
+ return Int(stringValue)
346
+ }
347
+ return nil
348
+ }
349
+
350
+ /// Parses a date from a JS value.
351
+ /// - For numbers, expects **milliseconds since Unix epoch**.
352
+ /// - For strings, accepts ISO 8601 and `yyyy-MM-dd` (UTC) formats.
353
+ private func parseDate(from value: Any) -> Date? {
354
+ if let doubleValue = value as? Double {
355
+ return parseDate(fromUnixNumeric: doubleValue)
356
+ }
357
+ if let intValue = value as? Int {
358
+ return parseDate(fromUnixNumeric: Double(intValue))
359
+ }
360
+ if let stringValue = value as? String {
361
+ let iso = ISO8601DateFormatter()
362
+ if let parsed = iso.date(from: stringValue) {
363
+ return parsed
364
+ }
365
+
366
+ // Common "YYYY-MM-DD" input used by Apple Pay examples.
367
+ let df = DateFormatter()
368
+ df.locale = Locale(identifier: "en_US_POSIX")
369
+ df.timeZone = TimeZone(secondsFromGMT: 0)
370
+ df.dateFormat = "yyyy-MM-dd"
371
+ return df.date(from: stringValue)
372
+ }
373
+
374
+ return nil
375
+ }
376
+
377
+ /// Parses a numeric date as **milliseconds since Unix epoch** (per the public TS contract).
378
+ private func parseDate(fromUnixNumeric value: Double) -> Date? {
379
+ guard value.isFinite else {
380
+ return nil
381
+ }
382
+ return Date(timeIntervalSince1970: value / 1000.0)
383
+ }
384
+
198
385
  private func paymentSummaryItems(from value: Any?) -> [PKPaymentSummaryItem] {
199
386
  guard let items = value as? [Any] else {
200
387
  return []
@@ -233,12 +420,42 @@ public class PayPlugin: CAPPlugin, CAPBridgedPlugin, PKPaymentAuthorizationContr
233
420
 
234
421
  return networkStrings.compactMap { element in
235
422
  if let stringValue = element as? String {
236
- return PKPaymentNetwork(rawValue: stringValue)
423
+ return PKPaymentNetwork(rawValue: normalizePaymentNetwork(stringValue))
237
424
  }
238
425
  return nil
239
426
  }
240
427
  }
241
428
 
429
+ private func normalizePaymentNetwork(_ value: String) -> String {
430
+ let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines)
431
+ let key = trimmed.lowercased()
432
+
433
+ // Accept common Apple Pay on the Web identifiers too.
434
+ // PassKit network raw values are case-sensitive (for example "Visa", "MasterCard", "AmEx").
435
+ switch key {
436
+ case "visa":
437
+ return PKPaymentNetwork.visa.rawValue
438
+ case "mastercard":
439
+ return PKPaymentNetwork.masterCard.rawValue
440
+ case "amex":
441
+ return PKPaymentNetwork.amex.rawValue
442
+ case "discover":
443
+ return PKPaymentNetwork.discover.rawValue
444
+ case "jcb":
445
+ return PKPaymentNetwork.JCB.rawValue
446
+ case "vpay":
447
+ return PKPaymentNetwork.vPay.rawValue
448
+ case "maestro":
449
+ return PKPaymentNetwork.maestro.rawValue
450
+ case "girocard":
451
+ return PKPaymentNetwork.girocard.rawValue
452
+ case "mada":
453
+ return PKPaymentNetwork.mada.rawValue
454
+ default:
455
+ return trimmed
456
+ }
457
+ }
458
+
242
459
  private func parseMerchantCapabilities(from values: [String]) -> PKMerchantCapability {
243
460
  var capabilities: PKMerchantCapability = []
244
461
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-pay",
3
- "version": "8.0.12",
3
+ "version": "8.1.0",
4
4
  "description": "Capacitor plugin to trigger native payment for iOS(Apple pay) and Android(Google Pay)",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",
@@ -35,20 +35,20 @@
35
35
  "Native payment"
36
36
  ],
37
37
  "scripts": {
38
- "verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
38
+ "verify": "bun run verify:ios && bun run verify:android && bun run verify:web",
39
39
  "verify:ios": "xcodebuild -scheme CapgoCapacitorPay -destination generic/platform=iOS",
40
40
  "verify:android": "cd android && ./gradlew clean build test && cd ..",
41
- "verify:web": "npm run build",
42
- "lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
43
- "fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --fix --format",
41
+ "verify:web": "bun run build",
42
+ "lint": "bun run eslint && bun run prettier -- --check && bun run swiftlint -- lint",
43
+ "fmt": "bun run eslint -- --fix && bun run prettier -- --write && bun run swiftlint -- --fix --format",
44
44
  "eslint": "eslint . --ext ts",
45
45
  "prettier": "prettier-pretty-check \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
46
46
  "swiftlint": "node-swiftlint",
47
47
  "docgen": "docgen --api PayPlugin --output-readme README.md --output-json dist/docs.json",
48
- "build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
48
+ "build": "bun run clean && bun run docgen && tsc && rollup -c rollup.config.mjs",
49
49
  "clean": "rimraf ./dist",
50
50
  "watch": "tsc --watch",
51
- "prepublishOnly": "npm run build",
51
+ "prepublishOnly": "bun run build",
52
52
  "check:wiring": "node scripts/check-capacitor-plugin-wiring.mjs"
53
53
  },
54
54
  "devDependencies": {