UNPKG

@mia-burton/klarna-node

Version:
150 lines (141 loc) 5.54 kB
import { ClientInterface } from './client.interface' import axios, { AxiosInstance } from 'axios' import { Location, OrderResponse, SessionResponse, OrderInput, Order, UrlsInput, PaymentSession } from './types' import { CreateOrderError, CreateSessionError, ReadOrderError, ReadSessionError } from './errors' import { SessionBodyBuilder } from './builders' import { PaymentSessionMapper } from './mappers' import { OrderBodyBuilder } from './builders' import { OrderMapper } from './mappers/order.mapper' import { Utils } from './utils' export class Client implements ClientInterface { private readonly uid: string private readonly password: string private readonly live: boolean private baseUrl: string|undefined private restClient: AxiosInstance /** * Create a Klarna client * @param uid string - Api key given from Klarna * @param password string - Password given from Klarna * @param live boolean - Switch live sandbox env */ constructor(uid: string, password: string, location: Location, live: boolean = true) { this.uid = uid this.password = password this.live = live this.setLocation(location) this.restClient = this.initAxios() } private setLocation(location: Location): void { switch (location) { case Location.America: this.baseUrl = this.live ? 'https://api-na.klarna.com/' : 'https://api-na.playground.klarna.com/' break; case Location.Europe: this.baseUrl = this.live ? 'https://api.klarna.com/' : 'https://api.playground.klarna.com/' break; case Location.Oceania: this.baseUrl = this.live ? 'https://api-oc.klarna.com/' : 'https://api-oc.playground.klarna.com/' break default: throw new Error('Invalid location') } this.restClient = this.initAxios() } /** * @param theOrder * @param urls Insert {session.id} and/or {order.id} as placeholder * @return Promise<SessionResponse> * @throws CreateSessionError */ public async createPaymentSession(theOrder: OrderInput, urls: UrlsInput): Promise<SessionResponse> { try { const bodyBuilder = new SessionBodyBuilder() const body = bodyBuilder.build(theOrder, urls) const res = await this.restClient.post('payments/v1/sessions', body) const session = new SessionResponse(res.data.session_id, res.data.client_token) return session } catch(err) { if (axios.isAxiosError(err)) { throw new CreateSessionError(err.message, err.response ? err.response.data : {}) } throw new CreateSessionError((err as Error).message, err as Error) } } public async getPaymentSession(theId: string): Promise<PaymentSession> { try { const res = await this.restClient.get(`payments/v1/sessions/${theId}`) return new PaymentSessionMapper().map(res.data) } catch(err) { if (axios.isAxiosError(err)) { throw new ReadSessionError(err.message, err.response ? err.response.data : {}) } throw new ReadSessionError((err as Error).message, err as Error) } } /** * @param theOrder * @returns Promise<OrderResponse> * @throws CreateOrderError */ public async createOrder(theSessionId: string): Promise<OrderResponse> { try { const paymentSesison = await this.getPaymentSession(theSessionId) if (paymentSesison.status === 'incomplete' && paymentSesison.clientToken && paymentSesison.authorizationToken) { const bodyBuilder = new OrderBodyBuilder() const body = bodyBuilder.build(paymentSesison) const res = await this.restClient.post(`payments/v1/authorizations/${paymentSesison.authorizationToken}/order`, body) const order = new OrderResponse(res.data.order_id, res.data.fraud_status) return order } throw new CreateOrderError('Session not valid', {}) } catch(err) { if (axios.isAxiosError(err)) { throw new CreateOrderError(err.message, err.response ? err.response.data : {}) } throw new CreateOrderError((err as Error).message, err as Error) } } /** * @param theId * @returns {Promise<Order>} */ public async getOrder(theId: string): Promise<Order> { try { const res = await this.restClient.get(`ordermanagement/v1/orders/${theId}`) return new OrderMapper().map(res.data) } catch(err) { if (axios.isAxiosError(err)) { throw new ReadOrderError(err.message, err.response ? err.response.data : {}) } throw new ReadOrderError((err as Error).message, err as Error) } } /** * Create a capture for the givend order of the given amount * @param theOrderId * @param theAmount * @returns {Promise<string>} */ public async captureOrder(theOrderId: string, theAmount: number): Promise<string> { try { const res = await this.restClient.post(`ordermanagement/v1/orders/${theOrderId}/captures`, { captured_amount: Utils.formatPrice(theAmount) }) return res.headers['capture-id'] } catch(err) { if (axios.isAxiosError(err)) { throw new ReadOrderError(err.message, err.response ? err.response.data : {}) } throw new ReadOrderError((err as Error).message, err as Error) } } private initAxios(): AxiosInstance { return axios.create({ baseURL: this.baseUrl, headers: { Authorization: `Basic ${Buffer.from(`${this.uid}:${this.password}`).toString('base64')}`, Accept: 'application/json', 'Content-Type': 'application/json' } }) } }