Skip to content

Commit

Permalink
Merge pull request #342 from yllaw/capacitor-stripe-terminal/confirmP…
Browse files Browse the repository at this point in the history
…aymentIntent

Add confirmPaymentIntent to process payments via StripeTerminal
  • Loading branch information
rdlabo authored Mar 19, 2024
2 parents 5f3183b + cb8762f commit 0f3caf9
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 16 deletions.
40 changes: 32 additions & 8 deletions packages/terminal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ And update minSdkVersion to 26 And compileSdkVersion to 34 in your `android/app/
await StripeTerminal.connectReader({
reader: readers[0],
});
// Collect payment intent
await StripeTerminal.collect({ paymentIntent: "**************" });
// Process and confirm payment intent
await StripeTerminal.confirmPaymentIntent();
});
```

Expand All @@ -94,7 +97,10 @@ And update minSdkVersion to 26 And compileSdkVersion to 34 in your `android/app/
await StripeTerminal.connectReader({
reader: readers[0],
});
// Collect payment intent
await StripeTerminal.collect({ paymentIntent: "**************" });
// Process and confirm payment intent
await StripeTerminal.confirmPaymentIntent();
});
````

Expand All @@ -115,7 +121,8 @@ And update minSdkVersion to 26 And compileSdkVersion to 34 in your `android/app/
* [`addListener(TerminalEventsEnum.RequestedConnectionToken, ...)`](#addlistenerterminaleventsenumrequestedconnectiontoken)
* [`addListener(TerminalEventsEnum.DiscoveredReaders, ...)`](#addlistenerterminaleventsenumdiscoveredreaders)
* [`addListener(TerminalEventsEnum.ConnectedReader, ...)`](#addlistenerterminaleventsenumconnectedreader)
* [`addListener(TerminalEventsEnum.Completed, ...)`](#addlistenerterminaleventsenumcompleted)
* [`addListener(TerminalEventsEnum.ConfirmedPaymentIntent, ...)`](#addlistenerterminaleventsenumconfirmedpaymentintent)
* [`addListener(TerminalEventsEnum.CollectedPaymentIntent, ...)`](#addlistenerterminaleventsenumcollectedpaymentintent)
* [`addListener(TerminalEventsEnum.Canceled, ...)`](#addlistenerterminaleventsenumcanceled)
* [`addListener(TerminalEventsEnum.Failed, ...)`](#addlistenerterminaleventsenumfailed)
* [Interfaces](#interfaces)
Expand Down Expand Up @@ -296,16 +303,32 @@ addListener(eventName: TerminalEventsEnum.ConnectedReader, listenerFunc: () => v
--------------------


### addListener(TerminalEventsEnum.Completed, ...)
### addListener(TerminalEventsEnum.ConfirmedPaymentIntent, ...)

```typescript
addListener(eventName: TerminalEventsEnum.Completed, listenerFunc: () => void) => PluginListenerHandle
addListener(eventName: TerminalEventsEnum.ConfirmedPaymentIntent, listenerFunc: () => void) => PluginListenerHandle
```

| Param | Type |
| ------------------ | --------------------------------------------------------------------------- |
| **`eventName`** | <code><a href="#terminaleventsenum">TerminalEventsEnum.Completed</a></code> |
| **`listenerFunc`** | <code>() =&gt; void</code> |
| Param | Type |
| ------------------ | ---------------------------------------------------------------------------------------- |
| **`eventName`** | <code><a href="#terminaleventsenum">TerminalEventsEnum.ConfirmedPaymentIntent</a></code> |
| **`listenerFunc`** | <code>() =&gt; void</code> |

**Returns:** <code><a href="#pluginlistenerhandle">PluginListenerHandle</a></code>

--------------------


### addListener(TerminalEventsEnum.CollectedPaymentIntent, ...)

```typescript
addListener(eventName: TerminalEventsEnum.CollectedPaymentIntent, listenerFunc: () => void) => PluginListenerHandle
```

| Param | Type |
| ------------------ | ---------------------------------------------------------------------------------------- |
| **`eventName`** | <code><a href="#terminaleventsenum">TerminalEventsEnum.CollectedPaymentIntent</a></code> |
| **`listenerFunc`** | <code>() =&gt; void</code> |

**Returns:** <code><a href="#pluginlistenerhandle">PluginListenerHandle</a></code>

Expand Down Expand Up @@ -385,7 +408,8 @@ addListener(eventName: TerminalEventsEnum.Failed, listenerFunc: () => void) => P
| **`CancelDiscoveredReaders`** | <code>'terminalCancelDiscoveredReaders'</code> |
| **`ConnectedReader`** | <code>'terminalConnectedReader'</code> |
| **`DisconnectedReader`** | <code>'terminalDisconnectedReader'</code> |
| **`Completed`** | <code>'terminalCompleted'</code> |
| **`ConfirmedPaymentIntent`** | <code>'terminalConfirmedPaymentIntent'</code> |
| **`CollectedPaymentIntent`** | <code>'terminalCollectedPaymentIntent'</code> |
| **`Canceled`** | <code>'terminalCanceled'</code> |
| **`Failed`** | <code>'terminalFailed'</code> |
| **`RequestedConnectionToken`** | <code>'terminalRequestedConnectionToken'</code> |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,11 @@ public class StripeTerminal extends Executor {
private List<Reader> readers;
private String locationId;
private PluginCall collectCall;
private PluginCall confirmPaymentIntentCall;
private final JSObject emptyObject = new JSObject();
private Boolean isTest;
private TerminalConnectTypes terminalConnectType;
private PaymentIntent paymentIntentInstance;

public StripeTerminal(
Supplier<Context> contextSupplier,
Expand Down Expand Up @@ -336,7 +338,8 @@ public void onFailure(@NonNull TerminalException ex) {
@Override
public void onSuccess(PaymentIntent paymentIntent) {
collectCancelable = null;
notifyListeners(TerminalEnumEvent.Completed.getWebEventName(), emptyObject);
paymentIntentInstance = paymentIntent;
notifyListeners(TerminalEnumEvent.CollectedPaymentIntent.getWebEventName(), emptyObject);

PaymentMethod pm = paymentIntent.getPaymentMethod();
CardPresentDetails card = pm.getCardPresentDetails() != null ? pm.getCardPresentDetails() : pm.getInteracPresentDetails();
Expand Down Expand Up @@ -370,6 +373,31 @@ public void onFailure(@NonNull TerminalException ex) {
}
};

public void confirmPaymentIntent(final PluginCall call) {
if (this.paymentIntentInstance == null) {
call.reject("PaymentIntent not found for confirmPaymentIntent. Use collect method first and try again.");
return;
}

this.confirmPaymentIntentCall = call;
Terminal.getInstance().confirmPaymentIntent(this.paymentIntentInstance, confirmPaymentMethodCallback);
}

private final PaymentIntentCallback confirmPaymentMethodCallback = new PaymentIntentCallback() {
@Override
public void onSuccess(PaymentIntent paymentIntent) {
notifyListeners(TerminalEnumEvent.ConfirmedPaymentIntent.getWebEventName(), emptyObject);
paymentIntentInstance = null;
confirmPaymentIntentCall.resolve();
}

@Override
public void onFailure(TerminalException exception) {
notifyListeners(TerminalEnumEvent.Failed.getWebEventName(), emptyObject);
confirmPaymentIntentCall.reject(exception.getLocalizedMessage());
}
};

private ReaderCallback readerCallback(final PluginCall call) {
return new ReaderCallback() {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,9 @@ public void collect(PluginCall call) {
public void cancelCollect(final PluginCall call) {
this.implementation.cancelCollect(call);
}

@PluginMethod
public void confirmPaymentIntent(PluginCall call) {
this.implementation.confirmPaymentIntent(call);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ enum class TerminalEnumEvent(val webEventName: String) {
CancelDiscoveredReaders("terminalCancelDiscoveredReaders"),
ConnectedReader("terminalConnectedReader"),
DisconnectedReader("terminalDisconnectedReader"),
Completed("terminalCompleted"),
ConfirmedPaymentIntent("terminalConfirmedPaymentIntent"),
CollectedPaymentIntent("terminalCollectedPaymentIntent"),
Canceled("terminalCanceled"),
Failed("terminalFailed"),
RequestedConnectionToken("terminalRequestedConnectionToken"),
Expand Down
8 changes: 8 additions & 0 deletions packages/terminal/ios/Plugin.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
50ADFFA42020D75100D50D53 /* Capacitor.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50ADFFA52020D75100D50D53 /* Capacitor.framework */; };
50ADFFA82020EE4F00D50D53 /* StripeTerminalPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 50ADFFA72020EE4F00D50D53 /* StripeTerminalPlugin.m */; };
50E1A94820377CB70090CE1A /* StripeTerminalPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E1A94720377CB70090CE1A /* StripeTerminalPlugin.swift */; };
A98C923F2BA2484200A09466 /* TerminalConnectTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C923D2BA2484200A09466 /* TerminalConnectTypes.swift */; };
A98C92402BA2484200A09466 /* TerminalEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C923E2BA2484200A09466 /* TerminalEvents.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -43,6 +45,8 @@
5E23F77F099397094342571A /* Pods-Plugin.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Plugin.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Plugin/Pods-Plugin.debug.xcconfig"; sourceTree = "<group>"; };
91781294A431A2A7CC6EB714 /* Pods-Plugin.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Plugin.release.xcconfig"; path = "Pods/Target Support Files/Pods-Plugin/Pods-Plugin.release.xcconfig"; sourceTree = "<group>"; };
96ED1B6440D6672E406C8D19 /* Pods-PluginTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PluginTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.debug.xcconfig"; sourceTree = "<group>"; };
A98C923D2BA2484200A09466 /* TerminalConnectTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TerminalConnectTypes.swift; sourceTree = "<group>"; };
A98C923E2BA2484200A09466 /* TerminalEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TerminalEvents.swift; sourceTree = "<group>"; };
F65BB2953ECE002E1EF3E424 /* Pods-PluginTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PluginTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.release.xcconfig"; sourceTree = "<group>"; };
F6753A823D3815DB436415E3 /* Pods_PluginTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PluginTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -93,6 +97,8 @@
isa = PBXGroup;
children = (
50E1A94720377CB70090CE1A /* StripeTerminalPlugin.swift */,
A98C923D2BA2484200A09466 /* TerminalConnectTypes.swift */,
A98C923E2BA2484200A09466 /* TerminalEvents.swift */,
2F98D68124C9AAE400613A4C /* StripeTerminal.swift */,
50ADFF8B201F53D600D50D53 /* StripeTerminalPlugin.h */,
50ADFFA72020EE4F00D50D53 /* StripeTerminalPlugin.m */,
Expand Down Expand Up @@ -308,8 +314,10 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A98C923F2BA2484200A09466 /* TerminalConnectTypes.swift in Sources */,
50E1A94820377CB70090CE1A /* StripeTerminalPlugin.swift in Sources */,
2F98D68224C9AAE500613A4C /* StripeTerminal.swift in Sources */,
A98C92402BA2484200A09466 /* TerminalEvents.swift in Sources */,
50ADFFA82020EE4F00D50D53 /* StripeTerminalPlugin.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
23 changes: 22 additions & 1 deletion packages/terminal/ios/Plugin/StripeTerminal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class StripeTerminal: NSObject, DiscoveryDelegate, LocalMobileReaderDeleg
var collectCancelable: Cancelable?
var type: DiscoveryMethod?
var isInitialize: Bool = false
var paymentIntent: PaymentIntent?

var readers: [Reader]?

Expand Down Expand Up @@ -192,7 +193,8 @@ public class StripeTerminal: NSObject, DiscoveryDelegate, LocalMobileReaderDeleg
self.plugin?.notifyListeners(TerminalEvents.Failed.rawValue, data: [:])
call.reject(error.localizedDescription)
} else if let paymentIntent = collectResult {
self.plugin?.notifyListeners(TerminalEvents.Completed.rawValue, data: [:])
self.plugin?.notifyListeners(TerminalEvents.CollectedPaymentIntent.rawValue, data: [:])
self.paymentIntent = paymentIntent
call.resolve()
}
}
Expand All @@ -208,6 +210,7 @@ public class StripeTerminal: NSObject, DiscoveryDelegate, LocalMobileReaderDeleg
} else {
self.plugin?.notifyListeners(TerminalEvents.Canceled.rawValue, data: [:])
self.collectCancelable = nil
self.paymentIntent = nil
call.resolve()
}
}
Expand All @@ -216,6 +219,24 @@ public class StripeTerminal: NSObject, DiscoveryDelegate, LocalMobileReaderDeleg
call.resolve()
}

public func confirmPaymentIntent(_ call: CAPPluginCall) {
if let paymentIntent = self.paymentIntent {
Terminal.shared.confirmPaymentIntent(paymentIntent) { confirmResult, confirmError in
if let error = confirmError {
print("confirmPaymentIntent failed: \(error)")
self.plugin?.notifyListeners(TerminalEvents.Failed.rawValue, data: [:])
call.reject(error.localizedDescription)
} else if let confirmedIntent = confirmResult {
print("PaymentIntent confirmed: \(confirmedIntent)")
self.plugin?.notifyListeners(TerminalEvents.ConfirmedPaymentIntent.rawValue, data: [:])
call.resolve()
}
}
} else {
call.reject("PaymentIntent not found for confirmPaymentIntent. Use collect method first and try again.")
}
}

// localMobile

public func localMobileReader(_ reader: Reader, didStartInstallingUpdate update: ReaderSoftwareUpdate, cancelable: Cancelable?) {
Expand Down
1 change: 1 addition & 0 deletions packages/terminal/ios/Plugin/StripeTerminalPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
CAP_PLUGIN_METHOD(disconnectReader, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(collect, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(cancelCollect, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(confirmPaymentIntent, CAPPluginReturnPromise);
)
4 changes: 4 additions & 0 deletions packages/terminal/ios/Plugin/StripeTerminalPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,8 @@ public class StripeTerminalPlugin: CAPPlugin {
@objc func cancelCollect(_ call: CAPPluginCall) {
self.implementation.cancelCollect(call)
}

@objc func confirmPaymentIntent(_ call: CAPPluginCall) {
self.implementation.confirmPaymentIntent(call)
}
}
3 changes: 2 additions & 1 deletion packages/terminal/ios/Plugin/TerminalEvents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ public enum TerminalEvents: String {
case DiscoveredReaders = "terminalDiscoveredReaders"
case ConnectedReader = "terminalConnectedReader"
case DisconnectedReader = "terminalDisconnectedReader"
case Completed = "terminalCompleted"
case ConfirmedPaymentIntent = "terminalConfirmedPaymentIntent"
case CollectedPaymentIntent = "terminalCollectedPaymentIntent"
case Canceled = "terminalCanceled"
case Failed = "terminalFailed"
case RequestedConnectionToken = "terminalRequestedConnectionToken"
Expand Down
7 changes: 6 additions & 1 deletion packages/terminal/src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export interface StripeTerminalPlugin {
cancelDiscoverReaders(): Promise<void>;
collect(options: { paymentIntent: string }): Promise<void>;
cancelCollect(): Promise<void>;
confirmPaymentIntent(): Promise<void>;
addListener(
eventName: TerminalEventsEnum.Loaded,
listenerFunc: () => void,
Expand All @@ -51,7 +52,11 @@ export interface StripeTerminalPlugin {
listenerFunc: () => void,
): PluginListenerHandle;
addListener(
eventName: TerminalEventsEnum.Completed,
eventName: TerminalEventsEnum.ConfirmedPaymentIntent,
listenerFunc: () => void,
): PluginListenerHandle;
addListener(
eventName: TerminalEventsEnum.CollectedPaymentIntent,
listenerFunc: () => void,
): PluginListenerHandle;
addListener(
Expand Down
6 changes: 4 additions & 2 deletions packages/terminal/src/events.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ export enum TerminalEventsEnum {
CancelDiscoveredReaders = 'terminalCancelDiscoveredReaders',
ConnectedReader = 'terminalConnectedReader',
DisconnectedReader = 'terminalDisconnectedReader',
Completed = 'terminalCompleted',
ConfirmedPaymentIntent = 'terminalConfirmedPaymentIntent',
CollectedPaymentIntent = 'terminalCollectedPaymentIntent',
Canceled = 'terminalCanceled',
Failed = 'terminalFailed',
RequestedConnectionToken = 'terminalRequestedConnectionToken',
}

export type TerminalResultInterface =
| TerminalEventsEnum.Completed
| TerminalEventsEnum.ConfirmedPaymentIntent
| TerminalEventsEnum.CollectedPaymentIntent
| TerminalEventsEnum.Canceled
| TerminalEventsEnum.Failed;
7 changes: 6 additions & 1 deletion packages/terminal/src/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,16 @@ export class StripeTerminalWeb

async collect(options: { paymentIntent: string }): Promise<void> {
console.log('collect', options);
this.notifyListeners(TerminalEventsEnum.Completed, null);
this.notifyListeners(TerminalEventsEnum.CollectedPaymentIntent, null);
}

async cancelCollect(): Promise<void> {
console.log('cancelCollect');
this.notifyListeners(TerminalEventsEnum.Canceled, null);
}

async confirmPaymentIntent(): Promise<void> {
console.log('confirmPaymentIntent');
this.notifyListeners(TerminalEventsEnum.ConfirmedPaymentIntent, null);
}
}

0 comments on commit 0f3caf9

Please sign in to comment.