You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

241 lines
8.7 KiB

# -*- coding: utf-8 -*-
###################################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2019-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# This program is free software: you can modify
# it under the terms of the GNU Affero General Public License (AGPL) as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
###################################################################################
import base64
import string
import random
import hashlib
from Crypto.Cipher import AES
from odoo.exceptions import ValidationError
from odoo import api, fields, models
from datetime import datetime
from werkzeug import urls
import hashlib
import json
import hmac
import base64
import logging
_logger = logging.getLogger(__name__)
class PaymentAcquirerAtom(models.Model):
_inherit = 'payment.acquirer'
provider = fields.Selection(selection_add=[('paytm', 'Paytm')])
paytm_merchant_id = fields.Char('Merchant ID', required_if_provider='Paytm',
groups='base.group_user')
paytm_merchant_key = fields.Char('Merchent Key', required_if_provider='Paytm',
groups='base.group_user')
@api.model
def _get_paytm_urls(self):
""" Atom URLS """
return {
'paytm_form_url':'https://securegw-stage.paytm.in/order/process'
}
@api.multi
def paytm_get_form_action_url(self):
return self._get_paytm_urls () ['paytm_form_url']
# def _paytm_generate_sign(self ,inout ,values):
# if inout not in ('in' ,'out'):
# raise Exception ("Type must be 'in' or 'out'")
#
# if inout == 'in':
# keys="merchant_id|merchant_key|txnid|ttype|prodid|amt||||||||||".split ('|')
# sign=''.join ('%s|' % (values.get (k) or '') for k in keys)
# sign+=self.paytm_merchant_key or ''
# else:
# keys="|status|||||||||||amt|prodid|ttype|txnid".split ('|')
# sign=''.join ('%s|' % (values.get (k) or '') for k in keys)
# sign=self.paytm_merchant_key + sign + self.paytm_merchant_id
#
# shasign=hashlib.sha512 (sign.encode ('utf-8')).hexdigest ()
# return shasign
@api.multi
def paytm_form_generate_values(self ,values):
self.ensure_one ()
print("values", values)
base_url=self.env ['ir.config_parameter'].sudo ().get_param ('web.base.url')
now=datetime.now ()
paytm_values=dict (
MID=self.paytm_merchant_id ,
ORDER_ID=str(values ['reference']) ,
CUST_ID = str(values.get('partner_id')),
INDUSTRY_TYPE_ID='Retail' ,
CHANNEL_ID = 'WEB',
TXN_AMOUNT=str(values ['amount']) ,
WEBSITE='WEBSTAGING',
EMAIL=str(values.get ('partner_email')) ,
MOBILE_NO = str(values.get('partner_phone')),
CALL_BACK_URL=urls.url_join (base_url ,'/payment/paytm/return/') ,
)
paytm_values ['reqHashKey']=self.generate_checksum(paytm_values, self.paytm_merchant_key)
print(paytm_values ['reqHashKey'])
return paytm_values
@api.multi
def __encode__(self,to_encode ,iv ,key):
__pad__=lambda s:s + (16 - len (s) % 16) * chr (16 - len (s) % 16)
# Pad
to_encode=__pad__ (to_encode)
# Encrypt
c=AES.new (key ,AES.MODE_CBC ,iv)
to_encode=c.encrypt (to_encode)
# Encode
to_encode=base64.b64encode (to_encode)
return to_encode.decode ("UTF-8")
@api.multi
def __decode__(self,to_decode ,iv ,key):
# Decode
to_decode=base64.b64decode (to_decode)
# Decrypt
c=AES.new (key ,AES.MODE_CBC ,iv)
to_decode=c.decrypt (to_decode)
if type (to_decode) == bytes:
# convert bytes array to str.
to_decode=to_decode.decode ()
# remove pad
return self.__unpad__ (to_decode)
@api.multi
def __id_generator__(self,size=6 ,chars=string.ascii_uppercase + string.digits + string.ascii_lowercase):
return ''.join (random.choice (chars) for _ in range (size))
@api.multi
def __get_param_string__(self,params ,escape_refund=True):
params_string=[]
print(params)
for key in sorted (params.keys ()):
print(key)
if ("|" in params [key] or (escape_refund == True and "REFUND" in params [key])):
respons_dict={}
exit ()
value=params [key]
params_string.append ('' if value == 'null' else str (value))
return '|'.join (params_string)
@api.multi
def generate_checksum(self,param_dict ,merchant_key ,salt=None):
params_string=self.__get_param_string__ (param_dict)
return self.generate_checksum_by_str (params_string ,merchant_key ,salt)
@api.multi
def generate_refund_checksum(self,param_dict ,merchant_key ,salt=None):
for i in param_dict:
if ("|" in param_dict [i]):
param_dict={}
exit ()
params_string=self.__get_param_string__ (param_dict ,False)
return self.generate_checksum_by_str (params_string ,merchant_key ,salt)
@api.multi
def generate_checksum_by_str(self,param_str ,merchant_key ,salt=None):
IV="@@@@&&&&####$$$$"
params_string=param_str
salt=salt if salt else self.__id_generator__ (4)
final_string='%s|%s' % (params_string ,salt)
hasher=hashlib.sha256 (final_string.encode ())
hash_string=hasher.hexdigest ()
hash_string+=salt
return self.__encode__ (hash_string ,IV ,merchant_key)
@api.multi
def verify_checksum(self,param_dict ,merchant_key ,checksum):
# Remove checksum
if 'CHECKSUMHASH' in param_dict:
param_dict.pop ('CHECKSUMHASH')
params_string=self.__get_param_string__ (param_dict ,False)
return self.verify_checksum_by_str (params_string ,merchant_key ,checksum)
@api.multi
def verify_checksum_by_str(self,param_str ,merchant_key ,checksum):
IV="@@@@&&&&####$$$$"
paytm_hash=self.__decode__ (checksum ,IV ,merchant_key)
salt=paytm_hash [-4:]
calculated_checksum=self.generate_checksum_by_str (param_str ,merchant_key ,salt=salt)
return calculated_checksum == checksum
class PaymentTransactionAtom(models.Model):
_inherit = 'payment.transaction'
paytm_txn_type = fields.Char('Transaction type')
@api.model
def _paytm_form_get_tx_from_data(self ,data):
print ("dataa" ,data)
reference =data.get ('ORDERID')
if not reference:
error_msg=_ ('Paytm: received data with missing reference (%s)') % (reference)
_logger.info (error_msg)
raise ValidationError (error_msg)
txs=self.env ['payment.transaction'].search ([('reference' ,'=' ,reference)])
if not txs or len (txs) > 1:
error_msg='Paytm: received data for reference %s' % (reference)
if not txs:
error_msg+='; no order found'
else:
error_msg+='; multiple order found'
_logger.info (error_msg)
raise ValidationError (error_msg)
return txs [0]
@api.multi
def _paytm_form_get_invalid_parameters(self ,data):
invalid_parameters=[]
if self.acquirer_reference and data.get ('mmp_txn') != self.acquirer_reference:
invalid_parameters.append (('ORDERID' ,data.get ('ORDERID') ,self.acquirer_reference))
return invalid_parameters
@api.multi
def _paytm_form_validate(self ,data):
print (data)
status=data.get ('STATUS')
result=self.write ({
'acquirer_reference':self.env ['payment.acquirer'].search ([]) ,
'date':fields.Datetime.now () ,
})
print (status)
if status == 'TXN_SUCCESS':
self._set_transaction_done ()
elif status != 'TXN_FAILED':
self._set_transaction_cancel ()
else:
self._set_transaction_pending ()
return result