UNPKG

klarna-checkout

Version:

Library for integrating Klarna Checkout in a nodejs environment

242 lines (203 loc) 6.69 kB
# Import modules crypto = require 'crypto' request = require 'request' Promise = require 'promise' # Flags flags = live: false, initalized: false # Credentials credentials = eid: null secret: null # Configuration (default: Sweden, SEK, Swedish) config = purchase_country: 'SE' purchase_currency: 'SEK' locale: 'sv-se' merchant: id: null terms_uri: null checkout_uri: null confirmation_uri: null push_uri: null gui: layout: 'desktop' # Klarna REST API constants klarna = url: test: 'https://checkout.testdrive.klarna.com/checkout/orders' live: 'https://checkout.klarna.com/checkout/orders' headers: contentType: 'application/vnd.klarna.checkout.aggregated-order-v2+json' accept: 'application/vnd.klarna.checkout.aggregated-order-v2+json' ### PRIVATE ### # Construct HTTP request according to Klarna specifications httpRequest = # Set HTTP request headers headers: (payload) -> # Create (digestive) biscuit from payload and hash from biscuit biscuit = if payload? then JSON.stringify(payload) + credentials.secret else credentials.secret hash = crypto.createHash('sha256').update(biscuit, 'utf-8').digest('base64') # Return headers 'Accept': klarna.headers.accept 'Authorization': 'Klarna ' + hash, 'Content-Type': klarna.headers.contentType # Set HTTP request options options: (data, id) -> # Set base url depending on live or test environment url = if flags.live then klarna.url.live else klarna.url.test # Return HTTP request options url: if id? then url + '/' + id else url headers: this.headers(data), body: data json: if data? then true else false # Wrapper for all exported (order related) functions wrapper = (f) -> # Module initalized? if not flags.initalized throw 'Klarna module not initialized. Please use init() method.' # All uris set? for key, value of config.merchant if not value? throw "Config error: #{key} not set" # If no problems -> return original function return f # Parse HTTP response for error parseError = (error, response, body) -> # If HTTP request error if error? return { type: 'HTTP' code: error.code message: error.message } # If Klarna error else if body body = if typeof body is 'string' then JSON.parse(body) else body return { type: 'Klarna' code: body.http_status_code + " - " + body.http_status_message message: body.internal_message } ### PUBLIC ### publicMethods = # Initialize init: (input) -> if not input? throw "Missing init values" # Set merchant ID if input.eid? credentials.eid = input.eid config.merchant.id = input.eid # Set shared secret if input.secret? credentials.secret = input.secret # Set/unset test flag if input.live? and typeof input.live is 'boolean' flags.live = input.live # If success -> set flag 'initialized' if input.eid? and input.secret? then flags.initalized = true # Set config config: (input) -> # Country, language and currency if input.purchase_country? config.purchase_country = input.purchase_country if input.purchase_currency? config.purchase_currency = input.purchase_currency if input.locale? config.locale = input.locale # Layout if input.layout? if input.layout is 'desktop' or input.layout is 'mobile' config.gui.layout = input.layout # Uris if input.terms_uri? config.merchant.terms_uri = input.terms_uri if input.cancellation_terms_uri? config.merchant.cancellation_terms_uri = input.cancellation_terms_uri if input.checkout_uri? config.merchant.checkout_uri = input.checkout_uri if input.confirmation_uri? config.merchant.confirmation_uri = input.confirmation_uri if input.push_uri? config.merchant.push_uri = input.push_uri # Place order place: (cart) -> f = () -> new Promise (resolve, reject) -> # New resource object based on config options resource = config # Add cart to resource resource.cart = cart # Construct HTTP request and send to Klarna request.post httpRequest.options(resource), (error, response, body) -> # Parse response for error. err = parseError(error, response, body) # If error -> reject with error if err? return reject err # Else, if OK from Klarna -> resolve with order id else if response.statusCode? and response.statusCode is 201 # Get order url location = response.headers.location # Get id from url and resolve promise resolve location.slice(location.lastIndexOf('/') + 1) # Apply wrapper wrapper(f)() # Fetch order fetch: (id) -> f = () -> new Promise (resolve, reject) -> # Construct HTTP request and send to Klarna request.get httpRequest.options(null, id), (error, response, body) -> # If OK -> resolve promise with order if response? if response.statusCode is 200 resolve JSON.parse(body) else reject parseError(error, response, body) # Else -> reject with error else reject parseError(error, response, body) # Apply wrapper wrapper(f)() # Update order update: (id, data) -> f = () -> new Promise (resolve, reject) -> # Construct HTTP request and send to Klarna request.post httpRequest.options(data, id), (error, response, body) -> # If OK -> resolve promise with order if response? if response.statusCode? and response.statusCode is 200 resolve body else reject parseError(error, response, body) # Else -> reject promise with error else reject parseError(error, response, body) # Apply wrapper wrapper(f)() # Confirm order (with or without merchant order ids) confirm: (id, orderid1, orderid2) -> f = () -> new Promise (resolve, reject) -> # New status data = status: 'created' # If merchant reference(s), add to data to send if orderid1? data.merchant_reference = orderid1: orderid1 if orderid2? data.merchant_reference.orderid2 = orderid2 # Update order publicMethods.update(id, data).then( (order) -> resolve order (error) -> reject error ) # Apply wrapper wrapper(f)() # Export module module.exports = publicMethods