@paypal/checkout-components 5.0.287-alpha.0 → 5.0.287-alpha.11

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/__sdk__.js CHANGED
@@ -52,10 +52,6 @@ module.exports = {
52
52
  fundingSources: SMART_FUNDING_SOURCES,
53
53
  cards: SMART_CARDS,
54
54
  },
55
- "hosted-buttons": {
56
- entry: "./src/interface/hosted-button",
57
- globals,
58
- },
59
55
  marks: {
60
56
  entry: "./src/interface/marks",
61
57
  globals,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paypal/checkout-components",
3
- "version": "5.0.287-alpha.0",
3
+ "version": "5.0.287-alpha.11",
4
4
  "description": "PayPal Checkout components, for integrating checkout products.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,22 +1,128 @@
1
1
  /* @flow */
2
+ import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
3
+ import { request, noop } from "@krakenjs/belter/src";
4
+ import { getSDKHost } from "@paypal/sdk-client/src";
5
+
2
6
  import { getButtonsComponent } from "../zoid/buttons";
3
7
 
8
+ type HostedButtonsProps = {|
9
+ hostedButtonId: string,
10
+ merchantId?: string,
11
+ |};
12
+
4
13
  type HostedButtonsInstance = {|
5
14
  render: (string | HTMLElement) => void,
6
15
  |};
7
16
 
8
- type HostedButtonsProps = {|
9
- hostedButtonId?: string,
10
- |};
17
+ type HostedButtonDetailsParams = (HostedButtonsProps) => ZalgoPromise<{|
18
+ merchantId: string,
19
+ style: {|
20
+ layout: string,
21
+ shape: string,
22
+ color: string,
23
+ label: string,
24
+ |},
25
+ |}>;
26
+
27
+ type ButtonVariables = $ReadOnlyArray<{|
28
+ name: string,
29
+ value: string,
30
+ |}>;
31
+
32
+ type CreateOrder = () => ZalgoPromise<string>;
33
+
34
+ type OnApprove = (data: {| orderID: string |}) => ZalgoPromise<void>;
11
35
 
12
36
  export type HostedButtonsComponent =
13
37
  (HostedButtonsProps) => HostedButtonsInstance;
14
38
 
39
+ const headers = {
40
+ "PayPal-Entry-Point": "SDK",
41
+ "Content-Type": "application/json",
42
+ };
43
+
44
+ const apiUrl = `https://${getSDKHost()}/v1/ncp`;
45
+
46
+ const getButtonVariable = (variables: ButtonVariables, key: string): string =>
47
+ variables.find((variable) => variable.name === key)?.value ?? "";
48
+
49
+ export const getHostedButtonDetails: HostedButtonDetailsParams = ({
50
+ hostedButtonId,
51
+ }) => {
52
+ return request({
53
+ url: `${apiUrl}/button/${hostedButtonId}`,
54
+ headers,
55
+ }).then(({ body }) => {
56
+ return {
57
+ merchantId: getButtonVariable(body.button_variables, "business"),
58
+ style: {
59
+ layout: getButtonVariable(body.button_variables, "layout"),
60
+ shape: getButtonVariable(body.button_variables, "shape"),
61
+ color: getButtonVariable(body.button_variables, "color"),
62
+ label: getButtonVariable(body.button_variables, "button_text"),
63
+ },
64
+ };
65
+ });
66
+ };
67
+
68
+ export const getHostedButtonCreateOrder = ({
69
+ hostedButtonId,
70
+ merchantId,
71
+ }: HostedButtonsProps): CreateOrder => {
72
+ return () => {
73
+ return request({
74
+ url: `${apiUrl}/orders`,
75
+ headers,
76
+ method: "POST",
77
+ body: JSON.stringify({
78
+ hosted_button_id: hostedButtonId,
79
+ merchant_id: merchantId,
80
+ }),
81
+ }).then(({ body }) => body.order_id);
82
+ };
83
+ };
84
+
85
+ export const getHostedButtonOnApprove = ({
86
+ hostedButtonId,
87
+ merchantId,
88
+ }: HostedButtonsProps): OnApprove => {
89
+ return (data) => {
90
+ return request({
91
+ url: `${apiUrl}/orders/${data.orderID}/capture`,
92
+ headers,
93
+ method: "POST",
94
+ body: JSON.stringify({
95
+ hosted_button_id: hostedButtonId,
96
+ id: data.orderID,
97
+ merchant_id: merchantId,
98
+ }),
99
+ }).then(noop);
100
+ };
101
+ };
102
+
15
103
  export const getHostedButtonsComponent = (): HostedButtonsComponent => {
16
- function HostedButtons(): HostedButtonsInstance {
104
+ function HostedButtons({
105
+ hostedButtonId,
106
+ }: HostedButtonsProps): HostedButtonsInstance {
17
107
  const Buttons = getButtonsComponent();
18
108
  const render = (selector) => {
19
- Buttons().render(selector);
109
+ getHostedButtonDetails({ hostedButtonId }).then(
110
+ ({ merchantId, style }) => {
111
+ // $FlowFixMe
112
+ Buttons({
113
+ style,
114
+ hostedButtonId,
115
+ createOrder: getHostedButtonCreateOrder({
116
+ hostedButtonId,
117
+ merchantId,
118
+ }),
119
+ onApprove: getHostedButtonOnApprove({
120
+ hostedButtonId,
121
+ merchantId,
122
+ }),
123
+ }).render(selector);
124
+ }
125
+ );
20
126
  };
21
127
  return {
22
128
  render,
@@ -0,0 +1,142 @@
1
+ /* @flow */
2
+
3
+ import { describe, test, expect, vi } from "vitest";
4
+ import { request } from "@krakenjs/belter/src";
5
+ import { ZalgoPromise } from "@krakenjs/zalgo-promise";
6
+
7
+ import { getButtonsComponent } from "../zoid/buttons";
8
+
9
+ import {
10
+ getHostedButtonDetails,
11
+ getHostedButtonCreateOrder,
12
+ getHostedButtonOnApprove,
13
+ getHostedButtonsComponent,
14
+ } from ".";
15
+
16
+ vi.mock("@krakenjs/belter/src", async () => {
17
+ return {
18
+ ...(await vi.importActual("@krakenjs/belter/src")),
19
+ request: vi.fn(),
20
+ };
21
+ });
22
+
23
+ vi.mock("@paypal/sdk-client/src", async () => {
24
+ return {
25
+ ...(await vi.importActual("@paypal/sdk-client/src")),
26
+ getSDKHost: () => "example.com",
27
+ };
28
+ });
29
+
30
+ vi.mock("../zoid/buttons", async () => {
31
+ return {
32
+ ...(await vi.importActual("../zoid/buttons")),
33
+ getButtonsComponent: vi.fn(),
34
+ };
35
+ });
36
+
37
+ const getHostedButtonDetailsResponse = {
38
+ body: {
39
+ button_variables: [
40
+ {
41
+ name: "business",
42
+ value: "M1234567890",
43
+ },
44
+ {
45
+ name: "shape",
46
+ value: "rect",
47
+ },
48
+ {
49
+ name: "layout",
50
+ value: "vertical",
51
+ },
52
+ {
53
+ name: "color",
54
+ value: "gold",
55
+ },
56
+ {
57
+ name: "button_text",
58
+ value: "paypal",
59
+ },
60
+ ],
61
+ },
62
+ };
63
+
64
+ describe("HostedButtons", () => {
65
+ test("paypal.Buttons calls getHostedButtonDetails and invokes v5 of the SDK", () => {
66
+ const Buttons = vi.fn();
67
+ // $FlowIssue
68
+ getButtonsComponent.mockImplementationOnce(() => Buttons);
69
+ const HostedButtons = getHostedButtonsComponent();
70
+ // $FlowIssue
71
+ request.mockImplementationOnce(() =>
72
+ ZalgoPromise.resolve(getHostedButtonDetailsResponse)
73
+ );
74
+ HostedButtons({
75
+ hostedButtonId: "B1234567890",
76
+ }).render("");
77
+ expect(Buttons).toHaveBeenCalled();
78
+ expect.assertions(1);
79
+ });
80
+
81
+ test("getHostedButtonDetails", async () => {
82
+ // $FlowIssue
83
+ request.mockImplementationOnce(() =>
84
+ ZalgoPromise.resolve(getHostedButtonDetailsResponse)
85
+ );
86
+ await getHostedButtonDetails({
87
+ hostedButtonId: "B1234567890",
88
+ }).then(({ merchantId, style }) => {
89
+ expect(merchantId).toBe("M1234567890");
90
+ expect(style).toEqual({
91
+ layout: "vertical",
92
+ shape: "rect",
93
+ color: "gold",
94
+ label: "paypal",
95
+ });
96
+ });
97
+ expect.assertions(2);
98
+ });
99
+
100
+ test("getHostedButtonCreateOrder", async () => {
101
+ const createOrder = getHostedButtonCreateOrder({
102
+ hostedButtonId: "B1234567890",
103
+ merchantId: "M1234567890",
104
+ });
105
+
106
+ // $FlowIssue
107
+ request.mockImplementationOnce(() =>
108
+ ZalgoPromise.resolve({
109
+ body: {
110
+ hosted_button_id: "B1234567890",
111
+ merchant_id: "M1234567890",
112
+ order_id: "EC-1234567890",
113
+ status: "PAYER_ACTION_REQUIRED",
114
+ },
115
+ })
116
+ );
117
+ const orderID = await createOrder();
118
+ expect(orderID).toBe("EC-1234567890");
119
+ expect.assertions(1);
120
+ });
121
+
122
+ test("getHostedButtonOnApprove", async () => {
123
+ const onApprove = getHostedButtonOnApprove({
124
+ hostedButtonId: "B1234567890",
125
+ merchantId: "M1234567890",
126
+ });
127
+
128
+ // $FlowIssue
129
+ request.mockImplementationOnce(() => ZalgoPromise.resolve({}));
130
+ await onApprove({ orderID: "EC-1234567890" });
131
+ expect(request).toHaveBeenCalledWith(
132
+ expect.objectContaining({
133
+ body: JSON.stringify({
134
+ hosted_button_id: "B1234567890",
135
+ id: "EC-1234567890",
136
+ merchant_id: "M1234567890",
137
+ }),
138
+ })
139
+ );
140
+ expect.assertions(1);
141
+ });
142
+ });
@@ -33,11 +33,19 @@ import {
33
33
  getModalComponent,
34
34
  type ModalComponent,
35
35
  } from "../zoid/modal/component";
36
+ import {
37
+ getHostedButtonsComponent,
38
+ type HostedButtonsComponent,
39
+ } from "../hosted-buttons";
36
40
 
37
41
  export const Buttons: LazyExport<ButtonsComponent> = {
38
42
  __get__: () => getButtonsComponent(),
39
43
  };
40
44
 
45
+ export const HostedButtons: LazyExport<HostedButtonsComponent> = {
46
+ __get__: () => getHostedButtonsComponent(),
47
+ };
48
+
41
49
  export const Checkout: LazyProtectedExport<CheckoutComponent> = {
42
50
  __get__: () => protectedExport(getCheckoutComponent()),
43
51
  };
@@ -834,6 +834,12 @@ export const getButtonsComponent: () => ButtonsComponent = memoize(() => {
834
834
  value: getExperimentation,
835
835
  },
836
836
 
837
+ hostedButtonId: {
838
+ type: "string",
839
+ required: false,
840
+ queryParam: true,
841
+ },
842
+
837
843
  displayOnly: {
838
844
  type: "array",
839
845
  queryParam: true,
@@ -1,10 +0,0 @@
1
- /* @flow */
2
- import type { LazyExport } from "../types";
3
- import {
4
- getHostedButtonsComponent,
5
- type HostedButtonsComponent,
6
- } from "../hosted-buttons";
7
-
8
- export const HostedButtons: LazyExport<HostedButtonsComponent> = {
9
- __get__: () => getHostedButtonsComponent(),
10
- };