Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
kehers committed Jan 29, 2016
0 parents commit 7b9cee0
Show file tree
Hide file tree
Showing 8 changed files with 411 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
responses.json
demo.js
/node_modules
82 changes: 82 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
## paystack-node

A Nodejs API wrapper for [Paystack](https://paystack.co/).

### Installation

```
npm install paystack-node
```

### Usage

```js
// Require the library
var paystack = require('./index')('secret_key');

// Make a call to the resource/method
// paystack.{resource}.{method}
paystack.customer.list(function(error, body) {
console.log(error);
console.log(body);
});
```

The resource method accepts an optional callback as the last argument. The callback returns two JSON objects - `error`, which will be null for successful calls, and `body`, the response from the API call.

For resource methods that use POST or PUT, the JSON body can be passed as the first argument.

```js
paystack.plan.create({
name: 'API demo',
amount: 10000,
interval: 'monthly'
},function(error, body) {
console.log(error);
console.log(body);
});
```

For GET, you can pass the required ID as string and optional parameters as an optioal object argument.

```js
paystack.plan.get(90, function(error, body) {
console.log(error);
console.log(body);
});
```

```js
paystack.transactions.list({
perPage: 20
}, function(error, body) {
console.log(error);
console.log(body);
});
```

### Resources

- customer
- create
- get
- list
- update
- transaction
- initialize
- charge
- get
- list
- totals
- verify
- plan
- create
- get
- list
- update

### Todo

- Proper resource examples
- Tests
- ES6 support
149 changes: 149 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
Paystack API wrapper
@author Obembe Opeyemi <@kehers>
*/

'use strict';

var
request = require('request')
, root = 'https://api.paystack.co'
;

var resources = {
customer: require('./resources/customer'),
plan: require('./resources/plan'),
transaction: require('./resources/transaction')
}

function Paystack(key) {
if (!(this instanceof Paystack)) {
return new Paystack(key);
}

this.key = key;
this.importResources();
}

Paystack.prototype = {

extend: function(params) {

return (function() {

// Convert argument to array
var args = new Array(arguments.length);
var l = args.length;
for(var i = 0; i < l; ++i) {
args[i] = arguments[i];
}

// Check for callback
var callback;
if (l > 0) {
l--;
// I expect it to be the last argument
if (args[l].constructor === Function)
callback = args[l];
args.splice(l, 1);
}

var body, qs;
var method = params.method;
// todo: Validate possible values of method (get, post, put...)
var endpoint = [root, params.endpoint].join('');

// Get arguments in endpoint => {id} in customer/{id}
var argsInEndpoint = endpoint.match(/{[^}]+}/g);
if (argsInEndpoint) {
l = argsInEndpoint.length;
// Do we have one or more?
if (l > 0) {
// Confirm resource declaration good
if (!Array.isArray(params.args)) {
// error
throw new Error('Resource declaration error');
}

// Confirm user passed the argument to method
// and replace in endpoint
var match, index;
for (var i=0;i<l;i++) {
match = argsInEndpoint[i].replace(/\W/g, '');
index = params.args.indexOf(match);
if (index != -1) {
if (!args[index]) {
// error
throw new Error('Resource declaration error');
}

// todo: args[index] must be string or int

endpoint = endpoint.replace(new RegExp(argsInEndpoint[i]), args[index]);
args.splice(index, 1);
}
}
}
}

// Add post/put/[delete?] body
if (args[0]) {
if (method == 'post' || method == 'put') {
// Body
body = args[0];
}
else if (method == 'get') {
qs = args[0];
}
}

// Make request
var options = {
url: endpoint,
method: method.toUpperCase(),
headers: {
'Authorization': ['Bearer ', this.key].join('')
}
}

if (body) {
options.body = body;
options.json = true;
}

if (qs)
options.qs = qs;

//console.log(options);

request(options, function(error, response, body) {
// return body
if (callback){

// Error from API??
if (!body.status) {
error = body;
body = null;
}

return callback(error, body);
}
});

}).bind(this); // bind, because access to Paystack object
},

importResources: function() {
var anon;
for (var j in resources) {
anon = function(){};
for(var i in resources[j]) {
anon.prototype[i] = this.extend(resources[j][i]);
}
Paystack.prototype[j] = new anon();
}
}
};


module.exports = Paystack;
20 changes: 20 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "paystack-node",
"version": "1.0.0",
"description": "Paystack API wrapper",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"payment",
"API",
"naira",
"paystack"
],
"author": "Opeyemi Obembe <[email protected]> (http://obem.be/opeyemi)",
"license": "MIT",
"dependencies": {
"request": "^2.67.0"
}
}
44 changes: 44 additions & 0 deletions resources/customer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use strict';

var root = '/customer';

module.exports = {

/*
Create customer
@param: first_name, last_name, email, phone
*/
create: {
method: 'post',
endpoint: root,
params: ['first_name', 'last_name', 'email', 'phone']
},

/*
Get customer
*/
get: {
method: 'get',
endpoint: [root, '/{id}'].join(''),
args: ['id']
},

/*
List customers
*/
list: {
method: 'get',
endpoint: root
},

/*
Update customer
@param: first_name, last_name, email, phone
*/
update: {
method: 'put',
endpoint: [root, '/{id}'].join(''),
params: ['first_name', 'last_name', 'email', 'phone'],
args: ['id']
}
};
42 changes: 42 additions & 0 deletions resources/plan.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict';

var root = '/plan';

module.exports = {

/*
Create plan
*/
create: {
method: 'post',
endpoint: root,
params: ['name', 'description', 'amount', 'interval', 'send_invoices', 'send_sms', 'hosted_page', 'hosted_page_url', 'hosted_page_summary', 'currency']
},

/*
Get plan
*/
get: {
method: 'get',
endpoint: [root, '/{id}'].join(''),
args: ['id']
},

/*
List plan
*/
list: {
method: 'get',
endpoint: root
},

/*
Update plan
*/
update: {
method: 'put',
endpoint: [root, '/{id}'].join(''),
params: ['name', 'description', 'amount', 'interval', 'send_invoices', 'send_sms', 'hosted_page', 'hosted_page_url', 'hosted_page_summary', 'currency'],
args: ['id']
}
};
Loading

0 comments on commit 7b9cee0

Please sign in to comment.