diff --git a/package.json b/package.json index 260b6fd..4bc2af0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "midtrans-payment", - "version": "1.2.5", + "version": "1.2.6", "description": "Midtrans Payment Gateway library for NodeJS", "main": "src/midtrans.js", "scripts": { diff --git a/src/midtrans.js b/src/midtrans.js index 6060fe3..6753fb8 100644 --- a/src/midtrans.js +++ b/src/midtrans.js @@ -30,13 +30,17 @@ class MidTrans extends Base64 { constructor(config) { super(); this.body = {}; - for(var key in config) { - if(config.hasOwnProperty(key)) { - this[key] = config[key]; + if(typeof config === 'object' && config.constructor === Object){ + for(var key in config) { + if(config.hasOwnProperty(key)) { + this[key] = config[key]; + } } - } - if(!config.mode) { - this.mode = "sandbox"; + if(!config.mode) { + this.mode = "sandbox"; + } + } else { + throw new Error('Config must be an object type!'); } } @@ -205,8 +209,10 @@ class MidTrans extends Base64 { var order_id = data; order_id.client_key = this.client_key; data = this[_convertObjectToURLParameter](order_id); + this.url = this[_url](this.mode)+'/'+name+'?'+data; + } else { + this.url = this[_url](this.mode)+'/'+name; } - this.url = this[_url](this.mode)+'/'+name+'?'+data; break; case 'point_inquiry': if(typeof additional_payload === 'object'){ @@ -221,8 +227,10 @@ class MidTrans extends Base64 { var order_id = data; order_id.client_key = this.client_key; data = this[_convertObjectToURLParameter](order_id); + this.url = this[_url](this.mode)+'/'+name+'?'+data; + } else { + this.url = this[_url](this.mode)+'/'+name; } - this.url = this[_url](this.mode)+'/'+name+'?'+data; break; case 'status/b2b': if(typeof additional_payload === 'object'){ @@ -379,7 +387,6 @@ class MidTrans extends Base64 { */ billing_address(first_name='',last_name='',email='',phone='',address='',city='',postal_code='',country_code='') { if(!this[_isEmpty](this.body.customer_details)) { - if(!this[_hasKey](this.body.customer_details,'billing_address')) this.add('billing_address',{}); var items = {}; if(first_name) items.first_name=first_name; if(last_name) items.last_name=last_name; @@ -408,7 +415,6 @@ class MidTrans extends Base64 { */ shipping_address(first_name='',last_name='',email='',phone='',address='',city='',postal_code='',country_code='') { if(!this[_isEmpty](this.body.customer_details)) { - if(!this[_hasKey](this.body.customer_details,'shipping_address')) this.add('shipping_address',{}); var items = {}; if(first_name) items.first_name=first_name; if(last_name) items.last_name=last_name; @@ -437,6 +443,7 @@ class MidTrans extends Base64 { * @return {callback} */ send(callback){ + if(this[_isEmptyConfig]('url')) throw new Error('Action method is required!'); if(this.url.endsWith(this.client_key) || (this.url.includes('/status') > 0) || (this.url.includes('/point_inquiry/') > 0) diff --git a/test/authorization.js b/test/authorization.js deleted file mode 100644 index 61d7992..0000000 --- a/test/authorization.js +++ /dev/null @@ -1,27 +0,0 @@ -var assert = require('assert'); -var MidTrans = require('../src/midtrans.js'); - -var config = { - client_key: "xxx", //don't change this - server_key: "xxx", //don't change this - mode: "" -}; - -describe('MidTrans authorization test', function(){ - - it('base64 encode', function(){ - var mdt = new MidTrans(config); - assert.equal(mdt.encode(mdt.server_key),'eHh4'); - }); - - it('base64 decode', function(){ - var mdt = new MidTrans(config); - assert.equal(mdt.decode('eHh4'),'xxx'); - }); - - it('base64 authorization', function(){ - var mdt = new MidTrans(config); - assert.equal(mdt.encode(mdt.server_key+':'),'eHh4Og=='); - }); - -}); \ No newline at end of file diff --git a/test/base64.js b/test/base64.js new file mode 100644 index 0000000..15e9606 --- /dev/null +++ b/test/base64.js @@ -0,0 +1,34 @@ +var assert = require('assert'); +var Base64 = require('../src/base64.js'); +var MidTrans = require('../src/midtrans.js'); + +var config = { + client_key: "xxx", //don't change this + server_key: "xxx", //don't change this + mode: "" +}; + +describe('Base64 String test', function(){ + var base64 = new Base64(); + it('encode',function(){ + var result = base64.encode('abcdefghijklmnopqrstuvwxyz'); + assert.equal(result,'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo='); + }); + + it('decode',function(){ + var result = base64.decode('YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo='); + assert.equal(result,'abcdefghijklmnopqrstuvwxyz'); + }); + + it('decode format buffer will return buffer',function(){ + var base64 = new Base64('buffer'); + var result = base64.decode('YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo='); + assert.equal(true,Buffer.isBuffer(result)); + }); + + it('base64 authorization', function(){ + var mdt = new MidTrans(config); + assert.equal(mdt.encode(mdt.server_key+':'),'eHh4Og=='); + }); + +}); \ No newline at end of file diff --git a/test/body.js b/test/body.js index 7a60b9b..01727bc 100644 --- a/test/body.js +++ b/test/body.js @@ -36,6 +36,26 @@ describe('MidTrans body test', function(){ assert.equal(body.item_details[0].brand,'Kid Toys'); assert.equal(body.item_details[0].category,undefined); assert.equal(body.item_details[0].merchant_name,undefined); + assert.equal(body.item_details[0].tenor,undefined); + assert.equal(body.item_details[0].code_plan,undefined); + assert.equal(body.item_details[0].mid,undefined); + }); + + it('item_details with full parameter', function(){ + var mdt = new MidTrans(config); + var body = mdt.type('snap').action('transactions') + .transaction_details('INV001',1000) + .item_details('Midtrans Bear',1000,1,'Kid Toys','Toys','Online Shop','03','000','mid') + .getBody(); + assert.equal(body.item_details[0].name,'Midtrans Bear'); + assert.equal(body.item_details[0].price,1000); + assert.equal(body.item_details[0].quantity,1); + assert.equal(body.item_details[0].brand,'Kid Toys'); + assert.equal(body.item_details[0].category,'Toys'); + assert.equal(body.item_details[0].merchant_name,'Online Shop'); + assert.equal(body.item_details[0].tenor,'03'); + assert.equal(body.item_details[0].code_plan,'000'); + assert.equal(body.item_details[0].mid,'mid'); }); it('multiple item_details', function(){ @@ -86,18 +106,43 @@ describe('MidTrans body test', function(){ assert.equal(body.customer_details.phone,'+62838'); }); + it('customer_details is optional', function(){ + var mdt = new MidTrans(config); + var body = mdt.type('snap').action('transactions') + .transaction_details('INV001',1000) + .item_details('Midtrans Bear',1000,1) + .customer_details() + .getBody(); + assert.deepEqual(body.customer_details,{}); + }); + it('billing_address', function(){ var mdt = new MidTrans(config); var body = mdt.type('snap').action('transactions') .transaction_details('INV001',1000) .item_details('Midtrans Bear',1000,1) .customer_details('John','Doe','john.doe@gmail.com','+62856') - .billing_address('John','Doe','john.doe@gmail.com','+62856') + .billing_address('John','Doe','john.doe@gmail.com','+62856','address','city','postal_code','country_code') .getBody(); assert.equal(body.customer_details.billing_address.first_name,'John'); assert.equal(body.customer_details.billing_address.last_name,'Doe'); assert.equal(body.customer_details.billing_address.email,'john.doe@gmail.com'); assert.equal(body.customer_details.billing_address.phone,'+62856'); + assert.equal(body.customer_details.billing_address.address,'address'); + assert.equal(body.customer_details.billing_address.city,'city'); + assert.equal(body.customer_details.billing_address.postal_code,'postal_code'); + assert.equal(body.customer_details.billing_address.country_code,'country_code'); + }); + + it('billing_address is optional', function(){ + var mdt = new MidTrans(config); + var body = mdt.type('snap').action('transactions') + .transaction_details('INV001',1000) + .item_details('Midtrans Bear',1000,1) + .customer_details('John','Doe','john.doe@gmail.com','+62856') + .billing_address() + .getBody(); + assert.deepEqual(body.customer_details.billing_address,{}); }); it('shipping_address', function(){ @@ -106,12 +151,27 @@ describe('MidTrans body test', function(){ .transaction_details('INV001',1000) .item_details('Midtrans Bear',1000,1) .customer_details('John','Doe','john.doe@gmail.com','+62856') - .shipping_address('John','Doe','john.doe@gmail.com','+62856') + .shipping_address('John','Doe','john.doe@gmail.com','+62856','address','city','postal_code','country_code') .getBody(); assert.equal(body.customer_details.shipping_address.first_name,'John'); assert.equal(body.customer_details.shipping_address.last_name,'Doe'); assert.equal(body.customer_details.shipping_address.email,'john.doe@gmail.com'); assert.equal(body.customer_details.shipping_address.phone,'+62856'); + assert.equal(body.customer_details.shipping_address.address,'address'); + assert.equal(body.customer_details.shipping_address.city,'city'); + assert.equal(body.customer_details.shipping_address.postal_code,'postal_code'); + assert.equal(body.customer_details.shipping_address.country_code,'country_code'); + }); + + it('shipping_address is optional', function(){ + var mdt = new MidTrans(config); + var body = mdt.type('snap').action('transactions') + .transaction_details('INV001',1000) + .item_details('Midtrans Bear',1000,1) + .customer_details('John','Doe','john.doe@gmail.com','+62856') + .shipping_address() + .getBody(); + assert.deepEqual(body.customer_details.shipping_address,{}); }); it('billing_address must have customer_details data', function(){ @@ -156,4 +216,10 @@ describe('MidTrans body test', function(){ assert.equal(isEmptyObject(body),true); }); + it('remove key in body', function(){ + var mdt = new MidTrans(config); + var body = mdt.type('snap').action('transactions').transaction_details('INV001',1000).remove('transaction_details').getBody(); + assert.deepEqual(body,{}); + }); + }); \ No newline at end of file diff --git a/test/config.js b/test/config.js new file mode 100644 index 0000000..acb5ba8 --- /dev/null +++ b/test/config.js @@ -0,0 +1,69 @@ +var assert = require('assert'); +var MidTrans = require('../src/midtrans.js'); + +var config = { + client_key: "xxx", //don't change this + server_key: "xxx", //don't change this + mode: "" +}; + +describe('MidTrans configuration test', function(){ + + it('configuration must be object type',function(){ + var result = false; + for(var key in config) { + if(config.hasOwnProperty(key)) { + result = true; + } + } + assert.equal(result, true); + }); + + it('configuration must be hasOwnProperty',function(){ + const config = Object.create({name: 'inherited'}) + var mdt = new MidTrans(config); + assert.equal(mdt.server_key,undefined); + assert.equal(mdt.client_key,undefined); + assert.equal(mdt.mode,'sandbox'); + }); + + it('configuration with array object will throw an error',function(){ + assert.throws(function(){new MidTrans([])},Error,'Error thrown'); + }); + + it('configuration with string object will throw an error',function(){ + assert.throws(function(){new MidTrans("")},Error,'Error thrown'); + }); + + it('configuration undefined will throw an error',function(){ + assert.throws(function(){new MidTrans(undefined)},Error,'Error thrown'); + }); + + it('configuration null will throw an error',function(){ + assert.throws(function(){new MidTrans(null)},Error,'Error thrown'); + }); + + it('complete configuration',function(){ + var mdt = new MidTrans(config); + assert.equal(mdt.client_key,'xxx'); + assert.equal(mdt.server_key,'xxx'); + assert.equal(mdt.mode,'sandbox'); + }); + + it('configuration without mode then mode value will be as \'sandbox\'',function(){ + delete config.mode; + var mdt = new MidTrans(config); + assert.equal(mdt.client_key,'xxx'); + assert.equal(mdt.server_key,'xxx'); + assert.equal(mdt.mode,'sandbox'); + }); + + it('configuration for production',function(){ + config.mode = 'production'; + var mdt = new MidTrans(config); + assert.equal(mdt.client_key,'xxx'); + assert.equal(mdt.server_key,'xxx'); + assert.equal(mdt.mode,'production'); + }); + +}); \ No newline at end of file diff --git a/test/endpoint.js b/test/endpoint.js index 219b53e..07320ae 100644 --- a/test/endpoint.js +++ b/test/endpoint.js @@ -41,6 +41,32 @@ describe('MidTrans endpoint url test', function(){ assert.equal(mdt.url,'https://api.sandbox.midtrans.com/v2/123/status/b2b?page=0&per_page=10'); }); + it('endpoint url status/b2b without pagination', function(){ + var mdt = new MidTrans(config); + mdt.action('status/b2b','123'); + assert.equal(mdt.url,'https://api.sandbox.midtrans.com/v2/123/status/b2b'); + }); + + it('endpoint url token',function(){ + var mdt = new MidTrans(config); + var payload = { + gross_amount:10000, + card_number:'4811 1111 1111 1114', + card_exp_month:12, + card_exp_year:2019, + card_cvv:123 + }; + + mdt.type('api').action('token',payload); + assert.equal(mdt.url,'https://api.sandbox.midtrans.com/v2/token?gross_amount=10000&card_number=4811%201111%201111%201114&card_exp_month=12&card_exp_year=2019&card_cvv=123&client_key=xxx'); + }); + + it('endpoint url token without payload', function(){ + var mdt = new MidTrans(config); + mdt.action('token'); + assert.equal(mdt.url,'https://api.sandbox.midtrans.com/v2/token'); + }); + it('endpoint url card/register', function(){ var mdt = new MidTrans(config); var payload = { @@ -53,6 +79,12 @@ describe('MidTrans endpoint url test', function(){ assert.equal(mdt.url,'https://api.sandbox.midtrans.com/v2/card/register?card_number=4811222233331114&card_exp_month=12&card_exp_year=2019&card_cvv=123&client_key=xxx'); }); + it('endpoint url card/register without payload', function(){ + var mdt = new MidTrans(config); + mdt.action('card/register'); + assert.equal(mdt.url,'https://api.sandbox.midtrans.com/v2/card/register'); + }); + it('endpoint url capture', function(){ var mdt = new MidTrans(config); mdt.action('capture'); @@ -143,4 +175,10 @@ describe('MidTrans endpoint url test', function(){ assert.equal(mdt.url,'https://api.sandbox.midtrans.com/v1/subscriptions/SUB1'); }); + it('endpoint without or wrong action method will return undefined', function(){ + var mdt = new MidTrans(config); + mdt.action([],'SUB1'); + assert.deepEqual(mdt.url,undefined); + }); + }); diff --git a/test/method.js b/test/method.js index cd6bb1a..989e888 100644 --- a/test/method.js +++ b/test/method.js @@ -13,5 +13,35 @@ describe('MidTrans method test', function(){ var mdt = new MidTrans(config); assert.equal(Array.isArray(mdt.showAllMethods(mdt)),true); }); + + it('method type() without following chain action() method will return undefined', function(){ + var mdt = new MidTrans(config); + mdt.type([]); + assert.deepEqual(mdt.url,undefined); + }); + + it('method action() will be auto fix type() method', function(){ + var mdt = new MidTrans(config); + mdt.type([]).action('status','INV001'); + assert.equal(mdt.url,'https://api.sandbox.midtrans.com/v2/INV001/status'); + }); + + it('method add() with wrong parameter object type or undefined parameter will not adding any key in body request', function(){ + var mdt = new MidTrans(config); + var body = mdt.action('transactions').add([],undefined).getBody(); + assert.deepEqual(body,{}); + }); + + it('method add() with second wrong parameter object type or undefined parameter will not adding any key in body request', function(){ + var mdt = new MidTrans(config); + var body = mdt.action('transactions').add('transaction_details',undefined).getBody(); + assert.deepEqual(body,{}); + }); + + it('method remove() with wrong parameter object type or undefined parameter will not remove any key in body request', function(){ + var mdt = new MidTrans(config); + var body = mdt.action('transactions').transaction_details('INV001',1000).remove().getBody(); + assert.deepEqual(body,{ transaction_details: { order_id: 'INV001', gross_amount: 1000 } }); + }); }); \ No newline at end of file diff --git a/test/request.js b/test/request.js index a277083..a0304de 100644 --- a/test/request.js +++ b/test/request.js @@ -1,3 +1,4 @@ +var assert = require('assert'); var MidTrans = require('../src/midtrans.js'); var config = { @@ -43,4 +44,50 @@ describe('MidTrans request test', function(){ }); }); + it('request with header: get', function(done){ + this.timeout(10000); + var mdt = new MidTrans(config); + var body = mdt.action('status'); + body.send(function(response) { + if(response.req.connection._httpMessage.method == 'GET'){ + done(); + } else { + done(new Error(JSON.stringify({url:mdt.url,method:response.req.connection._httpMessage.method}))); + } + }); + }); + + it('request with header: post', function(done){ + this.timeout(10000); + var mdt = new MidTrans(config); + var body = mdt.do('enable').type('api').action('subscriptions','sub1'); + body.send(function(response) { + if(response.req.connection._httpMessage.method == 'POST'){ + done(); + } else { + done(new Error(JSON.stringify({url:mdt.url,method:response.req.connection._httpMessage.method}))); + } + }); + }); + + it('request with header: patch', function(done){ + this.timeout(10000); + var mdt = new MidTrans(config); + var body = mdt.do('update').type('api').action('subscriptions','sub1'); + body.send(function(response) { + if(response.req.connection._httpMessage.method == 'PATCH'){ + done(); + } else { + done(new Error(JSON.stringify({url:mdt.url,method:response.req.connection._httpMessage.method}))); + } + }); + }); + + it('request without action method will not make http request', function(){ + this.timeout(10000); + var mdt = new MidTrans(config); + mdt.server_key = 'xxx'; + assert.throws(function(){mdt.type('api').send(function(response) {})}, Error, "Error thrown"); + }); + }); \ No newline at end of file