diff --git a/package.json b/package.json
index 98dd7ce..a29e7c4 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
   "author": "Adhidarma Hadiwinoto <me@adhisimon.org>",
   "license": "ISC",
   "dependencies": {
+    "redis": "^2.6.2",
     "request": "^2.72.0",
     "sate24": "git+http://gitlab.kodesumber.com/reload97/node-sate24.git",
     "sate24-expresso": "git+http://gitlab.kodesumber.com/reload97/sate24-expresso.git",
diff --git a/partner-bayarkilat.js b/partner-bayarkilat.js
index faf1ff9..7793598 100644
--- a/partner-bayarkilat.js
+++ b/partner-bayarkilat.js
@@ -2,17 +2,28 @@ var request = require('request');
 var url = require('url');
 var winston = require('winston');
 var xml2jsParser = require('xml2js').parseString;
+var redis = require('redis');
+
 
 var config;
 var aaa;
 var callbackReport;
 var logger;
+var redisClient;
 
 var maxCheckRetry = 20;
 var delayBeforeCheckRetry = 30 * 1000;
 
 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
 
+function createRedisClient(host, port) {
+    try {
+        redisClient = redis.createClient(port, host);
+    } catch(err) {
+        logger.warn("Error creating redis client to " + host + ':' + port);
+    }
+}
+
 function start(_config, _callbackReport, options) {
     config = _config;
     callbackReport = _callbackReport;
@@ -30,6 +41,8 @@ function start(_config, _callbackReport, options) {
             ]
         });
     }
+
+    createRedisClient(config.globals.redis_host, config.globals.redis_port);
 }
 
 function createRequestOptions(methodName, task) {
@@ -84,7 +97,21 @@ function topupCheck(task, retry) {
 }
 
 function topupRequest(task) {
-    requestToPartner('PURCHASE', task);
+    if (!aaa.isTodayTrx(task)) {
+        logger.warn('Maaf, transaksi beda hari tidak dapat dilakukan');
+        callbackReport(task.requestId, '68', 'Maaf, transaksi beda hari tidak dapat dilakukan');
+        return;
+    }
+
+    getTaskForDupeCheck(task, function(err, dupeTask) {
+        if (dupeTask) {
+            logger.info('Duplicate task detected, requesting topupCheck', {task});
+            topupCheck(task);
+        } else {
+            requestToPartner('PURCHASE', task);
+        }
+    });
+
 }
 
 function requestToPartner(methodName, task, retry) {
@@ -299,6 +326,43 @@ function paddingDestination(destination, width) {
     return (padder + destination).slice(-1 * width);
 }
 
+function getTaskKeyForDupeCheck(task) {
+    return config.globals.gateway_name + '.dupecheck.reqId:' + task.requestId;
+}
+
+function saveTaskForDupeCheck(task, cb) {
+    var key = getTaskKeyForDupeCheck(task);
+
+    redisClient.set(key, JSON.stringify(task), function() {
+        redisClient.expire(key, 3600*24*7);
+        if (cb) {
+            cb(null, task);
+        }
+    });
+}
+
+function getTaskForDupeCheck(task, cb) {
+    var key = getTaskKeyForDupeCheck(task);
+
+    redisClient.get(key, function(err, result) {
+        if (err) {
+            cb(err, null);
+            return;
+        }
+
+        var taskOnRedis = null;
+        try {
+            taskOnRedis = JSON.parse(result);
+        }
+        catch(err1) {
+            cb(err1, null);
+            return;
+        }
+
+        cb(null, taskOnRedis);
+    });
+}
+
 exports.start = start;
 exports.topupRequest = topupRequest;
 exports.prepareRemoteProductCode = prepareRemoteProductCode;