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
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
|