@capawesome/capacitor-square-mobile-payments 0.1.4 → 0.1.6
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/Package.swift
CHANGED
|
@@ -22,10 +22,6 @@ let package = Package(
|
|
|
22
22
|
.product(name: "SquareMobilePaymentsSDK", package: "mobile-payments-sdk-ios"),
|
|
23
23
|
.product(name: "MockReaderUI", package: "mobile-payments-sdk-ios")
|
|
24
24
|
],
|
|
25
|
-
path: "ios/Plugin")
|
|
26
|
-
.testTarget(
|
|
27
|
-
name: "SquareMobilePaymentsPluginTests",
|
|
28
|
-
dependencies: ["SquareMobilePaymentsPlugin"],
|
|
29
|
-
path: "ios/PluginTests")
|
|
25
|
+
path: "ios/Plugin")
|
|
30
26
|
]
|
|
31
27
|
)
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Capacitor Square Mobile Payments Plugin
|
|
2
2
|
|
|
3
3
|
Unofficial Capacitor plugin for [Square Mobile Payments SDK](https://developer.squareup.com/docs/mobile-payments-sdk).[^1]
|
|
4
4
|
|
|
@@ -25,6 +25,16 @@ This plugin provides a comprehensive integration with Square's Mobile Payments S
|
|
|
25
25
|
|
|
26
26
|
Missing a feature? Just [open an issue](https://github.com/capawesome-team/capacitor-plugins/issues) and we'll take a look!
|
|
27
27
|
|
|
28
|
+
## Use Cases
|
|
29
|
+
|
|
30
|
+
The Square Mobile Payments plugin is typically used to accept in-person payments in a Capacitor app, for example:
|
|
31
|
+
|
|
32
|
+
- **Point of sale**: Turn your app into a POS system that accepts tap, dip, swipe, and manually entered card payments with Square card readers.
|
|
33
|
+
- **Tap to Pay on iPhone**: Accept contactless payments directly on an iPhone without additional hardware by linking a Square seller account with an Apple ID.
|
|
34
|
+
- **Mobile and pop-up sales**: Pair, monitor, and manage Square readers for markets, food trucks, or events, and process payments offline with automatic sync when connectivity is limited.
|
|
35
|
+
- **Compliant receipts**: Access card details, authorization codes, and EMV data of completed payments to generate compliant receipts.
|
|
36
|
+
- **Testing without hardware**: Use the mock reader in debug builds to test the whole payment flow without a physical reader.
|
|
37
|
+
|
|
28
38
|
## Compatibility
|
|
29
39
|
|
|
30
40
|
| Plugin Version | Capacitor Version | Status |
|
|
@@ -33,6 +43,21 @@ Missing a feature? Just [open an issue](https://github.com/capawesome-team/capac
|
|
|
33
43
|
|
|
34
44
|
## Installation
|
|
35
45
|
|
|
46
|
+
You can use our **AI-Assisted Setup** to install the plugin.
|
|
47
|
+
Add the [Capawesome Skills](https://github.com/capawesome-team/skills) to your AI tool using the following command:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npx skills add capawesome-team/skills --skill capacitor-plugins
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Then use the following prompt:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
Use the `capacitor-plugins` skill from `capawesome-team/skills` to install the `@capawesome/capacitor-square-mobile-payments` plugin in my project.
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If you prefer **Manual Setup**, install the plugin by running the following commands and follow the platform-specific instructions below:
|
|
60
|
+
|
|
36
61
|
```bash
|
|
37
62
|
npm install @capawesome/capacitor-square-mobile-payments
|
|
38
63
|
npx cap sync
|
|
@@ -40,6 +65,38 @@ npx cap sync
|
|
|
40
65
|
|
|
41
66
|
### Android
|
|
42
67
|
|
|
68
|
+
#### SDK Initialization
|
|
69
|
+
|
|
70
|
+
The Square Mobile Payments SDK must be initialized in your `Application` class before using the plugin. Create a custom `Application` class (if you don't already have one) and add the following code:
|
|
71
|
+
|
|
72
|
+
1. Create a file `MainApplication.java` in your app's `android/app/src/main/java/<your-package>/` directory:
|
|
73
|
+
|
|
74
|
+
```java
|
|
75
|
+
package com.example.app;
|
|
76
|
+
|
|
77
|
+
import android.app.Application;
|
|
78
|
+
import com.squareup.sdk.mobilepayments.MobilePaymentsSdk;
|
|
79
|
+
|
|
80
|
+
public class MainApplication extends Application {
|
|
81
|
+
|
|
82
|
+
@Override
|
|
83
|
+
public void onCreate() {
|
|
84
|
+
super.onCreate();
|
|
85
|
+
MobilePaymentsSdk.initialize("YOUR_SQUARE_APPLICATION_ID", this);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Note**: Replace `YOUR_SQUARE_APPLICATION_ID` with your actual Square Application ID.
|
|
91
|
+
|
|
92
|
+
2. Register the custom `Application` class in your `AndroidManifest.xml`:
|
|
93
|
+
|
|
94
|
+
```xml
|
|
95
|
+
<application
|
|
96
|
+
android:name=".MainApplication"
|
|
97
|
+
...>
|
|
98
|
+
```
|
|
99
|
+
|
|
43
100
|
#### Variables
|
|
44
101
|
|
|
45
102
|
If needed, you can define the following project variable in your app's `variables.gradle` file to change the default version of the dependency:
|
|
@@ -122,8 +179,14 @@ No configuration required for this plugin.
|
|
|
122
179
|
|
|
123
180
|
## Usage
|
|
124
181
|
|
|
182
|
+
The following examples show how to initialize and authorize the SDK, pair and list readers, start a payment, read the available card input methods, and listen for payment and reader events.
|
|
183
|
+
|
|
184
|
+
### Initialize and authorize the SDK
|
|
185
|
+
|
|
186
|
+
Initialize the SDK with your Square location ID and authorize it with a Square access token. The `initialize(...)` method must be called before any other method:
|
|
187
|
+
|
|
125
188
|
```typescript
|
|
126
|
-
import { SquareMobilePayments
|
|
189
|
+
import { SquareMobilePayments } from '@capawesome/capacitor-square-mobile-payments';
|
|
127
190
|
|
|
128
191
|
const initializeSDK = async () => {
|
|
129
192
|
await SquareMobilePayments.initialize({
|
|
@@ -134,15 +197,39 @@ const initializeSDK = async () => {
|
|
|
134
197
|
accessToken: 'YOUR_ACCESS_TOKEN',
|
|
135
198
|
});
|
|
136
199
|
};
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Check the authorization state
|
|
203
|
+
|
|
204
|
+
Check whether the SDK is currently authorized, for example on app start:
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
import { SquareMobilePayments } from '@capawesome/capacitor-square-mobile-payments';
|
|
137
208
|
|
|
138
209
|
const checkAuthorization = async () => {
|
|
139
210
|
const { authorized } = await SquareMobilePayments.isAuthorized();
|
|
140
211
|
console.log('Authorized:', authorized);
|
|
141
212
|
};
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Pair a Square reader
|
|
216
|
+
|
|
217
|
+
Start the pairing process. The SDK searches for nearby readers and pairs with the first one found:
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
import { SquareMobilePayments } from '@capawesome/capacitor-square-mobile-payments';
|
|
142
221
|
|
|
143
222
|
const pairReader = async () => {
|
|
144
223
|
await SquareMobilePayments.startPairing();
|
|
145
224
|
};
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### List the paired readers
|
|
228
|
+
|
|
229
|
+
Get all paired readers with their serial number, model, and status:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
import { SquareMobilePayments } from '@capawesome/capacitor-square-mobile-payments';
|
|
146
233
|
|
|
147
234
|
const getReaders = async () => {
|
|
148
235
|
const { readers } = await SquareMobilePayments.getReaders();
|
|
@@ -150,6 +237,14 @@ const getReaders = async () => {
|
|
|
150
237
|
console.log('Reader:', reader.serialNumber, reader.model, reader.status);
|
|
151
238
|
}
|
|
152
239
|
};
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Start a payment
|
|
243
|
+
|
|
244
|
+
Present the payment UI and process a payment with the specified parameters. Only one payment can be active at a time:
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
import { SquareMobilePayments } from '@capawesome/capacitor-square-mobile-payments';
|
|
153
248
|
|
|
154
249
|
const processPayment = async () => {
|
|
155
250
|
await SquareMobilePayments.startPayment({
|
|
@@ -166,6 +261,14 @@ const processPayment = async () => {
|
|
|
166
261
|
},
|
|
167
262
|
});
|
|
168
263
|
};
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Listen for payment events
|
|
267
|
+
|
|
268
|
+
Listen for successful, failed, and cancelled payments to react to the result of a payment flow:
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
import { SquareMobilePayments } from '@capawesome/capacitor-square-mobile-payments';
|
|
169
272
|
|
|
170
273
|
const listenToPaymentEvents = () => {
|
|
171
274
|
SquareMobilePayments.addListener('paymentDidFinish', (event) => {
|
|
@@ -182,6 +285,14 @@ const listenToPaymentEvents = () => {
|
|
|
182
285
|
console.log('Payment cancelled');
|
|
183
286
|
});
|
|
184
287
|
};
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Listen for reader events
|
|
291
|
+
|
|
292
|
+
Listen for reader status changes and changes to the available card input methods:
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
import { SquareMobilePayments } from '@capawesome/capacitor-square-mobile-payments';
|
|
185
296
|
|
|
186
297
|
const listenToReaderEvents = () => {
|
|
187
298
|
SquareMobilePayments.addListener('readerWasAdded', (event) => {
|
|
@@ -196,6 +307,14 @@ const listenToReaderEvents = () => {
|
|
|
196
307
|
console.log('Available methods:', event.cardInputMethods);
|
|
197
308
|
});
|
|
198
309
|
};
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Get the available card input methods
|
|
313
|
+
|
|
314
|
+
Read the card entry methods that are currently available based on the connected readers (e.g. tap, dip, swipe, or keyed entry):
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
import { SquareMobilePayments } from '@capawesome/capacitor-square-mobile-payments';
|
|
199
318
|
|
|
200
319
|
const getAvailableMethods = async () => {
|
|
201
320
|
const { cardInputMethods } = await SquareMobilePayments.getAvailableCardInputMethods();
|
|
@@ -1376,6 +1495,46 @@ Callback to receive payment cancellation notifications.
|
|
|
1376
1495
|
|
|
1377
1496
|
</docgen-api>
|
|
1378
1497
|
|
|
1498
|
+
## FAQ
|
|
1499
|
+
|
|
1500
|
+
### Which platforms are supported by this plugin?
|
|
1501
|
+
|
|
1502
|
+
The plugin supports Android and iOS. There is no Web implementation, since the Square Mobile Payments SDK requires native hardware access to card readers.
|
|
1503
|
+
|
|
1504
|
+
### How can I test payments without a physical card reader?
|
|
1505
|
+
|
|
1506
|
+
Use the `showMockReader()` method to display a mock reader interface for testing payment flows without physical hardware. It is only intended for development and testing purposes and is therefore only available in debug builds. You can hide it again with `hideMockReader()`.
|
|
1507
|
+
|
|
1508
|
+
### What permissions does the plugin require?
|
|
1509
|
+
|
|
1510
|
+
The plugin requires location access to confirm that payments are occurring in a supported Square location, Bluetooth access to connect to Square card readers, and, on iOS, microphone access to receive data from magstripe readers. You can check and request the required permissions with `checkPermissions()` and `requestPermissions()`, and the corresponding privacy descriptions must be added to your `Info.plist` on iOS (see [Installation](#installation)).
|
|
1511
|
+
|
|
1512
|
+
### Does the plugin support Tap to Pay on iPhone?
|
|
1513
|
+
|
|
1514
|
+
Yes, on iOS you can link a Square seller account with an Apple ID using `linkAppleAccount()`, which presents an Apple sheet with the Tap to Pay on iPhone terms and conditions. Use `isDeviceCapable()` to check whether the device supports Tap to Pay on iPhone, and `relinkAppleAccount()` to switch to a different Apple ID.
|
|
1515
|
+
|
|
1516
|
+
### Why do the plugin methods fail before I call any of them?
|
|
1517
|
+
|
|
1518
|
+
The Square Mobile Payments SDK must be initialized natively with your Square Application ID before the plugin can be used: in a custom `Application` class on Android and in the `AppDelegate` on iOS (see [Installation](#installation)). Additionally, `initialize(...)` must be called before any other plugin method, followed by `authorize(...)` with a Square access token.
|
|
1519
|
+
|
|
1520
|
+
### Can I process payments without an internet connection?
|
|
1521
|
+
|
|
1522
|
+
Yes, the plugin supports processing payments online or offline with automatic sync. Note that for offline payments, the payment `id` may be `null` until the payment has been synced.
|
|
1523
|
+
|
|
1524
|
+
### Can I use this plugin with Ionic, React, Vue or Angular?
|
|
1525
|
+
|
|
1526
|
+
Yes, the plugin is framework-agnostic. It works in any Capacitor app regardless of the web framework, including Ionic with Angular, React, or Vue, as well as plain JavaScript projects.
|
|
1527
|
+
|
|
1528
|
+
## Related Plugins
|
|
1529
|
+
|
|
1530
|
+
- [Purchases](https://capawesome.io/docs/sdks/capacitor/purchases/): Support in-app purchases in your Capacitor app.
|
|
1531
|
+
- [Superwall](https://capawesome.io/docs/sdks/capacitor/superwall/): Present remotely-configured paywalls to drive subscriptions.
|
|
1532
|
+
- [Wallet](https://capawesome.io/docs/sdks/capacitor/wallet/): Add passes to Apple Wallet and Google Wallet.
|
|
1533
|
+
|
|
1534
|
+
## Newsletter
|
|
1535
|
+
|
|
1536
|
+
Stay up to date with the latest news and updates about the Capawesome, Capacitor, and Ionic ecosystem by subscribing to our [Capawesome Newsletter](https://cloud.capawesome.io/newsletter/).
|
|
1537
|
+
|
|
1379
1538
|
## Changelog
|
|
1380
1539
|
|
|
1381
1540
|
See [CHANGELOG.md](https://github.com/capawesome-team/capacitor-plugins/blob/main/packages/square-mobile-payments/CHANGELOG.md).
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package io.capawesome.capacitorjs.plugins.squaremobilepayments;
|
|
2
2
|
|
|
3
|
-
import android.
|
|
3
|
+
import android.os.Handler;
|
|
4
|
+
import android.os.Looper;
|
|
4
5
|
import androidx.annotation.NonNull;
|
|
5
6
|
import androidx.annotation.Nullable;
|
|
6
7
|
import com.getcapacitor.JSObject;
|
|
@@ -43,9 +44,15 @@ public class SquareMobilePayments {
|
|
|
43
44
|
@NonNull
|
|
44
45
|
private final SquareMobilePaymentsPlugin plugin;
|
|
45
46
|
|
|
47
|
+
@NonNull
|
|
48
|
+
private final Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
49
|
+
|
|
46
50
|
private boolean isInitialized = false;
|
|
47
51
|
private boolean isAuthorized = false;
|
|
48
52
|
|
|
53
|
+
@Nullable
|
|
54
|
+
private String locationId;
|
|
55
|
+
|
|
49
56
|
@Nullable
|
|
50
57
|
private Object pairingHandle;
|
|
51
58
|
|
|
@@ -58,18 +65,30 @@ public class SquareMobilePayments {
|
|
|
58
65
|
@Nullable
|
|
59
66
|
private CallbackReference availableCardInputMethodsCallbackReference;
|
|
60
67
|
|
|
68
|
+
@Nullable
|
|
69
|
+
private CallbackReference authorizationCallbackReference;
|
|
70
|
+
|
|
61
71
|
public SquareMobilePayments(@NonNull SquareMobilePaymentsPlugin plugin) {
|
|
62
72
|
this.plugin = plugin;
|
|
63
73
|
}
|
|
64
74
|
|
|
65
|
-
private String locationId;
|
|
66
|
-
|
|
67
75
|
public void initialize(@NonNull InitializeOptions options, @NonNull EmptyCallback callback) {
|
|
68
76
|
try {
|
|
69
77
|
this.locationId = options.getLocationId();
|
|
70
|
-
Application application = (Application) plugin.getContext().getApplicationContext();
|
|
71
78
|
|
|
72
|
-
|
|
79
|
+
// SDK must already be initialized in Application.onCreate() with the Square Application ID.
|
|
80
|
+
// Verify the SDK is ready by attempting to access the settings manager.
|
|
81
|
+
try {
|
|
82
|
+
MobilePaymentsSdk.settingsManager();
|
|
83
|
+
} catch (Exception e) {
|
|
84
|
+
callback.error(
|
|
85
|
+
new Exception(
|
|
86
|
+
"Square SDK not initialized. Make sure to call MobilePaymentsSdk.initialize() in your Application.onCreate().",
|
|
87
|
+
e
|
|
88
|
+
)
|
|
89
|
+
);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
73
92
|
|
|
74
93
|
isInitialized = true;
|
|
75
94
|
callback.success();
|
|
@@ -86,13 +105,33 @@ public class SquareMobilePayments {
|
|
|
86
105
|
|
|
87
106
|
String accessToken = options.getAccessToken();
|
|
88
107
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
108
|
+
mainHandler.post(() -> {
|
|
109
|
+
try {
|
|
110
|
+
AuthorizationManager authManager = MobilePaymentsSdk.authorizationManager();
|
|
111
|
+
|
|
112
|
+
authorizationCallbackReference = authManager.authorize(accessToken, locationId, result -> {
|
|
113
|
+
if (result.isSuccess()) {
|
|
114
|
+
isAuthorized = true;
|
|
115
|
+
callback.success();
|
|
116
|
+
} else {
|
|
117
|
+
isAuthorized = false;
|
|
118
|
+
String errorMsg = result.errorMessage();
|
|
119
|
+
if (errorMsg == null || errorMsg.isEmpty()) {
|
|
120
|
+
errorMsg = "Authorization failed";
|
|
121
|
+
}
|
|
122
|
+
if (result.errorCode() != null) {
|
|
123
|
+
errorMsg = errorMsg + " (Error code: " + result.errorCode().toString() + ")";
|
|
124
|
+
}
|
|
125
|
+
callback.error(new Exception(errorMsg));
|
|
126
|
+
}
|
|
127
|
+
if (authorizationCallbackReference != null) {
|
|
128
|
+
authorizationCallbackReference.clear();
|
|
129
|
+
authorizationCallbackReference = null;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
} catch (Exception exception) {
|
|
133
|
+
isAuthorized = false;
|
|
134
|
+
callback.error(exception);
|
|
96
135
|
}
|
|
97
136
|
});
|
|
98
137
|
} catch (Exception exception) {
|
|
@@ -107,9 +146,11 @@ public class SquareMobilePayments {
|
|
|
107
146
|
}
|
|
108
147
|
|
|
109
148
|
AuthorizationManager authManager = MobilePaymentsSdk.authorizationManager();
|
|
110
|
-
boolean
|
|
149
|
+
boolean sdkAuthorized = authManager.getAuthorizationState().isAuthorized();
|
|
111
150
|
|
|
112
|
-
|
|
151
|
+
isAuthorized = sdkAuthorized;
|
|
152
|
+
|
|
153
|
+
IsAuthorizedResult result = new IsAuthorizedResult(sdkAuthorized);
|
|
113
154
|
callback.success(result);
|
|
114
155
|
} catch (Exception exception) {
|
|
115
156
|
callback.error(exception);
|
|
@@ -122,10 +163,16 @@ public class SquareMobilePayments {
|
|
|
122
163
|
throw CustomExceptions.NOT_INITIALIZED;
|
|
123
164
|
}
|
|
124
165
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
166
|
+
mainHandler.post(() -> {
|
|
167
|
+
try {
|
|
168
|
+
AuthorizationManager authManager = MobilePaymentsSdk.authorizationManager();
|
|
169
|
+
authManager.deauthorize();
|
|
170
|
+
isAuthorized = false;
|
|
171
|
+
callback.success();
|
|
172
|
+
} catch (Exception exception) {
|
|
173
|
+
callback.error(exception);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
129
176
|
} catch (Exception exception) {
|
|
130
177
|
callback.error(exception);
|
|
131
178
|
}
|
|
@@ -140,14 +187,20 @@ public class SquareMobilePayments {
|
|
|
140
187
|
throw CustomExceptions.NOT_AUTHORIZED;
|
|
141
188
|
}
|
|
142
189
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
190
|
+
mainHandler.post(() -> {
|
|
191
|
+
try {
|
|
192
|
+
SettingsManager settingsManager = MobilePaymentsSdk.settingsManager();
|
|
193
|
+
settingsManager.showSettings(result -> {
|
|
194
|
+
if (result.isSuccess()) {
|
|
195
|
+
callback.success();
|
|
196
|
+
} else {
|
|
197
|
+
callback.error(new Exception(result.errorMessage()));
|
|
198
|
+
}
|
|
199
|
+
return null;
|
|
200
|
+
});
|
|
201
|
+
} catch (Exception exception) {
|
|
202
|
+
callback.error(exception);
|
|
149
203
|
}
|
|
150
|
-
return null;
|
|
151
204
|
});
|
|
152
205
|
} catch (Exception exception) {
|
|
153
206
|
callback.error(exception);
|
|
@@ -182,31 +235,34 @@ public class SquareMobilePayments {
|
|
|
182
235
|
throw CustomExceptions.NOT_AUTHORIZED;
|
|
183
236
|
}
|
|
184
237
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
238
|
+
mainHandler.post(() -> {
|
|
239
|
+
try {
|
|
240
|
+
ReaderManager readerManager = MobilePaymentsSdk.readerManager();
|
|
241
|
+
|
|
242
|
+
if (readerManager.isPairingInProgress()) {
|
|
243
|
+
throw CustomExceptions.PAIRING_ALREADY_IN_PROGRESS;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
plugin.notifyReaderPairingDidBeginListeners();
|
|
247
|
+
|
|
248
|
+
pairingHandle = readerManager.pairReader(result -> {
|
|
249
|
+
if (result.isSuccess()) {
|
|
250
|
+
plugin.notifyReaderPairingDidSucceedListeners();
|
|
251
|
+
} else {
|
|
252
|
+
ReaderPairingDidFailEvent event = new ReaderPairingDidFailEvent(
|
|
253
|
+
result.errorCode() != null ? result.errorCode().toString() : null,
|
|
254
|
+
result.errorMessage()
|
|
255
|
+
);
|
|
256
|
+
plugin.notifyReaderPairingDidFailListeners(event);
|
|
257
|
+
}
|
|
258
|
+
pairingHandle = null;
|
|
259
|
+
});
|
|
193
260
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
plugin.notifyReaderPairingDidSucceedListeners();
|
|
198
|
-
} else {
|
|
199
|
-
// Notify that pairing failed
|
|
200
|
-
ReaderPairingDidFailEvent event = new ReaderPairingDidFailEvent(
|
|
201
|
-
result.errorCode() != null ? result.errorCode().toString() : null,
|
|
202
|
-
result.errorMessage()
|
|
203
|
-
);
|
|
204
|
-
plugin.notifyReaderPairingDidFailListeners(event);
|
|
261
|
+
callback.success();
|
|
262
|
+
} catch (Exception exception) {
|
|
263
|
+
callback.error(exception);
|
|
205
264
|
}
|
|
206
|
-
pairingHandle = null;
|
|
207
265
|
});
|
|
208
|
-
|
|
209
|
-
callback.success();
|
|
210
266
|
} catch (Exception exception) {
|
|
211
267
|
callback.error(exception);
|
|
212
268
|
}
|
|
@@ -335,24 +391,20 @@ public class SquareMobilePayments {
|
|
|
335
391
|
|
|
336
392
|
PaymentManager paymentManager = MobilePaymentsSdk.paymentManager();
|
|
337
393
|
|
|
338
|
-
// Build Money object
|
|
339
394
|
Money amountMoney = new Money(params.getAmountMoney().getAmount(), CurrencyCode.valueOf(params.getAmountMoney().getCurrency()));
|
|
340
395
|
|
|
341
|
-
// Determine processing mode
|
|
342
396
|
ProcessingMode processingMode = ProcessingMode.AUTO_DETECT;
|
|
343
397
|
if (params.getProcessingMode() != null) {
|
|
344
398
|
processingMode = ProcessingMode.valueOf(params.getProcessingMode());
|
|
345
399
|
}
|
|
346
400
|
|
|
347
|
-
// Determine autocomplete
|
|
348
401
|
boolean autocomplete = params.getAutocomplete() != null ? params.getAutocomplete() : true;
|
|
349
402
|
|
|
350
|
-
// Build PaymentParameters
|
|
351
403
|
PaymentParameters.Builder paramsBuilder = new PaymentParameters.Builder(
|
|
352
404
|
amountMoney,
|
|
353
405
|
params.getPaymentAttemptId(),
|
|
354
406
|
processingMode,
|
|
355
|
-
false
|
|
407
|
+
false
|
|
356
408
|
);
|
|
357
409
|
|
|
358
410
|
paramsBuilder.autocomplete(autocomplete);
|
|
@@ -393,7 +445,6 @@ public class SquareMobilePayments {
|
|
|
393
445
|
|
|
394
446
|
PaymentParameters sdkPaymentParams = paramsBuilder.build();
|
|
395
447
|
|
|
396
|
-
// Build PromptParameters
|
|
397
448
|
PromptMode promptMode = PromptMode.DEFAULT;
|
|
398
449
|
if (promptParams.getMode() != null) {
|
|
399
450
|
promptMode = PromptMode.valueOf(promptParams.getMode());
|
|
@@ -406,28 +457,32 @@ public class SquareMobilePayments {
|
|
|
406
457
|
|
|
407
458
|
PromptParameters sdkPromptParams = new PromptParameters(promptMode, additionalMethods);
|
|
408
459
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
460
|
+
mainHandler.post(() -> {
|
|
461
|
+
try {
|
|
462
|
+
paymentHandle = paymentManager.startPaymentActivity(sdkPaymentParams, sdkPromptParams, result -> {
|
|
463
|
+
if (result.isSuccess()) {
|
|
464
|
+
Payment sdkPayment = result.value();
|
|
465
|
+
io.capawesome.capacitorjs.plugins.squaremobilepayments.classes.results.Payment payment =
|
|
466
|
+
convertSdkPaymentToPayment(sdkPayment);
|
|
467
|
+
|
|
468
|
+
PaymentDidFinishEvent event = new PaymentDidFinishEvent(payment);
|
|
469
|
+
plugin.notifyPaymentDidFinishListeners(event);
|
|
470
|
+
} else {
|
|
471
|
+
PaymentDidFailEvent event = new PaymentDidFailEvent(
|
|
472
|
+
null,
|
|
473
|
+
result.errorCode() != null ? result.errorCode().toString() : null,
|
|
474
|
+
result.errorMessage()
|
|
475
|
+
);
|
|
476
|
+
plugin.notifyPaymentDidFailListeners(event);
|
|
477
|
+
}
|
|
478
|
+
paymentHandle = null;
|
|
479
|
+
});
|
|
416
480
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
PaymentDidFailEvent event = new PaymentDidFailEvent(
|
|
421
|
-
null,
|
|
422
|
-
result.errorCode() != null ? result.errorCode().toString() : null,
|
|
423
|
-
result.errorMessage()
|
|
424
|
-
);
|
|
425
|
-
plugin.notifyPaymentDidFailListeners(event);
|
|
481
|
+
callback.success();
|
|
482
|
+
} catch (Exception exception) {
|
|
483
|
+
callback.error(exception);
|
|
426
484
|
}
|
|
427
|
-
paymentHandle = null;
|
|
428
485
|
});
|
|
429
|
-
|
|
430
|
-
callback.success();
|
|
431
486
|
} catch (Exception exception) {
|
|
432
487
|
callback.error(exception);
|
|
433
488
|
}
|
|
@@ -439,17 +494,23 @@ public class SquareMobilePayments {
|
|
|
439
494
|
throw CustomExceptions.NOT_INITIALIZED;
|
|
440
495
|
}
|
|
441
496
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
497
|
+
mainHandler.post(() -> {
|
|
498
|
+
try {
|
|
499
|
+
if (paymentHandle != null) {
|
|
500
|
+
paymentHandle.cancel();
|
|
501
|
+
paymentHandle = null;
|
|
445
502
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
503
|
+
PaymentDidCancelEvent event = new PaymentDidCancelEvent(null);
|
|
504
|
+
plugin.notifyPaymentDidCancelListeners(event);
|
|
505
|
+
} else {
|
|
506
|
+
throw CustomExceptions.NO_PAYMENT_IN_PROGRESS;
|
|
507
|
+
}
|
|
451
508
|
|
|
452
|
-
|
|
509
|
+
callback.success();
|
|
510
|
+
} catch (Exception exception) {
|
|
511
|
+
callback.error(exception);
|
|
512
|
+
}
|
|
513
|
+
});
|
|
453
514
|
} catch (Exception exception) {
|
|
454
515
|
callback.error(exception);
|
|
455
516
|
}
|
|
@@ -483,15 +544,21 @@ public class SquareMobilePayments {
|
|
|
483
544
|
throw CustomExceptions.NOT_AUTHORIZED;
|
|
484
545
|
}
|
|
485
546
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
547
|
+
mainHandler.post(() -> {
|
|
548
|
+
try {
|
|
549
|
+
Class<?> mockReaderUIClass = Class.forName("com.squareup.sdk.mockreader.ui.MockReaderUI");
|
|
550
|
+
mockReaderUIClass.getMethod("show").invoke(null);
|
|
551
|
+
callback.success();
|
|
552
|
+
} catch (ClassNotFoundException e) {
|
|
553
|
+
callback.error(
|
|
554
|
+
new Exception(
|
|
555
|
+
"MockReaderUI is only available in Debug builds. Please ensure you're using a Debug build configuration."
|
|
556
|
+
)
|
|
557
|
+
);
|
|
558
|
+
} catch (Exception exception) {
|
|
559
|
+
callback.error(exception);
|
|
560
|
+
}
|
|
561
|
+
});
|
|
495
562
|
} catch (Exception exception) {
|
|
496
563
|
callback.error(exception);
|
|
497
564
|
}
|
|
@@ -499,15 +566,21 @@ public class SquareMobilePayments {
|
|
|
499
566
|
|
|
500
567
|
public void hideMockReader(@NonNull EmptyCallback callback) {
|
|
501
568
|
try {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
569
|
+
mainHandler.post(() -> {
|
|
570
|
+
try {
|
|
571
|
+
Class<?> mockReaderUIClass = Class.forName("com.squareup.sdk.mockreader.ui.MockReaderUI");
|
|
572
|
+
mockReaderUIClass.getMethod("hide").invoke(null);
|
|
573
|
+
callback.success();
|
|
574
|
+
} catch (ClassNotFoundException e) {
|
|
575
|
+
callback.error(
|
|
576
|
+
new Exception(
|
|
577
|
+
"MockReaderUI is only available in Debug builds. Please ensure you're using a Debug build configuration."
|
|
578
|
+
)
|
|
579
|
+
);
|
|
580
|
+
} catch (Exception exception) {
|
|
581
|
+
callback.error(exception);
|
|
582
|
+
}
|
|
583
|
+
});
|
|
511
584
|
} catch (Exception exception) {
|
|
512
585
|
callback.error(exception);
|
|
513
586
|
}
|
|
@@ -528,7 +601,6 @@ public class SquareMobilePayments {
|
|
|
528
601
|
sdkReader
|
|
529
602
|
);
|
|
530
603
|
|
|
531
|
-
// Notify based on change type
|
|
532
604
|
if (change == ReaderChangedEvent.Change.ADDED) {
|
|
533
605
|
ReaderWasAddedEvent addedEvent = new ReaderWasAddedEvent(reader);
|
|
534
606
|
plugin.notifyReaderWasAddedListeners(addedEvent);
|
|
@@ -537,7 +609,6 @@ public class SquareMobilePayments {
|
|
|
537
609
|
plugin.notifyReaderWasRemovedListeners(removedEvent);
|
|
538
610
|
}
|
|
539
611
|
|
|
540
|
-
// Also notify general reader changed event
|
|
541
612
|
ReaderDidChangeEvent didChangeEvent = new ReaderDidChangeEvent(reader, convertReaderChangeToString(change));
|
|
542
613
|
plugin.notifyReaderDidChangeListeners(didChangeEvent);
|
|
543
614
|
});
|
|
@@ -572,8 +643,6 @@ public class SquareMobilePayments {
|
|
|
572
643
|
}
|
|
573
644
|
}
|
|
574
645
|
|
|
575
|
-
// Helper methods for converting SDK types to plugin types
|
|
576
|
-
|
|
577
646
|
@Nullable
|
|
578
647
|
private com.squareup.sdk.mobilepayments.cardreader.ReaderInfo findReaderBySerialNumber(@NonNull String serialNumber) {
|
|
579
648
|
ReaderManager readerManager = MobilePaymentsSdk.readerManager();
|
|
@@ -596,8 +665,14 @@ public class SquareMobilePayments {
|
|
|
596
665
|
String model = convertReaderModelToString(sdkReader.getModel());
|
|
597
666
|
String status = convertReaderStatusToString(sdkReader.getStatus());
|
|
598
667
|
String firmwareVersion = sdkReader.getFirmwareVersion();
|
|
599
|
-
|
|
600
|
-
|
|
668
|
+
|
|
669
|
+
Integer batteryLevel = null;
|
|
670
|
+
Boolean isCharging = null;
|
|
671
|
+
com.squareup.sdk.mobilepayments.cardreader.ReaderInfo.BatteryStatus batteryStatus = sdkReader.getBatteryStatus();
|
|
672
|
+
if (batteryStatus != null) {
|
|
673
|
+
batteryLevel = batteryStatus.getPercent();
|
|
674
|
+
isCharging = batteryStatus.isCharging();
|
|
675
|
+
}
|
|
601
676
|
|
|
602
677
|
List<String> supportedCardInputMethods = sdkReader
|
|
603
678
|
.getSupportedCardEntryMethods()
|
|
@@ -638,7 +713,6 @@ public class SquareMobilePayments {
|
|
|
638
713
|
type = "ONLINE";
|
|
639
714
|
status = convertPaymentStatusToString(onlinePayment.getStatus());
|
|
640
715
|
|
|
641
|
-
// Extract card details
|
|
642
716
|
com.squareup.sdk.mobilepayments.payment.CardPaymentDetails sdkCardDetails = onlinePayment.getCardDetails();
|
|
643
717
|
if (sdkCardDetails != null) {
|
|
644
718
|
cardDetails = convertSdkCardDetailsToCardPaymentDetails(sdkCardDetails);
|
|
@@ -649,7 +723,6 @@ public class SquareMobilePayments {
|
|
|
649
723
|
type = "OFFLINE";
|
|
650
724
|
status = "PENDING";
|
|
651
725
|
|
|
652
|
-
// Extract card details
|
|
653
726
|
com.squareup.sdk.mobilepayments.payment.CardPaymentDetails sdkCardDetails = offlinePayment.getCardDetails();
|
|
654
727
|
if (sdkCardDetails != null) {
|
|
655
728
|
cardDetails = convertSdkCardDetailsToCardPaymentDetails(sdkCardDetails);
|
|
@@ -664,13 +737,15 @@ public class SquareMobilePayments {
|
|
|
664
737
|
sdkPayment.getTotalMoney().getCurrencyCode().toString()
|
|
665
738
|
);
|
|
666
739
|
|
|
667
|
-
MoneyResult tipMoney =
|
|
668
|
-
|
|
669
|
-
|
|
740
|
+
MoneyResult tipMoney =
|
|
741
|
+
sdkPayment.getTipMoney() != null
|
|
742
|
+
? new MoneyResult((int) sdkPayment.getTipMoney().getAmount(), sdkPayment.getTipMoney().getCurrencyCode().toString())
|
|
743
|
+
: null;
|
|
670
744
|
|
|
671
|
-
MoneyResult applicationFee =
|
|
672
|
-
|
|
673
|
-
|
|
745
|
+
MoneyResult applicationFee =
|
|
746
|
+
sdkPayment.getAppFeeMoney() != null
|
|
747
|
+
? new MoneyResult((int) sdkPayment.getAppFeeMoney().getAmount(), sdkPayment.getAppFeeMoney().getCurrencyCode().toString())
|
|
748
|
+
: null;
|
|
674
749
|
|
|
675
750
|
return new io.capawesome.capacitorjs.plugins.squaremobilepayments.classes.results.Payment(
|
|
676
751
|
id,
|
|
@@ -770,7 +845,6 @@ public class SquareMobilePayments {
|
|
|
770
845
|
} else if (change == ReaderChangedEvent.Change.REMOVED) {
|
|
771
846
|
return "REMOVED";
|
|
772
847
|
}
|
|
773
|
-
// Default for any other status changes
|
|
774
848
|
return "STATUS_DID_CHANGE";
|
|
775
849
|
}
|
|
776
850
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capawesome/capacitor-square-mobile-payments",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Unofficial Capacitor plugin for Square Mobile Payments SDK.",
|
|
3
|
+
"version": "0.1.6",
|
|
4
|
+
"description": "Unofficial Capacitor plugin for Square Mobile Payments SDK to accept in-person payments on Android and iOS.",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
7
7
|
"types": "dist/esm/index.d.ts",
|
|
@@ -36,7 +36,16 @@
|
|
|
36
36
|
"keywords": [
|
|
37
37
|
"capacitor",
|
|
38
38
|
"plugin",
|
|
39
|
-
"native"
|
|
39
|
+
"native",
|
|
40
|
+
"capacitor-plugin",
|
|
41
|
+
"square",
|
|
42
|
+
"mobile payments",
|
|
43
|
+
"in-person payments",
|
|
44
|
+
"card reader",
|
|
45
|
+
"point of sale",
|
|
46
|
+
"pos",
|
|
47
|
+
"tap to pay",
|
|
48
|
+
"payment processing"
|
|
40
49
|
],
|
|
41
50
|
"scripts": {
|
|
42
51
|
"verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
|
|
@@ -58,24 +67,21 @@
|
|
|
58
67
|
},
|
|
59
68
|
"devDependencies": {
|
|
60
69
|
"@capacitor/android": "8.0.0",
|
|
61
|
-
"@capacitor/cli": "8.
|
|
70
|
+
"@capacitor/cli": "8.4.2",
|
|
62
71
|
"@capacitor/core": "8.0.0",
|
|
63
72
|
"@capacitor/docgen": "0.3.1",
|
|
64
73
|
"@capacitor/ios": "8.0.0",
|
|
65
74
|
"@ionic/eslint-config": "0.4.0",
|
|
66
|
-
"@ionic/swiftlint-config": "2.0.0",
|
|
67
75
|
"eslint": "8.57.0",
|
|
68
|
-
"prettier": "
|
|
69
|
-
"prettier-plugin-java": "2.6.7",
|
|
76
|
+
"prettier-plugin-java": "2.9.7",
|
|
70
77
|
"rimraf": "6.1.2",
|
|
71
|
-
"rollup": "4.
|
|
78
|
+
"rollup": "4.62.3",
|
|
72
79
|
"swiftlint": "2.0.0",
|
|
73
80
|
"typescript": "5.9.3"
|
|
74
81
|
},
|
|
75
82
|
"peerDependencies": {
|
|
76
83
|
"@capacitor/core": ">=8.0.0"
|
|
77
84
|
},
|
|
78
|
-
"swiftlint": "@ionic/swiftlint-config",
|
|
79
85
|
"eslintConfig": {
|
|
80
86
|
"extends": "@ionic/eslint-config/recommended"
|
|
81
87
|
},
|