diff --git a/.changeset/seven-hornets-shout.md b/.changeset/seven-hornets-shout.md new file mode 100644 index 0000000..2fc0fb2 --- /dev/null +++ b/.changeset/seven-hornets-shout.md @@ -0,0 +1,5 @@ +--- +"@oaknetwork/api": minor +--- + +added sync and balance API diff --git a/packages/api/__tests__/unit/services.test.ts b/packages/api/__tests__/unit/services.test.ts index 261e167..99f6415 100644 --- a/packages/api/__tests__/unit/services.test.ts +++ b/packages/api/__tests__/unit/services.test.ts @@ -200,6 +200,27 @@ describe("Crowdsplit services (Unit)", () => { authConfig, ], }); + await expectSuccess({ + client, + call: () => + service.sync("cust-1", { providers: ["stripe"], fields: ["shipping"] }), + httpMethod: "post", + expectedArgs: [ + `${SANDBOX_URL}/api/v1/customers/cust-1/sync`, + { providers: ["stripe"], fields: ["shipping"] }, + authConfig, + ], + }); + await expectSuccess({ + client, + call: () => + service.balance("cust-1", { provider: "stripe", role: "customer" }), + httpMethod: "get", + expectedArgs: [ + `${SANDBOX_URL}/api/v1/customers/cust-1/balance?provider=stripe&role=customer`, + authConfig, + ], + }); await expectFailure({ call: () => service.update("cust-1", { email: "new@example.com" }), httpMethod: "put", @@ -216,6 +237,18 @@ describe("Crowdsplit services (Unit)", () => { await expectTokenFailure(() => tokenErrorService.update("cust-1", { email: "t@t.com" }), ); + await expectTokenFailure(() => + tokenErrorService.sync("cust-1", { + providers: ["stripe"], + fields: ["shipping"], + }), + ); + await expectTokenFailure(() => + tokenErrorService.balance("cust-1", { + provider: "stripe", + role: "customer", + }), + ); }); it("payment service methods", async () => { diff --git a/packages/api/src/services/customerService.ts b/packages/api/src/services/customerService.ts index 4a0f71d..a549408 100644 --- a/packages/api/src/services/customerService.ts +++ b/packages/api/src/services/customerService.ts @@ -13,6 +13,13 @@ export interface CustomerService { id: string, customer: Customer.Request, ): Promise>; + + sync(id: string, sync: Customer.Sync): Promise>; + + balance( + customer_id: string, + filter: Customer.BalanceFilter, + ): Promise>; } export const createCustomerService = (client: OakClient): CustomerService => ({ @@ -91,4 +98,47 @@ export const createCustomerService = (client: OakClient): CustomerService => ({ }, ); }, + + async sync( + id: string, + sync: Customer.Sync, + ): Promise> { + const token = await client.getAccessToken(); + if (!token.ok) { + return err(token.error); + } + + return httpClient.post( + `${client.config.baseUrl}/api/v1/customers/${id}/sync`, + sync, + { + headers: { + Authorization: `Bearer ${token.value}`, + }, + retryOptions: client.retryOptions, + }, + ); + }, + + async balance( + customer_id: string, + filter: Customer.BalanceFilter, + ): Promise> { + const token = await client.getAccessToken(); + if (!token.ok) { + return err(token.error); + } + + const queryString = buildQueryString(filter); + + return httpClient.get( + `${client.config.baseUrl}/api/v1/customers/${customer_id}/balance${queryString}`, + { + headers: { + Authorization: `Bearer ${token.value}`, + }, + retryOptions: client.retryOptions, + }, + ); + }, }); diff --git a/packages/api/src/types/customer.ts b/packages/api/src/types/customer.ts index 7fc2a00..6cdb73b 100644 --- a/packages/api/src/types/customer.ts +++ b/packages/api/src/types/customer.ts @@ -53,6 +53,23 @@ export namespace Customer { account_type?: string | null; } + type Provider = + | "stripe" + | "bridge" + | "pagar_me" + | "brla" + | "avenia" + | "mercado_pago"; + + type SyncField = "shipping" | "email" | "first_name" | "last_name"; + + export interface Sync { + providers: [Provider]; // exactly 1 + fields: SyncField[]; + } + + export type SyncResponse = ApiResponse; + export interface Request extends Partial {} export type Response = ApiResponse; @@ -72,4 +89,35 @@ export namespace Customer { document_type?: string; country_code?: string; } + export interface BalanceFilter { + provider: string; + role: string; + } + + export interface BalanceResponse + extends ApiResponse<{ + as_of: string; + filters: { + customer_id: string; + provider?: string; + role?: string; + }; + + balances: { + account_id: string; + provider: string; + customer: { + id: string; + role: string; + }; + as_of: string; + totals: { + currency: string; + amount: number; + pending: number; + reserved: number; + instant_payouts: number; + }[]; + }[]; + }> {} }