[IMP] payment_applepay, payment_hyperpay: implement PCI DSS v4.0 requirements
This commit is contained in:
parent
cce1b3ee3a
commit
5d768c745f
|
|
@ -1,20 +1,24 @@
|
||||||
import json
|
import json
|
||||||
|
import secrets
|
||||||
|
import requests
|
||||||
|
|
||||||
from odoo.http import route, request, Controller
|
from odoo.http import route, request, Controller
|
||||||
|
|
||||||
|
|
||||||
class ApplePayFastCheckout(Controller):
|
class ApplePayFastCheckout(Controller):
|
||||||
|
|
||||||
@route('/applepay', type='http', auth='public', website=True, csrf=False)
|
@route('/applepay', type='http', auth='public', website=True, csrf=False)
|
||||||
def apple_pay_iframe(self, **kwargs):
|
def apple_pay_iframe(self, **kwargs):
|
||||||
|
nonce = secrets.token_urlsafe(16)
|
||||||
acquirer_id = request.env['payment.acquirer'].sudo().search([('provider', '=', 'applepay')], limit=1)
|
acquirer_id = request.env['payment.acquirer'].sudo().search([('provider', '=', 'applepay')], limit=1)
|
||||||
|
|
||||||
if acquirer_id.state == 'test':
|
if acquirer_id.state == 'test':
|
||||||
url = "https://eu-test.oppwa.com/v1/paymentWidgets.js"
|
url = "https://eu-test.oppwa.com/v1/paymentWidgets.js"
|
||||||
else:
|
else:
|
||||||
url = "https://oppwa.com/v1/paymentWidgets.js"
|
url = "https://eu-prod.oppwa.com/v1/paymentWidgets.js"
|
||||||
|
|
||||||
response = request.render("applepay_fast_checkout.apple_pay_iframe", {'hyperpay_src': url, 'merchant_id': acquirer_id.applepay_entity_id})
|
integrity = requests.get(f'{url}/v1/fastcheckout/integrity').json().get('integrity', '')
|
||||||
|
|
||||||
|
response = request.render("applepay_fast_checkout.apple_pay_iframe", {'hyperpay_src': url, 'merchant_id': acquirer_id.applepay_entity_id, 'nonce': nonce, 'integrity': integrity})
|
||||||
response.headers['Content-Security-Policy'] = "script-src blob: 'self' 'unsafe-inline' 'unsafe-eval' https://*; worker-src blob: 'self' 'unsafe-inline' 'unsafe-eval' https://*;connect-src 'self' https://* wss://*;frame-src 'self' blob: https://*;"
|
response.headers['Content-Security-Policy'] = "script-src blob: 'self' 'unsafe-inline' 'unsafe-eval' https://*; worker-src blob: 'self' 'unsafe-inline' 'unsafe-eval' https://*;connect-src 'self' https://* wss://*;frame-src 'self' blob: https://*;"
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,20 @@
|
||||||
<template id="apple_pay_iframe" name="Apple Pay Iframe">
|
<template id="apple_pay_iframe" name="Apple Pay Iframe">
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<script t-att-src="hyperpay_src" />
|
<meta http-equiv="Content-Security-Policy"
|
||||||
|
t-attf-content="
|
||||||
|
style-src 'self' https://*.oppwa.com 'unsafe-inline';
|
||||||
|
frame-src 'self' https://*.oppwa.com https://applepay.cdn-apple.com;
|
||||||
|
script-src 'self' https://*.oppwa.com https://applepay.cdn-apple.com 'nonce-{{nonce}}';
|
||||||
|
connect-src 'self' https://*.oppwa.com;
|
||||||
|
img-src 'self' https://*.oppwa.com;" />
|
||||||
|
|
||||||
|
<script t-att-src="hyperpay_src" t-att-integrity="integrity" crossorigin="anonymous" />
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js" />
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js" />
|
||||||
<script>
|
<script>
|
||||||
merchant_id = "<t t-esc="merchant_id" />";
|
merchant_id = "<t t-esc="merchant_id" />";
|
||||||
</script>
|
</script>
|
||||||
<script src="/applepay_fast_checkout/static/src/js/applepay_iframe.js" />
|
<script src="/applepay_fast_checkout/static/src/js/applepay_iframe.js" t-att-nonce="nonce"/>
|
||||||
<link rel="stylesheet" href="/applepay_fast_checkout/static/src/css/applepay_iframe_content.css" />
|
<link rel="stylesheet" href="/applepay_fast_checkout/static/src/css/applepay_iframe_content.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,10 @@
|
||||||
#################################################################################
|
#################################################################################
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from odoo import http
|
|
||||||
import random
|
import random
|
||||||
|
import secrets
|
||||||
|
|
||||||
|
from odoo import http
|
||||||
|
|
||||||
from odoo.http import request
|
from odoo.http import request
|
||||||
from odoo.addons.payment_hyperpay.data.payment_icon import payment_icon
|
from odoo.addons.payment_hyperpay.data.payment_icon import payment_icon
|
||||||
|
|
@ -15,8 +17,7 @@ from odoo.addons.payment_hyperpay.data.payment_icon import payment_icon
|
||||||
import logging
|
import logging
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# test_domain = "https://test.oppwa.com"
|
|
||||||
# live_domain = "https://oppwa.com"
|
|
||||||
test_domain = "https://eu-test.oppwa.com"
|
test_domain = "https://eu-test.oppwa.com"
|
||||||
live_domain = "https://eu-prod.oppwa.com"
|
live_domain = "https://eu-prod.oppwa.com"
|
||||||
|
|
||||||
|
|
@ -46,6 +47,7 @@ class HyperPayController(http.Controller):
|
||||||
@http.route('/payment/hyperpay/checkout/create', type='json', auth='public', csrf=False, website=True)
|
@http.route('/payment/hyperpay/checkout/create', type='json', auth='public', csrf=False, website=True)
|
||||||
def create_hyperpay_checkout(self, **post):
|
def create_hyperpay_checkout(self, **post):
|
||||||
_logger.info('--post---%r', post)
|
_logger.info('--post---%r', post)
|
||||||
|
nonce = secrets.token_urlsafe(16)
|
||||||
tx = request.env['payment.transaction'].sudo().search([('id', '=', int(post.get('txId', 0)))])
|
tx = request.env['payment.transaction'].sudo().search([('id', '=', int(post.get('txId', 0)))])
|
||||||
final_response = {}
|
final_response = {}
|
||||||
if tx:
|
if tx:
|
||||||
|
|
@ -65,6 +67,7 @@ class HyperPayController(http.Controller):
|
||||||
"currency": tx.currency_id and tx.sudo().currency_id.name or '',
|
"currency": tx.currency_id and tx.sudo().currency_id.name or '',
|
||||||
"paymentType": "DB",
|
"paymentType": "DB",
|
||||||
"env": acq.state,
|
"env": acq.state,
|
||||||
|
"integrity": "true",
|
||||||
"customParameters[SHOPPER_tx_id]": tx.id,
|
"customParameters[SHOPPER_tx_id]": tx.id,
|
||||||
"merchantTransactionId": tx.reference,
|
"merchantTransactionId": tx.reference,
|
||||||
"billing.street1": partner_id.street or 'Riyadh',
|
"billing.street1": partner_id.street or 'Riyadh',
|
||||||
|
|
@ -95,7 +98,9 @@ class HyperPayController(http.Controller):
|
||||||
'base_url': base_url,
|
'base_url': base_url,
|
||||||
'data_brands': data_brands,
|
'data_brands': data_brands,
|
||||||
'acq': acq.id,
|
'acq': acq.id,
|
||||||
'website_id': request.session.get('force_website_id') or request.website.id
|
'website_id': request.session.get('force_website_id') or request.website.id,
|
||||||
|
'integrity': resp.get('integrity', ''),
|
||||||
|
'nonce': nonce,
|
||||||
}
|
}
|
||||||
|
|
||||||
return final_response
|
return final_response
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ odoo.define("payment_hyperpay.payment_hyperpay", function (require) {
|
||||||
|
|
||||||
// Reference
|
// Reference
|
||||||
// https://dev.to/pulljosh/how-to-load-html-css-and-js-code-into-an-iframe-2blc
|
// https://dev.to/pulljosh/how-to-load-html-css-and-js-code-into-an-iframe-2blc
|
||||||
const getGeneratedPageURL = ({ html, css, js }) => {
|
const getGeneratedPageURL = ({ html, css, js, meta, nonce}) => {
|
||||||
const getBlobURL = (code, type) => {
|
const getBlobURL = (code, type) => {
|
||||||
const blob = new Blob([code], { type });
|
const blob = new Blob([code], { type });
|
||||||
return URL.createObjectURL(blob);
|
return URL.createObjectURL(blob);
|
||||||
|
|
@ -25,11 +25,12 @@ odoo.define("payment_hyperpay.payment_hyperpay", function (require) {
|
||||||
const source = `
|
const source = `
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
${meta}
|
||||||
${css}
|
${css}
|
||||||
${js}
|
${js}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script>
|
<script nonce="${nonce}">
|
||||||
var wpwlOptions = {
|
var wpwlOptions = {
|
||||||
onReady: function(){
|
onReady: function(){
|
||||||
var shopOrigin = $('input[name="shopOrigin"]');
|
var shopOrigin = $('input[name="shopOrigin"]');
|
||||||
|
|
@ -66,7 +67,7 @@ odoo.define("payment_hyperpay.payment_hyperpay", function (require) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script nonce="${nonce}">
|
||||||
var wpwlOptions = {
|
var wpwlOptions = {
|
||||||
browser: {threeDChallengeWindow: 5 },
|
browser: {threeDChallengeWindow: 5 },
|
||||||
locale: "ar",
|
locale: "ar",
|
||||||
|
|
@ -103,20 +104,20 @@ odoo.define("payment_hyperpay.payment_hyperpay", function (require) {
|
||||||
txId: self.tx_id,
|
txId: self.tx_id,
|
||||||
}).then(function (result) {
|
}).then(function (result) {
|
||||||
if (result) {
|
if (result) {
|
||||||
self._renderHyperpayModal(result.checkoutId, result.domain, result.base_url, result.data_brands, result.acq, result.website_id);
|
self._renderHyperpayModal(result.checkoutId, result.domain, result.base_url, result.data_brands, result.acq, result.website_id, result);
|
||||||
} else {
|
} else {
|
||||||
console.log("Error Occured");
|
console.log("Error Occured");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
_renderHyperpayModal: function (checkoutId, domain, base_url, data_brands, acq, website_id) {
|
_renderHyperpayModal: function (checkoutId, domain, base_url, data_brands, acq, website_id, result) {
|
||||||
var self = this;
|
var self = this;
|
||||||
try {
|
try {
|
||||||
var $modal_html = $($(".payment_hyper_modal").get()[0]);
|
var $modal_html = $($(".payment_hyper_modal").get()[0]);
|
||||||
$modal_html.appendTo($("body")).modal({ keyboard: false, backdrop: "static" });
|
$modal_html.appendTo($("body")).modal({ keyboard: false, backdrop: "static" });
|
||||||
var style_css = '<link rel="stylesheet" href="' + base_url + '/payment_hyperpay/static/src/css/hyperpay_style.css" />';
|
var style_css = '<link rel="stylesheet" href="' + base_url + '/payment_hyperpay/static/src/css/hyperpay_style.css" />';
|
||||||
var script = '<script async src="' + domain + "/v1/paymentWidgets.js?checkoutId=" + checkoutId + '"></script>';
|
var script = `<script async src="${domain}/v1/paymentWidgets.js?checkoutId=${checkoutId}" integrity="${result.integrity}" crossorigin="anonymous"></script>`
|
||||||
var js_script = '<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>';
|
var js_script = '<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>'
|
||||||
var shopperResultUrlTag =
|
var shopperResultUrlTag =
|
||||||
'<form action="' +
|
'<form action="' +
|
||||||
base_url +
|
base_url +
|
||||||
|
|
@ -131,10 +132,20 @@ odoo.define("payment_hyperpay.payment_hyperpay", function (require) {
|
||||||
theIframe.style = "display:none";
|
theIframe.style = "display:none";
|
||||||
var html = script + shopperResultUrlTag;
|
var html = script + shopperResultUrlTag;
|
||||||
|
|
||||||
|
let meta = `<meta http-equiv="Content-Security-Policy"
|
||||||
|
t-attf-content="
|
||||||
|
style-src 'self' https://*.oppwa.com 'unsafe-inline';
|
||||||
|
frame-src 'self' https://*.oppwa.com;
|
||||||
|
script-src 'self' https://*.oppwa.com https://src.mastercard.com https://p11.techlab-cdn.com 'nonce-${result.nonce}';
|
||||||
|
connect-src 'self' https://*.oppwa.com;
|
||||||
|
img-src 'self' https://*.oppwa.com;" />`
|
||||||
|
|
||||||
const url = getGeneratedPageURL({
|
const url = getGeneratedPageURL({
|
||||||
html: html,
|
html: html,
|
||||||
css: style_css,
|
css: style_css,
|
||||||
js: js_script,
|
js: js_script,
|
||||||
|
meta: meta,
|
||||||
|
nonce: result.nonce
|
||||||
});
|
});
|
||||||
theIframe.src = url;
|
theIframe.src = url;
|
||||||
$("#hyperpay-modal-body")[0].appendChild(theIframe);
|
$("#hyperpay-modal-body")[0].appendChild(theIframe);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue