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.
 
 
 
 

271 lines
14 KiB

# coding: utf-8
#from hashlib import sha1
from urllib.parse import urlparse, urljoin
from odoo import api, fields, tools, models, _
from odoo.addons.acquirer_payplug.controllers.main import PayPlugController
from odoo.http import request
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
from datetime import datetime, timedelta
from odoo.exceptions import AccessError, UserError, ValidationError
import logging
_logger = logging.getLogger(__name__)
import pprint
import payplug
payplug.set_api_version("2019-08-06")
class TxPayPlug(models.Model):
_inherit = 'payment.transaction'
provider_type_payplug = fields.Selection([
('payplug', 'PayPlug'),
('oney', 'Paylater by Oney'),
('amex', 'Americam Express'),
('bancontact', 'Bancontact'),
], string="Acquirer Payplug")
# TO EXTRACT THE NAME AND FIRST NAME FROM THE "NAME" FIELD
def _partner_values(self, partner):
vals=[]
if partner:
if len(partner.name.split(' ')) == 1:
vals.append(partner.name)
vals.append('None')
else:
vals=partner.name.split(' ',1)
return vals
# CREATE SPECIFIC VALUES FOR ONEY
def _order_lines_oney(self, order):
shop_lines=[]
if order:
for line in order.order_line:
shop_lines.append({
'expected_delivery_date': (datetime.now()+timedelta(days=2)).strftime(DEFAULT_SERVER_DATE_FORMAT),
'delivery_label': order.company_id.name,
'brand': order.company_id.name,
'delivery_type': 'carrier',
'merchant_item_id': 'REF-'+str(line.id),
'name': line.product_id.name,
'total_amount': int(line.price_total*100),
'price': int(line.price_unit+(line.price_tax/line.product_uom_qty)*100),
'quantity': int(line.product_uom_qty),
})
return shop_lines
def _get_specific_rendering_values(self, processing_values):
tx_values = super()._get_specific_rendering_values(processing_values)
# IF NOT PROVIDER PAYPLUG
if self.provider_code != 'payplug':
return tx_values
# DOWNLOAD SECRET KEY PAYPLUG TEST OR LIVE
secret_payplug_key = request.env['payment.provider']._key_acquirer_state(self.provider_id)
# BASE URL FOR RETURN
base_url = self.provider_id.get_base_url()
# SECRET KEY TEST OR LIVE
payplug.set_secret_key(secret_payplug_key)
# PROCESSING TO EXTRACT THE ORDER NUMBER WITHOUT SO000-1, SO000-2 ADD IF SEVERAL PAYMENT ATTEMPTS
if self.reference:
order_id = self.reference.split('-',1)[0]
# FROM ORDERS
order = request.env['sale.order'].sudo().search([('name', '=', order_id)])
type_of_request = 'sale.order'
partner_invoice = order.partner_invoice_id
if not order:
# FROM INVOICE
order = request.env['account.move'].sudo().search([('name', '=', self.reference)])
type_of_request = 'account.move'
partner_invoice = order.partner_id
# MANDATORY VALUE CONTROL
if not order.partner_shipping_id.country_id or not order.partner_invoice_id.country_id :
raise ValidationError("PayPlug: " + _("COUNTRY is required!"))
if not order.partner_shipping_id.city or not order.partner_invoice_id.city :
raise ValidationError("PayPlug: " + _("CITY is required!"))
if not order.partner_shipping_id.zip or not order.partner_invoice_id.zip :
raise ValidationError("PayPlug: " + _("ZIP is required!"))
if not order.partner_shipping_id.phone or not order.partner_invoice_id.phone :
raise ValidationError("PayPlug: " + _("PHONE is required!"))
if not order.partner_shipping_id.email or not order.partner_invoice_id.email :
raise ValidationError("PayPlug: " + _("EMAIL is required!"))
# GENERATE DIGITAL KEY
payment_generate_key = {
'reference': order.name,
'customer_name': order.partner_id.name,
'customer_postcode': order.partner_id.zip,
}
digital_Key = self.env['payment.provider']._playplug_generate_digital_sign(payment_generate_key)
partner_billing=self._partner_values(order.partner_invoice_id)
partner_shipping=self._partner_values(order.partner_shipping_id)
# FORMAT INTERNATIONNAL PHONE BILLING
if order.partner_invoice_id.phone:
BillingPhoneFormat=request.env['res.partner'].sudo()._phone_format(
partner_invoice.phone or order.partner_id.phone,
partner_invoice.country_id,
order.company_id)
if BillingPhoneFormat:
BillingPhoneFormat=BillingPhoneFormat.replace(' ','')
# FORMAT INTERNATIONNAL PHONE SHIPPING
if order.partner_shipping_id.phone:
ShippingPhoneFormat=request.env['res.partner'].sudo()._phone_format(
order.partner_shipping_id.phone or order.partner_id.phone,
order.partner_shipping_id.country_id,
order.company_id)
if ShippingPhoneFormat:
ShippingPhoneFormat=ShippingPhoneFormat.replace(' ','')
# BILLING FULL ADDRESS
billing_full_address = order.partner_id.street
if partner_invoice.street2:
billing_full_address += ' - '+partner_invoice.street2
# SHIPPING FULL ADDRESS
shipping_full_address = order.partner_shipping_id.street
if order.partner_shipping_id.street2:
shipping_full_address += ' - '+order.partner_shipping_id.street2
payment_data = {}
payment_data = {
# AMOUNT DIFFERENT BY PAYPLUG PROVIDER
'currency': str(order.currency_id.name),
'billing': {
'first_name': partner_billing[0],
'last_name': partner_billing[1],
'email': partner_invoice.email,
'address1': billing_full_address,
'postcode': partner_invoice.zip,
'city': partner_invoice.city,
'country': partner_invoice.country_id.code,
'language': partner_invoice.country_id.code.lower(),
},
'shipping': {
'first_name': partner_shipping[0],
'last_name': partner_shipping[0],
'email': order.partner_shipping_id.email or order.partner_id.email,
'address1': shipping_full_address,
'postcode': order.partner_shipping_id.zip,
'city': order.partner_shipping_id.city,
'country': order.partner_shipping_id.country_id.code,
'language': order.partner_shipping_id.country_id.code.lower(),
'delivery_type': 'BILLING'
},
'hosted_payment': {
'return_url': '%s' % urljoin(base_url, PayPlugController._return_url+'?transaction='+str(self.id)),
'cancel_url': '%s' % urljoin(base_url, PayPlugController._webhook_url+'?transaction='+str(self.id)),
},
'metadata': {
'DigitalKey': digital_Key,
'return_validate_url': '',
},
}
# TO DEFINE THE METHOD ACCORDING TO THE PAYPLUG PROVIDER AND SPECIFIC VALUES
payment_method = request.session.get('provider_payplug')
payment_method_oney = request.session.get('type_oney')
amount_order = int(processing_values.get('amount')*100)
if payment_method == 'payplug':
payment_method_type = 'payplug'
payment_data['amount'] = amount_order
payment_data['metadata']['payment_method'] = 'payplug'
if payment_method == 'oney':
payment_method_type = 'oney'
payment_data['metadata']['payment_method'] = 'oney'
payment_data['authorized_amount'] = amount_order
payment_data['payment_method'] = payment_method_oney
payment_data['billing']['mobile_phone_number'] = BillingPhoneFormat
payment_data['shipping']['mobile_phone_number'] = ShippingPhoneFormat
payment_data['shipping']['company_name'] = partner_invoice.parent_id.name or partner_invoice.company_id.name
payment_data['payment_context'] = {}
payment_data['payment_context']['cart'] = self._order_lines_oney(order)
if payment_method == 'american_express':
payment_method_type = 'amex'
payment_data['amount'] = amount_order
payment_data['payment_method'] = 'american_express'
payment_data['shipping']['company_name'] = partner_invoice.parent_id.name or partner_invoice.company_id.name
payment_data['metadata']['payment_method'] = 'amex'
if payment_method == 'bancontact':
payment_method_type = 'bancontact'
payment_data['amount'] = amount_order
payment_data['payment_method'] = 'bancontact'
payment_data['shipping']['company_name'] = partner_invoice.parent_id.name or partner_invoice.company_id.name
payment_data['metadata']['payment_method'] = 'bancontact'
payplug_tx_values = {}
if processing_values.get('reference') != '/':
# CREATE PAYMENT
payment = payplug.Payment.create(**payment_data)
payment_id = str(payment.id)
# RETURN URL PAYPLUG FOR PAYMENT
payplug_tx_values = dict(processing_values)
if self.provider_code == 'payplug':
payplug_tx_values.update({
'payplug_url': '%s' % payment.hosted_payment.payment_url,
})
# WRITE REFERENCE SUPPLIER IN PAYMENT TRANSACTION
if processing_values.get('reference') != '/':
transaction_id = request.env['payment.transaction'].sudo().search([('reference', '=', str(processing_values.get('reference')))], limit=1)
transaction_id.sudo().write({
'provider_reference': payment_id,
'provider_type_payplug': payment_method_type})
return payplug_tx_values
# RETOUR A PARTIR DU CONTROLEUR
@api.model
def _get_tx_from_notification_data(self, provider, Payment):
tx = key = False
tx = super()._get_tx_from_notification_data(provider, Payment)
if provider != 'payplug' or len(tx) == 1:
return tx
if isinstance(Payment,object) == True:
tx = self.search([('provider_reference', '=', str(Payment.id))], limit=1)
if tx:
vals = {
'reference': tx.reference.split('-')[0],
'customer_name': tx.partner_id.name,
'customer_postcode': tx.partner_id.zip,
}
# CREATE NEW DIGITAL KEY FOR CONTROL
key = Payment.metadata.get('DigitalKey')
control_digital_key = tx.provider_id._playplug_generate_digital_sign(vals)
if key.upper() != control_digital_key.upper():
raise ValidationError(
"PayPlug: " + _(
"Invalid Key: received %(sign)s, computed %(check)s",
sign=key.upper(), check=control_digital_key.upper()
)
)
return tx
def _process_notification_data(self, notification_data):
super()._process_notification_data(notification_data)
if self.provider_code != 'payplug':
return
# SPECIFIC STATE ONEY
if notification_data.metadata.get('payment_method') == 'oney':
if notification_data.authorization and notification_data.authorization.get('authorized_at'):
# ACCEPTED BY ONEY
self.sudo().write({'provider_reference': self.provider_reference})
self._set_done(_("Your payment %s has been validated by Oney.", notification_data.payment_method.get('type')))
return True
if notification_data.is_paid == False and notification_data.failure == None:
# WAITING FOR VALIDATION BY ONEY
self.sudo().write({'state_message': 'Oney: awaiting approval'})
self._set_pending(_("Your payment %s has been successfully processed but is awaiting approval by Oney.", notification_data.payment_method.get('type')))
return None
if notification_data.is_paid == False and notification_data.failure != None:
# REFUSE BY ONEY
self.sudo().write({'state_message': 'Oney: feedback error'})
self._set_error(_("Your payment in %s was refused by Oney.", notification_data.payment_method.get('type')))
# OTHER PROVIDER PAYPLUG
else:
if notification_data.is_paid == True and notification_data.failure == None:
# ACCEPTED
self.sudo().write({'provider_reference': self.provider_reference})
self._set_done()
return True
if notification_data.is_paid == False and notification_data.failure == None:
# WAITING FOR VALIDATION
self.sudo().write({'state_message': 'PayPlug: feedback error'})
self._set_pending()
return None
if notification_data.is_paid == False and notification_data.failure != None:
# REFUSE
self.sudo().write({'state_message': 'PayPlug: feedback error'})
self._set_error(_("Your payment was refused."))
return False