From b52a9283bb3fd5aeb7c3f05b96ccba0a28b051eb Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Fri, 25 Sep 2020 21:52:00 +0530 Subject: [PATCH] feat: rsa encryption with public key --- .../e_invoice_settings/e_invoice_settings.js | 16 +++++++-- .../e_invoice_settings.json | 12 +++++-- .../e_invoice_settings/e_invoice_settings.py | 35 +++++++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/erpnext/erpnext_integrations/doctype/e_invoice_settings/e_invoice_settings.js b/erpnext/erpnext_integrations/doctype/e_invoice_settings/e_invoice_settings.js index 9c67e619504..1f9054461f4 100644 --- a/erpnext/erpnext_integrations/doctype/e_invoice_settings/e_invoice_settings.js +++ b/erpnext/erpnext_integrations/doctype/e_invoice_settings/e_invoice_settings.js @@ -2,7 +2,19 @@ // For license information, please see license.txt frappe.ui.form.on('E Invoice Settings', { - // refresh: function(frm) { + refresh: function(frm) { + frm.trigger("show_fetch_token_btn"); + }, - // } + show_fetch_token_btn(frm) { + frm.add_custom_button(__("Fetch Token"), + () => { + frm.call({ + doc: frm.doc, + method: 'make_authentication_request', + freeze: true + }); + } + ); + } }); diff --git a/erpnext/erpnext_integrations/doctype/e_invoice_settings/e_invoice_settings.json b/erpnext/erpnext_integrations/doctype/e_invoice_settings/e_invoice_settings.json index b91ef817520..5278c6eebd2 100644 --- a/erpnext/erpnext_integrations/doctype/e_invoice_settings/e_invoice_settings.json +++ b/erpnext/erpnext_integrations/doctype/e_invoice_settings/e_invoice_settings.json @@ -12,7 +12,8 @@ "column_break_3", "gstin", "username", - "password" + "password", + "auto_refresh_token" ], "fields": [ { @@ -61,12 +62,19 @@ "fieldtype": "Long Text", "hidden": 1, "read_only": 1 + }, + { + "default": "0", + "description": "Token will be automatically refreshed 10 mins before expiry", + "fieldname": "auto_refresh_token", + "fieldtype": "Check", + "label": "Auto Refresh Token" } ], "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2020-09-25 21:24:00.404460", + "modified": "2020-09-25 21:32:36.553678", "modified_by": "Administrator", "module": "ERPNext Integrations", "name": "E Invoice Settings", diff --git a/erpnext/erpnext_integrations/doctype/e_invoice_settings/e_invoice_settings.py b/erpnext/erpnext_integrations/doctype/e_invoice_settings/e_invoice_settings.py index 62e945af87a..129dcd35b6e 100644 --- a/erpnext/erpnext_integrations/doctype/e_invoice_settings/e_invoice_settings.py +++ b/erpnext/erpnext_integrations/doctype/e_invoice_settings/e_invoice_settings.py @@ -3,9 +3,15 @@ # For license information, please see license.txt from __future__ import unicode_literals +import os +import json +import base64 import frappe from frappe.utils import cstr +from Crypto.PublicKey import RSA +from Crypto.Cipher import PKCS1_v1_5 from frappe.model.document import Document +from frappe.integrations.utils import make_post_request class EInvoiceSettings(Document): def validate(self): @@ -19,3 +25,32 @@ class EInvoiceSettings(Document): key_file = frappe.get_doc('File', dict(attached_to_name=self.doctype, attached_to_field='public_key_file')) with open(key_file.get_full_path(), 'rb') as f: return cstr(f.read()) + + def rsa_encrypt(self, msg, key): + if not (isinstance(msg, bytes) or isinstance(msg, bytearray)): + msg = str.encode(msg) + + rsa_pub_key = RSA.import_key(key) + cipher = PKCS1_v1_5.new(rsa_pub_key) + enc_msg = cipher.encrypt(msg) + b64_enc_msg = base64.b64encode(enc_msg) + return b64_enc_msg.decode() + + def make_authentication_request(self): + endpoint = 'https://einv-apisandbox.nic.in/eivital/v1.03/auth' + headers = { 'content-type': 'application/json' } + headers.update(dict(client_id=self.client_id, client_secret=self.client_secret)) + payload = dict(UserName=self.username, ForceRefreshAccessToken=bool(self.auto_refresh_token)) + + appkey = bytearray(os.urandom(32)) + enc_appkey = self.rsa_encrypt(appkey, self.public_key) + + password = self.get_password(fieldname='password') + enc_password = self.rsa_encrypt(password, self.public_key) + + payload.update(dict(Password=enc_password, AppKey=enc_appkey)) + + res = make_post_request(endpoint, headers=headers, data=json.dumps({ 'data': payload })) + + print(res) +