Commit a433d0ba572514381cf2b69b50901b8c52c3f812
1 parent
52fa01ba17
Exists in
master
typo fix
Showing 2 changed files with 11 additions and 1 deletions Inline Diff
partner-misc.js
1 | "use strict"; | 1 | "use strict"; |
2 | 2 | ||
3 | const crypto = require('crypto'); | 3 | const crypto = require('crypto'); |
4 | const moment = require('moment'); | 4 | const moment = require('moment'); |
5 | 5 | ||
6 | const config = require('komodo-sdk/config'); | 6 | const config = require('komodo-sdk/config'); |
7 | const logger = require('komodo-sdk/logger'); | 7 | const logger = require('komodo-sdk/logger'); |
8 | const pull = require('komodo-sdk/gateway/pull'); | 8 | const pull = require('komodo-sdk/gateway/pull'); |
9 | 9 | ||
10 | const partner = require('./partner'); | 10 | const partner = require('./partner'); |
11 | 11 | ||
12 | function calculateSign(dt, trx_ref_id, cust_num, username, password) { | 12 | function calculateSign(dt, trx_ref_id, cust_num, username, password) { |
13 | const cryptoHashPassword = crypto.createHash('sha1'); | 13 | const cryptoHashPassword = crypto.createHash('sha1'); |
14 | const cryptoHashUsernamePassword = crypto.createHash('sha1'); | 14 | const cryptoHashUsernamePassword = crypto.createHash('sha1'); |
15 | const cryptoHashOutest = crypto.createHash('sha1'); | 15 | const cryptoHashOutest = crypto.createHash('sha1'); |
16 | 16 | ||
17 | cryptoHashPassword.update(password); | 17 | cryptoHashPassword.update(password); |
18 | const hashPassword = cryptoHashPassword.digest('hex'); | 18 | const hashPassword = cryptoHashPassword.digest('hex'); |
19 | 19 | ||
20 | cryptoHashUsernamePassword.update(username + hashPassword); | 20 | cryptoHashUsernamePassword.update(username + hashPassword); |
21 | const hashUsernamePassword = cryptoHashUsernamePassword.digest('hex'); | 21 | const hashUsernamePassword = cryptoHashUsernamePassword.digest('hex'); |
22 | 22 | ||
23 | cryptoHashOutest.update(dt + trx_ref_id + cust_num + hashUsernamePassword); | 23 | cryptoHashOutest.update(dt + trx_ref_id + cust_num + hashUsernamePassword); |
24 | return cryptoHashOutest.digest('hex'); | 24 | return cryptoHashOutest.digest('hex'); |
25 | } | 25 | } |
26 | 26 | ||
27 | function createRequestOptions(task, config) { | 27 | function createRequestOptions(task, config) { |
28 | const dt = moment().format('YYYY-MM-DD HH:mm:ss'); | 28 | const dt = moment().format('YYYY-MM-DD HH:mm:ss'); |
29 | const sign = calculateSign(dt, task.trx_id, task.destination, config.partner.username, config.partner.password); | 29 | const sign = calculateSign(dt, task.trx_id, task.destination, config.partner.username, config.partner.password); |
30 | 30 | ||
31 | return = { | 31 | return = { |
32 | url: config.partner.url, | 32 | url: config.partner.url, |
33 | form: { | 33 | form: { |
34 | username: config.partner.username, | 34 | username: config.partner.username, |
35 | datetime: dt, | 35 | datetime: dt, |
36 | code: task.remote_product, | 36 | code: task.remote_product, |
37 | trx_ref_id: task.trx_id, | 37 | trx_ref_id: task.trx_id, |
38 | cust_num: task.destination, | 38 | cust_num: task.destination, |
39 | sign: sign | 39 | sign: sign |
40 | } | 40 | } |
41 | } | 41 | } |
42 | } | 42 | } |
43 | 43 | ||
44 | function decodeResponseBody(responseBody) { | 44 | function decodeResponseBody(responseBody) { |
45 | let response; | 45 | let response; |
46 | 46 | ||
47 | try { | 47 | try { |
48 | response = JSON.parse(responseBody) | 48 | response = JSON.parse(responseBody) |
49 | } | 49 | } |
50 | catch(e) { | 50 | catch(e) { |
51 | logger.warn('Error parsing response body'); | 51 | logger.warn('Error parsing response body'); |
52 | } | 52 | } |
53 | 53 | ||
54 | return response; | 54 | return response; |
55 | } | 55 | } |
56 | 56 | ||
57 | function cleanBalance(balance) { | 57 | function cleanBalance(balance) { |
58 | try { | 58 | try { |
59 | balance = balance.replace(/\D/g, ''); | 59 | balance = balance.replace(/\D/g, ''); |
60 | } | 60 | } |
61 | catch(e) { }; | 61 | catch(e) { }; |
62 | 62 | ||
63 | return balance; | 63 | return balance; |
64 | 64 | ||
65 | } | 65 | } |
66 | 66 | ||
67 | function processPartnerResponseBody(body, task) { | 67 | function processPartnerResponseBody(body, task) { |
68 | let response = decodeResponseBody(responseBody); | 68 | let response = decodeResponseBody(responseBody); |
69 | let messages = []; | 69 | let messages = []; |
70 | 70 | ||
71 | if (!response) { | 71 | if (!response) { |
72 | return; | 72 | return; |
73 | } | 73 | } |
74 | 74 | ||
75 | logger.verbose('RESPONSE', {response: response}); | 75 | logger.verbose('RESPONSE', {response: response}); |
76 | 76 | ||
77 | const responseStatus = response.status; | 77 | const responseStatus = response.status; |
78 | const responseInfo = response.info; | 78 | const responseInfo = response.info; |
79 | 79 | ||
80 | let taskTrxId; | 80 | let taskTrxId; |
81 | if (task && task.trx_id) { | 81 | if (task && task.trx_id) { |
82 | taskTrxId = task.trx_id; | 82 | taskTrxId = task.trx_id; |
83 | } | 83 | } |
84 | 84 | ||
85 | let responseRequestId; | 85 | let responseRequestId; |
86 | if (response.data && response.data.request_id) { | 86 | if (response.data && response.data.request_id) { |
87 | responseRequestId = response.data.request_id; | 87 | responseRequestId = response.data.request_id; |
88 | } | 88 | } |
89 | 89 | ||
90 | 90 | ||
91 | let responseTrxStatus; | 91 | let responseTrxStatus; |
92 | if (response.data && response.data.trx_status) { | 92 | if (response.data && response.data.trx_status) { |
93 | responseTrxStatus = response.data.trx_status; | 93 | responseTrxStatus = response.data.trx_status; |
94 | } | 94 | } |
95 | 95 | ||
96 | let responseTimestamp; | 96 | let responseTimestamp; |
97 | if (response.data && response.data.timestamp) { | 97 | if (response.data && response.data.timestamp) { |
98 | responseTimestamp = response.data.timestamp; | 98 | responseTimestamp = response.data.timestamp; |
99 | messages.push(responseTimestamp); | 99 | messages.push(responseTimestamp); |
100 | } | 100 | } |
101 | 101 | ||
102 | let responseDiag; | 102 | let responseDiag; |
103 | if (response.data && response.data.diag) { | 103 | if (response.data && response.data.diag) { |
104 | responseDiag = response.data.diag; | 104 | responseDiag = response.data.diag; |
105 | messages.push(responseDiag); | 105 | messages.push(responseDiag); |
106 | } | 106 | } |
107 | 107 | ||
108 | let responseMessage; | 108 | let responseMessage; |
109 | if (response.data && response.data.message) { | 109 | if (response.data && response.data.message) { |
110 | responseMessage = response.data.message; | 110 | responseMessage = response.data.message; |
111 | messages.push(responseMessage); | 111 | messages.push(responseMessage); |
112 | } | 112 | } |
113 | 113 | ||
114 | let responseAmount; | ||
115 | if (response.data && response.data.info && response.data.info.amount) { | ||
116 | responseAmount = response.data.info.amount; | ||
117 | |||
118 | if (responseAmount) { | ||
119 | messages.push('Amount: ' + responseAmount); | ||
120 | } | ||
121 | } | ||
122 | |||
114 | let responseBalance; | 123 | let responseBalance; |
115 | if (response.data && response.data.balance) { | 124 | if (response.data && response.data.balance) { |
116 | responseBalance = response.data.balance; | 125 | responseBalance = response.data.balance; |
117 | messages.push('Balance: ' + responseBalance); | 126 | messages.push('Balance: ' + responseBalance); |
118 | if (responseBalance) { | 127 | if (responseBalance) { |
119 | responseBalance = cleanBalance(responseBalance); | 128 | responseBalance = cleanBalance(responseBalance); |
120 | } | 129 | } |
121 | } | 130 | } |
122 | 131 | ||
123 | if (messages.length <= 0) { messages.push('Transaksi anda sedang diproses'); } | 132 | if (messages.length <= 0) { messages.push('Transaksi anda sedang diproses'); } |
124 | 133 | ||
125 | let coreReportData = { | 134 | let coreReportData = { |
126 | trx_id: taskTrxId || responseRequestId, | 135 | trx_id: taskTrxId || responseRequestId, |
127 | rc: '68', | 136 | rc: '68', |
128 | message: messages.join('. ') + '.', | 137 | message: messages.join('. ') + '.', |
129 | sn: '', | 138 | sn: '', |
130 | handler: config.handler_name, | 139 | handler: config.handler_name, |
140 | amount: responseAmount, | ||
131 | balance: responseBalance, | 141 | balance: responseBalance, |
132 | core_task: task, | 142 | core_task: task, |
133 | raw: body | 143 | raw: body |
134 | } | 144 | } |
135 | 145 | ||
136 | if (responseStatus == 'Error') { | 146 | if (responseStatus == 'Error') { |
137 | if (responseInfo == 'insufficient balance') { | 147 | if (responseInfo == 'insufficient balance') { |
138 | coreReportData.rc = '91'; | 148 | coreReportData.rc = '91'; |
139 | } | 149 | } |
140 | 150 | ||
141 | coreReportData.message = [responseStatus, responseInfo].join(': '); | 151 | coreReportData.message = [responseStatus, responseInfo].join(': '); |
142 | 152 | ||
143 | partner.reportToCore(coreReportData); | 153 | partner.reportToCore(coreReportData); |
144 | return; | 154 | return; |
145 | } | 155 | } |
146 | 156 | ||
147 | 157 | ||
148 | if (responseTrxStatus == 'P') { | 158 | if (responseTrxStatus == 'P') { |
149 | logger.verbose('Got pending trx response', {response: response.data}); | 159 | logger.verbose('Got pending trx response', {response: response.data}); |
150 | coreReportData.rc = '68'; | 160 | coreReportData.rc = '68'; |
151 | } | 161 | } |
152 | else if (responseTrxStatus == 'S') { | 162 | else if (responseTrxStatus == 'S') { |
153 | logger.verbose('Got succcess trx response', {response: response.data}); | 163 | logger.verbose('Got succcess trx response', {response: response.data}); |
154 | 164 | ||
155 | coreReportData.rc = '00' | 165 | coreReportData.rc = '00' |
156 | 166 | ||
157 | coreReportData.sn = composeSn(response); | 167 | coreReportData.sn = composeSn(response); |
158 | coreReportData.message += ' SN=' + coreReportData.sn + '.'; | 168 | coreReportData.message += ' SN=' + coreReportData.sn + '.'; |
159 | } | 169 | } |
160 | else if (trxStatus == 'R') { | 170 | else if (trxStatus == 'R') { |
161 | logger.verbose('Got rejected trx response', {response: response.data}); | 171 | logger.verbose('Got rejected trx response', {response: response.data}); |
162 | 172 | ||
163 | const partnerRC = getPartnerRCFromDiagMessage(responseDiag); | 173 | const partnerRC = getPartnerRCFromDiagMessage(responseDiag); |
164 | if (partnerRC == '15') { | 174 | if (partnerRC == '15') { |
165 | coreReportData.rc = '14'; | 175 | coreReportData.rc = '14'; |
166 | } | 176 | } |
167 | else { | 177 | else { |
168 | coreReportData.rc = '40'; | 178 | coreReportData.rc = '40'; |
169 | } | 179 | } |
170 | } | 180 | } |
171 | 181 | ||
172 | partner.reportToCore(coreReportData); | 182 | partner.reportToCore(coreReportData); |
173 | } | 183 | } |
174 | 184 | ||
175 | function composeSn(response) { | 185 | function composeSn(response) { |
176 | if (!response && !response.data) { return; } | 186 | if (!response && !response.data) { return; } |
177 | 187 | ||
178 | if (!response.data.info) { | 188 | if (!response.data.info) { |
179 | return response.data.serial; | 189 | return response.data.serial; |
180 | } | 190 | } |
181 | 191 | ||
182 | let token = response.data.serial; | 192 | let token = response.data.serial; |
183 | let cust_name = response.data.info.cust_name; | 193 | let cust_name = response.data.info.cust_name; |
184 | let tariff = response.data.info.kelas; | 194 | let tariff = response.data.info.kelas; |
185 | let total_kwh = response.data.info.size; | 195 | let total_kwh = response.data.info.size; |
186 | 196 | ||
187 | if (tariff.indexOf('VA') < 0) { | 197 | if (tariff.indexOf('VA') < 0) { |
188 | tariff += 'VA'; | 198 | tariff += 'VA'; |
189 | } | 199 | } |
190 | 200 | ||
191 | if (cust_name) { | 201 | if (cust_name) { |
192 | cust_name = cust_name.replace(/\W+/g, ' ').trim().replace(/\W+/g, '-').toUpperCase(); | 202 | cust_name = cust_name.replace(/\W+/g, ' ').trim().replace(/\W+/g, '-').toUpperCase(); |
193 | } | 203 | } |
194 | 204 | ||
195 | return [ token, cust_name, tariff, total_kwh ].join('/'); | 205 | return [ token, cust_name, tariff, total_kwh ].join('/'); |
196 | } | 206 | } |
197 | 207 | ||
198 | function getPartnerRCFromDiagMessage(diag) { | 208 | function getPartnerRCFromDiagMessage(diag) { |
199 | let matches = diag.match(/^\s*\[(.*)\]/); | 209 | let matches = diag.match(/^\s*\[(.*)\]/); |
200 | if (!matches || matches.length < 2) { | 210 | if (!matches || matches.length < 2) { |
201 | return; | 211 | return; |
202 | } | 212 | } |
203 | 213 | ||
204 | return matches[1]; | 214 | return matches[1]; |
205 | } | 215 | } |
206 | 216 | ||
207 | 217 | ||
208 | exports.calculateSign = calculateSign; | 218 | exports.calculateSign = calculateSign; |
209 | exports.createRequestOptions = createRequestOptions; | 219 | exports.createRequestOptions = createRequestOptions; |
210 | 220 |
partner.js
1 | "use strict"; | 1 | "use strict"; |
2 | 2 | ||
3 | const config = require('komodo-sdk/config'); | 3 | const config = require('komodo-sdk/config'); |
4 | const logger = require('komodo-sdk/logger'); | 4 | const logger = require('komodo-sdk/logger'); |
5 | const matrix = require('komodo-sdk/matrix'); | 5 | const matrix = require('komodo-sdk/matrix'); |
6 | const pull = require('komodo-sdk/gateway/pull'); | 6 | const pull = require('komodo-sdk/gateway/pull'); |
7 | 7 | ||
8 | const misc = require('./partner-misc'); | 8 | const misc = require('./partner-misc'); |
9 | 9 | ||
10 | /** | 10 | /** |
11 | * Pembelian ke partner | 11 | * Pembelian ke partner |
12 | * | 12 | * |
13 | * Merupakan fungsi mandatory yang harus dimiliki oleh setiap gateway. | 13 | * Merupakan fungsi mandatory yang harus dimiliki oleh setiap gateway. |
14 | */ | 14 | */ |
15 | function buy(task) { | 15 | function buy(task) { |
16 | _requestToPartner(task, false); | 16 | _requestToPartner(task, false); |
17 | } | 17 | } |
18 | 18 | ||
19 | /** | 19 | /** |
20 | * Pemeriksaan status transaksi ke partner | 20 | * Pemeriksaan status transaksi ke partner |
21 | * Merupakan fungsi mandatory yang harus dimiliki oleh setiap gateway. | 21 | * Merupakan fungsi mandatory yang harus dimiliki oleh setiap gateway. |
22 | */ | 22 | */ |
23 | function statusCheck(task) { | 23 | function statusCheck(task) { |
24 | _requestToPartner(task, true); | 24 | _requestToPartner(task, true); |
25 | } | 25 | } |
26 | 26 | ||
27 | /** | 27 | /** |
28 | * Mengirim request ke partner. | 28 | * Mengirim request ke partner. |
29 | * | 29 | * |
30 | * Untuk digunakan oleh buy dan checkStatus. | 30 | * Untuk digunakan oleh buy dan checkStatus. |
31 | */ | 31 | */ |
32 | function _requestToPartner(task, pendingOnError) { | 32 | function _requestToPartner(task, pendingOnError) { |
33 | 33 | ||
34 | const requestOptions = misc.createRequestOptions(task, config); | 34 | const requestOptions = misc.createRequestOptions(task, config); |
35 | 35 | ||
36 | logger.verbose('Requeting to partner', {requestOptions: requestOptions}); | 36 | logger.verbose('Requeting to partner', {requestOptions: requestOptions}); |
37 | request.post(requestOptions, function(err, res, body) { | 37 | request.post(requestOptions, function(err, res, body) { |
38 | 38 | ||
39 | if (err) { | 39 | if (err) { |
40 | 40 | ||
41 | let rc = '68'; | 41 | let rc = '68'; |
42 | if (!pendingOnError) { rc = '91'; } | 42 | if (!pendingOnError) { rc = '91'; } |
43 | 43 | ||
44 | logger.warn('Error requesting to partner', {task: task, err: err}) | 44 | logger.warn('Error requesting to partner', {task: task, err: err}) |
45 | 45 | ||
46 | _reportToCore({ | 46 | _reportToCore({ |
47 | trx_id: task.trx_id, | 47 | trx_id: task.trx_id, |
48 | rc: rc, | 48 | rc: rc, |
49 | message: 'Error requesting to partner: ' + err, | 49 | message: 'Error requesting to partner: ' + err, |
50 | handler: config.handler_name | 50 | handler: config.handler_name |
51 | }) | 51 | }) |
52 | 52 | ||
53 | return; | 53 | return; |
54 | } | 54 | } |
55 | 55 | ||
56 | if (res.statusCode != 200) { | 56 | if (res.statusCode != 200) { |
57 | let rc = '68'; | 57 | let rc = '68'; |
58 | logger.warn('Partner returning non 200 HTTP STATUS CODE', {task: task, http_status_code: res.statusCode}) | 58 | logger.warn('Partner returning non 200 HTTP STATUS CODE', {task: task, http_status_code: res.statusCode}) |
59 | 59 | ||
60 | _reportToCore({ | 60 | _reportToCore({ |
61 | trx_id: task.trx_id, | 61 | trx_id: task.trx_id, |
62 | rc: rc, | 62 | rc: rc, |
63 | message: 'Partner returning HTTP STATUS CODE ' + res.statusCode + ' instead of 200'; | 63 | message: 'Partner returning HTTP STATUS CODE ' + res.statusCode + ' instead of 200', |
64 | handler: config.handler_name | 64 | handler: config.handler_name |
65 | }) | 65 | }) |
66 | 66 | ||
67 | return; | 67 | return; |
68 | } | 68 | } |
69 | 69 | ||
70 | misc.processPartnerResponseBody(body, task); | 70 | misc.processPartnerResponseBody(body, task); |
71 | }) | 71 | }) |
72 | } | 72 | } |
73 | 73 | ||
74 | /** | 74 | /** |
75 | * Mengirim report hasil transaksi ke CORE | 75 | * Mengirim report hasil transaksi ke CORE |
76 | */ | 76 | */ |
77 | function reportToCore(data) { | 77 | function reportToCore(data) { |
78 | pull.report(data); | 78 | pull.report(data); |
79 | } | 79 | } |
80 | 80 | ||
81 | exports.buy = buy; | 81 | exports.buy = buy; |
82 | exports.statusCheck = statusCheck; | 82 | exports.statusCheck = statusCheck; |
83 | exports.reportToCore = reportToCore; | 83 | exports.reportToCore = reportToCore; |
84 | 84 |