Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

One-click Payment flow for external developers #29

Merged
merged 11 commits into from
Oct 31, 2024
7 changes: 7 additions & 0 deletions .changeset/brown-planes-wait.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@livechat/agent-app-sdk": minor
"@livechat/helpdesk-sdk": minor
"@livechat/widget-core-sdk": minor
---

Added `startTransaction` for all widget types to support One-click Payment flow
79 changes: 79 additions & 0 deletions packages/agent-app-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,85 @@ createDetailsWidget().then(widget => {

Each widget type offers a different set of events that you can listen to. Check them out in the descriptions below.

## Payments

All widgets allow you to pass a registered charge and display a summary of it to the customer within the payment modal in the Agent App application, enabling them to complete or decline the transaction.

### Events

#### `transaction_accepted`

Emitted when a payment transaction is approved by the customer and successfully processed by the Billing API.

```ts
interface ITransactionAccepted {
chargeId: string;
}
```

#### `transaction_declined`

Emitted when a payment transaction is declined by the customer (e.g., the user closes the payment modal or clicks the cancel button), and the charge is subsequently marked as declined in the Billing API.

```ts
interface ITransactionDeclined {
chargeId: string;
}
```
#### `transaction_failed`

Emitted when a payment transaction fails and cannot be processed by the billing API.

```ts
interface ITransactionAccepted {
error: unknown;
}
```

#### `update_billing_cycle`

This event is triggered when a customer selects a different billing cycle for a transaction. It only emits if the `showBillingCyclePicker` flag is set to `true` in the `metadata` object at the start of the transaction. The event includes the new billing cycle number and key charge details, allowing you to register the updated charge with the provided information.

```ts
interface ITransactionAccepted {
billingCycle: number,
paymentIntent: {
name: string,
price: number,
per_account: boolean,
test: boolean,
return_url: string | null,
months?: number,
trial_days?: number,
quantity?: number,
metadata: {
type: string,
isExternalTransaction: boolean,
showBillingCyclePicker: boolean,
icon: string,
description?: string,
}
}
}
```

### Methods

#### `startTransaction(charge: Charge, metadata: Metadata): Promise<void>`

This method allows you to pass a registered charge and accompanying metadata to the Agent App. The payment modal will then be displayed to the customer, enabling them to complete the transaction. For more information on registering a charge, refer to the [Billing API documentation](https://platform.text.com/docs/monetization/billing-api).

```ts
const charge = {...} // Billing API charge object
const metadata = {
icon: "https://icon.url";
description: "This is a description of the transaction.";
showBillingCyclePicker: true; // optional, use if you want to display the billing cycle picker to the customer
}

widget.startTransaction(charge, metadata);
```

## Details widget (`IDetailsWidget`)

A type of widget that has access to the Chat Details context.
Expand Down
4 changes: 3 additions & 1 deletion packages/agent-app-sdk/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export { Charge, IDirectCharge, IRecurrentCharge, Metadata, TransactionError, TransactionEvent, UpdateBillingCycleEvent } from '@livechat/widget-core-sdk';
export * from './widgets/details';
export * from './widgets/messagebox';
export * from './widgets/fullscreen';
export * from './widgets/messagebox';
export * from './widgets/settings';
export * from './widgets/shared/customer-profile';

16 changes: 4 additions & 12 deletions packages/agent-app-sdk/src/widgets/details/details-widget.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
import {
createWidget,
withAmplitude,
createConnection,
IConnection
} from '@livechat/widget-core-sdk';
import { createConnection, createWidget, IConnection, withAmplitude, withPayments } from '@livechat/widget-core-sdk';
import { withCustomerProfile } from '../shared/customer-profile';
import { withRichMessages } from '../shared/rich-messages';
import assertSection from './custom-sections';
import {
IDetailsWidgetEvents,
IDetailsWidgetApi,
ISection
} from './interfaces';
import { IDetailsWidgetApi, IDetailsWidgetEvents, ISection } from './interfaces';


export function DetailsWidget(connection: IConnection<IDetailsWidgetEvents>) {
const base = createWidget<IDetailsWidgetApi, IDetailsWidgetEvents>(
Expand All @@ -33,7 +25,7 @@ export function DetailsWidget(connection: IConnection<IDetailsWidgetEvents>) {
}
);

const widget = withAmplitude(withRichMessages(withCustomerProfile(base)));
const widget = withAmplitude(withRichMessages(withCustomerProfile(withPayments(base))));

return widget;
}
Expand Down
16 changes: 4 additions & 12 deletions packages/agent-app-sdk/src/widgets/fullscreen/fullscreen-widget.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
import {
createWidget,
withAmplitude,
createConnection,
IConnection
} from '@livechat/widget-core-sdk';
import {
IFullscreenWidgetApi,
IFullscreenWidgetEvents,
ReportsFilters
} from './interfaces';
import { createConnection, createWidget, IConnection, withAmplitude, withPayments } from '@livechat/widget-core-sdk';
import { withPageData } from '../shared/page-data';
import { IFullscreenWidgetApi, IFullscreenWidgetEvents, ReportsFilters } from './interfaces';

export { ReportsFilters } from './interfaces';

Expand All @@ -36,7 +27,8 @@ export function FullscreenWidget(
}
}
);
return withAmplitude(withPageData(base));

return withAmplitude(withPageData(withPayments(base)));
}

export type IFullscreenWidget = ReturnType<typeof FullscreenWidget>;
Expand Down
15 changes: 3 additions & 12 deletions packages/agent-app-sdk/src/widgets/messagebox/messagebox-widget.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
import {
createWidget,
withAmplitude,
createConnection,
IConnection
} from '@livechat/widget-core-sdk';
import { createConnection, createWidget, IConnection, withAmplitude, withPayments } from '@livechat/widget-core-sdk';
import { withCustomerProfile } from '../shared/customer-profile';
import { withRichMessages } from '../shared/rich-messages';
import {
IMessageBoxWidgetApi,
IMessageBoxWidgetEvents,
IRichMessage
} from './interfaces';
import { IMessageBoxWidgetApi, IMessageBoxWidgetEvents, IRichMessage } from './interfaces';

export function MessageBoxWidget(
connection: IConnection<IMessageBoxWidgetEvents>
Expand All @@ -30,7 +21,7 @@ export function MessageBoxWidget(
}
);

const widget = withAmplitude(withRichMessages(withCustomerProfile(base)));
const widget = withAmplitude(withRichMessages(withCustomerProfile(withPayments(base))));

return widget;
}
Expand Down
11 changes: 3 additions & 8 deletions packages/agent-app-sdk/src/widgets/settings/settings-widget.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import {
createWidget,
withAmplitude,
createConnection,
IConnection
} from '@livechat/widget-core-sdk';
import { ISettingsWidgetApi, ISettingsWidgetEvents } from './interfaces';
import { createConnection, createWidget, IConnection, withAmplitude, withPayments } from '@livechat/widget-core-sdk';
import { withPageData } from '../shared/page-data';
import { ISettingsWidgetApi, ISettingsWidgetEvents } from './interfaces';

export function SettingsWidget(connection: IConnection<ISettingsWidgetEvents>) {
const base = createWidget<ISettingsWidgetApi, ISettingsWidgetEvents>(
Expand All @@ -16,7 +11,7 @@ export function SettingsWidget(connection: IConnection<ISettingsWidgetEvents>) {
}
}
);
return withAmplitude(withPageData(base));
return withAmplitude(withPageData(withPayments(base)));
}

export type ISettingsWidget = ReturnType<typeof SettingsWidget>;
Expand Down
79 changes: 79 additions & 0 deletions packages/helpdesk-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,85 @@ createDetailsWidget().then(widget => {

Each widget type offers a different set of events that you can listen to. Check them out in the descriptions below.

## Payments

All widgets allow you to pass a registered charge and display a summary of it to the customer within the payment modal in the helpdesk application, enabling them to complete or decline the transaction.

### Events

#### `transaction_accepted`

Emitted when a payment transaction is approved by the customer and successfully processed by the Billing API.

```ts
interface ITransactionAccepted {
chargeId: string;
}
```

#### `transaction_declined`

Emitted when a payment transaction is declined by the customer (e.g., the user closes the payment modal or clicks the cancel button), and the charge is subsequently marked as declined in the Billing API.

```ts
interface ITransactionDeclined {
chargeId: string;
}
```
#### `transaction_failed`

Emitted when a payment transaction fails and cannot be processed by the billing API.

```ts
interface ITransactionAccepted {
error: unknown;
}
```

#### `update_billing_cycle`

This event is triggered when a customer selects a different billing cycle for a transaction. It only emits if the `showBillingCyclePicker` flag is set to `true` in the `metadata` object at the start of the transaction. The event includes the new billing cycle number and key charge details, allowing you to register the updated charge with the provided information.

```ts
interface ITransactionAccepted {
billingCycle: number,
paymentIntent: {
name: string,
price: number,
per_account: boolean,
test: boolean,
return_url: string | null,
months?: number,
trial_days?: number,
quantity?: number,
metadata: {
type: string,
isExternalTransaction: boolean,
showBillingCyclePicker: boolean,
icon: string,
description?: string,
}
}
}
```

### Methods

#### `startTransaction(charge: Charge, metadata: Metadata): Promise<void>`

This method allows you to pass a registered charge and accompanying metadata to the HelpDesk App. The payment modal will then be displayed to the customer, enabling them to complete the transaction. For more information on registering a charge, refer to the [Billing API documentation](https://platform.text.com/docs/monetization/billing-api).

```ts
const charge = {...} // Billing API charge object
const metadata = {
icon: "https://icon.url";
description: "This is a description of the transaction.";
showBillingCyclePicker: true; // optional, use if you want to display the billing cycle picker to the customer
}

widget.startTransaction(charge, metadata);
```

## Details widget (`IDetailsWidget`)

A type of widget that has access to the Chat Details context.
Expand Down
4 changes: 3 additions & 1 deletion packages/helpdesk-sdk/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from './widgets/fullscreen';
export { Charge, IDirectCharge, IRecurrentCharge, Metadata, TransactionError, TransactionEvent, UpdateBillingCycleEvent } from '@livechat/widget-core-sdk';
export * from './widgets/details';
export * from './widgets/fullscreen';

19 changes: 5 additions & 14 deletions packages/helpdesk-sdk/src/widgets/details/details-widget.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
import {
createWidget,
withAmplitude,
createConnection,
IConnection
} from '@livechat/widget-core-sdk';
import { withTicketInfo } from './ticket-info';
import { createConnection, createWidget, IConnection, withAmplitude, withPayments } from '@livechat/widget-core-sdk';
import assertSection from './custom-sections';
import {
IDetailsWidgetEvents,
IDetailsWidgetApi,
ISection
} from './interfaces';
import { IDetailsWidgetApi, IDetailsWidgetEvents, ISection } from './interfaces';
import { withTicketInfo } from './ticket-info';

export function DetailsWidget(connection: IConnection<IDetailsWidgetEvents>) {
const base = createWidget<IDetailsWidgetApi, IDetailsWidgetEvents>(
Expand All @@ -23,12 +14,12 @@ export function DetailsWidget(connection: IConnection<IDetailsWidgetEvents>) {
}
);

const widget = withAmplitude(withTicketInfo(base));
const widget = withAmplitude(withTicketInfo(withPayments(base)));

return widget;
}

export interface IDetailsWidget extends ReturnType<typeof DetailsWidget> {}
export interface IDetailsWidget extends ReturnType<typeof DetailsWidget> { }

export default function createDetailsWidget(): Promise<IDetailsWidget> {
let widget: IDetailsWidget;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
createWidget,
withAmplitude,
createConnection,
IConnection
} from '@livechat/widget-core-sdk';
import { createConnection, createWidget, IConnection, withAmplitude, withPayments } from '@livechat/widget-core-sdk';
import { IFullscreenWidgetApi, IFullscreenWidgetEvents } from './interfaces';

export function FullscreenWidget(
Expand All @@ -21,11 +16,11 @@ export function FullscreenWidget(
}
);

return withAmplitude(base);
return withAmplitude(withPayments(base));
}

export interface IFullscreenWidget
extends ReturnType<typeof FullscreenWidget> {}
extends ReturnType<typeof FullscreenWidget> { }

export default function createFullscreenWidget(): Promise<IFullscreenWidget> {
return createConnection<IFullscreenWidgetEvents>().then(connection =>
Expand Down
4 changes: 3 additions & 1 deletion packages/widget-core-sdk/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export * from './widget';
export * from './amplitude';
export * from './connection';
export * from './payments';
export * from './widget';

Loading
Loading