UNPKG

paymill-wrapper

Version:

PAYMILL REST API Javascrip wrapper. Work with Node, parse.com and is easily extendable for other platforms

1,997 lines (1,816 loc) 146 kB
/** @module paymill */ var __ = require("underscore"); var apiHost = "api.paymill.com"; var apiBaseUrl = "/v2.1"; var apiEncoding = "utf8"; /* note, we have to edit this manually, as the package.json is available only in node*/ var version = "2.0.3"; var sourcePrefix = "paymill-js"; function ExternalHandler() { } ExternalHandler.prototype.apiKey = null; ExternalHandler.prototype.setApiKey = function(apiKey) { this.apiKey = apiKey; }; ExternalHandler.prototype.getDeferedObject = function() { throw new PMError(PMError.Type.INTERNAL, "ExternalHandler.getDeferedObject() is abstract! Did you initialze?"); }; ExternalHandler.prototype.getPromiseObject = function(defer) { throw new PMError(PMError.Type.INTERNAL, "ExternalHandler.getPromiseObject() is abstract! Did you initialze?"); }; /** * Make a single http request. * @param {HttpRequest} httpRequest a http request object, describing all properties of the request * @abstract * @return {object} a promise */ ExternalHandler.prototype.httpRequest = function(httpRequest) { throw new PMError(PMError.Type.INTERNAL, "ExternalHandler.httpRequest() is abstract! Did you initialze?"); }; ExternalHandler.prototype.includeCallbackInPromise = function(httpRequest) { throw new PMError(PMError.Type.INTERNAL, "ExternalHandler.includeCallbackInPromise() is abstract! Did you initialze?"); }; /* * Identifis the handler type. * @abstract * @return {string} the identifier of this handler, e.g. "node","parse" */ ExternalHandler.prototype.getHandlerIdentifier = function() { throw new PMError(PMError.Type.INTERNAL, "ExternalHandler.getSourceIdentifier() is abstract! Did you initialze?"); }; /* * Identify the wrapper version against the REST API. * @abstract * @return {string} the source parameter for transactions and preauthorizations. handler, e.g. "paymill-js-node-1.0.1" */ function getSourceIdentifier() { return sourcePrefix + "-" + platformIdentifier + "-" + version; } /** * Callback for HttpClient requests. * @callback HttpClient~requestCallback * @param {PMError} error a PMError for failure * @param {string} responseMessage */ function HttpRequest(path, method, params) { this.path = path; this.method = method; this.params = params; this.requestBody = null; this.headers = {}; if (method === "GET" || method === "DELETE") { this.path = this.path + urlEncode(params, true); this.headers = { "Content-Length" : 0 }; } else { if (params !== null) { this.requestBody = urlEncode(params, false); this.headers = { "Content-Type" : "application/x-www-form-urlencoded", "Content-Length" : this.requestBody.length }; } } } /** * Checks if an http text response contains json and a data field. * @param data the http response as string * @returns {boolean} true if json and data is present, else otherwise (e.g. error) */ function isDataPresent(data) { try { var parsedData = JSON.parse(data); if (parsedData.data !== undefined && parsedData.data !== null) { return true; } else { return false; } } catch (e) { return false; } } /** * PaymillContecxt loads the context of PAYMILL for a single account, by providing a merchants private key<br /> * It creates 8 services, which represents the PAYMILL API: * @param apiKey * @constructor */ /** * * A PaymillContext represents one client of the PAYMILL API. It holds the API key and exposes the 8 services, * which correspond to the API endpoints. * @class PaymillContext */ function PaymillContext(apiKey) { // initalize services this.handler = handlerConstructor(apiKey); this.clients = new ClientService(); this.clients.setHandler(this.handler); this.offers = new OfferService(); this.offers.setHandler(this.handler); this.payments = new PaymentService(); this.payments.setHandler(this.handler); this.preauthorizations = new PreauthorizationService(); this.preauthorizations.setHandler(this.handler); this.refunds = new RefundService(); this.refunds.setHandler(this.handler); this.subscriptions = new SubscriptionService(); this.subscriptions.setHandler(this.handler); this.transactions = new TransactionService(); this.transactions.setHandler(this.handler); this.webhooks = new WebhookService(); this.webhooks.setHandler(this.handler); this.checksums = new ChecksumService(); this.checksums.setHandler(this.handler); } PaymillContext.prototype.constructor = PaymillContext; PaymillContext.prototype.handler = null; PaymillContext.prototype.apiKey = null; PaymillContext.prototype.setApiKey = function(apiKey) { this.handler.setApiKey(apiKey); }; /** * The {@link ClientService} service. */ PaymillContext.prototype.clients = null; /** * The {@link OfferService} service. */ PaymillContext.prototype.offers = null; /** * The {@link PaymentService} service. */ PaymillContext.prototype.payments = null; /** * The {@link PreauthorizationService} service. */ PaymillContext.prototype.preauthorizations = null; /** * The {@link RefundService} service. */ PaymillContext.prototype.refunds = null; /** * The {@link TransactionService} service. */ PaymillContext.prototype.transactions = null; /** * The {@link SubscriptionService} service. */ PaymillContext.prototype.subscriptions = null; /** * The {@link WebhookService} service. */ PaymillContext.prototype.webhooks = null; /** * The {@link ChecksumService} service. */ PaymillContext.prototype.checksums = null; exports.PaymillContext = PaymillContext; exports.getContext = function(apiKey) { return new PaymillContext(apiKey); }; function NodeHandler() { this.when = require("when"); this.https = require("https"); } NodeHandler.prototype = ExternalHandler.prototype; NodeHandler.prototype.constructor = NodeHandler; NodeHandler.prototype.getDeferedObject = function() { return this.when.defer(); }; NodeHandler.prototype.getPromiseObject = function(defer) { return defer.promise; }; NodeHandler.prototype.httpRequest = function(httpRequest) { var defer = this.getDeferedObject(); var promise = this.getPromiseObject(defer); var options = { hostname : apiHost, port : 443, path : apiBaseUrl + httpRequest.path, auth : this.apiKey + ":", method : httpRequest.method, headers : httpRequest.headers }; var req = this.https.request(options, function(res) { res.setEncoding(apiEncoding); var status = res.statusCode; var headers = res.headers; var data = ""; res.on("data", function(d) { data = data + d; }); res.on("end", function() { if (!isDataPresent(data)) { defer.reject(new PMError(PMError.Type.API, data, "http status code:" + status + "\nheaders:" + headers + "\ndata:" + data, JSON.stringify(data))); } else { defer.resolve(data); } }); }); req.on("error", function(e) { defer.reject(new PMError(PMError.Type.IO, null, e.toString())); }); if ( typeof httpRequest.requestBody === "string" && httpRequest.requestBody.length > 0) { req.write(httpRequest.requestBody); } req.end(); return promise; }; NodeHandler.prototype.includeCallbackInPromise = function(promise, callback) { var positive, negative; if (__.isFunction(callback)) { var when = this.when; positive = function(result) { callback(null, result); return when.resolve(result); }; negative = function(error) { callback(error); return when.reject(error); }; promise.then(positive, negative); } return promise; }; NodeHandler.prototype.getHandlerIdentifier = function() { return "node"; }; var handlerConstructor = function(apiKey) { var handler=new NodeHandler(); handler.setApiKey(apiKey); return handler; }; var platformIdentifier = 'node'; function PMError(type, message, detailMessage, apiMessage) { if (message && message.length > 0) { this.message = type + ":" + message; } else { this.message = type + "."; } this.detailMessage = detailMessage; this.apiMessage = apiMessage; this.type = type; return this; } PMError.prototype = new Error(); PMError.prototype.constructor = PMError; PMError.prototype.name = "PMError"; PMError.Type = { API : "API Error", WRONG_PARAMS : "Invalid arguments", IO : "Network issue", NOT_INIT : "Not initialized", INTERNAL : "Internal error" }; exports.PMError=PMError; function deserializePaymillObject(parsedJson, objectType) { if (parsedJson === undefined || parsedJson === null) { return null; } var result = new objectType.prototype.constructor(); result.fromJson(parsedJson); return result; } function deserializePaymillObjectList(parsedJson, objectType) { if (parsedJson === undefined || parsedJson === null) { return null; } var result = new Array(parsedJson.length); for (var i = 0; i < parsedJson.length; i++) { result[i] = deserializePaymillObject(parsedJson[i], objectType); } return result; } function deserializeDate(unixTime) { if (unixTime === undefined || unixTime === null) { return null; } if (!__.isNumber(unixTime)) { return unixTime; } return new Date(unixTime*1000); } function urlEncode(params, appendQuestion) { if (!params) { return ""; } var ret = []; for (var key in params) { if (key === "" || __.isFunction(params[key])) { continue; } ret.push(key + "=" + encodeURIComponent(params[key])); } if (ret.length > 0) { var result = ret.join("&"); if (appendQuestion) { return "?" + result; } else { return result; } } else { return ""; } } function getTimeFromObject(obj) { if ( obj instanceof Date) { return obj.getTime(); } if (__.isString(obj) || __.isNumber(obj)) { return obj; } throw new PMError(PMError.Type.WRONG_PARAMS, obj + "must be either a string, a number or a Date"); } function validateField(validationFunc, field, fieldName, optional) { if (field !== undefined && field !== null) { validationFunc(field,fieldName); } else { if (!optional) { throw new PMError(PMError.Type.WRONG_PARAMS, fieldName + " is mandatory"); } } } function validateMandatory(field,fieldName) { if (__.isEmpty(field)) { throw new PMError(PMError.Type.WRONG_PARAMS, fieldName + " is mandatory"); } } function validateNumber(field, fieldname, optional) { return validateField(function (number,numberName) { if (! (__.isNumber(number) || __.isNumber(parseInt(number,10))) ) { throw new PMError(PMError.Type.WRONG_PARAMS, numberName + " must be a number or a string representing a number"); } },field,fieldname,optional); } function validateBoolean(field, fieldname, optional) { return validateField(function (boolean, booleanName) { if (! (__.isBoolean(boolean)) ) { throw new PMError(PMError.Type.WRONG_PARAMS, booleanName + " must be a boolean"); } },field,fieldname,optional); } function validateString(field, fieldname, optional) { return validateField(function (string,stringName) { if (!(__.isString(string) ) ) { throw new PMError(PMError.Type.WRONG_PARAMS, stringName + " must be a string"); } },field,fieldname,optional); } function validateList(field, fieldname, fieldtype, optional) { // check empty and mandatory if (__.isEmpty(field)) { if (optional) { return; } else { throw new PMError(PMError.Type.WRONG_PARAMS, fieldname + " is mandatory."); } } // check array if (!__.isArray(field)) { throw new PMError(PMError.Type.WRONG_PARAMS, fieldname + " must be an array of type " + fieldtype); } for (var i=0; i<field.length; i++) { if (!(field[i] instanceof fieldtype)) { throw new PMError(PMError.Type.WRONG_PARAMS, fieldname + "[" + i + "] is not " + fieldtype); } } } function validateObject(field, fieldname, fieldtype, optional) { // check empty and mandatory if (__.isEmpty(field)) { if (optional) { return; } else { throw new PMError(PMError.Type.WRONG_PARAMS, fieldname + " is mandatory."); } } if (!(field instanceof fieldtype)) { throw new PMError(PMError.Type.WRONG_PARAMS, fieldname + " is not " + fieldtype); } } function getTimeFilter(from, to) { return getTimeFromObject(from) + "-" + getTimeFromObject(to); } function getIdFromObject(obj, objectType) { if (!obj) { throw new PMError(PMError.Type.WRONG_PARAMS, "Object must be either a string or object with a string member 'id', but it is not defined"); } if (__.isString(obj) && !__.isEmpty(obj)) { return obj; } if (objectType) { //there is an object type if ( obj instanceof objectType && obj.id && __.isString(obj.id)) { return obj.id; } } else { // no object type defined if (obj.id && __.isString(obj.id)) { return obj.id; } } throw new PMError(PMError.Type.WRONG_PARAMS, obj + "must be either a string or " + objectType + " with a valid id."); } function getRefreshObject(obj,type) { if ( obj instanceof type ) { if (!__.isEmpty(obj.id)) { return obj; } else { throw new PMError(PMError.Type.WRONG_PARAMS, obj + " is of correct type ( " + type + " ), but has no valid id."); } } else { var id = getIdFromObject(obj, type); var result = new type.prototype.constructor(); result.id=id; return result; } } function getRealEquality(equality) { if (equality === undefined) { return Filter.EQUALITY.EQUAL; } else { return equality; } } function getUnixTimeFromParam(param, paramName) { if ( param instanceof Date) { return Math.floor((param.getTime())/1000); } else if (__.isNumber(param) || __.isString(param)) { return param; } else { throw new PMError(PMError.Type.WRONG_PARAMS, "parameter " + paramName + " must be a Date, number or string"); } } /** * * Creates a new Address. * @class Address * @extends PaymillObject * @classdesc An address object belongs to exactly one transaction and can represent either its shipping address or billing address. Note, that state and postal_code are mandatory for PayPal transactions in certain countries, please consult PayPal documentation for more details. */ function Address() { } Address.prototype = new PaymillObject(); Address.prototype.constructor = Address; /** * Street address (incl. street number), max. 100 characters. * @type {string} * @memberof Address.prototype */ Address.prototype.street_address = null; /** * Addition to street address (e.g. building, floor, or c/o), max. 100 characters. * @type {string} * @memberof Address.prototype */ Address.prototype.street_address_addition = null; /** * City, max. 40 characters. * @type {string} * @memberof Address.prototype */ Address.prototype.city = null; /** * State or province, max. 40 characters. * @type {string} * @memberof Address.prototype */ Address.prototype.state = null; /** * Country-specific postal code, max. 20 characters. * @type {string} * @memberof Address.prototype */ Address.prototype.postal_code = null; /** * 2-letter country code according to ISO 3166-1 alpha-2 * @type {string} * @memberof Address.prototype */ Address.prototype.country = null; /** * Contact phone number, max. 20 characters * @type {string} * @memberof Address.prototype */ Address.prototype.phone = null; /** * The {@link Address} object. */ exports.Address = Address; /** * * Creates a new payment. Generally you should never create a PAYMILL object on your own. * @class Checksum * @classdesc Checksum validation is a simple method to ensure the integrity of transferred data. Basically, we generate a hash out of the given parameters and your private API key. If you send us a request with transaction data and the generated checksum, we can easily validate the data. To make the checksum computation as easy as possible we provide this endpoint for you. For transactions that are started client-side, e.g. PayPal checkout, it is required to first create a checksum on your server and then provide that checksum when starting the transaction in the browser. The checksum needs to contain all data required to subsequently create the actual transaction. */ function Checksum() { } Checksum.prototype = new PaymillObject(); Checksum.prototype.constructor = Checksum; /** * Unique identifier for this checksum. * @type {string} * @memberof Checksum.prototype */ Checksum.prototype.id = null; /** * The type of the checksum. Currently only 'paypal' * @type {string} * @memberof Checksum.prototype */ Checksum.prototype.type = null; /** * The actual checksum. * @type {string} * @memberof Checksum.prototype */ Checksum.prototype.checksum = null; /** * Transaction data. * @type {string} * @memberof Checksum.prototype */ Checksum.prototype.data = null; Checksum.prototype.created_at = null; /** * Unix-Timestamp for the last update. * @type {Date} * @memberof Checksum.prototype */ Checksum.prototype.updated_at = null; /** * App (ID) that created this checksum or null if created by yourself. * @type {string} * @memberof Checksum.prototype */ Checksum.prototype.app_id = null; /* * special fields */ Checksum.prototype.getFieldDefinitions = function() { return { created_at : deserializeDate, updated_at : deserializeDate }; }; exports.Checksum = Checksum; /** * * Creates a new Client. Generally you should never create a PAYMILL object on your own. * @class Client * @extends PaymillObject * @classdesc The clients object is used to edit, delete, update clients as well as to permit refunds, subscriptions, insert credit card details for a client, edit client details and of course make transactions. Clients can be created individually by you or they will be automatically generated with the transaction if there is no client ID transmitted. */ function Client() { } Client.prototype = new PaymillObject(); Client.prototype.constructor = Client; /** * Unique identifier of this preauthorization * @type {string} * @memberof Client.prototype */ Client.prototype.id = null; /** * Mail address of this client. * @type {string} * @memberof Client.prototype */ Client.prototype.email = null; /** * Additional description for this client, perhaps the identifier from your CRM system? * @type {string} * @memberof Client.prototype */ Client.prototype.description = null; /** * Unix-Timestamp for the creation date. * @type {Date} * @memberof Client.prototype */ Client.prototype.created_at = null; /** * Unix-Timestamp for the last update. * @type {Date} * @memberof Client.prototype */ Client.prototype.updated_at = null; /** * List of payments. * @type {Array.<Payment>} * @memberof Client.prototype */ Client.prototype.payment = null; /** * List of subscriptions. * @type {Array.<Subscription>} * @memberof Client.prototype */ Client.prototype.subscription = null; /** * App (ID) that created this client or null if created by yourself. * @type {string} * @memberof Client.prototype */ Client.prototype.app_id = null; /* * special fields */ Client.prototype.getFieldDefinitions = function() { return { created_at : deserializeDate, updated_at : deserializeDate, payment : function(json) { return deserializePaymillObjectList(json, Payment); }, subscription : function(json) { return deserializePaymillObjectList(json, Subscription); } }; }; Client.prototype.getUpdateableFields = function() { return ["email", "description"]; }; /** * Specify an order for clients. * @class Client.Order * @memberof Client * @extends Order */ Client.Order = function() { Order.call(this); }; Client.Order.prototype = new Order(); Client.Order.constructor = Client.Order; /** * @returns {Order} order by creditcard * @memberof Client.Order */ Client.Order.creditcard = function() { var order = new Client.Order(); order.type = "creditcard"; return order; }; /** * @returns {Order} order by email * @memberof Client.Order */ Client.Order.email = function() { var order = new Client.Order(); order.type = "email"; return order; }; /** * @returns {Order} order by created_at * @memberof Client.Order */ Client.Order.created_at = function() { var order = new Client.Order(); order.type = "created_at"; return order; }; /** * Specify a filter for clients. * @class Client.Filter * @memberof Client * @extends Filter */ Client.Filter = function() { Filter.call(this); }; Client.Filter.prototype = new Filter(); Client.Filter.constructor = Client.Filter; /** * Add filtering by payment * @param {(string|Payment)} payment the payment object or its id. * @returns {Filter} the same filter. * @memberof Client.Filter */ Client.Filter.prototype.payment = function(payment) { this.payment = getIdFromObject(payment); return this; }; /** * Add filtering by subscription * @param {(string|Subscription)} subscription the subscription object or its id. * @returns {Filter} the same filter. * @memberof Client.Filter */ Client.Filter.prototype.subscription = function(subscription) { this.subscription = getIdFromObject(subscription); return this; }; /** * Add filtering by offer * @param {(string|Offer)} offer the offer object or its id. * @returns {Filter} the same filter. * @memberof Client.Filter */ Client.Filter.prototype.offer = function(offer) { this.offer = getIdFromObject(offer); return this; }; /** * Add filtering by description * @param {string} description the description * @returns {Filter} the same filter. * @memberof Client.Filter */ Client.Filter.prototype.description = function(description) { this.description = description; return this; }; /** * Add filtering by email * @param {string} email the email * @returns {Filter} the same filter. * @memberof Client.Filter */ Client.Filter.prototype.email = function(email) { this.email = email; return this; }; /** * Add filtering by created_at * @param {(number|Date)} from the start date of the filter, either as Date or Unix-time number. * @param {(number|Date)} to the end date of the filter, either as Date or Unix-time number. * @returns {Filter} the same filter. * @memberof Client.Filter */ Client.Filter.prototype.created_at = function(from, to) { this.created_at = getTimeFilter(from,to); return this; }; /** * Add filtering by updated_at * @param {(number|Date)} from the start date of the filter, either as Date or Unix-time number. * @param {(number|Date)} to the end date of the filter, either as Date or Unix-time number. * @returns {Filter} the same filter. * @memberof Client.Filter */ Client.Filter.prototype.updated_at = function(from, to) { this.updated_at = getTimeFilter(from,to); return this; }; /** * The {@link Client} object. */ exports.Client = Client; /** * * Creates a new Fee. Generally you should never create a PAYMILL object on your own. * @class Fee * @extends PaymillObject * @classdesc Describes app fees. */ function Fee() { } Fee.prototype = new PaymillObject(); Fee.prototype.constructor = Fee; /** * Fee type * @type {Fee.Type} * @memberof Fee.prototype */ Fee.prototype.type = null; /** * Unique identifier of the app which charges the fee * @type {string} * @memberof Fee.prototype */ Fee.prototype.application = null; /** * Unique identifier of the payment from which the fee will be charged * @type {string} * @memberof Fee.prototype */ Fee.prototype.payment = null; /** * Fee amount in the smallest currency unit e.g. "420" for 4.20 € * @type {number} * @memberof Fee.prototype */ Fee.prototype.amount = null; /** * ISO 4217 formatted currency code. * @type {string} * @memberof Fee.prototype */ Fee.prototype.currency = null; /** * Unix-Timestamp for the billing date. * @type {Date} * @memberof Fee.prototype */ Fee.prototype.billed_at = null; /* * special fields */ Fee.prototype.getFieldDefinitions = function() { return { billed_at : deserializeDate }; }; /** * Type of a Fee. * @memberof Fee * @property {string} APPLICATION */ Fee.Type = { "APPLICATION" : "application" }; /** * * Creates a new Filter. Use factories of implementing classes. * @class Filter */ function Filter() { } /** * Descibes equality for filters. * @memberof Filter * @property {string} EQUAL * @property {string} LESS_THAN * @property {string} GREATER_THAN */ Filter.EQUALITY = { "LESS_THAN" : "<", "GREATER_THAN" : ">", "EQUAL" : "" }; /** * * Creates a new Interval. * @class Interval * @param {number} length length of the interval (in units) * @param {string|Interval.Unit} Unit for the interval * @param {string|Interval.Weekday} weekday on which a charge should occur * @extends PaymillObject * @classdesc Defining an interval for an offer. */ function Interval(length, unit, weekday) { this.length = length; this.unit = unit; this.chargeday = weekday; } Interval.prototype = new PaymillObject(); Interval.prototype.constructor = Interval; /** * Length of the interval (in units) * @type {number} * @memberof Interval.prototype */ Interval.prototype.length = null; /** * Unit for the interval * @type {Interval.Unit} * @memberof Interval.prototype */ Interval.prototype.unit = null; /** * Charge day in the week * @type {Interval.Weekday} * @memberof Interval.prototype */ Interval.prototype.chargeday = null; Interval.prototype.fromJson = function(jsonObj) { var weekdayParts = jsonObj.split(','); if (weekdayParts.length > 1) { this.chargeday = weekdayParts[1]; } var split = weekdayParts[0].split(" "); this.length = parseInt(split[0],10); this.unit = split[1]; this.originalJson = jsonObj; }; Interval.prototype.toString = function() { var chargedayPart = (__.isEmpty(this.chargeday)) ? '': ',' + this.chargeday; return "" + this.length + " " + this.unit + chargedayPart; }; Interval.prototype.getUpdateIdentifier = function() { return this.toString(); }; /** * Units for an Interval. * @memberof Interval * @property {string} DAY * @property {string} WEEK * @property {string} MONTH * @property {string} YEAR */ Interval.Unit = { "DAY" : "DAY", "WEEK" : "WEEK", "MONTH" : "MONTH", "YEAR" : "YEAR" }; /** * Weekdays for an Interval. * @memberof Interval * @property {string} MONDAY * @property {string} TUESDAY * @property {string} WEDNESDAY * @property {string} THURSDAY * @property {string} FRIDAY * @property {string} SATURDAY * @property {string} SUNDAY */ Interval.Weekday = { MONDAY : "MONDAY", TUESDAY : "TUESDAY", WEDNESDAY : "WEDNESDAY", THURSDAY : "THURSDAY", FRIDAY : "FRIDAY", SATURDAY : "SATURDAY", SUNDAY : "SUNDAY" }; exports.Interval=Interval; /** * * Creates a new Offer. Generally you should never create a PAYMILL object on your own. * @class Offer * @extends PaymillObject * @classdesc An offer is a recurring plan which a user can subscribe to. You can create different offers with different plan attributes e.g. a monthly or a yearly based paid offer/plan. */ function Offer() { } Offer.prototype = new PaymillObject(); Offer.prototype.constructor = Offer; /** * Unique identifier of this offer. * @type {string} * @memberof Offer.prototype */ Offer.prototype.id = null; /** * Your name for this offer * @type {string} * @memberof Offer.prototype */ Offer.prototype.name = null; /** * Every interval the specified amount will be charged. Only integer values are allowed (e.g. 42.00 = 4200). * @type {number} * @memberof Offer.prototype */ Offer.prototype.amount = null; /** * ISO 4217 formatted currency code * @type {string} * @memberof Offer.prototype */ Offer.prototype.currency = null; /** * Defining how often the client should be charged. * @type {Interval} * @memberof Offer.prototype */ Offer.prototype.interval = null; /** * Give it a try or charge directly?. * @type {number} * @memberof Offer.prototype */ Offer.prototype.trial_period_days = null; /** * Unix-Timestamp for the creation date. * @type {Date} * @memberof Offer.prototype */ Offer.prototype.created_at = null; /** * Unix-Timestamp for the last update. * @type {Date} * @memberof Offer.prototype */ Offer.prototype.updated_at = null; /** * Unix-Timestamp for the last update. * @type {Date} * @memberof SubscriptionCount.prototype */ Offer.prototype.subscription_count = null; /** * App (ID) that created this offer or null if created by yourself. * @type {string} * @memberof Offer.prototype */ Offer.prototype.app_id = null; /* * special fields */ Offer.prototype.getFieldDefinitions = function() { return { created_at : deserializeDate, updated_at : deserializeDate, interval : function(json) { return deserializePaymillObject(json, Interval); }, subscription_count : function(json) { return deserializePaymillObject(json, SubscriptionCount); } }; }; Offer.prototype.getUpdateableFields = function() { return ["name"]; }; /** * Specify an order for clients. * @class Offer.Order * @memberof Offer * @extends Order */ Offer.Order = function() { Order.call(this); }; Offer.Order.prototype = new Order(); Offer.Order.constructor = Offer.Order; /** * @returns {Order} order by creditcard * @memberof Offer.Order */ Offer.Order.interval = function() { var order = new Offer.Order(); order.type = "interval"; return order; }; /** * @returns {Order} order by creditcard * @memberof Offer.Order */ Offer.Order.amount = function() { var order = new Offer.Order(); order.type = "amount"; return order; }; /** * @returns {Order} order by creditcard * @memberof Offer.Order */ Offer.Order.created_at = function() { var order = new Offer.Order(); order.type = "created_at"; return order; }; /** * @returns {Order} order by creditcard * @memberof Offer.Order */ Offer.Order.trial_period_days = function() { var order = new Offer.Order(); order.type = "trial_period_days"; return order; }; /** * Specify a filter for offers. * @class Offer.Filter * @memberof Offer * @extends Filter */ Offer.Filter = function() { Filter.call(this); }; Offer.Filter.prototype = new Filter(); Offer.Filter.constructor = Offer.Filter; /** * Add filtering by name * @param {string} name the name of the offer. * @returns {Filter} the same filter. * @memberof Offer.Filter */ Offer.Filter.prototype.name = function(name) { this.name = name; return this; }; /** * Add filtering by trial_period_days * @param {(string|number)} client the trial_period_days of the offer. * @returns {Filter} the same filter. * @memberof Offer.Filter */ Offer.Filter.prototype.trial_period_days = function(trial_period_days) { this.trial_period_days = trial_period_days; return this; }; /** * Add filtering by amount. e.g. "300" or ">300" or "<300" * @param {(string|number)} amount the amount to be filtered * @param {(string|Filter.EQUALITY)} equality equality for the filter. If none is specified EQUAL is used. * @returns {Filter} the same filter. * @memberof Offer.Filter */ Offer.Filter.prototype.amount = function(amount, equality) { this.amount = getRealEquality(equality) + amount; return this; }; /** * Add filtering by created_at * @param {(number|Date)} from the start date of the filter, either as Date or Unix-time number. * @param {(number|Date)} to the end date of the filter, either as Date or Unix-time number. * @returns {Filter} the same filter. * @memberof Offer.Filter */ Offer.Filter.prototype.created_at = function(from, to) { this.created_at = getTimeFilter(from,to); return this; }; /** * Add filtering by updated_at * @param {(number|Date)} from the start date of the filter, either as Date or Unix-time number. * @param {(number|Date)} to the end date of the filter, either as Date or Unix-time number. * @returns {Filter} the same filter. * @memberof Offer.Filter */ Offer.Filter.prototype.updated_at = function(from, to) { this.updated_at = getTimeFilter(from,to); return this; }; /** * The {@link Offer} object. */ exports.Offer = Offer; /** * * Creates a new Order. Use factories of implementing classes. * @class Order */ function Order() { } /** * Is the order ascending? * @type {boolean} * @memberOf Order */ Order.prototype.ascending = null; /** * The type of the order, overwritten by concrete implmentations * @abstract * @type {boolean} * @memberOf Order */ Order.prototype.type = null; /** * Change the order to ascending * @return {Order} the same order for chaining * @memberOf Order */ Order.prototype.asc = function() { this.ascending = true; return this; }; /** * Change the order to descending. * @return {Order} the same order for chaining * @memberOf Order */ Order.prototype.desc = function() { this.ascending = false; return this; }; /** * Create the http map for an order * @return {*} a mixed object with the Order * @memberOf Order */ Order.prototype.toHttpMap = function() { var s = this.type; if ( typeof this.ascending !== null) { if (this.ascending) { s = s + "_asc"; } else { s = s + "_desc"; } } return { "order" : s }; }; /** * * Creates a new payment. Generally you should never create a PAYMILL object on your own. * @class Payment * @classdesc The Payment object represents a payment with a credit card or via direct debit. It is used for several function calls (e.g. transactions, subscriptions, clients, ...). To be PCI compliant these information is encoded by our Paymill PSP. You only get in touch with safe data (token) and needn't to care about the security problematic of informations like credit card data. */ function Payment() { } Payment.prototype = new PaymillObject(); Payment.prototype.constructor = Payment; /** * Unique identifier for this payment. * @type {string} * @memberof Payment.prototype */ Payment.prototype.id = null; /** * The type of the payment. * @type {Payment.Type} * @memberof Payment.prototype */ Payment.prototype.type = null; /** * The identifier of a client (client-object) * @type {string} * @memberof Payment.prototype */ Payment.prototype.client = null; /** * Card type eg. visa, mastercard. Only for credit card payments. * @type {string} * @memberof Payment.prototype */ Payment.prototype.card_type = null; /** * Country. Only for credit card payments. * @type {string} * @memberof Payment.prototype */ Payment.prototype.country = null; /** * Expiry month of the credit card. Only for credit card payments. * @type {number} * @memberof Payment.prototype */ Payment.prototype.expire_month = null; /** * Expiry year of the credit card. Only for credit card payments. * @type {number} * @memberof Payment.prototype */ Payment.prototype.expire_year = null; /** * The last four digits of the credit card. Only for credit card payments. * @type {string} * @memberof Payment.prototype */ Payment.prototype.last4 = null; /** * Unix-Timestamp for the creation date. * @type {Date} * @memberof Payment.prototype */ Payment.prototype.created_at = null; /** * Unix-Timestamp for the last update. * @type {Date} * @memberof Payment.prototype */ Payment.prototype.updated_at = null; /** * App (ID) that created this payment or null if created by yourself. * @type {string} * @memberof Payment.prototype */ Payment.prototype.app_id = null; /** * The used account number, for security reasons the number is masked. Only for direct debit payments. * @type {string} * @memberof Payment.prototype */ Payment.prototype.account = null; /** * Whether or not this payment is recurring (can be used more than once). * @type {boolean} * @memberof Payment.prototype */ Payment.prototype.is_recurring = null; /** * Whether or not this payment is usable for preauthorization. * @type {boolean} * @memberof Payment.prototype */ Payment.prototype.is_usable_for_preauthorization = null; /** * Name of the account holder. Only for direct debit payments. * @type {string} * @memberof Payment.prototype */ Payment.prototype.holder = null; /** * The type of payment. * @memberof Payment * @property {string} CREDITCARD a credit card payment. * @property {string} DEBIT a direct debit payment. */ Payment.Type = { CREDITCARD : "creditcard", DEBIT : "debit" }; /* * special fields */ Payment.prototype.getFieldDefinitions = function() { return { created_at : deserializeDate, updated_at : deserializeDate }; }; /** * Specify an order for payments. * @class Payment.Order * @memberof Payment * @extends Order */ Payment.Order = function() { Order.call(this); }; Payment.Order.prototype = new Order(); Payment.Order.constructor = Payment.Order; /** * @returns {Order} order by created_at * @memberof Payment.Order */ Payment.Order.created_at = function() { var order = new Payment.Order(); order.type = "created_at"; return order; }; /** * Specify a filter for payments. * @class Payment.Filter * @memberof Payment * @extends Filter */ Payment.Filter = function() { Filter.call(this); }; Payment.Filter.prototype = new Filter(); Payment.Filter.constructor = Payment.Filter; /** * Add filtering by card_type * @param {string} card_type e.g. "visa", "mastercard" etc. * @returns {Filter} the same filter. * @memberof Payment.Filter */ Payment.Filter.prototype.card_type = function(card_type) { this.card_type = card_type; return this; }; /** * Add filtering by created_at * @param {(number|Date)} from the start date of the filter, either as Date or Unix-time number. * @param {(number|Date)} to the end date of the filter, either as Date or Unix-time number. * @returns {Filter} the same filter. * @memberof Payment.Filter */ Payment.Filter.prototype.created_at = function(from, to) { this.created_at = getTimeFilter(from,to); return this; }; /** * The {@link Payment} object. */ exports.Payment = Payment; /** * * Creates a new PaymillList. Used internally. * @class PaymillList * @extends PaymillObject * @classdesc The list object is used to devliver list results. The actual array is contained in the items property, while count holds the total count. */ function PaymillList() { } /** * Total count of items. Usefull to control pagination. * @type {number} * @memberof PaymillList.prototype */ PaymillList.prototype.count = null; /** * The actual items. * @type {Array} * @memberof PaymillList.prototype */ PaymillList.prototype.items = null; exports.PaymillList = PaymillList; function PaymillObject() { } PaymillObject.prototype.originalJson = null; /** * @return {object} an object with fields, that require special deserialization */ PaymillObject.prototype.getFieldDefinitions = function() { return {}; }; PaymillObject.prototype.fromJson = function(jsonObj) { // if we only have a string, it's just the id if ( __.isString(jsonObj) ) { this.id = jsonObj; this.originalJson = jsonObj; } else { // if we have a complex object, deserialize var fieldDefs = this.getFieldDefinitions(); for (var key in jsonObj) { if (jsonObj.hasOwnProperty(key)) { var value = jsonObj[key]; if (fieldDefs[key] !== undefined) { this[key] = fieldDefs[key](value); } else { if (this[key] !== undefined) { this[key] = value; } } } } this.originalJson = jsonObj; } }; PaymillObject.prototype.getUpdateMap = function() { var updateFields = this.getUpdateableFields(); var result = {}; for (var i = 0; i < updateFields.length; i++) { var key = updateFields[i]; if (this[key] !== undefined && this[key] !== null) { result[key] = getUpdateValueOrId(this[key]); } } return result; }; PaymillObject.prototype.getUpdateIdentifier = function() { return this.id; }; /* * use by updatemap to extract paymillobject ids for updates */ function getUpdateValueOrId(value) { if ( value instanceof PaymillObject ) { return value.getUpdateIdentifier(); } else { return value.toString(); } } PaymillObject.prototype.getUpdateableFields = function() { return {}; }; /** * * Creates a new Preauthorization. Generally you should never create a PAYMILL object on your own. * @class Preauthorization * @classdesc If you'd like to reserve some money from the client's credit card but you'd also like to execute the transaction itself a bit later, then use preauthorizations. This is NOT possible with direct debit. <br/>A preauthorization is valid for 7 days. */ function Preauthorization() { } Preauthorization.prototype = new PaymillObject(); Preauthorization.prototype.constructor = Preauthorization; /** * Unique identifier for this payment. * @type {string} * @memberof Preauthorization.prototype */ Preauthorization.prototype.id = null; /** * Formatted amount which will be reserved for further transactions. * @type {string} * @memberof Preauthorization.prototype */ Preauthorization.prototype.amount = null; /** * ISO 4217 formatted currency code. * @type {string} * @memberof Preauthorization.prototype */ Preauthorization.prototype.currency = null; /** * Additional description for this preauthorization. * @type {string} * @memberof Preauthorization.prototype */ Preauthorization.prototype.description = null; /** * Indicates the current status of this preauthorization. * @type {Preauthorization.Status} * @memberof Preauthorization.prototype */ Preauthorization.prototype.status = null; /** * Whether this preauthorization was issued while being in live mode or not. * @type {boolean} * @memberof Preauthorization.prototype */ Preauthorization.prototype.livemode = null; /** * Corresponding payment object. * @type {Payment} * @memberof Preauthorization.prototype */ Preauthorization.prototype.payment = null; /** * Corresponding client object. * @type {Client} * @memberof Preauthorization.prototype */ Preauthorization.prototype.client = null; /** * Corresponding Transaction object. * @type {Transaction} * @memberof Preauthorization.prototype */ Preauthorization.prototype.transaction = null; /** * Unix-Timestamp for the creation date. * @type {Date} * @memberof Preauthorization.prototype */ Preauthorization.prototype.created_at = null; /** * Unix-Timestamp for the last update. * @type {Date} * @memberof Preauthorization.prototype */ Preauthorization.prototype.updated_at = null; /** * App (ID) that created this payment or null if created by yourself. * @type {string} * @memberof Preauthorization.prototype */ Preauthorization.prototype.app_id = null; /** * Status of a Preauthorization. * @memberof Preauthorization * @property {string} OPEN * @property {string} PENDING * @property {string} CLOSED * @property {string} FAILED * @property {string} DELETED * @property {string} PREAUTH */ Preauthorization.Status = { OPEN : "open", PENDING : "pending", CLOSED : "closed", FAILED : "failed", DELETED : "deleted", PREAUTH : "preauth" }; /* * special fields */ Preauthorization.prototype.getFieldDefinitions = function() { return { created_at : deserializeDate, updated_at : deserializeDate, payment : function(json) { return deserializePaymillObject(json, Payment); }, client : function(json) { return deserializePaymillObject(json, Client); } }; }; /** * Specify an order for preauthorizations. * @class Preauthorization.Order * @memberof Preauthorization * @extends Order */ Preauthorization.Order = function() { Order.call(this); }; Preauthorization.Order.prototype = new Order(); Preauthorization.Order.constructor = Preauthorization.Order; /** * @returns {Order} order by created_at * @memberof Client.Order */ Preauthorization.Order.created_at = function() { var order = new Client.Order(); order.type = "created_at"; return order; }; /** * Specify a filter for preauthorizations. * @class Preauthorization.Filter * @memberof Preauthorization * @extends Filter */ Preauthorization.Filter = function() { Filter.call(this); }; Preauthorization.Filter.prototype = new Filter(); Preauthorization.Filter.constructor = Preauthorization.Filter; /** * Add filtering by payment * @param {(string|Client)} client the client object or its id. * @returns {Filter} the same filter. * @memberof Preauthorization.Filter */ Preauthorization.Filter.prototype.client = function(client) { this.client = getIdFromObject(client); return this; }; /** * Add filtering by payment * @param {(string|Payment)} payment the payment object or its id. * @returns {Filter} the same filter. * @memberof Preauthorization.Filter */ Preauthorization.Filter.prototype.payment = function(payment) { this.payment = getIdFromObject(payment); return this; }; /** * Add filtering by amount. e.g. "300" or ">300" or "<300" * @param {(string|number)} amount the target amount * @param {(string|Filter.EQUALITY)} equality equality for the filter. If none is specified EQUAL is used. * @returns {Filter} the same filter. * @memberof Preauthorization.Filter */ Preauthorization.Filter.prototype.amount = function(amount, equality) { this.amount = getRealEquality(equality) + amount; return this; }; /** * Add filtering by created_at * @param {(number|Date)} from the start date of the filter, either as Date or Unix-time number. * @param {(number|Date)} to the end date of the filter, either as Date or Unix-time number. * @returns {Filter} the same filter. * @memberof Preauthorization.Filter */ Preauthorization.Filter.prototype.created_at = function(from, to) { this.created_at = getTimeFilter(from,to); return this; }; /** * The {@link Preauthorization} object. */ exports.Preauthorization = Preauthorization; /** * * Creates a new Refund. Generally you should never create a PAYMILL object on your own. * @class Refund * @extends PaymillObject * @classdesc Refunds are own objects with own calls for existing transactions. The refunded amount will be credited to the account of the client. */ function Refund() { } Refund.prototype = new PaymillObject(); Refund.prototype.constructor = Refund; /** * Unique identifier of this refund. * @type {string} * @memberof Client.prototype */ Refund.prototype.id = null; /** * Corresponding transaction object. * @type {Transaction} * @memberof Refund.prototype */ Refund.prototype.transaction = null; /** * The refunded amount. * @type {number} * @memberof Refund.prototype */ Refund.prototype.amount = null; /** * Indicates the current status of this refund. * @type {Refund.Status} * @memberof Refund.prototype */ Refund.prototype.status = null; /** * The description given for this refund. * @type {string} * @memberof Refund.prototype */ Refund.prototype.description = null; /** * Whether this refund happend in test- or in livemode. * @type {boolean} * @memberof Refund.prototype */ Refund.prototype.livemode = null; /** * Unix-Timestamp for the creation date. * @type {Date} * @memberof Refund.prototype */ Refund.prototype.created_at = null; /** * Unix-Timestamp for the last update. * @type {Date} * @memberof Refund.prototype */ Refund.prototype.updated_at = null; /** * App (ID) that created this payment or null if created by yourself. * @type {string} * @memberof Refund.prototype */ Refund.prototype.app_id = null; /** * A response code or null if details are called. * @type {number} * @memberof Refund.prototype */ Refund.prototype.response_code = null; /** * Status of a Refund. * @memberof Refund * @property {string} OPEN * @property {string} PENDING * @property {string} REFUNDED */ Refund.Status = { OPEN : "open", PENDING : "pending", REFUNDED : "refunded" }; Refund.prototype.getFieldDefinitions = function() { return { created_at : deserializeDate, updated_at : deserializeDate, transaction : function(json) { return deserializePaymillObject(json, Transaction); } }; }; /** * Specify an order for clients. * @class Refund.Order * @memberof Refund * @extends Order */ Refund.Order = function() { Order.call(this); }; Refund.Order.prototype = new Order(); Refund.Order.constructor = Refund.Order; /** * @returns {Order} order by transaction * @memberof Refund.Order */ Refund.Order.transaction = function() { var order = new Refund.Order(); order.type = "transaction"; return order; }; /** * @returns {Order} order by client * @memberof Refund.Order */ Refund.Order.client = function() { var order = new Refund.Order(); order.type = "client"; return order; }; /** * @returns {Order} order by transaction * @memberof Refund.Order */ Refund.Order.amount = function() { var order = new Refund.Order(); order.type = "amount"; return order; }; /** * @returns {Order} order by transaction * @memberof Refund.Order */ Refund.Order.created_at = function() { var order = new Refund.Order(); order.type = "created_at"; return order; }; /** * Specify a filter for refunds. * @class Refund.Filter * @memberof Refund * @extends Filter */ Refund.Filter = function() { Filter.call(this); }; Refund.Filter.prototype = new Filter(); Refund.Filter.constructor = Refund.Filter; /** * Add filtering by client * @param {(string|Client)} client the client object or its id. * @returns {Filter} the same filter. * @memberof Refund.Filter */ Refund.Filter.prototype.client = function(client) { this.payment = getIdFromObject(client); return this; }; /** * Add filtering by transaction * @param {(string|Transaction)} transaction the transaction object or its id. * @returns {Filter} the same filter. * @memberof Refund.Filter */ Refund.Filter.prototype.transaction = function(transaction) { this.transaction = getIdFromObject(transaction); return this; }; /** * Add filtering by amount. e.g. "300" or ">300" or "<300" * @param {(string|number)} amount the target amount * @param {(string|Filter.EQUALITY)} equality equality for the filter. If none is specified EQUAL is used. * @returns {Filter} the same filter. * @memberof Refund.Filter */ Refund.Filter.prototype.amount = fun