mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 13:44:42 +08:00
Merge branch 'trunk' into fix/PCP-1713_update_wroding_preview_button
This commit is contained in:
commit
cce7709330
27 changed files with 273 additions and 471 deletions
|
@ -13,20 +13,20 @@ BLOCK_CART_URL="/cart-block"
|
||||||
PRODUCT_URL="/product/prod"
|
PRODUCT_URL="/product/prod"
|
||||||
PRODUCT_ID=123
|
PRODUCT_ID=123
|
||||||
|
|
||||||
|
SUBSCRIPTION_URL="/product/sub"
|
||||||
|
|
||||||
WP_MERCHANT_USER="admin"
|
WP_MERCHANT_USER="admin"
|
||||||
WP_MERCHANT_PASSWORD="admin"
|
WP_MERCHANT_PASSWORD="admin"
|
||||||
MERCHANT_USER="merchant"
|
|
||||||
MERCHANT_PASSWORD="merchant"
|
|
||||||
|
|
||||||
WP_CUSTOMER_USER="customer"
|
WP_CUSTOMER_USER="customer"
|
||||||
WP_CUSTOMER_PASSWORD="password"
|
WP_CUSTOMER_PASSWORD="password"
|
||||||
|
|
||||||
CUSTOMER_EMAIL="customer@example.com"
|
CUSTOMER_EMAIL="customer@example.com"
|
||||||
CUSTOMER_PASSWORD="password"
|
CUSTOMER_PASSWORD="password"
|
||||||
CUSTOMER_FIRST_NAME="first"
|
CUSTOMER_FIRST_NAME="John"
|
||||||
CUSTOMER_LAST_NAME="last"
|
CUSTOMER_LAST_NAME="Doe"
|
||||||
CUSTOMER_COUNTRY="country"
|
CUSTOMER_COUNTRY="DE"
|
||||||
CUSTOMER_ADDRESS="address"
|
CUSTOMER_ADDRESS="street 1"
|
||||||
CUSTOMER_POSTCODE="12345"
|
CUSTOMER_POSTCODE="12345"
|
||||||
CUSTOMER_CITY="city"
|
CUSTOMER_CITY="city"
|
||||||
CUSTOMER_PHONE="1234567890"
|
CUSTOMER_PHONE="1234567890"
|
||||||
|
|
|
@ -93,7 +93,7 @@ const PayPalComponent = ({
|
||||||
throw new Error(config.scriptData.labels.error.generic)
|
throw new Error(config.scriptData.labels.error.generic)
|
||||||
}
|
}
|
||||||
|
|
||||||
const order = json.data;
|
const order = await actions.order.get();
|
||||||
|
|
||||||
setPaypalOrder(order);
|
setPaypalOrder(order);
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ class CheckoutActionHandler {
|
||||||
const input = document.createElement('input');
|
const input = document.createElement('input');
|
||||||
input.setAttribute('type', 'hidden');
|
input.setAttribute('type', 'hidden');
|
||||||
input.setAttribute('name', 'ppcp-resume-order');
|
input.setAttribute('name', 'ppcp-resume-order');
|
||||||
input.setAttribute('value', data.data.purchase_units[0].custom_id);
|
input.setAttribute('value', data.data.custom_id);
|
||||||
document.querySelector(formSelector).appendChild(input);
|
document.querySelector(formSelector).appendChild(input);
|
||||||
return data.data.id;
|
return data.data.id;
|
||||||
});
|
});
|
||||||
|
|
|
@ -180,7 +180,7 @@ class ApproveOrderEndpoint implements EndpointInterface {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$this->session_handler->replace_order( $order );
|
$this->session_handler->replace_order( $order );
|
||||||
wp_send_json_success( $order->to_array() );
|
wp_send_json_success();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $this->order_helper->contains_physical_goods( $order ) && ! $order->status()->is( OrderStatus::APPROVED ) && ! $order->status()->is( OrderStatus::CREATED ) ) {
|
if ( $this->order_helper->contains_physical_goods( $order ) && ! $order->status()->is( OrderStatus::APPROVED ) && ! $order->status()->is( OrderStatus::CREATED ) ) {
|
||||||
|
@ -198,7 +198,7 @@ class ApproveOrderEndpoint implements EndpointInterface {
|
||||||
$this->session_handler->replace_funding_source( $funding_source );
|
$this->session_handler->replace_funding_source( $funding_source );
|
||||||
|
|
||||||
$this->session_handler->replace_order( $order );
|
$this->session_handler->replace_order( $order );
|
||||||
wp_send_json_success( $order->to_array() );
|
wp_send_json_success();
|
||||||
return true;
|
return true;
|
||||||
} catch ( Exception $error ) {
|
} catch ( Exception $error ) {
|
||||||
$this->logger->error( 'Order approve failed: ' . $error->getMessage() );
|
$this->logger->error( 'Order approve failed: ' . $error->getMessage() );
|
||||||
|
|
|
@ -88,7 +88,7 @@ class ApproveSubscriptionEndpoint implements EndpointInterface {
|
||||||
WC()->session->set( 'ppcp_subscription_id', $data['subscription_id'] );
|
WC()->session->set( 'ppcp_subscription_id', $data['subscription_id'] );
|
||||||
}
|
}
|
||||||
|
|
||||||
wp_send_json_success( $order );
|
wp_send_json_success();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -292,7 +292,7 @@ class CreateOrderEndpoint implements EndpointInterface {
|
||||||
! $this->early_order_handler->should_create_early_order()
|
! $this->early_order_handler->should_create_early_order()
|
||||||
|| $this->registration_needed
|
|| $this->registration_needed
|
||||||
|| isset( $data['createaccount'] ) && '1' === $data['createaccount'] ) {
|
|| isset( $data['createaccount'] ) && '1' === $data['createaccount'] ) {
|
||||||
wp_send_json_success( $order->to_array() );
|
wp_send_json_success( $this->make_response( $order ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->early_order_handler->register_for_order( $order );
|
$this->early_order_handler->register_for_order( $order );
|
||||||
|
@ -304,7 +304,7 @@ class CreateOrderEndpoint implements EndpointInterface {
|
||||||
$wc_order->save_meta_data();
|
$wc_order->save_meta_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
wp_send_json_success( $order->to_array() );
|
wp_send_json_success( $this->make_response( $order ) );
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} catch ( ValidationException $error ) {
|
} catch ( ValidationException $error ) {
|
||||||
|
@ -362,7 +362,7 @@ class CreateOrderEndpoint implements EndpointInterface {
|
||||||
* during the "onApprove"-JS callback or the webhook listener.
|
* during the "onApprove"-JS callback or the webhook listener.
|
||||||
*/
|
*/
|
||||||
if ( ! $this->early_order_handler->should_create_early_order() ) {
|
if ( ! $this->early_order_handler->should_create_early_order() ) {
|
||||||
wp_send_json_success( $order->to_array() );
|
wp_send_json_success( $this->make_response( $order ) );
|
||||||
}
|
}
|
||||||
$this->early_order_handler->register_for_order( $order );
|
$this->early_order_handler->register_for_order( $order );
|
||||||
return $data;
|
return $data;
|
||||||
|
@ -569,4 +569,17 @@ class CreateOrderEndpoint implements EndpointInterface {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the response data for success response.
|
||||||
|
*
|
||||||
|
* @param Order $order The PayPal order.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function make_response( Order $order ): array {
|
||||||
|
return array(
|
||||||
|
'id' => $order->id(),
|
||||||
|
'custom_id' => $order->purchase_units()[0]->custom_id(),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,6 +123,11 @@ class LoginSellerEndpoint implements EndpointInterface {
|
||||||
public function handle_request(): bool {
|
public function handle_request(): bool {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
||||||
|
wp_send_json_error( 'Not admin.', 403 );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$data = $this->request_data->read_request( $this->nonce() );
|
$data = $this->request_data->read_request( $this->nonce() );
|
||||||
$is_sandbox = isset( $data['env'] ) && 'sandbox' === $data['env'];
|
$is_sandbox = isset( $data['env'] ) && 'sandbox' === $data['env'];
|
||||||
$this->settings->set( 'sandbox_on', $is_sandbox );
|
$this->settings->set( 'sandbox_on', $is_sandbox );
|
||||||
|
|
|
@ -107,6 +107,11 @@ class PayUponInvoiceEndpoint implements EndpointInterface {
|
||||||
* @throws NotFoundException When order not found or handling failed.
|
* @throws NotFoundException When order not found or handling failed.
|
||||||
*/
|
*/
|
||||||
public function handle_request(): bool {
|
public function handle_request(): bool {
|
||||||
|
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
||||||
|
wp_send_json_error( 'Not admin.', 403 );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$signup_links = array();
|
$signup_links = array();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -85,6 +85,11 @@ class OrderTrackingEndpoint {
|
||||||
* Handles the request.
|
* Handles the request.
|
||||||
*/
|
*/
|
||||||
public function handle_request(): void {
|
public function handle_request(): void {
|
||||||
|
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
||||||
|
wp_send_json_error( 'Not admin.', 403 );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$data = $this->request_data->read_request( $this->nonce() );
|
$data = $this->request_data->read_request( $this->nonce() );
|
||||||
$action = $data['action'];
|
$action = $data['action'];
|
||||||
|
|
|
@ -81,8 +81,14 @@ class UninstallModule implements ModuleInterface {
|
||||||
"wc_ajax_{$nonce}",
|
"wc_ajax_{$nonce}",
|
||||||
static function () use ( $request_data, $clear_db, $nonce, $option_names, $scheduled_action_names ) {
|
static function () use ( $request_data, $clear_db, $nonce, $option_names, $scheduled_action_names ) {
|
||||||
try {
|
try {
|
||||||
|
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
||||||
|
wp_send_json_error( 'Not admin.', 403 );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Validate nonce.
|
// Validate nonce.
|
||||||
$request_data->read_request( $nonce );
|
$request_data->read_request( $nonce );
|
||||||
|
|
||||||
$clear_db->delete_options( $option_names );
|
$clear_db->delete_options( $option_names );
|
||||||
$clear_db->clear_scheduled_actions( $scheduled_action_names );
|
$clear_db->clear_scheduled_actions( $scheduled_action_names );
|
||||||
|
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* WooCommerce Payment token for PayPal ACDC (Advanced Credit and Debit Card).
|
|
||||||
*
|
|
||||||
* @package WooCommerce\PayPalCommerce\Vaulting
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace WooCommerce\PayPalCommerce\Vaulting;
|
|
||||||
|
|
||||||
use WC_Payment_Token;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class PaymentTokenACDC
|
|
||||||
*/
|
|
||||||
class PaymentTokenACDC extends WC_Payment_Token {
|
|
||||||
/**
|
|
||||||
* Token Type String.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $type = 'ACDC';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores Credit Card payment token data.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
protected $extra_data = array(
|
|
||||||
'last4' => '',
|
|
||||||
'card_type' => '',
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the last four digits.
|
|
||||||
*
|
|
||||||
* @param string $context The context.
|
|
||||||
* @return mixed|null
|
|
||||||
*/
|
|
||||||
public function get_last4( $context = 'view' ) {
|
|
||||||
return $this->get_prop( 'last4', $context );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the last four digits.
|
|
||||||
*
|
|
||||||
* @param string $last4 Last four digits.
|
|
||||||
*/
|
|
||||||
public function set_last4( $last4 ) {
|
|
||||||
$this->set_prop( 'last4', $last4 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the card type (mastercard, visa, ...).
|
|
||||||
*
|
|
||||||
* @param string $context The context.
|
|
||||||
* @return string Card type
|
|
||||||
*/
|
|
||||||
public function get_card_type( $context = 'view' ) {
|
|
||||||
return $this->get_prop( 'card_type', $context );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the card type (mastercard, visa, ...).
|
|
||||||
*
|
|
||||||
* @param string $type Credit card type (mastercard, visa, ...).
|
|
||||||
*/
|
|
||||||
public function set_card_type( $type ) {
|
|
||||||
$this->set_prop( 'card_type', $type );
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -19,14 +19,12 @@ class PaymentTokenFactory {
|
||||||
*
|
*
|
||||||
* @param string $type The type of WC payment token.
|
* @param string $type The type of WC payment token.
|
||||||
*
|
*
|
||||||
* @return void|PaymentTokenACDC|PaymentTokenPayPal
|
* @return void|PaymentTokenPayPal
|
||||||
*/
|
*/
|
||||||
public function create( string $type ) {
|
public function create( string $type ) {
|
||||||
switch ( $type ) {
|
switch ( $type ) {
|
||||||
case 'paypal':
|
case 'paypal':
|
||||||
return new PaymentTokenPayPal();
|
return new PaymentTokenPayPal();
|
||||||
case 'acdc':
|
|
||||||
return new PaymentTokenACDC();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\Vaulting;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
use WC_Payment_Token_CC;
|
||||||
use WC_Payment_Tokens;
|
use WC_Payment_Tokens;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||||
|
@ -64,27 +65,26 @@ class PaymentTokensMigration {
|
||||||
* @param int $id WooCommerce customer id.
|
* @param int $id WooCommerce customer id.
|
||||||
*/
|
*/
|
||||||
public function migrate_payment_tokens_for_user( int $id ):void {
|
public function migrate_payment_tokens_for_user( int $id ):void {
|
||||||
$tokens = $this->payment_token_repository->all_for_user_id( $id );
|
$tokens = $this->payment_token_repository->all_for_user_id( $id );
|
||||||
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $id );
|
|
||||||
|
|
||||||
$total_tokens = count( $tokens );
|
$total_tokens = count( $tokens );
|
||||||
$this->logger->info( 'Migrating ' . (string) $total_tokens . ' tokens for user ' . (string) $id );
|
$this->logger->info( 'Migrating ' . (string) $total_tokens . ' tokens for user ' . (string) $id );
|
||||||
|
|
||||||
foreach ( $tokens as $token ) {
|
foreach ( $tokens as $token ) {
|
||||||
if ( $this->token_exist( $wc_tokens, $token ) ) {
|
|
||||||
$this->logger->info( 'Token already exist for user ' . (string) $id );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( isset( $token->source()->card ) ) {
|
if ( isset( $token->source()->card ) ) {
|
||||||
$payment_token_acdc = $this->payment_token_factory->create( 'acdc' );
|
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $id, CreditCardGateway::ID );
|
||||||
assert( $payment_token_acdc instanceof PaymentTokenACDC );
|
if ( $this->token_exist( $wc_tokens, $token ) ) {
|
||||||
|
$this->logger->info( 'Token already exist for user ' . (string) $id );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$payment_token_acdc = new WC_Payment_Token_CC();
|
||||||
$payment_token_acdc->set_token( $token->id() );
|
$payment_token_acdc->set_token( $token->id() );
|
||||||
$payment_token_acdc->set_user_id( $id );
|
$payment_token_acdc->set_user_id( $id );
|
||||||
$payment_token_acdc->set_gateway_id( CreditCardGateway::ID );
|
$payment_token_acdc->set_gateway_id( CreditCardGateway::ID );
|
||||||
$payment_token_acdc->set_last4( $token->source()->card->last_digits );
|
$payment_token_acdc->set_last4( $token->source()->card->last_digits );
|
||||||
$payment_token_acdc->set_card_type( $token->source()->card->brand );
|
$payment_token_acdc->set_card_type( $token->source()->card->brand );
|
||||||
|
$payment_token_acdc->set_expiry_year( '0000' );
|
||||||
|
$payment_token_acdc->set_expiry_month( '00' );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$payment_token_acdc->save();
|
$payment_token_acdc->save();
|
||||||
|
@ -96,6 +96,12 @@ class PaymentTokensMigration {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} elseif ( $token->source()->paypal ) {
|
} elseif ( $token->source()->paypal ) {
|
||||||
|
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $id, PayPalGateway::ID );
|
||||||
|
if ( $this->token_exist( $wc_tokens, $token ) ) {
|
||||||
|
$this->logger->info( 'Token already exist for user ' . (string) $id );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$payment_token_paypal = $this->payment_token_factory->create( 'paypal' );
|
$payment_token_paypal = $this->payment_token_factory->create( 'paypal' );
|
||||||
assert( $payment_token_paypal instanceof PaymentTokenPayPal );
|
assert( $payment_token_paypal instanceof PaymentTokenPayPal );
|
||||||
|
|
||||||
|
|
|
@ -88,10 +88,6 @@ class VaultingModule implements ModuleInterface {
|
||||||
* @psalm-suppress MissingClosureParamType
|
* @psalm-suppress MissingClosureParamType
|
||||||
*/
|
*/
|
||||||
function ( $type ) {
|
function ( $type ) {
|
||||||
if ( $type === 'WC_Payment_Token_ACDC' ) {
|
|
||||||
return PaymentTokenACDC::class;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $type === 'WC_Payment_Token_PayPal' ) {
|
if ( $type === 'WC_Payment_Token_PayPal' ) {
|
||||||
return PaymentTokenPayPal::class;
|
return PaymentTokenPayPal::class;
|
||||||
}
|
}
|
||||||
|
@ -112,13 +108,6 @@ class VaultingModule implements ModuleInterface {
|
||||||
return $item;
|
return $item;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( strtolower( $payment_token->get_type() ) === 'acdc' ) {
|
|
||||||
assert( $payment_token instanceof PaymentTokenACDC );
|
|
||||||
$item['method']['brand'] = $payment_token->get_card_type() . ' ...' . $payment_token->get_last4();
|
|
||||||
|
|
||||||
return $item;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( strtolower( $payment_token->get_type() ) === 'paypal' ) {
|
if ( strtolower( $payment_token->get_type() ) === 'paypal' ) {
|
||||||
assert( $payment_token instanceof PaymentTokenPayPal );
|
assert( $payment_token instanceof PaymentTokenPayPal );
|
||||||
$item['method']['brand'] = $payment_token->get_email();
|
$item['method']['brand'] = $payment_token->get_email();
|
||||||
|
|
|
@ -40,7 +40,6 @@ use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\GatewayRepository;
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\GatewayRepository;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\OXXO\OXXO;
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\OXXO\OXXO;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\OXXO\OXXOEndpoint;
|
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\OXXO\OXXOGateway;
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\OXXO\OXXOGateway;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\FraudNet\FraudNet;
|
use WooCommerce\PayPalCommerce\WcGateway\FraudNet\FraudNet;
|
||||||
|
@ -1076,15 +1075,6 @@ return array(
|
||||||
$container->get( 'woocommerce.logger.woocommerce' )
|
$container->get( 'woocommerce.logger.woocommerce' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'wcgateway.endpoint.oxxo' => static function ( ContainerInterface $container ): OXXOEndpoint {
|
|
||||||
return new OXXOEndpoint(
|
|
||||||
$container->get( 'button.request-data' ),
|
|
||||||
$container->get( 'api.endpoint.order' ),
|
|
||||||
$container->get( 'api.factory.purchase-unit' ),
|
|
||||||
$container->get( 'api.factory.shipping-preference' ),
|
|
||||||
$container->get( 'woocommerce.logger.woocommerce' )
|
|
||||||
);
|
|
||||||
},
|
|
||||||
'wcgateway.logging.is-enabled' => function ( ContainerInterface $container ) : bool {
|
'wcgateway.logging.is-enabled' => function ( ContainerInterface $container ) : bool {
|
||||||
$settings = $container->get( 'wcgateway.settings' );
|
$settings = $container->get( 'wcgateway.settings' );
|
||||||
|
|
||||||
|
|
|
@ -228,24 +228,5 @@ class OXXO {
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
wp_localize_script(
|
|
||||||
'ppcp-oxxo',
|
|
||||||
'OXXOConfig',
|
|
||||||
array(
|
|
||||||
'oxxo_endpoint' => \WC_AJAX::get_endpoint( 'ppc-oxxo' ),
|
|
||||||
'oxxo_nonce' => wp_create_nonce( 'ppc-oxxo' ),
|
|
||||||
'error' => array(
|
|
||||||
'generic' => __(
|
|
||||||
'Something went wrong. Please try again or choose another payment source.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
'js_validation' => __(
|
|
||||||
'Required form fields are not filled or invalid.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,156 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Handles OXXO payer action.
|
|
||||||
*
|
|
||||||
* @package WooCommerce\PayPalCommerce\Onboarding\Endpoint
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace WooCommerce\PayPalCommerce\WcGateway\Gateway\OXXO;
|
|
||||||
|
|
||||||
use Psr\Log\LoggerInterface;
|
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingPreferenceFactory;
|
|
||||||
use WooCommerce\PayPalCommerce\Button\Endpoint\EndpointInterface;
|
|
||||||
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OXXOEndpoint constructor.
|
|
||||||
*/
|
|
||||||
class OXXOEndpoint implements EndpointInterface {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The request data
|
|
||||||
*
|
|
||||||
* @var RequestData
|
|
||||||
*/
|
|
||||||
protected $request_data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The purchase unit factory.
|
|
||||||
*
|
|
||||||
* @var PurchaseUnitFactory
|
|
||||||
*/
|
|
||||||
protected $purchase_unit_factory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The shipping preference factory.
|
|
||||||
*
|
|
||||||
* @var ShippingPreferenceFactory
|
|
||||||
*/
|
|
||||||
protected $shipping_preference_factory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The order endpoint.
|
|
||||||
*
|
|
||||||
* @var OrderEndpoint
|
|
||||||
*/
|
|
||||||
protected $order_endpoint;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The logger.
|
|
||||||
*
|
|
||||||
* @var LoggerInterface
|
|
||||||
*/
|
|
||||||
protected $logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OXXOEndpoint constructor
|
|
||||||
*
|
|
||||||
* @param RequestData $request_data The request data.
|
|
||||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
|
||||||
* @param PurchaseUnitFactory $purchase_unit_factory The purchase unit factory.
|
|
||||||
* @param ShippingPreferenceFactory $shipping_preference_factory The shipping preference factory.
|
|
||||||
* @param LoggerInterface $logger The logger.
|
|
||||||
*/
|
|
||||||
public function __construct(
|
|
||||||
RequestData $request_data,
|
|
||||||
OrderEndpoint $order_endpoint,
|
|
||||||
PurchaseUnitFactory $purchase_unit_factory,
|
|
||||||
ShippingPreferenceFactory $shipping_preference_factory,
|
|
||||||
LoggerInterface $logger
|
|
||||||
) {
|
|
||||||
$this->request_data = $request_data;
|
|
||||||
$this->purchase_unit_factory = $purchase_unit_factory;
|
|
||||||
$this->shipping_preference_factory = $shipping_preference_factory;
|
|
||||||
$this->order_endpoint = $order_endpoint;
|
|
||||||
$this->logger = $logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The nonce
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public static function nonce(): string {
|
|
||||||
return 'ppc-oxxo';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the request.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function handle_request(): bool {
|
|
||||||
$purchase_unit = $this->purchase_unit_factory->from_wc_cart();
|
|
||||||
$payer_action = '';
|
|
||||||
|
|
||||||
try {
|
|
||||||
$shipping_preference = $this->shipping_preference_factory->from_state(
|
|
||||||
$purchase_unit,
|
|
||||||
'checkout'
|
|
||||||
);
|
|
||||||
|
|
||||||
$order = $this->order_endpoint->create( array( $purchase_unit ), $shipping_preference );
|
|
||||||
|
|
||||||
$payment_source = array(
|
|
||||||
'oxxo' => array(
|
|
||||||
'name' => 'John Doe',
|
|
||||||
'email' => 'foo@bar.com',
|
|
||||||
'country_code' => 'MX',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
$payment_method = $this->order_endpoint->confirm_payment_source( $order->id(), $payment_source );
|
|
||||||
|
|
||||||
foreach ( $payment_method->links as $link ) {
|
|
||||||
if ( $link->rel === 'payer-action' ) {
|
|
||||||
$payer_action = $link->href;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch ( RuntimeException $exception ) {
|
|
||||||
$error = $exception->getMessage();
|
|
||||||
|
|
||||||
if ( is_a( $exception, PayPalApiException::class ) && is_array( $exception->details() ) ) {
|
|
||||||
$details = '';
|
|
||||||
foreach ( $exception->details() as $detail ) {
|
|
||||||
$issue = $detail->issue ?? '';
|
|
||||||
$field = $detail->field ?? '';
|
|
||||||
$description = $detail->description ?? '';
|
|
||||||
$details .= $issue . ' ' . $field . ' ' . $description . '<br>';
|
|
||||||
}
|
|
||||||
|
|
||||||
$error = $details;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->logger->error( $error );
|
|
||||||
wc_add_notice( $error, 'error' );
|
|
||||||
|
|
||||||
wp_send_json_error( 'Could not get OXXO payer action.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
WC()->session->set( 'ppcp_payer_action', $payer_action );
|
|
||||||
|
|
||||||
wp_send_json_success(
|
|
||||||
array( 'payer_action' => $payer_action )
|
|
||||||
);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -323,14 +323,6 @@ class WCGatewayModule implements ModuleInterface {
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
|
|
||||||
add_action(
|
|
||||||
'wc_ajax_ppc-oxxo',
|
|
||||||
static function () use ( $c ) {
|
|
||||||
$endpoint = $c->get( 'wcgateway.endpoint.oxxo' );
|
|
||||||
$endpoint->handle_request();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
add_action(
|
add_action(
|
||||||
'woocommerce_order_status_changed',
|
'woocommerce_order_status_changed',
|
||||||
static function ( int $order_id, string $from, string $to ) use ( $c ) {
|
static function ( int $order_id, string $from, string $to ) use ( $c ) {
|
||||||
|
|
|
@ -58,6 +58,11 @@ class ResubscribeEndpoint {
|
||||||
* Handles the incoming request.
|
* Handles the incoming request.
|
||||||
*/
|
*/
|
||||||
public function handle_request() {
|
public function handle_request() {
|
||||||
|
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
||||||
|
wp_send_json_error( 'Not admin.', 403 );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Validate nonce.
|
// Validate nonce.
|
||||||
$this->request_data->read_request( $this->nonce() );
|
$this->request_data->read_request( $this->nonce() );
|
||||||
|
|
|
@ -61,6 +61,11 @@ class SimulateEndpoint {
|
||||||
* Handles the incoming request.
|
* Handles the incoming request.
|
||||||
*/
|
*/
|
||||||
public function handle_request() {
|
public function handle_request() {
|
||||||
|
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
||||||
|
wp_send_json_error( 'Not admin.', 403 );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Validate nonce.
|
// Validate nonce.
|
||||||
$this->request_data->read_request( $this->nonce() );
|
$this->request_data->read_request( $this->nonce() );
|
||||||
|
|
|
@ -51,6 +51,11 @@ class SimulationStateEndpoint {
|
||||||
* Handles the incoming request.
|
* Handles the incoming request.
|
||||||
*/
|
*/
|
||||||
public function handle_request() {
|
public function handle_request() {
|
||||||
|
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
||||||
|
wp_send_json_error( 'Not admin.', 403 );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$state = $this->simulation->get_state();
|
$state = $this->simulation->get_state();
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
const {test, expect} = require('@playwright/test');
|
const {test, expect} = require('@playwright/test');
|
||||||
const {serverExec} = require("./utils/server");
|
const {serverExec} = require("./utils/server");
|
||||||
|
const {fillCheckoutForm, expectOrderReceivedPage} = require("./utils/checkout");
|
||||||
|
const {openPaypalPopup, loginIntoPaypal, waitForPaypalShippingList, completePaypalPayment} = require("./utils/paypal-popup");
|
||||||
|
|
||||||
const {
|
const {
|
||||||
CUSTOMER_EMAIL,
|
|
||||||
CUSTOMER_PASSWORD,
|
|
||||||
CREDIT_CARD_NUMBER,
|
CREDIT_CARD_NUMBER,
|
||||||
CREDIT_CARD_EXPIRATION,
|
CREDIT_CARD_EXPIRATION,
|
||||||
CREDIT_CARD_CVV,
|
CREDIT_CARD_CVV,
|
||||||
|
@ -11,81 +11,11 @@ const {
|
||||||
PRODUCT_ID,
|
PRODUCT_ID,
|
||||||
CHECKOUT_URL,
|
CHECKOUT_URL,
|
||||||
CHECKOUT_PAGE_ID,
|
CHECKOUT_PAGE_ID,
|
||||||
CART_URL,
|
|
||||||
BLOCK_CHECKOUT_URL,
|
BLOCK_CHECKOUT_URL,
|
||||||
BLOCK_CHECKOUT_PAGE_ID,
|
BLOCK_CHECKOUT_PAGE_ID,
|
||||||
BLOCK_CART_URL,
|
BLOCK_CART_URL,
|
||||||
} = process.env;
|
} = process.env;
|
||||||
|
|
||||||
async function fillCheckoutForm(page) {
|
|
||||||
await page.fill('#billing_first_name', 'John');
|
|
||||||
await page.fill('#billing_last_name', 'Doe');
|
|
||||||
await page.selectOption('select#billing_country', 'DE');
|
|
||||||
await page.fill('#billing_address_1', 'Badensche Str. 24');
|
|
||||||
await page.fill('#billing_postcode', '10715');
|
|
||||||
await page.fill('#billing_city', '10715');
|
|
||||||
await page.fill('#billing_phone', '1234567890');
|
|
||||||
await page.fill('#billing_email', CUSTOMER_EMAIL);
|
|
||||||
|
|
||||||
const differentShippingLocator = page.locator('[name="ship_to_different_address"]');
|
|
||||||
if (await differentShippingLocator.count() > 0) {
|
|
||||||
await differentShippingLocator.uncheck();
|
|
||||||
}
|
|
||||||
|
|
||||||
const termsLocator = page.locator('[name="terms"]');
|
|
||||||
if (await termsLocator.count() > 0) {
|
|
||||||
await termsLocator.check();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function openPaypalPopup(page, retry = true) {
|
|
||||||
try {
|
|
||||||
await page.locator('.component-frame').scrollIntoViewIfNeeded();
|
|
||||||
|
|
||||||
const [popup] = await Promise.all([
|
|
||||||
page.waitForEvent('popup', {timeout: 5000}),
|
|
||||||
page.frameLocator('.component-frame').locator('[data-funding-source="paypal"]').click(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
await popup.waitForLoadState();
|
|
||||||
|
|
||||||
return popup;
|
|
||||||
} catch (err) {
|
|
||||||
if (retry) {
|
|
||||||
return openPaypalPopup(page, false);
|
|
||||||
}
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loginIntoPaypal(popup) {
|
|
||||||
await Promise.any([
|
|
||||||
popup.locator('[name="login_email"]'),
|
|
||||||
popup.click("text=Log in"),
|
|
||||||
]);
|
|
||||||
|
|
||||||
await popup.fill('[name="login_email"]', CUSTOMER_EMAIL);
|
|
||||||
await popup.locator('#btnNext').click();
|
|
||||||
await popup.fill('[name="login_password"]', CUSTOMER_PASSWORD);
|
|
||||||
await popup.locator('#btnLogin').click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function waitForPaypalShippingList(popup) {
|
|
||||||
await expect(popup.locator('#shippingMethodsDropdown')).toBeVisible({timeout: 15000});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function completePaypalPayment(popup) {
|
|
||||||
await Promise.all([
|
|
||||||
popup.waitForEvent('close', {timeout: 20000}),
|
|
||||||
popup.click('#payment-submit-btn'),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function expectOrderReceivedPage(page) {
|
|
||||||
const title = await page.locator('.entry-title');
|
|
||||||
await expect(title).toHaveText('Order received');
|
|
||||||
}
|
|
||||||
|
|
||||||
async function completeBlockContinuation(page) {
|
async function completeBlockContinuation(page) {
|
||||||
await expect(page.locator('#radio-control-wc-payment-method-options-ppcp-gateway')).toBeChecked();
|
await expect(page.locator('#radio-control-wc-payment-method-options-ppcp-gateway')).toBeChecked();
|
||||||
|
|
||||||
|
|
|
@ -1,36 +1,34 @@
|
||||||
const {test, expect} = require('@playwright/test');
|
const {test, expect} = require('@playwright/test');
|
||||||
const {fillCheckoutForm, loginAsAdmin, loginAsCustomer} = require('./utils');
|
const {loginAsAdmin, loginAsCustomer} = require('./utils/user');
|
||||||
|
const {openPaypalPopup, loginIntoPaypal, completePaypalPayment} = require("./utils/paypal-popup");
|
||||||
|
const {fillCheckoutForm, expectOrderReceivedPage} = require("./utils/checkout");
|
||||||
const {
|
const {
|
||||||
AUTHORIZATION,
|
AUTHORIZATION,
|
||||||
CUSTOMER_EMAIL,
|
SUBSCRIPTION_URL,
|
||||||
CUSTOMER_PASSWORD
|
CHECKOUT_URL,
|
||||||
|
CART_URL,
|
||||||
} = process.env;
|
} = process.env;
|
||||||
|
|
||||||
async function purchaseSubscriptionFromCart(page) {
|
async function purchaseSubscriptionFromCart(page) {
|
||||||
await loginAsCustomer(page);
|
await loginAsCustomer(page);
|
||||||
await page.goto('/product/subscription');
|
await page.goto(SUBSCRIPTION_URL);
|
||||||
await page.click("text=Sign up now");
|
await page.click("text=Sign up now");
|
||||||
await page.goto('/cart');
|
await page.goto(CART_URL);
|
||||||
|
|
||||||
const [popup] = await Promise.all([
|
const popup = await openPaypalPopup(page);
|
||||||
page.waitForEvent('popup'),
|
await loginIntoPaypal(popup);
|
||||||
page.frameLocator('.component-frame').locator('[data-funding-source="paypal"]').click(),
|
|
||||||
]);
|
|
||||||
await popup.waitForLoadState();
|
|
||||||
|
|
||||||
await popup.fill('#email', CUSTOMER_EMAIL);
|
await popup.getByText('Continue', { exact: true }).click();
|
||||||
await popup.locator('#btnNext').click();
|
|
||||||
await popup.fill('#password', CUSTOMER_PASSWORD);
|
|
||||||
await popup.locator('#btnLogin').click();
|
|
||||||
await popup.locator('text=Continue').click();
|
|
||||||
await popup.locator('#confirmButtonTop').click();
|
await popup.locator('#confirmButtonTop').click();
|
||||||
|
|
||||||
await fillCheckoutForm(page);
|
await fillCheckoutForm(page);
|
||||||
|
|
||||||
await page.locator('text=Sign up now').click();
|
await Promise.all([
|
||||||
|
page.waitForNavigation(),
|
||||||
|
page.locator('text=Sign up now').click(),
|
||||||
|
]);
|
||||||
|
|
||||||
const title = page.locator('.entry-title');
|
await expectOrderReceivedPage(page);
|
||||||
await expect(title).toHaveText('Order received');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test.describe.serial('Subscriptions Merchant', () => {
|
test.describe.serial('Subscriptions Merchant', () => {
|
||||||
|
@ -203,53 +201,42 @@ test.describe('Subscriber purchase a Subscription', () => {
|
||||||
test('Purchase Subscription from Checkout Page', async ({page}) => {
|
test('Purchase Subscription from Checkout Page', async ({page}) => {
|
||||||
await loginAsCustomer(page);
|
await loginAsCustomer(page);
|
||||||
|
|
||||||
await page.goto('/product/subscription');
|
await page.goto(SUBSCRIPTION_URL);
|
||||||
await page.click("text=Sign up now");
|
await page.click("text=Sign up now");
|
||||||
await page.goto('/checkout');
|
await page.goto(CHECKOUT_URL);
|
||||||
await fillCheckoutForm(page);
|
await fillCheckoutForm(page);
|
||||||
|
|
||||||
const [popup] = await Promise.all([
|
const popup = await openPaypalPopup(page);
|
||||||
page.waitForEvent('popup'),
|
await loginIntoPaypal(popup);
|
||||||
page.frameLocator('.component-frame').locator('[data-funding-source="paypal"]').click(),
|
|
||||||
|
await popup.getByText('Continue', { exact: true }).click();
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
page.waitForNavigation(),
|
||||||
|
await popup.locator('text=Agree & Subscribe').click(),
|
||||||
]);
|
]);
|
||||||
await popup.waitForLoadState();
|
|
||||||
|
|
||||||
await popup.fill('#email', CUSTOMER_EMAIL);
|
await expectOrderReceivedPage(page);
|
||||||
await popup.locator('#btnNext').click();
|
|
||||||
await popup.fill('#password', CUSTOMER_PASSWORD);
|
|
||||||
await popup.locator('#btnLogin').click();
|
|
||||||
await popup.locator('text=Continue').click();
|
|
||||||
await popup.locator('text=Agree & Subscribe').click();
|
|
||||||
|
|
||||||
await page.waitForTimeout(10000);
|
|
||||||
|
|
||||||
const title = page.locator('.entry-title');
|
|
||||||
await expect(title).toHaveText('Order received');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Purchase Subscription from Single Product Page', async ({page}) => {
|
test('Purchase Subscription from Single Product Page', async ({page}) => {
|
||||||
await loginAsCustomer(page);
|
await loginAsCustomer(page);
|
||||||
await page.goto('/product/subscription');
|
await page.goto(SUBSCRIPTION_URL);
|
||||||
|
|
||||||
const [popup] = await Promise.all([
|
const popup = await openPaypalPopup(page);
|
||||||
page.waitForEvent('popup'),
|
await loginIntoPaypal(popup);
|
||||||
page.frameLocator('.component-frame').locator('[data-funding-source="paypal"]').click(),
|
|
||||||
]);
|
|
||||||
await popup.waitForLoadState();
|
|
||||||
|
|
||||||
await popup.fill('#email', CUSTOMER_EMAIL);
|
await popup.getByText('Continue', { exact: true }).click();
|
||||||
await popup.locator('#btnNext').click();
|
|
||||||
await popup.fill('#password', CUSTOMER_PASSWORD);
|
|
||||||
await popup.locator('#btnLogin').click();
|
|
||||||
await popup.locator('text=Continue').click();
|
|
||||||
await popup.locator('#confirmButtonTop').click();
|
await popup.locator('#confirmButtonTop').click();
|
||||||
|
|
||||||
await fillCheckoutForm(page);
|
await fillCheckoutForm(page);
|
||||||
|
|
||||||
await page.locator('text=Sign up now').click();
|
await Promise.all([
|
||||||
|
page.waitForNavigation(),
|
||||||
|
page.locator('text=Sign up now').click(),
|
||||||
|
]);
|
||||||
|
|
||||||
const title = page.locator('.entry-title');
|
await expectOrderReceivedPage(page);
|
||||||
await expect(title).toHaveText('Order received');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Purchase Subscription from Cart Page', async ({page}) => {
|
test('Purchase Subscription from Cart Page', async ({page}) => {
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
const {
|
|
||||||
WP_MERCHANT_USER,
|
|
||||||
WP_MERCHANT_PASSWORD,
|
|
||||||
WP_CUSTOMER_USER,
|
|
||||||
WP_CUSTOMER_PASSWORD,
|
|
||||||
CUSTOMER_EMAIL,
|
|
||||||
CUSTOMER_FIRST_NAME,
|
|
||||||
CUSTOMER_LAST_NAME,
|
|
||||||
CUSTOMER_COUNTRY,
|
|
||||||
CUSTOMER_ADDRESS,
|
|
||||||
CUSTOMER_POSTCODE,
|
|
||||||
CUSTOMER_CITY,
|
|
||||||
CUSTOMER_PHONE
|
|
||||||
} = process.env;
|
|
||||||
|
|
||||||
async function loginAsAdmin(page) {
|
|
||||||
await page.goto('/wp-admin');
|
|
||||||
await page.locator('input[name="log"]').fill(WP_MERCHANT_USER);
|
|
||||||
await page.locator('input[name="pwd"]').fill(WP_MERCHANT_PASSWORD);
|
|
||||||
await Promise.all([
|
|
||||||
page.waitForNavigation(),
|
|
||||||
page.locator('text=Log In').click()
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loginAsCustomer(page) {
|
|
||||||
await page.goto('/wp-admin');
|
|
||||||
await page.locator('input[name="log"]').fill(WP_CUSTOMER_USER);
|
|
||||||
await page.locator('input[name="pwd"]').fill(WP_CUSTOMER_PASSWORD);
|
|
||||||
await Promise.all([
|
|
||||||
page.waitForNavigation(),
|
|
||||||
page.locator('text=Log In').click()
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fillCheckoutForm(page) {
|
|
||||||
await page.fill('#billing_first_name', CUSTOMER_FIRST_NAME);
|
|
||||||
await page.fill('#billing_last_name', CUSTOMER_LAST_NAME);
|
|
||||||
await page.selectOption('select#billing_country', CUSTOMER_COUNTRY);
|
|
||||||
await page.fill('#billing_address_1', CUSTOMER_ADDRESS);
|
|
||||||
await page.fill('#billing_postcode', CUSTOMER_POSTCODE);
|
|
||||||
await page.fill('#billing_city', CUSTOMER_CITY);
|
|
||||||
await page.fill('#billing_phone', CUSTOMER_PHONE);
|
|
||||||
await page.fill('#billing_email', CUSTOMER_EMAIL);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {loginAsAdmin, loginAsCustomer, fillCheckoutForm};
|
|
38
tests/playwright/utils/checkout.js
Normal file
38
tests/playwright/utils/checkout.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import {expect} from "@playwright/test";
|
||||||
|
|
||||||
|
const {
|
||||||
|
CUSTOMER_EMAIL,
|
||||||
|
CUSTOMER_FIRST_NAME,
|
||||||
|
CUSTOMER_LAST_NAME,
|
||||||
|
CUSTOMER_COUNTRY,
|
||||||
|
CUSTOMER_ADDRESS,
|
||||||
|
CUSTOMER_POSTCODE,
|
||||||
|
CUSTOMER_CITY,
|
||||||
|
CUSTOMER_PHONE,
|
||||||
|
} = process.env;
|
||||||
|
|
||||||
|
export const fillCheckoutForm = async (page) => {
|
||||||
|
await page.fill('#billing_first_name', CUSTOMER_FIRST_NAME);
|
||||||
|
await page.fill('#billing_last_name', CUSTOMER_LAST_NAME);
|
||||||
|
await page.selectOption('select#billing_country', CUSTOMER_COUNTRY);
|
||||||
|
await page.fill('#billing_address_1', CUSTOMER_ADDRESS);
|
||||||
|
await page.fill('#billing_postcode', CUSTOMER_POSTCODE);
|
||||||
|
await page.fill('#billing_city', CUSTOMER_CITY);
|
||||||
|
await page.fill('#billing_phone', CUSTOMER_PHONE);
|
||||||
|
await page.fill('#billing_email', CUSTOMER_EMAIL);
|
||||||
|
|
||||||
|
const differentShippingLocator = page.locator('[name="ship_to_different_address"]');
|
||||||
|
if (await differentShippingLocator.count() > 0) {
|
||||||
|
await differentShippingLocator.uncheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
const termsLocator = page.locator('[name="terms"]');
|
||||||
|
if (await termsLocator.count() > 0) {
|
||||||
|
await termsLocator.check();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const expectOrderReceivedPage = async (page) => {
|
||||||
|
const title = await page.locator('.entry-title');
|
||||||
|
await expect(title).toHaveText('Order received');
|
||||||
|
}
|
91
tests/playwright/utils/paypal-popup.js
Normal file
91
tests/playwright/utils/paypal-popup.js
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
import {expect} from "@playwright/test";
|
||||||
|
|
||||||
|
const {
|
||||||
|
CUSTOMER_EMAIL,
|
||||||
|
CUSTOMER_PASSWORD,
|
||||||
|
} = process.env;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the PayPal popup by pressing the button, and returns the popup object.
|
||||||
|
* @param page
|
||||||
|
* @param {boolean} retry Retries the button click if the popup did not appear after timeout.
|
||||||
|
* @param {int} timeout
|
||||||
|
*/
|
||||||
|
export const openPaypalPopup = async (page, retry = true, timeout = 5000) => {
|
||||||
|
try {
|
||||||
|
await page.locator('.component-frame').scrollIntoViewIfNeeded();
|
||||||
|
|
||||||
|
const [popup] = await Promise.all([
|
||||||
|
page.waitForEvent('popup', {timeout}),
|
||||||
|
page.frameLocator('.component-frame').locator('[data-funding-source="paypal"]').click(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
await popup.waitForLoadState();
|
||||||
|
|
||||||
|
return popup;
|
||||||
|
} catch (err) {
|
||||||
|
try {
|
||||||
|
for (const f of page.mainFrame().childFrames()) {
|
||||||
|
if (f.name().startsWith('__paypal_checkout')) {
|
||||||
|
for (const f2 of f.childFrames()) {
|
||||||
|
if (f.name().includes('__paypal_checkout')) {
|
||||||
|
await f2.waitForLoadState();
|
||||||
|
await expect(await f2.locator('#main')).toBeVisible();
|
||||||
|
return f2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (frameErr) {
|
||||||
|
console.log(frameErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retry) {
|
||||||
|
return openPaypalPopup(page, false);
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const loginIntoPaypal = async (popup, retry = true) => {
|
||||||
|
await Promise.any([
|
||||||
|
popup.locator('[name="login_email"]'),
|
||||||
|
popup.click("text=Log in"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
await popup.fill('[name="login_email"]', CUSTOMER_EMAIL);
|
||||||
|
|
||||||
|
const nextButtonLocator = popup.locator('#btnNext');
|
||||||
|
// Sometimes we get a popup with email and password fields at the same screen
|
||||||
|
if (await nextButtonLocator.count() > 0) {
|
||||||
|
await nextButtonLocator.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await popup.fill('[name="login_password"]', CUSTOMER_PASSWORD, {timeout: 5000});
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Failed to fill password, possibly need to enter email again, retrying')
|
||||||
|
if (retry) {
|
||||||
|
return loginIntoPaypal(popup, false);
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
await popup.locator('#btnLogin').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits up to 15 sec for the shipping methods list to load.
|
||||||
|
* @param popup
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
export const waitForPaypalShippingList = async (popup) => {
|
||||||
|
await expect(popup.locator('#shippingMethodsDropdown')).toBeVisible({timeout: 15000});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const completePaypalPayment = async (popup) => {
|
||||||
|
await Promise.all([
|
||||||
|
popup.waitForEvent('close', {timeout: 20000}),
|
||||||
|
popup.click('#payment-submit-btn'),
|
||||||
|
]);
|
||||||
|
}
|
26
tests/playwright/utils/user.js
Normal file
26
tests/playwright/utils/user.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
const {
|
||||||
|
WP_MERCHANT_USER,
|
||||||
|
WP_MERCHANT_PASSWORD,
|
||||||
|
WP_CUSTOMER_USER,
|
||||||
|
WP_CUSTOMER_PASSWORD,
|
||||||
|
} = process.env;
|
||||||
|
|
||||||
|
export const loginAsAdmin = async (page) => {
|
||||||
|
await page.goto('/wp-admin');
|
||||||
|
await page.locator('input[name="log"]').fill(WP_MERCHANT_USER);
|
||||||
|
await page.locator('input[name="pwd"]').fill(WP_MERCHANT_PASSWORD);
|
||||||
|
await Promise.all([
|
||||||
|
page.waitForNavigation(),
|
||||||
|
page.locator('text=Log In').click()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const loginAsCustomer = async (page) => {
|
||||||
|
await page.goto('/wp-admin');
|
||||||
|
await page.locator('input[name="log"]').fill(WP_CUSTOMER_USER);
|
||||||
|
await page.locator('input[name="pwd"]').fill(WP_CUSTOMER_PASSWORD);
|
||||||
|
await Promise.all([
|
||||||
|
page.waitForNavigation(),
|
||||||
|
page.locator('text=Log In').click()
|
||||||
|
]);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue