mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 16:24:33 +08:00
Merge branch '3d-secure'
This commit is contained in:
commit
cb1494f103
14 changed files with 337 additions and 22 deletions
|
@ -55,6 +55,7 @@ document.addEventListener(
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
! document.querySelector(PayPalCommerceGateway.button.wrapper) &&
|
! document.querySelector(PayPalCommerceGateway.button.wrapper) &&
|
||||||
|
! document.querySelector(PayPalCommerceGateway.button.mini_cart_wrapper) &&
|
||||||
! document.querySelector(PayPalCommerceGateway.hosted_fields.wrapper)
|
! document.querySelector(PayPalCommerceGateway.hosted_fields.wrapper)
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -11,11 +11,14 @@ class CartActionHandler {
|
||||||
configuration() {
|
configuration() {
|
||||||
const createOrder = (data, actions) => {
|
const createOrder = (data, actions) => {
|
||||||
const payer = payerData();
|
const payer = payerData();
|
||||||
|
const bnCode = typeof this.config.bn_codes[this.config.context] !== 'undefined' ?
|
||||||
|
this.config.bn_codes[this.config.context] : '';
|
||||||
return fetch(this.config.ajax.create_order.endpoint, {
|
return fetch(this.config.ajax.create_order.endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
nonce: this.config.ajax.create_order.nonce,
|
nonce: this.config.ajax.create_order.nonce,
|
||||||
purchase_units: [],
|
purchase_units: [],
|
||||||
|
bn_code:bnCode,
|
||||||
payer
|
payer
|
||||||
}),
|
}),
|
||||||
}).then(function(res) {
|
}).then(function(res) {
|
||||||
|
@ -30,7 +33,7 @@ class CartActionHandler {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createOrder,
|
createOrder,
|
||||||
onApprove: onApprove(this),
|
onApprove: onApprove(this, this.errorHandler),
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
this.errorHandler.message(error);
|
this.errorHandler.message(error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,14 @@ class CheckoutActionHandler {
|
||||||
|
|
||||||
const createOrder = (data, actions) => {
|
const createOrder = (data, actions) => {
|
||||||
const payer = payerData();
|
const payer = payerData();
|
||||||
|
const bnCode = typeof this.config.bn_codes[this.config.context] !== 'undefined' ?
|
||||||
|
this.config.bn_codes[this.config.context] : '';
|
||||||
return fetch(this.config.ajax.create_order.endpoint, {
|
return fetch(this.config.ajax.create_order.endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
nonce: this.config.ajax.create_order.nonce,
|
nonce: this.config.ajax.create_order.nonce,
|
||||||
payer
|
payer,
|
||||||
|
bn_code:bnCode
|
||||||
})
|
})
|
||||||
}).then(function (res) {
|
}).then(function (res) {
|
||||||
return res.json();
|
return res.json();
|
||||||
|
@ -29,7 +32,7 @@ class CheckoutActionHandler {
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
createOrder,
|
createOrder,
|
||||||
onApprove:onApprove(this),
|
onApprove:onApprove(this, this.errorHandler),
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
this.errorHandler.message(error);
|
this.errorHandler.message(error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ class SingleProductActionHandler {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createOrder: this.createOrder(),
|
createOrder: this.createOrder(),
|
||||||
onApprove: onApprove(this),
|
onApprove: onApprove(this, this.errorHandler),
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
this.errorHandler.message(error);
|
this.errorHandler.message(error);
|
||||||
}
|
}
|
||||||
|
@ -75,12 +75,15 @@ class SingleProductActionHandler {
|
||||||
|
|
||||||
const onResolve = (purchase_units) => {
|
const onResolve = (purchase_units) => {
|
||||||
const payer = payerData();
|
const payer = payerData();
|
||||||
|
const bnCode = typeof this.config.bn_codes[this.config.context] !== 'undefined' ?
|
||||||
|
this.config.bn_codes[this.config.context] : '';
|
||||||
return fetch(this.config.ajax.create_order.endpoint, {
|
return fetch(this.config.ajax.create_order.endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
nonce: this.config.ajax.create_order.nonce,
|
nonce: this.config.ajax.create_order.nonce,
|
||||||
purchase_units,
|
purchase_units,
|
||||||
payer
|
payer,
|
||||||
|
bn_code:bnCode
|
||||||
})
|
})
|
||||||
}).then(function (res) {
|
}).then(function (res) {
|
||||||
return res.json();
|
return res.json();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const onApprove = (context) => {
|
const onApprove = (context, errorHandler) => {
|
||||||
return (data, actions) => {
|
return (data, actions) => {
|
||||||
return fetch(context.config.ajax.approve_order.endpoint, {
|
return fetch(context.config.ajax.approve_order.endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
@ -10,7 +10,8 @@ const onApprove = (context) => {
|
||||||
return res.json();
|
return res.json();
|
||||||
}).then((data)=>{
|
}).then((data)=>{
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
throw Error(data.data);
|
errorHandler.message(data.data);
|
||||||
|
throw new Error(data.data);
|
||||||
}
|
}
|
||||||
location.href = context.config.redirect;
|
location.href = context.config.redirect;
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,7 +10,8 @@ const onApprove = (context) => {
|
||||||
return res.json();
|
return res.json();
|
||||||
}).then((data)=>{
|
}).then((data)=>{
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
throw Error(data.data);
|
errorHandler.message(data.data);
|
||||||
|
throw new Error(data.data);
|
||||||
}
|
}
|
||||||
document.querySelector('#place_order').click()
|
document.querySelector('#place_order').click()
|
||||||
});
|
});
|
||||||
|
|
|
@ -47,15 +47,6 @@ class CreditCardRenderer {
|
||||||
contingencies: ['3D_SECURE']
|
contingencies: ['3D_SECURE']
|
||||||
}).then((payload) => {
|
}).then((payload) => {
|
||||||
payload.orderID = payload.orderId;
|
payload.orderID = payload.orderId;
|
||||||
console.log(payload);
|
|
||||||
|
|
||||||
if (payload.liabilityShift === 'POSSIBLE') {
|
|
||||||
return contextConfig.onApprove(payload);
|
|
||||||
}
|
|
||||||
if (payload.liabilityShift) {
|
|
||||||
return contextConfig.onApprove(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
return contextConfig.onApprove(payload);
|
return contextConfig.onApprove(payload);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ use Inpsyde\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint;
|
||||||
use Inpsyde\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint;
|
use Inpsyde\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint;
|
||||||
use Inpsyde\PayPalCommerce\Button\Endpoint\RequestData;
|
use Inpsyde\PayPalCommerce\Button\Endpoint\RequestData;
|
||||||
use Inpsyde\PayPalCommerce\Button\Exception\RuntimeException;
|
use Inpsyde\PayPalCommerce\Button\Exception\RuntimeException;
|
||||||
|
use Inpsyde\PayPalCommerce\Button\Helper\ThreeDSecure;
|
||||||
use Inpsyde\PayPalCommerce\Onboarding\Environment;
|
use Inpsyde\PayPalCommerce\Onboarding\Environment;
|
||||||
use Inpsyde\PayPalCommerce\Onboarding\State;
|
use Inpsyde\PayPalCommerce\Onboarding\State;
|
||||||
|
|
||||||
|
@ -91,12 +92,17 @@ return [
|
||||||
$repository = $container->get('api.repository.cart');
|
$repository = $container->get('api.repository.cart');
|
||||||
$apiClient = $container->get('api.endpoint.order');
|
$apiClient = $container->get('api.endpoint.order');
|
||||||
$payerFactory = $container->get('api.factory.payer');
|
$payerFactory = $container->get('api.factory.payer');
|
||||||
return new CreateOrderEndpoint($requestData, $repository, $apiClient, $payerFactory);
|
$sessionHandler = $container->get('session.handler');
|
||||||
|
return new CreateOrderEndpoint($requestData, $repository, $apiClient, $payerFactory, $sessionHandler);
|
||||||
},
|
},
|
||||||
'button.endpoint.approve-order' => static function (ContainerInterface $container): ApproveOrderEndpoint {
|
'button.endpoint.approve-order' => static function (ContainerInterface $container): ApproveOrderEndpoint {
|
||||||
$requestData = $container->get('button.request-data');
|
$requestData = $container->get('button.request-data');
|
||||||
$apiClient = $container->get('api.endpoint.order');
|
$apiClient = $container->get('api.endpoint.order');
|
||||||
$sessionHandler = $container->get('session.handler');
|
$sessionHandler = $container->get('session.handler');
|
||||||
return new ApproveOrderEndpoint($requestData, $apiClient, $sessionHandler);
|
$threeDSecure = $container->get('button.endpoint.helper.three-d-secure');
|
||||||
|
return new ApproveOrderEndpoint($requestData, $apiClient, $sessionHandler, $threeDSecure);
|
||||||
|
},
|
||||||
|
'button.endpoint.helper.three-d-secure' => static function (ContainerInterface $container): ThreeDSecure {
|
||||||
|
return new ThreeDSecure();
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -236,6 +236,7 @@ class SmartButton implements SmartButtonInterface
|
||||||
'nonce' => wp_create_nonce(ApproveOrderEndpoint::nonce()),
|
'nonce' => wp_create_nonce(ApproveOrderEndpoint::nonce()),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
'bn_codes' => $this->bnCodes(),
|
||||||
'payer' => $this->payerData(),
|
'payer' => $this->payerData(),
|
||||||
'button' => [
|
'button' => [
|
||||||
'wrapper' => '#ppc-button',
|
'wrapper' => '#ppc-button',
|
||||||
|
@ -310,7 +311,9 @@ class SmartButton implements SmartButtonInterface
|
||||||
|
|
||||||
private function attributes(): array
|
private function attributes(): array
|
||||||
{
|
{
|
||||||
$attributes = [];
|
$attributes = [
|
||||||
|
'data-partner-attribution-id' => $this->bnCodeForContext($this->context()),
|
||||||
|
];
|
||||||
try {
|
try {
|
||||||
$clientToken = $this->identityToken->generate();
|
$clientToken = $this->identityToken->generate();
|
||||||
$attributes['data-client-token'] = $clientToken->token();
|
$attributes['data-client-token'] = $clientToken->token();
|
||||||
|
@ -320,6 +323,33 @@ class SmartButton implements SmartButtonInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $context
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function bnCodeForContext(string $context): string
|
||||||
|
{
|
||||||
|
|
||||||
|
$codes = $this->bnCodes();
|
||||||
|
return (isset($codes[$context])) ? $codes[$context] : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BN Codes
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function bnCodes(): array
|
||||||
|
{
|
||||||
|
|
||||||
|
return [
|
||||||
|
'checkout' => 'Woo_PPCP',
|
||||||
|
'cart' => 'Woo_PPCP',
|
||||||
|
'mini-cart' => 'Woo_PPCP',
|
||||||
|
'product' => 'Woo_PPCP',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
private function components(): array
|
private function components(): array
|
||||||
{
|
{
|
||||||
$components = ['buttons'];
|
$components = ['buttons'];
|
||||||
|
|
|
@ -5,8 +5,10 @@ declare(strict_types=1);
|
||||||
namespace Inpsyde\PayPalCommerce\Button\Endpoint;
|
namespace Inpsyde\PayPalCommerce\Button\Endpoint;
|
||||||
|
|
||||||
use Inpsyde\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
use Inpsyde\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||||
|
use Inpsyde\PayPalCommerce\ApiClient\Entity\Order;
|
||||||
use Inpsyde\PayPalCommerce\ApiClient\Entity\OrderStatus;
|
use Inpsyde\PayPalCommerce\ApiClient\Entity\OrderStatus;
|
||||||
use Inpsyde\PayPalCommerce\Button\Exception\RuntimeException;
|
use Inpsyde\PayPalCommerce\Button\Exception\RuntimeException;
|
||||||
|
use Inpsyde\PayPalCommerce\Button\Helper\ThreeDSecure;
|
||||||
use Inpsyde\PayPalCommerce\Session\SessionHandler;
|
use Inpsyde\PayPalCommerce\Session\SessionHandler;
|
||||||
|
|
||||||
class ApproveOrderEndpoint implements EndpointInterface
|
class ApproveOrderEndpoint implements EndpointInterface
|
||||||
|
@ -17,15 +19,18 @@ class ApproveOrderEndpoint implements EndpointInterface
|
||||||
private $requestData;
|
private $requestData;
|
||||||
private $sessionHandler;
|
private $sessionHandler;
|
||||||
private $apiEndpoint;
|
private $apiEndpoint;
|
||||||
|
private $threedSecure;
|
||||||
public function __construct(
|
public function __construct(
|
||||||
RequestData $requestData,
|
RequestData $requestData,
|
||||||
OrderEndpoint $apiEndpoint,
|
OrderEndpoint $apiEndpoint,
|
||||||
SessionHandler $sessionHandler
|
SessionHandler $sessionHandler,
|
||||||
|
ThreeDSecure $threedSecure
|
||||||
) {
|
) {
|
||||||
|
|
||||||
$this->requestData = $requestData;
|
$this->requestData = $requestData;
|
||||||
$this->apiEndpoint = $apiEndpoint;
|
$this->apiEndpoint = $apiEndpoint;
|
||||||
$this->sessionHandler = $sessionHandler;
|
$this->sessionHandler = $sessionHandler;
|
||||||
|
$this->threedSecure = $threedSecure;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function nonce(): string
|
public static function nonce(): string
|
||||||
|
@ -52,6 +57,23 @@ class ApproveOrderEndpoint implements EndpointInterface
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($order->paymentSource() && $order->paymentSource()->card()) {
|
||||||
|
$proceed = $this->threedSecure->proceedWithOrder($order);
|
||||||
|
if ($proceed === ThreeDSecure::RETRY) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
__('Something went wrong. Please try again.', 'woocommerce-paypal-commerce-gateway')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ($proceed === ThreeDSecure::REJECT) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
__(
|
||||||
|
'Unfortunatly, we can\'t accept your card. Please choose a different payment method.',
|
||||||
|
'woocommerce-paypal-commerce-gateway'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (! $order->status()->is(OrderStatus::APPROVED)) {
|
if (! $order->status()->is(OrderStatus::APPROVED)) {
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
sprintf(
|
sprintf(
|
||||||
|
|
|
@ -8,6 +8,7 @@ use Inpsyde\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
||||||
use Inpsyde\PayPalCommerce\Button\Exception\RuntimeException;
|
use Inpsyde\PayPalCommerce\Button\Exception\RuntimeException;
|
||||||
use Inpsyde\PayPalCommerce\ApiClient\Repository\CartRepository;
|
use Inpsyde\PayPalCommerce\ApiClient\Repository\CartRepository;
|
||||||
use Inpsyde\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
use Inpsyde\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||||
|
use Inpsyde\PayPalCommerce\Session\SessionHandler;
|
||||||
|
|
||||||
class CreateOrderEndpoint implements EndpointInterface
|
class CreateOrderEndpoint implements EndpointInterface
|
||||||
{
|
{
|
||||||
|
@ -18,17 +19,20 @@ class CreateOrderEndpoint implements EndpointInterface
|
||||||
private $repository;
|
private $repository;
|
||||||
private $apiEndpoint;
|
private $apiEndpoint;
|
||||||
private $payerFactory;
|
private $payerFactory;
|
||||||
|
private $sessionHandler;
|
||||||
public function __construct(
|
public function __construct(
|
||||||
RequestData $requestData,
|
RequestData $requestData,
|
||||||
CartRepository $repository,
|
CartRepository $repository,
|
||||||
OrderEndpoint $apiEndpoint,
|
OrderEndpoint $apiEndpoint,
|
||||||
PayerFactory $payerFactory
|
PayerFactory $payerFactory,
|
||||||
|
SessionHandler $sessionHandler
|
||||||
) {
|
) {
|
||||||
|
|
||||||
$this->requestData = $requestData;
|
$this->requestData = $requestData;
|
||||||
$this->repository = $repository;
|
$this->repository = $repository;
|
||||||
$this->apiEndpoint = $apiEndpoint;
|
$this->apiEndpoint = $apiEndpoint;
|
||||||
$this->payerFactory = $payerFactory;
|
$this->payerFactory = $payerFactory;
|
||||||
|
$this->sessionHandler = $sessionHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function nonce(): string
|
public static function nonce(): string
|
||||||
|
@ -52,6 +56,11 @@ class CreateOrderEndpoint implements EndpointInterface
|
||||||
}
|
}
|
||||||
$payer = $this->payerFactory->fromPayPalResponse(json_decode(json_encode($data['payer'])));
|
$payer = $this->payerFactory->fromPayPalResponse(json_decode(json_encode($data['payer'])));
|
||||||
}
|
}
|
||||||
|
$bnCode = isset($data['bn_code']) ? (string) $data['bn_code'] : '';
|
||||||
|
if ($bnCode) {
|
||||||
|
$this->sessionHandler->replaceBnCode($bnCode);
|
||||||
|
$this->apiEndpoint->withBnCode($bnCode);
|
||||||
|
}
|
||||||
$order = $this->apiEndpoint->createForPurchaseUnits(
|
$order = $this->apiEndpoint->createForPurchaseUnits(
|
||||||
$purchaseUnits,
|
$purchaseUnits,
|
||||||
$payer
|
$payer
|
||||||
|
|
92
modules.local/ppcp-button/src/Helper/ThreeDSecure.php
Normal file
92
modules.local/ppcp-button/src/Helper/ThreeDSecure.php
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Inpsyde\PayPalCommerce\Button\Helper;
|
||||||
|
|
||||||
|
use Inpsyde\PayPalCommerce\ApiClient\Entity\CardAuthenticationResult;
|
||||||
|
use Inpsyde\PayPalCommerce\ApiClient\Entity\Order;
|
||||||
|
|
||||||
|
class ThreeDSecure
|
||||||
|
{
|
||||||
|
|
||||||
|
public const NO_DECISION = 0;
|
||||||
|
public const PROCCEED = 1;
|
||||||
|
public const REJECT = 2;
|
||||||
|
public const RETRY = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine, how we proceed with a given order.
|
||||||
|
*
|
||||||
|
* @link https://developer.paypal.com/docs/business/checkout/add-capabilities/3d-secure/#authenticationresult
|
||||||
|
* @param Order $order
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function proceedWithOrder(Order $order): int
|
||||||
|
{
|
||||||
|
if (! $order->paymentSource()) {
|
||||||
|
return self::NO_DECISION;
|
||||||
|
}
|
||||||
|
if (! $order->paymentSource()->card()) {
|
||||||
|
return self::NO_DECISION;
|
||||||
|
}
|
||||||
|
if (! $order->paymentSource()->card()->authenticationResult()) {
|
||||||
|
return self::NO_DECISION;
|
||||||
|
}
|
||||||
|
$result = $order->paymentSource()->card()->authenticationResult();
|
||||||
|
if ($result->liabilityShift() === CardAuthenticationResult::LIABILITY_SHIFT_POSSIBLE) {
|
||||||
|
return self::PROCCEED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result->liabilityShift() === CardAuthenticationResult::LIABILITY_SHIFT_UNKNOWN) {
|
||||||
|
return self::RETRY;
|
||||||
|
}
|
||||||
|
if ($result->liabilityShift() === CardAuthenticationResult::LIABILITY_SHIFT_NO) {
|
||||||
|
return $this->noLiabilityShift($result);
|
||||||
|
}
|
||||||
|
return self::NO_DECISION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function noLiabilityShift(CardAuthenticationResult $result): int
|
||||||
|
{
|
||||||
|
|
||||||
|
if (
|
||||||
|
$result->enrollmentStatus() === CardAuthenticationResult::ENROLLMENT_STATUS_BYPASS
|
||||||
|
&& ! $result->authenticationResult()
|
||||||
|
) {
|
||||||
|
return self::PROCCEED;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
$result->enrollmentStatus() === CardAuthenticationResult::ENROLLMENT_STATUS_UNAVAILABLE
|
||||||
|
&& ! $result->authenticationResult()
|
||||||
|
) {
|
||||||
|
return self::PROCCEED;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
$result->enrollmentStatus() === CardAuthenticationResult::ENROLLMENT_STATUS_NO
|
||||||
|
&& ! $result->authenticationResult()
|
||||||
|
) {
|
||||||
|
return self::PROCCEED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result->authenticationResult() === CardAuthenticationResult::AUTHENTICATION_RESULT_REJECTED) {
|
||||||
|
return self::REJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result->authenticationResult() === CardAuthenticationResult::AUTHENTICATION_RESULT_NO) {
|
||||||
|
return self::REJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result->authenticationResult() === CardAuthenticationResult::AUTHENTICATION_RESULT_UNABLE) {
|
||||||
|
return self::RETRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $result->authenticationResult()) {
|
||||||
|
return self::RETRY;
|
||||||
|
}
|
||||||
|
return self::NO_DECISION;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,9 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Inpsyde\PayPalCommerce\WcGateway;
|
namespace Inpsyde\PayPalCommerce\WcGateway;
|
||||||
|
|
||||||
|
use Inpsyde\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||||
|
use Inpsyde\PayPalCommerce\Session\SessionHandler;
|
||||||
|
use Inpsyde\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
use Inpsyde\Woocommerce\Logging\Logger\NullLogger;
|
use Inpsyde\Woocommerce\Logging\Logger\NullLogger;
|
||||||
use Inpsyde\Woocommerce\Logging\Logger\WooCommerceLogger;
|
use Inpsyde\Woocommerce\Logging\Logger\WooCommerceLogger;
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
|
@ -32,6 +35,33 @@ return [
|
||||||
$settings = $container->get('wcgateway.settings');
|
$settings = $container->get('wcgateway.settings');
|
||||||
return $settings->has('client_secret') ? (string) $settings->get('client_secret') : '';
|
return $settings->has('client_secret') ? (string) $settings->get('client_secret') : '';
|
||||||
},
|
},
|
||||||
|
'api.endpoint.order' => static function (ContainerInterface $container): OrderEndpoint {
|
||||||
|
$orderFactory = $container->get('api.factory.order');
|
||||||
|
$patchCollectionFactory = $container->get('api.factory.patch-collection-factory');
|
||||||
|
$logger = $container->get('woocommerce.logger.woocommerce');
|
||||||
|
/**
|
||||||
|
* @var SessionHandler $sessionHandler
|
||||||
|
*/
|
||||||
|
$sessionHandler = $container->get('session.handler');
|
||||||
|
$bnCode = $sessionHandler->bnCode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Settings $settings
|
||||||
|
*/
|
||||||
|
$settings = $container->get('wcgateway.settings');
|
||||||
|
$intent = $settings->has('intent') && strtoupper((string) $settings->get('intent')) === 'AUTHORIZE' ? 'AUTHORIZE' : 'CAPTURE';
|
||||||
|
$applicationContextRepository = $container->get('api.repository.application-context');
|
||||||
|
return new OrderEndpoint(
|
||||||
|
$container->get('api.host'),
|
||||||
|
$container->get('api.bearer'),
|
||||||
|
$orderFactory,
|
||||||
|
$patchCollectionFactory,
|
||||||
|
$intent,
|
||||||
|
$logger,
|
||||||
|
$applicationContextRepository,
|
||||||
|
$bnCode
|
||||||
|
);
|
||||||
|
},
|
||||||
'woocommerce.logger.woocommerce' => function (ContainerInterface $container): LoggerInterface {
|
'woocommerce.logger.woocommerce' => function (ContainerInterface $container): LoggerInterface {
|
||||||
$settings = $container->get('wcgateway.settings');
|
$settings = $container->get('wcgateway.settings');
|
||||||
if (! $settings->has('logging_enabled') || ! $settings->get('logging_enabled')) {
|
if (! $settings->has('logging_enabled') || ! $settings->get('logging_enabled')) {
|
||||||
|
|
123
tests/PHPUnit/Button/Helper/ThreeDSecureTest.php
Normal file
123
tests/PHPUnit/Button/Helper/ThreeDSecureTest.php
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Inpsyde\PayPalCommerce\Button\Helper;
|
||||||
|
|
||||||
|
|
||||||
|
use Inpsyde\PayPalCommerce\ApiClient\Entity\CardAuthenticationResult;
|
||||||
|
use Inpsyde\PayPalCommerce\ApiClient\Entity\Order;
|
||||||
|
use Inpsyde\PayPalCommerce\ApiClient\Entity\PaymentSource;
|
||||||
|
use Inpsyde\PayPalCommerce\ApiClient\Entity\PaymentSourceCard;
|
||||||
|
use Inpsyde\PayPalCommerce\TestCase;
|
||||||
|
use Mockery\Mock;
|
||||||
|
|
||||||
|
class ThreeDSecureTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataForTestDefault
|
||||||
|
* @param Order $order
|
||||||
|
* @param int $expected
|
||||||
|
*/
|
||||||
|
public function testDefault(int $expected, string $liabilityShift, string $authenticationResult, string $enrollment)
|
||||||
|
{
|
||||||
|
$result = \Mockery::mock(CardAuthenticationResult::class);
|
||||||
|
$result->shouldReceive('liabilityShift')->andReturn($liabilityShift);
|
||||||
|
$result->shouldReceive('authenticationResult')->andReturn($authenticationResult);
|
||||||
|
$result->shouldReceive('enrollmentStatus')->andReturn($enrollment);
|
||||||
|
$card = \Mockery::mock(PaymentSourceCard::class);
|
||||||
|
$card->shouldReceive('authenticationResult')->andReturn($result);
|
||||||
|
$source = \Mockery::mock(PaymentSource::class);
|
||||||
|
$source->shouldReceive('card')->andReturn($card);
|
||||||
|
$order = \Mockery::mock(Order::class);
|
||||||
|
$order->shouldReceive('paymentSource')->andReturn($source);
|
||||||
|
$testee = new ThreeDSecure();
|
||||||
|
$result = $testee->proceedWithOrder($order);
|
||||||
|
$this->assertEquals($expected, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataForTestDefault() : array
|
||||||
|
{
|
||||||
|
$matrix = [
|
||||||
|
'test_1' => [
|
||||||
|
ThreeDSecure::PROCCEED,
|
||||||
|
CardAuthenticationResult::LIABILITY_SHIFT_POSSIBLE,
|
||||||
|
CardAuthenticationResult::AUTHENTICATION_RESULT_YES,
|
||||||
|
CardAuthenticationResult::ENROLLMENT_STATUS_YES,
|
||||||
|
],
|
||||||
|
'test_2' => [
|
||||||
|
ThreeDSecure::REJECT,
|
||||||
|
CardAuthenticationResult::LIABILITY_SHIFT_NO,
|
||||||
|
CardAuthenticationResult::AUTHENTICATION_RESULT_NO,
|
||||||
|
CardAuthenticationResult::ENROLLMENT_STATUS_YES,
|
||||||
|
],
|
||||||
|
'test_3' => [
|
||||||
|
ThreeDSecure::REJECT,
|
||||||
|
CardAuthenticationResult::LIABILITY_SHIFT_NO,
|
||||||
|
CardAuthenticationResult::AUTHENTICATION_RESULT_REJECTED,
|
||||||
|
CardAuthenticationResult::ENROLLMENT_STATUS_YES,
|
||||||
|
],
|
||||||
|
'test_4' => [
|
||||||
|
ThreeDSecure::PROCCEED,
|
||||||
|
CardAuthenticationResult::LIABILITY_SHIFT_POSSIBLE,
|
||||||
|
CardAuthenticationResult::AUTHENTICATION_RESULT_ATTEMPTED,
|
||||||
|
CardAuthenticationResult::ENROLLMENT_STATUS_YES,
|
||||||
|
],
|
||||||
|
'test_5' => [
|
||||||
|
ThreeDSecure::RETRY,
|
||||||
|
CardAuthenticationResult::LIABILITY_SHIFT_UNKNOWN,
|
||||||
|
CardAuthenticationResult::AUTHENTICATION_RESULT_UNABLE,
|
||||||
|
CardAuthenticationResult::ENROLLMENT_STATUS_YES,
|
||||||
|
],
|
||||||
|
'test_6' => [
|
||||||
|
ThreeDSecure::RETRY,
|
||||||
|
CardAuthenticationResult::LIABILITY_SHIFT_NO,
|
||||||
|
CardAuthenticationResult::AUTHENTICATION_RESULT_UNABLE,
|
||||||
|
CardAuthenticationResult::ENROLLMENT_STATUS_YES,
|
||||||
|
],
|
||||||
|
'test_7' => [
|
||||||
|
ThreeDSecure::RETRY,
|
||||||
|
CardAuthenticationResult::LIABILITY_SHIFT_UNKNOWN,
|
||||||
|
CardAuthenticationResult::AUTHENTICATION_RESULT_CHALLENGE_REQUIRED,
|
||||||
|
CardAuthenticationResult::ENROLLMENT_STATUS_YES,
|
||||||
|
],
|
||||||
|
'test_8' => [
|
||||||
|
ThreeDSecure::RETRY,
|
||||||
|
CardAuthenticationResult::LIABILITY_SHIFT_NO,
|
||||||
|
'',
|
||||||
|
CardAuthenticationResult::ENROLLMENT_STATUS_YES,
|
||||||
|
],
|
||||||
|
'test_9' => [
|
||||||
|
ThreeDSecure::PROCCEED,
|
||||||
|
CardAuthenticationResult::LIABILITY_SHIFT_NO,
|
||||||
|
'',
|
||||||
|
CardAuthenticationResult::ENROLLMENT_STATUS_NO,
|
||||||
|
],
|
||||||
|
'test_10' => [
|
||||||
|
ThreeDSecure::PROCCEED,
|
||||||
|
CardAuthenticationResult::LIABILITY_SHIFT_NO,
|
||||||
|
'',
|
||||||
|
CardAuthenticationResult::ENROLLMENT_STATUS_UNAVAILABLE,
|
||||||
|
],
|
||||||
|
'test_11' => [
|
||||||
|
ThreeDSecure::RETRY,
|
||||||
|
CardAuthenticationResult::LIABILITY_SHIFT_UNKNOWN,
|
||||||
|
'',
|
||||||
|
CardAuthenticationResult::ENROLLMENT_STATUS_UNAVAILABLE,
|
||||||
|
],
|
||||||
|
'test_12' => [
|
||||||
|
ThreeDSecure::PROCCEED,
|
||||||
|
CardAuthenticationResult::LIABILITY_SHIFT_NO,
|
||||||
|
'',
|
||||||
|
CardAuthenticationResult::ENROLLMENT_STATUS_BYPASS,
|
||||||
|
],
|
||||||
|
'test_13' => [
|
||||||
|
ThreeDSecure::RETRY,
|
||||||
|
CardAuthenticationResult::LIABILITY_SHIFT_UNKNOWN,
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
return $matrix;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue