@sumup/sdk
Version:
The official TypeScript SDK for the SumUp API
863 lines (862 loc) • 27.6 kB
JavaScript
class APIResource {
_client;
constructor(client){
this._client = client;
}
}
class SumUpError extends Error {
}
class APIError extends SumUpError {
status;
error;
response;
constructor(status, error, response){
const message = "string" == typeof error ? error : JSON.stringify(error);
super(`${status}: ${message}`);
this.status = status;
this.error = error;
this.response = response;
}
}
async function parseResponse(res) {
if (204 === res.status || 205 === res.status) return;
const contentLength = res.headers.get("content-length");
if ("0" === contentLength) return;
const contentType = res.headers.get("content-type");
const isJSON = contentType?.includes("json");
if (!isJSON) throw new SumUpError("Unexpected non-json response.");
return await res.json();
}
const UNKNOWN = "unknown";
const normalizeArch = (arch)=>{
const lower = arch.toLowerCase();
if ("x64" === lower || "x86_64" === lower || "amd64" === lower) return "x86_64";
if ("ia32" === lower || "x86" === lower || "x32" === lower) return "x86";
if ("aarch64" === lower || "arm64" === lower) return "arm64";
if ("arm" === lower) return "arm";
return lower || UNKNOWN;
};
let cachedRuntimeInfo;
function getRuntimeInfo() {
if (cachedRuntimeInfo) return cachedRuntimeInfo;
const isVercel = "u" > typeof process && "1" === process.env.VERCEL;
const globalAny = globalThis;
if (globalAny.Bun?.version) {
cachedRuntimeInfo = {
runtime: "bun",
runtimeVersion: globalAny.Bun.version || UNKNOWN,
os: globalAny.process?.platform || UNKNOWN,
arch: normalizeArch(globalAny.process?.arch || "")
};
return cachedRuntimeInfo;
}
if (globalAny.Deno?.version?.deno) {
cachedRuntimeInfo = {
runtime: "deno",
runtimeVersion: globalAny.Deno.version.deno || UNKNOWN,
os: globalAny.Deno.build?.os || UNKNOWN,
arch: normalizeArch(globalAny.Deno.build?.arch || "")
};
return cachedRuntimeInfo;
}
if (globalAny.process?.versions?.node) {
cachedRuntimeInfo = {
runtime: isVercel ? "vercel" : "node",
runtimeVersion: globalAny.process.version || UNKNOWN,
os: globalAny.process.platform || UNKNOWN,
arch: normalizeArch(globalAny.process.arch || "")
};
return cachedRuntimeInfo;
}
if (globalAny.EdgeRuntime) {
cachedRuntimeInfo = {
runtime: isVercel ? "vercel-edge" : "edge",
runtimeVersion: globalAny.process?.version || UNKNOWN,
os: UNKNOWN,
arch: `${globalAny.EdgeRuntime}`
};
return cachedRuntimeInfo;
}
if (globalAny.navigator) {
const userAgent = globalAny.navigator.userAgent || "";
if (userAgent.includes("Cloudflare-Workers")) {
cachedRuntimeInfo = {
runtime: "cloudflare-workers",
runtimeVersion: userAgent,
os: UNKNOWN,
arch: UNKNOWN
};
return cachedRuntimeInfo;
}
const platform = globalAny.navigator.userAgentData?.platform || globalAny.navigator.platform || "";
cachedRuntimeInfo = {
runtime: "browser",
runtimeVersion: UNKNOWN,
os: platform || UNKNOWN,
arch: UNKNOWN
};
return cachedRuntimeInfo;
}
cachedRuntimeInfo = {
runtime: UNKNOWN,
runtimeVersion: UNKNOWN,
os: UNKNOWN,
arch: UNKNOWN
};
return cachedRuntimeInfo;
}
function buildRuntimeHeaders() {
const { runtime, runtimeVersion, os, arch } = getRuntimeInfo();
return {
"X-Sumup-Api-Version": "1.0.0",
"X-Sumup-Lang": "javascript",
"X-Sumup-Package-Version": "0.1.6",
"X-Sumup-Os": os,
"X-Sumup-Arch": arch,
"X-Sumup-Runtime": runtime,
"X-Sumup-Runtime-Version": runtimeVersion
};
}
class HTTPClient {
host;
apiKey;
baseParams;
constructor({ apiKey, host = "https://api.sumup.com", baseParams = {}, maxRetries = 0, timeout } = {}){
this.host = host;
this.apiKey = apiKey;
const headers = new Headers({
Accept: "application/problem+json, application/json",
"Content-Type": "application/json",
"User-Agent": "sumup-ts/v0.1.6",
...buildRuntimeHeaders()
});
if (apiKey) headers.append("Authorization", `Bearer ${apiKey}`);
this.baseParams = mergeParams({
headers,
maxRetries,
timeout
}, baseParams);
}
get({ ...params }) {
return this.request({
method: "GET",
...params
});
}
getWithResponse({ ...params }) {
return this.requestWithResponse({
method: "GET",
...params
});
}
post({ ...params }) {
return this.request({
method: "POST",
...params
});
}
postWithResponse({ ...params }) {
return this.requestWithResponse({
method: "POST",
...params
});
}
put({ ...params }) {
return this.request({
method: "PUT",
...params
});
}
putWithResponse({ ...params }) {
return this.requestWithResponse({
method: "PUT",
...params
});
}
patch({ ...params }) {
return this.request({
method: "PATCH",
...params
});
}
patchWithResponse({ ...params }) {
return this.requestWithResponse({
method: "PATCH",
...params
});
}
delete({ ...params }) {
return this.request({
method: "DELETE",
...params
});
}
deleteWithResponse({ ...params }) {
return this.requestWithResponse({
method: "DELETE",
...params
});
}
request({ ...params }) {
return this.requestWithResponse(params).then(({ data })=>data);
}
async requestWithResponse({ body, path, query, host: hostOverride, ...requestOptions }) {
const host = hostOverride || this.host;
const url = new URL(host + (host.endsWith("/") && path.startsWith("/") ? path.slice(1) : path));
if ("object" == typeof query && query && !Array.isArray(query)) url.search = this.stringifyQuery(query);
const mergedOptions = mergeParams(this.baseParams, requestOptions);
const { maxRetries, timeout, ...fetchParams } = mergedOptions;
const init = {
...fetchParams,
body: JSON.stringify(body)
};
const response = await this.do(url, init, {
maxRetries,
signal: fetchParams.signal,
timeout
});
const data = await parseResponse(response.clone());
return {
data,
response
};
}
async do(input, init, options) {
const maxRetries = options.maxRetries ?? 0;
for(let attempt = 0;; attempt++){
const { cleanup, didTimeout, signal } = withTimeoutSignal(options.signal, options.timeout);
try {
const res = await fetch(input, {
...init,
signal
});
if (!res.ok) {
if (attempt < maxRetries && isRetryableStatus(res.status)) continue;
const contentType = res.headers.get("content-type");
const isJSON = contentType?.includes("json");
throw new APIError(res.status, isJSON ? await res.json() : await res.text(), res);
}
return res;
} catch (error) {
if (attempt < maxRetries && isRetryableError(error, options.signal)) continue;
if (didTimeout()) throw new SumUpError(`Request timed out after ${options.timeout}ms.`);
throw error;
} finally{
cleanup();
}
}
}
stringifyQuery(query) {
return Object.entries(query).filter(([_, value])=>void 0 !== value).map(([key, value])=>{
if ("string" == typeof value || "number" == typeof value || "boolean" == typeof value) return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
if (null === value) return `${encodeURIComponent(key)}=`;
if (Array.isArray(value)) return value.map((v)=>`${encodeURIComponent(key)}=${encodeURIComponent(v)}`).join("&");
throw new Error(`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null.`);
}).join("&");
}
}
function mergeParams(a, b) {
const { authorization: defaultAuthorization, headers: defaultHeaders, ...defaultParams } = a;
const { authorization: overrideAuthorization, headers: overrideHeaders, ...overrideParams } = b;
const headers = new Headers(defaultHeaders);
for (const [key, value] of new Headers(overrideHeaders).entries())headers.set(key, value);
const authorization = overrideAuthorization ?? defaultAuthorization;
if (authorization) headers.set("Authorization", authorization);
return {
...defaultParams,
...overrideParams,
headers
};
}
function isRetryableStatus(status) {
return 408 === status || 409 === status || 429 === status || status >= 500;
}
function isRetryableError(error, signal) {
if (signal?.aborted) return false;
return error instanceof TypeError || isAbortError(error);
}
function isAbortError(error) {
return error instanceof DOMException ? "AbortError" === error.name : error instanceof Error && "AbortError" === error.name;
}
function withTimeoutSignal(signal, timeout) {
if (!signal && void 0 === timeout) return {
cleanup: ()=>{},
didTimeout: ()=>false,
signal: void 0
};
const controller = new AbortController();
let timedOut = false;
const onAbort = ()=>{
controller.abort(signal?.reason);
};
if (signal) if (signal.aborted) onAbort();
else signal.addEventListener("abort", onAbort, {
once: true
});
const timeoutId = "number" == typeof timeout ? setTimeout(()=>{
timedOut = true;
controller.abort(new SumUpError(`Request timed out after ${timeout}ms.`));
}, timeout) : void 0;
return {
cleanup: ()=>{
if (void 0 !== timeoutId) clearTimeout(timeoutId);
signal?.removeEventListener("abort", onAbort);
},
didTimeout: ()=>timedOut,
signal: controller.signal
};
}
class Checkouts extends APIResource {
listAvailablePaymentMethods(merchantCode, query, options) {
return this._client.get({
path: `/v0.1/merchants/${merchantCode}/payment-methods`,
query,
...options
});
}
listAvailablePaymentMethodsWithResponse(merchantCode, query, options) {
return this._client.getWithResponse({
path: `/v0.1/merchants/${merchantCode}/payment-methods`,
query,
...options
});
}
list(query, options) {
return this._client.get({
path: "/v0.1/checkouts",
query,
...options
});
}
listWithResponse(query, options) {
return this._client.getWithResponse({
path: "/v0.1/checkouts",
query,
...options
});
}
create(body, options) {
return this._client.post({
path: "/v0.1/checkouts",
body,
...options
});
}
createWithResponse(body, options) {
return this._client.postWithResponse({
path: "/v0.1/checkouts",
body,
...options
});
}
get(id, options) {
return this._client.get({
path: `/v0.1/checkouts/${id}`,
...options
});
}
getWithResponse(id, options) {
return this._client.getWithResponse({
path: `/v0.1/checkouts/${id}`,
...options
});
}
process(id, body, options) {
return this._client.put({
path: `/v0.1/checkouts/${id}`,
body,
...options
});
}
processWithResponse(id, body, options) {
return this._client.putWithResponse({
path: `/v0.1/checkouts/${id}`,
body,
...options
});
}
deactivate(id, options) {
return this._client.delete({
path: `/v0.1/checkouts/${id}`,
...options
});
}
deactivateWithResponse(id, options) {
return this._client.deleteWithResponse({
path: `/v0.1/checkouts/${id}`,
...options
});
}
createApplePaySession(id, body, options) {
return this._client.put({
path: `/v0.2/checkouts/${id}/apple-pay-session`,
body,
...options
});
}
createApplePaySessionWithResponse(id, body, options) {
return this._client.putWithResponse({
path: `/v0.2/checkouts/${id}/apple-pay-session`,
body,
...options
});
}
}
class Customers extends APIResource {
create(body, options) {
return this._client.post({
path: "/v0.1/customers",
body,
...options
});
}
createWithResponse(body, options) {
return this._client.postWithResponse({
path: "/v0.1/customers",
body,
...options
});
}
get(customerId, options) {
return this._client.get({
path: `/v0.1/customers/${customerId}`,
...options
});
}
getWithResponse(customerId, options) {
return this._client.getWithResponse({
path: `/v0.1/customers/${customerId}`,
...options
});
}
update(customerId, body, options) {
return this._client.put({
path: `/v0.1/customers/${customerId}`,
body,
...options
});
}
updateWithResponse(customerId, body, options) {
return this._client.putWithResponse({
path: `/v0.1/customers/${customerId}`,
body,
...options
});
}
listPaymentInstruments(customerId, options) {
return this._client.get({
path: `/v0.1/customers/${customerId}/payment-instruments`,
...options
});
}
listPaymentInstrumentsWithResponse(customerId, options) {
return this._client.getWithResponse({
path: `/v0.1/customers/${customerId}/payment-instruments`,
...options
});
}
deactivatePaymentInstrument(customerId, token, options) {
return this._client.delete({
path: `/v0.1/customers/${customerId}/payment-instruments/${token}`,
...options
});
}
deactivatePaymentInstrumentWithResponse(customerId, token, options) {
return this._client.deleteWithResponse({
path: `/v0.1/customers/${customerId}/payment-instruments/${token}`,
...options
});
}
}
class Members extends APIResource {
list(merchantCode, query, options) {
return this._client.get({
path: `/v0.1/merchants/${merchantCode}/members`,
query,
...options
});
}
listWithResponse(merchantCode, query, options) {
return this._client.getWithResponse({
path: `/v0.1/merchants/${merchantCode}/members`,
query,
...options
});
}
create(merchantCode, body, options) {
return this._client.post({
path: `/v0.1/merchants/${merchantCode}/members`,
body,
...options
});
}
createWithResponse(merchantCode, body, options) {
return this._client.postWithResponse({
path: `/v0.1/merchants/${merchantCode}/members`,
body,
...options
});
}
get(merchantCode, memberId, options) {
return this._client.get({
path: `/v0.1/merchants/${merchantCode}/members/${memberId}`,
...options
});
}
getWithResponse(merchantCode, memberId, options) {
return this._client.getWithResponse({
path: `/v0.1/merchants/${merchantCode}/members/${memberId}`,
...options
});
}
update(merchantCode, memberId, body, options) {
return this._client.put({
path: `/v0.1/merchants/${merchantCode}/members/${memberId}`,
body,
...options
});
}
updateWithResponse(merchantCode, memberId, body, options) {
return this._client.putWithResponse({
path: `/v0.1/merchants/${merchantCode}/members/${memberId}`,
body,
...options
});
}
delete(merchantCode, memberId, options) {
return this._client.delete({
path: `/v0.1/merchants/${merchantCode}/members/${memberId}`,
...options
});
}
deleteWithResponse(merchantCode, memberId, options) {
return this._client.deleteWithResponse({
path: `/v0.1/merchants/${merchantCode}/members/${memberId}`,
...options
});
}
}
class Memberships extends APIResource {
list(query, options) {
return this._client.get({
path: "/v0.1/memberships",
query,
...options
});
}
listWithResponse(query, options) {
return this._client.getWithResponse({
path: "/v0.1/memberships",
query,
...options
});
}
}
class Merchants extends APIResource {
get(merchantCode, query, options) {
return this._client.get({
path: `/v1/merchants/${merchantCode}`,
query,
...options
});
}
getWithResponse(merchantCode, query, options) {
return this._client.getWithResponse({
path: `/v1/merchants/${merchantCode}`,
query,
...options
});
}
listPersons(merchantCode, query, options) {
return this._client.get({
path: `/v1/merchants/${merchantCode}/persons`,
query,
...options
});
}
listPersonsWithResponse(merchantCode, query, options) {
return this._client.getWithResponse({
path: `/v1/merchants/${merchantCode}/persons`,
query,
...options
});
}
getPerson(merchantCode, personId, query, options) {
return this._client.get({
path: `/v1/merchants/${merchantCode}/persons/${personId}`,
query,
...options
});
}
getPersonWithResponse(merchantCode, personId, query, options) {
return this._client.getWithResponse({
path: `/v1/merchants/${merchantCode}/persons/${personId}`,
query,
...options
});
}
}
class Payouts extends APIResource {
list(merchantCode, query, options) {
return this._client.get({
path: `/v1.0/merchants/${merchantCode}/payouts`,
query,
...options
});
}
listWithResponse(merchantCode, query, options) {
return this._client.getWithResponse({
path: `/v1.0/merchants/${merchantCode}/payouts`,
query,
...options
});
}
}
class Readers extends APIResource {
list(merchantCode, options) {
return this._client.get({
path: `/v0.1/merchants/${merchantCode}/readers`,
...options
});
}
listWithResponse(merchantCode, options) {
return this._client.getWithResponse({
path: `/v0.1/merchants/${merchantCode}/readers`,
...options
});
}
create(merchantCode, body, options) {
return this._client.post({
path: `/v0.1/merchants/${merchantCode}/readers`,
body,
...options
});
}
createWithResponse(merchantCode, body, options) {
return this._client.postWithResponse({
path: `/v0.1/merchants/${merchantCode}/readers`,
body,
...options
});
}
get(merchantCode, id, options) {
return this._client.get({
path: `/v0.1/merchants/${merchantCode}/readers/${id}`,
...options
});
}
getWithResponse(merchantCode, id, options) {
return this._client.getWithResponse({
path: `/v0.1/merchants/${merchantCode}/readers/${id}`,
...options
});
}
delete(merchantCode, id, options) {
return this._client.delete({
path: `/v0.1/merchants/${merchantCode}/readers/${id}`,
...options
});
}
deleteWithResponse(merchantCode, id, options) {
return this._client.deleteWithResponse({
path: `/v0.1/merchants/${merchantCode}/readers/${id}`,
...options
});
}
update(merchantCode, id, body, options) {
return this._client.patch({
path: `/v0.1/merchants/${merchantCode}/readers/${id}`,
body,
...options
});
}
updateWithResponse(merchantCode, id, body, options) {
return this._client.patchWithResponse({
path: `/v0.1/merchants/${merchantCode}/readers/${id}`,
body,
...options
});
}
createCheckout(merchantCode, readerId, body, options) {
return this._client.post({
path: `/v0.1/merchants/${merchantCode}/readers/${readerId}/checkout`,
body,
...options
});
}
createCheckoutWithResponse(merchantCode, readerId, body, options) {
return this._client.postWithResponse({
path: `/v0.1/merchants/${merchantCode}/readers/${readerId}/checkout`,
body,
...options
});
}
getStatus(merchantCode, readerId, options) {
return this._client.get({
path: `/v0.1/merchants/${merchantCode}/readers/${readerId}/status`,
...options
});
}
getStatusWithResponse(merchantCode, readerId, options) {
return this._client.getWithResponse({
path: `/v0.1/merchants/${merchantCode}/readers/${readerId}/status`,
...options
});
}
terminateCheckout(merchantCode, readerId, body, options) {
return this._client.post({
path: `/v0.1/merchants/${merchantCode}/readers/${readerId}/terminate`,
body,
...options
});
}
terminateCheckoutWithResponse(merchantCode, readerId, body, options) {
return this._client.postWithResponse({
path: `/v0.1/merchants/${merchantCode}/readers/${readerId}/terminate`,
body,
...options
});
}
}
class Receipts extends APIResource {
get(id, query, options) {
return this._client.get({
path: `/v1.1/receipts/${id}`,
query,
...options
});
}
getWithResponse(id, query, options) {
return this._client.getWithResponse({
path: `/v1.1/receipts/${id}`,
query,
...options
});
}
}
class Roles extends APIResource {
list(merchantCode, options) {
return this._client.get({
path: `/v0.1/merchants/${merchantCode}/roles`,
...options
});
}
listWithResponse(merchantCode, options) {
return this._client.getWithResponse({
path: `/v0.1/merchants/${merchantCode}/roles`,
...options
});
}
create(merchantCode, body, options) {
return this._client.post({
path: `/v0.1/merchants/${merchantCode}/roles`,
body,
...options
});
}
createWithResponse(merchantCode, body, options) {
return this._client.postWithResponse({
path: `/v0.1/merchants/${merchantCode}/roles`,
body,
...options
});
}
get(merchantCode, roleId, options) {
return this._client.get({
path: `/v0.1/merchants/${merchantCode}/roles/${roleId}`,
...options
});
}
getWithResponse(merchantCode, roleId, options) {
return this._client.getWithResponse({
path: `/v0.1/merchants/${merchantCode}/roles/${roleId}`,
...options
});
}
delete(merchantCode, roleId, options) {
return this._client.delete({
path: `/v0.1/merchants/${merchantCode}/roles/${roleId}`,
...options
});
}
deleteWithResponse(merchantCode, roleId, options) {
return this._client.deleteWithResponse({
path: `/v0.1/merchants/${merchantCode}/roles/${roleId}`,
...options
});
}
update(merchantCode, roleId, body, options) {
return this._client.patch({
path: `/v0.1/merchants/${merchantCode}/roles/${roleId}`,
body,
...options
});
}
updateWithResponse(merchantCode, roleId, body, options) {
return this._client.patchWithResponse({
path: `/v0.1/merchants/${merchantCode}/roles/${roleId}`,
body,
...options
});
}
}
class Transactions extends APIResource {
refund(merchantCode, id, body, options) {
return this._client.post({
path: `/v1.0/merchants/${merchantCode}/payments/${id}/refunds`,
body,
...options
});
}
refundWithResponse(merchantCode, id, body, options) {
return this._client.postWithResponse({
path: `/v1.0/merchants/${merchantCode}/payments/${id}/refunds`,
body,
...options
});
}
get(merchantCode, query, options) {
return this._client.get({
path: `/v2.1/merchants/${merchantCode}/transactions`,
query,
...options
});
}
getWithResponse(merchantCode, query, options) {
return this._client.getWithResponse({
path: `/v2.1/merchants/${merchantCode}/transactions`,
query,
...options
});
}
list(merchantCode, query, options) {
return this._client.get({
path: `/v2.1/merchants/${merchantCode}/transactions/history`,
query,
...options
});
}
listWithResponse(merchantCode, query, options) {
return this._client.getWithResponse({
path: `/v2.1/merchants/${merchantCode}/transactions/history`,
query,
...options
});
}
}
class SumUp extends HTTPClient {
checkouts = new Checkouts(this);
customers = new Customers(this);
members = new Members(this);
memberships = new Memberships(this);
merchants = new Merchants(this);
payouts = new Payouts(this);
readers = new Readers(this);
receipts = new Receipts(this);
roles = new Roles(this);
transactions = new Transactions(this);
}
const src = SumUp;
export default src;
export { APIError, Checkouts, Customers, Members, Memberships, Merchants, Payouts, Readers, Receipts, Roles, SumUp, SumUpError, Transactions };
//# sourceMappingURL=index.js.map