Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SPIKE] 3DS iframe for token payments #1222

Draft
wants to merge 85 commits into
base: prestashop/8.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
8402ca6
Draft for httpclient refactoring
btafforeau Jan 3, 2024
6dd7d1c
Modified payment client and configuration builder (#1199)
L3RAZ Feb 13, 2024
29aebcc
PAYSHIP-2630 (#1182)
Matt75 Feb 13, 2024
52a474d
Fixed old Order client class extension
L3RAZ Mar 4, 2024
e02044c
Removed abstract property from PshHttpClientAdapter
L3RAZ Mar 6, 2024
345a7cb
Added logger to new API client
L3RAZ Mar 6, 2024
7380e30
Draft for httpclient refactoring
btafforeau Jan 3, 2024
b305f0b
Modified payment client and configuration builder (#1199)
L3RAZ Feb 13, 2024
a0bf104
PAYSHIP-2630 (#1182)
Matt75 Feb 13, 2024
7298811
Changed CreateOrderHandler to use new HttpClient
L3RAZ Feb 12, 2024
2a655a4
Fix
L3RAZ Feb 13, 2024
da3d354
Added order managing functions to OrderHttpClient
L3RAZ Feb 13, 2024
6d3fc0c
CS fix
L3RAZ Feb 13, 2024
86a0c2f
Added json encoding for request sending
L3RAZ Feb 14, 2024
0310a61
Added dependency config
L3RAZ Feb 14, 2024
fe55342
Create order unit tests
btafforeau Feb 19, 2024
175ae2d
Renamed service names
L3RAZ Feb 19, 2024
140b092
Fixed interface and tests
L3RAZ Feb 19, 2024
4652037
Handling more errors for PaymentService
btafforeau Feb 23, 2024
67eacb4
Symfony serializer (#1202)
L3RAZ Mar 5, 2024
92dea79
[PAYSHIP-2679] New DB structure for PayPal Order (#1203)
L3RAZ Mar 5, 2024
1267349
Updated PayPal order getters and removed PsCheckoutCart creation
L3RAZ Mar 5, 2024
8547e25
Fixed oldPaymentClient
L3RAZ Mar 7, 2024
6181a7a
PHPStan fix
L3RAZ Mar 7, 2024
1a5aa3a
Split services into separate files and renamed services (#1211)
L3RAZ Mar 18, 2024
037b24b
Replace client token by user id token
Matt75 Jan 15, 2024
f5ef9ad
Implement payment method token
Matt75 Jan 15, 2024
3680039
Adding payment method token events for each webhook
btafforeau Mar 6, 2024
fa194cb
Added is_favorite column to token table
L3RAZ Mar 8, 2024
6ded1db
PaymentToken entity and repository
L3RAZ Mar 8, 2024
72ee1df
Added new JS component for vaulted payment methods
L3RAZ Mar 13, 2024
0b15f00
Added correct payment logo display
L3RAZ Mar 13, 2024
feaf7ad
Added custom marks for vaulted payment methods
L3RAZ Mar 13, 2024
6eb6b1e
Moved vaulting config check to fundingSourceProvider
L3RAZ Mar 13, 2024
646f7d4
CS fix
L3RAZ Mar 13, 2024
d1654f7
Added forms for vaulting payments and setting as favorite
L3RAZ Mar 14, 2024
b5f7431
Renamed smarty template variables
L3RAZ Mar 14, 2024
4f89ef0
Added token delete handler and repository functions
L3RAZ Mar 15, 2024
6235c54
Temp fix for token events
L3RAZ Mar 15, 2024
30c5c0f
Changed delete function argument type
L3RAZ Mar 15, 2024
f305590
Undid database table changes
L3RAZ Mar 15, 2024
f7845fc
Added event subscriber implementation
L3RAZ Mar 15, 2024
8978e56
CS fix
L3RAZ Mar 15, 2024
753a4fb
Fixed OrderDispatcher
L3RAZ Mar 15, 2024
fa9cf77
PHPStan fixes
L3RAZ Mar 15, 2024
d68fd96
Added PayPal customer saving
L3RAZ Mar 18, 2024
edc5b29
Added logic to set token as favorite after receiving webhook
L3RAZ Mar 18, 2024
f402bf4
CS fix
L3RAZ Mar 18, 2024
c9e1e95
phpStan fix
L3RAZ Mar 18, 2024
5a8e626
Remove final_capture from pscheckout_order table
Matt75 Mar 19, 2024
f28596c
Added payment token delete without confirmation
L3RAZ Mar 19, 2024
5cce7d2
Added modal component and confirmation for payment token delete
L3RAZ Mar 19, 2024
fbb9416
Added config for token event subscriber
L3RAZ Mar 20, 2024
04f875b
Added token deletion
L3RAZ Mar 20, 2024
c3cf3ca
Added total count function for admin ajax controller
L3RAZ Mar 20, 2024
ff1ba51
Added setting payment token as favorite on order create
L3RAZ Mar 20, 2024
9888ab1
Added userIdToken loading
L3RAZ Mar 20, 2024
61cf35d
Added payment token status to Db table, entity and repository
L3RAZ Mar 21, 2024
89da15f
Added API call to get userIdToken
L3RAZ Mar 21, 2024
8a313c1
added payment token status fetching from webhook
L3RAZ Mar 21, 2024
67a824d
Added token filtering by status
L3RAZ Mar 21, 2024
543c58e
Added Payment controller for validating orders with payment token
L3RAZ Mar 22, 2024
92b3d0c
Added check if payment token belongs to customer
L3RAZ Mar 22, 2024
02ebb46
Replaced new order payload builder with old one in create order comma…
L3RAZ Mar 22, 2024
d4de4b7
Changed token and oauth functions to match API specifications
L3RAZ Mar 25, 2024
fde9181
Added new handler to save paypal order and related entities to database
L3RAZ Mar 25, 2024
cd1e08c
CS fix
L3RAZ Mar 25, 2024
57c15d0
Added template for 3DS error
L3RAZ Mar 25, 2024
8442ed9
Removed OauthHttpClient and added configuration for CheckoutHttpCLien…
L3RAZ Mar 26, 2024
54750b9
CS fix
L3RAZ Mar 26, 2024
79c6aa5
Add vault to legacy OrderPayloadBuilder
Matt75 Mar 26, 2024
a64c088
Added 3DS logic to payment controller and moved order entities
L3RAZ Mar 26, 2024
d577d95
Fix ExpressCheckout product data
Matt75 Mar 22, 2024
b5fcc71
Fix create order payload address
Matt75 Mar 21, 2024
f16007a
Fix json array for card brands
Matt75 Mar 13, 2024
e5a2921
Added cancel_url to order payload
L3RAZ Mar 26, 2024
bd75d0d
Changed PayPal Order update functions and added Order update on PayPa…
L3RAZ Mar 27, 2024
806e55f
Fixed total token count query
L3RAZ Mar 28, 2024
4e99daf
PHPStan fixes
L3RAZ Mar 29, 2024
419fbb9
CS fix
L3RAZ Mar 29, 2024
68296e8
Fixes payment token saving during order capture
L3RAZ Mar 29, 2024
46139a9
Fixes for vaulting order creation and capture
L3RAZ Apr 2, 2024
ce981d4
Added Iframe 3DS validation
L3RAZ Mar 28, 2024
cc98a5e
Fixes for iframe event handling
L3RAZ Mar 28, 2024
41197bf
Removed testing code
L3RAZ Apr 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ jobs:
phpunit:
name: PHPUnit
runs-on: ubuntu-latest
strategy:
matrix:
presta-versions: [ '8.0.0', 'latest' ]
steps:
- name: Checkout
uses: actions/checkout@v2
Expand All @@ -111,5 +114,9 @@ jobs:

- run: composer install

- name: Pull PrestaShop files (Tag ${{ matrix.presta-versions }})
run: docker run -tid --rm -v ps-volume:/var/www/html --name temp-ps prestashop/prestashop:${{ matrix.presta-versions }}

- name: Run PHPUnit
run: php vendor/bin/phpunit tests/Unit
run: docker run --rm --volumes-from temp-ps -v $PWD:/var/www/html/modules/ps_checkout -e _PS_ROOT_DIR_=/var/www/html/ --workdir=/var/www/html/modules/ps_checkout php:7.2 ./vendor/bin/phpunit -c ./tests/Unit/phpunit.xml
# run: php vendor/bin/phpunit tests/Unit
31 changes: 31 additions & 0 deletions _dev/js/front/src/api/ps-checkout.api.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,35 @@ export class PsCheckoutApi extends BaseClass {
})
);
}

postDeleteVaultedToken(data) {
return fetch(this.config.vaultUrl, {
method: 'post',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json'
},
...(data ? { body: JSON.stringify({action: 'deleteToken', ...data}) } : {})
})
.then((response) => {
const contentType = response.headers.get('content-type');
const isJsonResponse =
contentType && contentType.indexOf('application/json') !== -1;

if (isJsonResponse) {
if (false === response.ok || response.status >= 400) {
return response.json().then((response) => {
throw response.body && response.body.error
? response.body.error
: { message: this.$('checkout.form.error.label') };
});
}

return response.json();
}

throw new Error(this.$('checkout.form.error.label'));
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,24 +43,11 @@ export class ExpressButtonProductComponent extends BaseComponent {

buttonContainer.append(this.checkoutExpressButton);

const {
id_product,
id_product_attribute,
id_customization,
quantity_wanted
} = this.prestashopService.getProductDetails();

this.children.expressCheckoutButton = new ExpressCheckoutButtonComponent(
this.app,
{
fundingSource: 'paypal',
querySelector: '#ps-checkout-express-button',
data: {
id_product,
id_product_attribute,
id_customization,
quantity_wanted
}
querySelector: '#ps-checkout-express-button'
}
).render();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,24 +47,11 @@ export class PayLaterButtonProductComponent extends BaseComponent {
buttonContainer.append(this.checkoutExpressButton);
}

const {
id_product,
id_product_attribute,
id_customization,
quantity_wanted
} = this.prestashopService.getProductDetails();

this.children.expressCheckoutButton = new ExpressCheckoutButtonComponent(
this.app,
{
fundingSource: 'paylater',
querySelector: '#ps-checkout-express-button',
data: {
id_product,
id_product_attribute,
id_customization,
quantity_wanted
}
querySelector: '#ps-checkout-express-button'
}
).render();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ export class PaymentOptionsComponent extends BaseComponent {
if (
this.config.expressCheckout.active &&
'ps_checkout-' + this.payPalService.getFundingSource() !==
HTMLListenerElements[index].button.dataset.moduleName
HTMLListenerElements[index].button.dataset.moduleName &&
this.payPalService.getOrderId()
) {
this.psCheckoutApi
.postCancelOrder({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,24 +51,11 @@ export class ExpressButtonProductComponent extends BaseComponent {
this.updateButtonContainerVisibility();
});

const {
id_product,
id_product_attribute,
id_customization,
quantity_wanted
} = this.prestashopService.getProductDetails();

this.children.expressCheckoutButton = new ExpressCheckoutButtonComponent(
this.app,
{
fundingSource: 'paypal',
querySelector: `#${BUTTON_CONTAINER_SELECTOR}`,
data: {
id_product,
id_product_attribute,
id_customization,
quantity_wanted
}
querySelector: `#${BUTTON_CONTAINER_SELECTOR}`
}
).render();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,24 +55,11 @@ export class PayLaterButtonProductComponent extends BaseComponent {
this.updateButtonContainerVisibility();
});

const {
id_product,
id_product_attribute,
id_customization,
quantity_wanted
} = this.prestashopService.getProductDetails();

this.children.expressCheckoutButton = new ExpressCheckoutButtonComponent(
this.app,
{
fundingSource: 'paylater',
querySelector: `#${BUTTON_CONTAINER_SELECTOR}`,
data: {
id_product,
id_product_attribute,
id_customization,
quantity_wanted
}
querySelector: `#${BUTTON_CONTAINER_SELECTOR}`
}
).render();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ export class PaymentOptionsComponent extends BaseComponent {
if (
this.config.expressCheckout.active &&
'ps_checkout-' + this.payPalService.getFundingSource() !==
radio.dataset.moduleName
radio.dataset.moduleName &&
this.payPalService.getOrderId()
) {
this.psCheckoutApi
.postCancelOrder({
Expand Down
16 changes: 14 additions & 2 deletions _dev/js/front/src/components/common/card-fields.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,18 @@ export class CardFieldsComponent extends BaseComponent {
this.toggleCardFieldsErrors();
}

getVaultFormData() {
if (this.data.HTMLElementCardForm) {
const formData = new FormData(this.data.HTMLElementCardForm);
return {
vault: formData.get(`ps_checkout-vault-payment-${this.data.name}`) === '1',
favorite: formData.get(`ps_checkout-favorite-payment-${this.data.name}`) === '1'
};

}
return {};
}

renderPayPalCardFields() {
this.data.HTMLElementCardForm.classList.toggle('loading', true);

Expand Down Expand Up @@ -223,10 +235,10 @@ export class CardFieldsComponent extends BaseComponent {

return this.psCheckoutApi
.postCreateOrder({
...this.getVaultFormData(),
...data,
fundingSource: this.data.name,
isHostedFields: true
// vault: storeCardInVault
isCardFields: true
})
.then((data) => {
this.data.orderId = data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export class ExpressCheckoutButtonComponent extends BaseComponent {
static Inject = {
payPalService: 'PayPalService',
psCheckoutApi: 'PsCheckoutApi',
prestashopService: 'PrestashopService',
$: '$'
};

Expand Down Expand Up @@ -88,7 +89,22 @@ export class ExpressCheckoutButtonComponent extends BaseComponent {
}

createOrder(data) {
const extraData = this.props?.data ? this.props.data : {};
let extraData = {};

if (this.prestashopService.isProductPage()) {
let {
id_product,
id_product_attribute,
id_customization,
quantity_wanted
} = this.prestashopService.getProductDetails();
extraData = {
id_product,
id_product_attribute,
id_customization,
quantity_wanted
};
}

return this.psCheckoutApi
.postCreateOrder({
Expand Down
65 changes: 65 additions & 0 deletions _dev/js/front/src/components/common/iframe.component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @author PrestaShop SA <[email protected]>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/
import { BaseComponent } from '../../core/dependency-injection/base.component';

export class IframeComponent extends BaseComponent {
static Inject = {
querySelectorService: 'QuerySelectorService',
config: 'PsCheckoutConfig',
$: '$'
};

created() {
this.data.parent = this.querySelectorService.getLoaderParent();
this.data.src = this.props.src;
this.data.onConfirm = this.props.onConfirm || (() => {});
this.data.onClose = this.props.onClose || (() => {});
}

render() {
this.overlay = document.createElement('div');
this.overlay.classList.add('ps-checkout', 'overlay');

this.iframe = document.createElement('iframe');
this.iframe.src = this.data.src;
this.iframe.classList.add('ps-checkout', 'ps-checkout-iframe');

this.overlay.append(this.iframe);
this.data.parent.append(this.overlay);

return this;
}

reload(url = null) {
if (url) {
this.iframe.src = url;
}
this.iframe.contentWindow.location.reload();
}

show() {
this.overlay.classList.add('visible');
document.body.style.overflow = 'hidden';
}

hide() {
this.overlay.classList.remove('visible');
document.body.style.overflow = '';
}
}
2 changes: 1 addition & 1 deletion _dev/js/front/src/components/common/marker.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class MarkComponent extends BaseComponent {
const src = this.config.customMark[this.data.name];
let logoList = [];

if (this.config.cardSupportedBrands && this.config.cardLogoBrands) {
if (this.data.name === 'card' && this.config.cardSupportedBrands && this.config.cardLogoBrands) {
this.config.cardSupportedBrands.forEach(brand => {
if (this.config.cardLogoBrands[brand]) {
let customMarkImg = document.createElement('img');
Expand Down
Loading
Loading