mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-04 08:47:23 +08:00
Merge pull request #1953 from woocommerce/PCP-461-error-when-adding-changing-subscription-payment-method-to-pay-pal-dcc-while-no-vault-token-exists
WC Subscriptions change subscription payment
This commit is contained in:
commit
be3d58e3de
15 changed files with 380 additions and 149 deletions
|
@ -112,6 +112,14 @@ class CardFieldsRenderer {
|
|||
|
||||
show(buttonSelector);
|
||||
|
||||
if(this.defaultConfig.cart_contains_subscription) {
|
||||
const saveToAccount = document.querySelector('#wc-ppcp-credit-card-gateway-new-payment-method');
|
||||
if(saveToAccount) {
|
||||
saveToAccount.checked = true;
|
||||
saveToAccount.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelector(buttonSelector).addEventListener("click", (event) => {
|
||||
event.preventDefault();
|
||||
this.spinner.block();
|
||||
|
|
|
@ -1056,6 +1056,7 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages
|
|||
'endpoint' => \WC_AJAX::get_endpoint( CartScriptParamsEndpoint::ENDPOINT ),
|
||||
),
|
||||
),
|
||||
'cart_contains_subscription' => $this->subscription_helper->cart_contains_subscription(),
|
||||
'subscription_plan_id' => $this->subscription_helper->paypal_subscription_id(),
|
||||
'variable_paypal_subscription_variations' => $this->subscription_helper->variable_paypal_subscription_variations(),
|
||||
'subscription_product_allowed' => $this->subscription_helper->checkout_subscription_product_allowed(),
|
||||
|
|
|
@ -212,6 +212,19 @@ trait ContextTrait {
|
|||
return $page_id && is_page( $page_id ) && isset( $wp->query_vars['add-payment-method'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this user is changing the payment method for a subscription.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_subscription_change_payment_method_page(): bool {
|
||||
if ( isset( $_GET['change_payment_method'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
return wcs_is_subscription( wc_clean( wp_unslash( $_GET['change_payment_method'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if it is the block editor page.
|
||||
*/
|
||||
|
|
|
@ -28,6 +28,14 @@ document.addEventListener(
|
|||
init()
|
||||
});
|
||||
|
||||
if(ppcp_add_payment_method.is_subscription_change_payment_page) {
|
||||
const saveToAccount = document.querySelector('#wc-ppcp-credit-card-gateway-new-payment-method');
|
||||
if(saveToAccount) {
|
||||
saveToAccount.checked = true;
|
||||
saveToAccount.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
loadScript({
|
||||
clientId: ppcp_add_payment_method.client_id,
|
||||
|
@ -38,54 +46,57 @@ document.addEventListener(
|
|||
.then((paypal) => {
|
||||
errorHandler.clear();
|
||||
|
||||
paypal.Buttons(
|
||||
{
|
||||
createVaultSetupToken: async () => {
|
||||
const response = await fetch(ppcp_add_payment_method.ajax.create_setup_token.endpoint, {
|
||||
method: "POST",
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nonce: ppcp_add_payment_method.ajax.create_setup_token.nonce,
|
||||
const paypalButtonContainer = document.querySelector(`#ppc-button-${PaymentMethods.PAYPAL}-save-payment-method`);
|
||||
if(paypalButtonContainer) {
|
||||
paypal.Buttons(
|
||||
{
|
||||
createVaultSetupToken: async () => {
|
||||
const response = await fetch(ppcp_add_payment_method.ajax.create_setup_token.endpoint, {
|
||||
method: "POST",
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nonce: ppcp_add_payment_method.ajax.create_setup_token.nonce,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const result = await response.json()
|
||||
if (result.data.id) {
|
||||
return result.data.id
|
||||
}
|
||||
const result = await response.json()
|
||||
if (result.data.id) {
|
||||
return result.data.id
|
||||
}
|
||||
|
||||
errorHandler.message(ppcp_add_payment_method.error_message);
|
||||
},
|
||||
onApprove: async ({vaultSetupToken}) => {
|
||||
const response = await fetch(ppcp_add_payment_method.ajax.create_payment_token.endpoint, {
|
||||
method: "POST",
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nonce: ppcp_add_payment_method.ajax.create_payment_token.nonce,
|
||||
vault_setup_token: vaultSetupToken,
|
||||
errorHandler.message(ppcp_add_payment_method.error_message);
|
||||
},
|
||||
onApprove: async ({vaultSetupToken}) => {
|
||||
const response = await fetch(ppcp_add_payment_method.ajax.create_payment_token.endpoint, {
|
||||
method: "POST",
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nonce: ppcp_add_payment_method.ajax.create_payment_token.nonce,
|
||||
vault_setup_token: vaultSetupToken,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const result = await response.json();
|
||||
if(result.success === true) {
|
||||
window.location.href = ppcp_add_payment_method.payment_methods_page;
|
||||
return;
|
||||
const result = await response.json();
|
||||
if(result.success === true) {
|
||||
window.location.href = ppcp_add_payment_method.payment_methods_page;
|
||||
return;
|
||||
}
|
||||
|
||||
errorHandler.message(ppcp_add_payment_method.error_message);
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error(error)
|
||||
errorHandler.message(ppcp_add_payment_method.error_message);
|
||||
}
|
||||
|
||||
errorHandler.message(ppcp_add_payment_method.error_message);
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error(error)
|
||||
errorHandler.message(ppcp_add_payment_method.error_message);
|
||||
}
|
||||
},
|
||||
).render(`#ppc-button-${PaymentMethods.PAYPAL}-save-payment-method`);
|
||||
).render(`#ppc-button-${PaymentMethods.PAYPAL}-save-payment-method`);
|
||||
}
|
||||
|
||||
const cardField = paypal.CardFields({
|
||||
createVaultSetupToken: async () => {
|
||||
|
@ -125,6 +136,33 @@ document.addEventListener(
|
|||
|
||||
const result = await response.json();
|
||||
if(result.success === true) {
|
||||
if(ppcp_add_payment_method.is_subscription_change_payment_page) {
|
||||
const subscriptionId = ppcp_add_payment_method.subscription_id_to_change_payment;
|
||||
if(subscriptionId && result.data) {
|
||||
const req = await fetch(ppcp_add_payment_method.ajax.subscription_change_payment_method.endpoint, {
|
||||
method: "POST",
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nonce: ppcp_add_payment_method.ajax.subscription_change_payment_method.nonce,
|
||||
subscription_id: subscriptionId,
|
||||
payment_method: getCurrentPaymentMethod(),
|
||||
wc_payment_token_id: result.data
|
||||
})
|
||||
});
|
||||
|
||||
const res = await req.json();
|
||||
if (res.success === true) {
|
||||
window.location.href = `${ppcp_add_payment_method.view_subscriptions_page}/${subscriptionId}`;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
window.location.href = ppcp_add_payment_method.payment_methods_page;
|
||||
return;
|
||||
}
|
||||
|
@ -167,7 +205,15 @@ document.addEventListener(
|
|||
}
|
||||
}
|
||||
|
||||
document.querySelector('#place_order').addEventListener("click", (event) => {
|
||||
document.querySelector('#place_order')?.addEventListener("click", (event) => {
|
||||
const cardPaymentToken = document.querySelector('input[name="wc-ppcp-credit-card-gateway-payment-token"]:checked')?.value;
|
||||
if (
|
||||
getCurrentPaymentMethod() !== 'ppcp-credit-card-gateway'
|
||||
|| cardPaymentToken && cardPaymentToken !== 'new'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
cardField.submit()
|
||||
|
|
|
@ -80,7 +80,8 @@ class CreatePaymentToken implements EndpointInterface {
|
|||
*/
|
||||
public function handle_request(): bool {
|
||||
try {
|
||||
$data = $this->request_data->read_request( $this->nonce() );
|
||||
$data = $this->request_data->read_request( $this->nonce() );
|
||||
$wc_token_id = 0;
|
||||
|
||||
/**
|
||||
* Suppress ArgumentTypeCoercion
|
||||
|
@ -98,7 +99,8 @@ class CreatePaymentToken implements EndpointInterface {
|
|||
$result = $this->payment_method_tokens_endpoint->payment_tokens( $payment_source );
|
||||
|
||||
if ( is_user_logged_in() && isset( $result->customer->id ) ) {
|
||||
update_user_meta( get_current_user_id(), '_ppcp_target_customer_id', $result->customer->id );
|
||||
$current_user_id = get_current_user_id();
|
||||
update_user_meta( $current_user_id, '_ppcp_target_customer_id', $result->customer->id );
|
||||
|
||||
if ( isset( $result->payment_source->paypal ) ) {
|
||||
$email = '';
|
||||
|
@ -106,34 +108,19 @@ class CreatePaymentToken implements EndpointInterface {
|
|||
$email = $result->payment_source->paypal->email_address;
|
||||
}
|
||||
|
||||
$this->wc_payment_tokens->create_payment_token_paypal(
|
||||
get_current_user_id(),
|
||||
$wc_token_id = $this->wc_payment_tokens->create_payment_token_paypal(
|
||||
$current_user_id,
|
||||
$result->id,
|
||||
$email
|
||||
);
|
||||
}
|
||||
|
||||
if ( isset( $result->payment_source->card ) ) {
|
||||
$token = new \WC_Payment_Token_CC();
|
||||
$token->set_token( $result->id );
|
||||
$token->set_user_id( get_current_user_id() );
|
||||
$token->set_gateway_id( CreditCardGateway::ID );
|
||||
|
||||
$token->set_last4( $result->payment_source->card->last_digits ?? '' );
|
||||
$expiry = explode( '-', $result->payment_source->card->expiry ?? '' );
|
||||
$token->set_expiry_year( $expiry[0] ?? '' );
|
||||
$token->set_expiry_month( $expiry[1] ?? '' );
|
||||
|
||||
$brand = $result->payment_source->card->brand ?? __( 'N/A', 'woocommerce-paypal-payments' );
|
||||
if ( $brand ) {
|
||||
$token->set_card_type( $brand );
|
||||
}
|
||||
|
||||
$token->save();
|
||||
$wc_token_id = $this->wc_payment_tokens->create_payment_token_card( $current_user_id, $result );
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json_success( $result );
|
||||
wp_send_json_success( $wc_token_id );
|
||||
return true;
|
||||
} catch ( Exception $exception ) {
|
||||
wp_send_json_error();
|
||||
|
|
|
@ -28,6 +28,7 @@ use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
|||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Endpoint\SubscriptionChangePaymentMethod;
|
||||
|
||||
/**
|
||||
* Class SavePaymentMethodsModule
|
||||
|
@ -176,7 +177,7 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
|||
add_action(
|
||||
'wp_enqueue_scripts',
|
||||
function() use ( $c ) {
|
||||
if ( ! is_user_logged_in() || ! $this->is_add_payment_method_page() ) {
|
||||
if ( ! is_user_logged_in() || ! ( $this->is_add_payment_method_page() || $this->is_subscription_change_payment_method_page() ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -207,17 +208,22 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
|||
assert( $settings instanceof Settings );
|
||||
$verification_method = $settings->has( '3d_secure_contingency' ) ? $settings->get( '3d_secure_contingency' ) : '';
|
||||
|
||||
$change_payment_method = wc_clean( wp_unslash( $_GET['change_payment_method'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
||||
|
||||
wp_localize_script(
|
||||
'ppcp-add-payment-method',
|
||||
'ppcp_add_payment_method',
|
||||
array(
|
||||
'client_id' => $c->get( 'button.client_id' ),
|
||||
'merchant_id' => $c->get( 'api.merchant_id' ),
|
||||
'id_token' => $id_token,
|
||||
'payment_methods_page' => wc_get_account_endpoint_url( 'payment-methods' ),
|
||||
'error_message' => __( 'Could not save payment method.', 'woocommerce-paypal-payments' ),
|
||||
'verification_method' => $verification_method,
|
||||
'ajax' => array(
|
||||
'client_id' => $c->get( 'button.client_id' ),
|
||||
'merchant_id' => $c->get( 'api.merchant_id' ),
|
||||
'id_token' => $id_token,
|
||||
'payment_methods_page' => wc_get_account_endpoint_url( 'payment-methods' ),
|
||||
'view_subscriptions_page' => wc_get_account_endpoint_url( 'view-subscription' ),
|
||||
'is_subscription_change_payment_page' => $this->is_subscription_change_payment_method_page(),
|
||||
'subscription_id_to_change_payment' => $this->is_subscription_change_payment_method_page() ? (int) $change_payment_method : 0,
|
||||
'error_message' => __( 'Could not save payment method.', 'woocommerce-paypal-payments' ),
|
||||
'verification_method' => $verification_method,
|
||||
'ajax' => array(
|
||||
'create_setup_token' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( CreateSetupToken::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( CreateSetupToken::nonce() ),
|
||||
|
@ -226,6 +232,10 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
|||
'endpoint' => \WC_AJAX::get_endpoint( CreatePaymentToken::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( CreatePaymentToken::nonce() ),
|
||||
),
|
||||
'subscription_change_payment_method' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( SubscriptionChangePaymentMethod::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( SubscriptionChangePaymentMethod::nonce() ),
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
|
|
@ -11,10 +11,13 @@ namespace WooCommerce\PayPalCommerce\SavePaymentMethods;
|
|||
|
||||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use stdClass;
|
||||
use WC_Payment_Token_CC;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenFactory;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenHelper;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenPayPal;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
|
||||
/**
|
||||
|
@ -67,17 +70,17 @@ class WooCommercePaymentTokens {
|
|||
* @param string $token The PayPal payment token.
|
||||
* @param string $email The PayPal customer email.
|
||||
*
|
||||
* @return void
|
||||
* @return int
|
||||
*/
|
||||
public function create_payment_token_paypal(
|
||||
int $customer_id,
|
||||
string $token,
|
||||
string $email
|
||||
): void {
|
||||
): int {
|
||||
|
||||
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id, PayPalGateway::ID );
|
||||
if ( $this->payment_token_helper->token_exist( $wc_tokens, $token ) ) {
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
$payment_token_paypal = $this->payment_token_factory->create( 'paypal' );
|
||||
|
@ -98,5 +101,48 @@ class WooCommercePaymentTokens {
|
|||
"Could not create WC payment token PayPal for customer {$customer_id}. " . $exception->getMessage()
|
||||
);
|
||||
}
|
||||
|
||||
return $payment_token_paypal->get_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a WC Payment Token for Credit Card payment.
|
||||
*
|
||||
* @param int $customer_id The WC customer ID.
|
||||
* @param stdClass $payment_token The Credit Card payment token.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function create_payment_token_card( int $customer_id, stdClass $payment_token ): int {
|
||||
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id, CreditCardGateway::ID );
|
||||
if ( $this->payment_token_helper->token_exist( $wc_tokens, $payment_token->id ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$token = new WC_Payment_Token_CC();
|
||||
$token->set_token( $payment_token->id );
|
||||
$token->set_user_id( get_current_user_id() );
|
||||
$token->set_gateway_id( CreditCardGateway::ID );
|
||||
|
||||
$token->set_last4( $payment_token->payment_source->card->last_digits ?? '' );
|
||||
$expiry = explode( '-', $payment_token->payment_source->card->expiry ?? '' );
|
||||
$token->set_expiry_year( $expiry[0] ?? '' );
|
||||
$token->set_expiry_month( $expiry[1] ?? '' );
|
||||
|
||||
$brand = $payment_token->payment_source->card->brand ?? __( 'N/A', 'woocommerce-paypal-payments' );
|
||||
if ( $brand ) {
|
||||
$token->set_card_type( $brand );
|
||||
}
|
||||
|
||||
try {
|
||||
$token->save();
|
||||
} catch ( Exception $exception ) {
|
||||
$this->logger->error(
|
||||
"Could not create WC payment token card for customer {$customer_id}. " . $exception->getMessage()
|
||||
);
|
||||
}
|
||||
|
||||
$token->save();
|
||||
return $token->get_id();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,19 +143,6 @@ class VaultedCreditCardHandler {
|
|||
string $saved_credit_card,
|
||||
WC_Order $wc_order
|
||||
): WC_Order {
|
||||
if (
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
isset( $_POST['woocommerce_change_payment'] )
|
||||
&& $this->subscription_helper->has_subscription( $wc_order->get_id() )
|
||||
&& $this->subscription_helper->is_subscription_change_payment()
|
||||
&& $saved_credit_card
|
||||
) {
|
||||
$wc_order->update_meta_data( 'payment_token_id', $saved_credit_card );
|
||||
$wc_order->save();
|
||||
|
||||
return $wc_order;
|
||||
}
|
||||
|
||||
$tokens = $this->payment_token_repository->all_for_user_id( $wc_order->get_customer_id() );
|
||||
$selected_token = null;
|
||||
foreach ( $tokens as $token ) {
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Gateway;
|
|||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Order;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
|
@ -377,11 +378,11 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
|||
}
|
||||
|
||||
/**
|
||||
* If customer has chosen a saved credit card payment.
|
||||
* If customer has chosen a saved credit card payment from checkout page.
|
||||
*/
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$saved_credit_card = wc_clean( wp_unslash( $_POST['saved_credit_card'] ?? '' ) );
|
||||
if ( $saved_credit_card ) {
|
||||
if ( $saved_credit_card && is_checkout() ) {
|
||||
try {
|
||||
$wc_order = $this->vaulted_credit_card_handler->handle_payment(
|
||||
$saved_credit_card,
|
||||
|
@ -395,6 +396,40 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If customer is changing subscription payment.
|
||||
*/
|
||||
if (
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Missing
|
||||
isset( $_POST['woocommerce_change_payment'] )
|
||||
&& $this->subscription_helper->has_subscription( $wc_order->get_id() )
|
||||
&& $this->subscription_helper->is_subscription_change_payment()
|
||||
) {
|
||||
$saved_credit_card = wc_clean( wp_unslash( $_POST['wc-ppcp-credit-card-gateway-payment-token'] ?? '' ) );
|
||||
if ( ! $saved_credit_card ) {
|
||||
$saved_credit_card = wc_clean( wp_unslash( $_POST['saved_credit_card'] ?? '' ) );
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||||
}
|
||||
|
||||
if ( $saved_credit_card ) {
|
||||
$payment_token = WC_Payment_Tokens::get( $saved_credit_card );
|
||||
if ( $payment_token ) {
|
||||
$wc_order->add_payment_token( $payment_token );
|
||||
$wc_order->save();
|
||||
|
||||
return $this->handle_payment_success( $wc_order );
|
||||
}
|
||||
}
|
||||
|
||||
wc_add_notice( __( 'Could not change payment.', 'woocommerce-paypal-payments' ), 'error' );
|
||||
|
||||
return array(
|
||||
'result' => 'failure',
|
||||
'redirect' => wc_get_checkout_url(),
|
||||
'errorMessage' => __( 'Could not change payment.', 'woocommerce-paypal-payments' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the WC_Order is paid through the approved webhook.
|
||||
*/
|
||||
|
|
|
@ -12,11 +12,11 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Gateway;
|
|||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Order;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
|
@ -522,10 +522,21 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$saved_paypal_payment = wc_clean( wp_unslash( $_POST['saved_paypal_payment'] ?? '' ) );
|
||||
if ( $saved_paypal_payment ) {
|
||||
$wc_order->update_meta_data( 'payment_token_id', $saved_paypal_payment );
|
||||
$wc_order->save();
|
||||
$payment_token = WC_Payment_Tokens::get( $saved_paypal_payment );
|
||||
if ( $payment_token ) {
|
||||
$wc_order->add_payment_token( $payment_token );
|
||||
$wc_order->save();
|
||||
|
||||
return $this->handle_payment_success( $wc_order );
|
||||
return $this->handle_payment_success( $wc_order );
|
||||
}
|
||||
|
||||
wc_add_notice( __( 'Could not change payment.', 'woocommerce-paypal-payments' ), 'error' );
|
||||
|
||||
return array(
|
||||
'result' => 'failure',
|
||||
'redirect' => wc_get_checkout_url(),
|
||||
'errorMessage' => __( 'Could not change payment.', 'woocommerce-paypal-payments' ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,10 +9,9 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\WcSubscriptions;
|
||||
|
||||
use WooCommerce\PayPalCommerce\PayPalSubscriptions\DeactivatePlanEndpoint;
|
||||
use WooCommerce\PayPalCommerce\PayPalSubscriptions\SubscriptionsApiHandler;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Endpoint\SubscriptionChangePaymentMethod;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
|
||||
return array(
|
||||
|
@ -45,4 +44,9 @@ return array(
|
|||
$endpoint = $container->get( 'api.endpoint.payment-token' );
|
||||
return new PaymentTokenRepository( $factory, $endpoint );
|
||||
},
|
||||
'wc-subscriptions.endpoint.subscription-change-payment-method' => static function( ContainerInterface $container ): SubscriptionChangePaymentMethod {
|
||||
return new SubscriptionChangePaymentMethod(
|
||||
$container->get( 'button.request-data' )
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
/**
|
||||
* The Create Payment Token endpoint.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\WcSubscriptions\Endpoint
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\WcSubscriptions\Endpoint;
|
||||
|
||||
use Exception;
|
||||
use WC_Order;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\EndpointInterface;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
||||
|
||||
/**
|
||||
* Class SubscriptionChangePaymentMethod
|
||||
*/
|
||||
class SubscriptionChangePaymentMethod implements EndpointInterface {
|
||||
|
||||
const ENDPOINT = 'ppc-subscription-change-payment-method';
|
||||
|
||||
/**
|
||||
* The request data.
|
||||
*
|
||||
* @var RequestData
|
||||
*/
|
||||
private $request_data;
|
||||
|
||||
/**
|
||||
* SubscriptionChangePaymentMethod constructor.
|
||||
*
|
||||
* @param RequestData $request_data $request_data The request data.
|
||||
*/
|
||||
public function __construct( RequestData $request_data ) {
|
||||
$this->request_data = $request_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nonce.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function nonce(): string {
|
||||
return self::ENDPOINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the request.
|
||||
*
|
||||
* @return bool
|
||||
* @throws Exception On Error.
|
||||
*/
|
||||
public function handle_request(): bool {
|
||||
try {
|
||||
$data = $this->request_data->read_request( $this->nonce() );
|
||||
|
||||
$subscription = wcs_get_subscription( $data['subscription_id'] );
|
||||
if ( $subscription instanceof WC_Order ) {
|
||||
$subscription->set_payment_method( $data['payment_method'] );
|
||||
|
||||
$wc_payment_token = WC_Payment_Tokens::get( $data['wc_payment_token_id'] );
|
||||
if ( $wc_payment_token ) {
|
||||
$subscription->add_payment_token( $wc_payment_token );
|
||||
$subscription->save();
|
||||
}
|
||||
|
||||
wp_send_json_success();
|
||||
return true;
|
||||
}
|
||||
|
||||
wp_send_json_error();
|
||||
return false;
|
||||
} catch ( Exception $exception ) {
|
||||
wp_send_json_error();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,8 @@ namespace WooCommerce\PayPalCommerce\WcSubscriptions;
|
|||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Order;
|
||||
use WC_Subscription;
|
||||
use WC_Payment_Token_CC;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||
|
@ -23,6 +24,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
|||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Endpoint\SubscriptionChangePaymentMethod;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
|
||||
/**
|
||||
|
@ -135,6 +137,10 @@ class WcSubscriptionsModule implements ModuleInterface {
|
|||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function ( $default_fields, $id ) use ( $c ) {
|
||||
if ( $c->has( 'save-payment-methods.eligible' ) && $c->get( 'save-payment-methods.eligible' ) ) {
|
||||
return $default_fields;
|
||||
}
|
||||
|
||||
$payment_token_repository = $c->get( 'vaulting.repository.payment-token' );
|
||||
$settings = $c->get( 'wcgateway.settings' );
|
||||
$subscription_helper = $c->get( 'wc-subscriptions.helper' );
|
||||
|
@ -144,6 +150,40 @@ class WcSubscriptionsModule implements ModuleInterface {
|
|||
20,
|
||||
2
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'woocommerce_available_payment_gateways',
|
||||
function( array $methods ) use ( $c ) : array {
|
||||
if (
|
||||
! is_wc_endpoint_url( 'order-pay' )
|
||||
|| $c->has( 'save-payment-methods.eligible' ) && $c->get( 'save-payment-methods.eligible' )
|
||||
) {
|
||||
return $methods;
|
||||
}
|
||||
|
||||
$paypal_tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), PayPalGateway::ID );
|
||||
if ( ! $paypal_tokens ) {
|
||||
unset( $methods[ PayPalGateway::ID ] );
|
||||
}
|
||||
|
||||
$card_tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), CreditCardGateway::ID );
|
||||
if ( ! $card_tokens ) {
|
||||
unset( $methods[ CreditCardGateway::ID ] );
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'wc_ajax_' . SubscriptionChangePaymentMethod::ENDPOINT,
|
||||
static function () use ( $c ) {
|
||||
$endpoint = $c->get( 'wc-subscriptions.endpoint.subscription-change-payment-method' );
|
||||
assert( $endpoint instanceof SubscriptionChangePaymentMethod );
|
||||
|
||||
$endpoint->handle_request();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -224,30 +264,18 @@ class WcSubscriptionsModule implements ModuleInterface {
|
|||
&& PayPalGateway::ID === $id
|
||||
&& $subscription_helper->is_subscription_change_payment()
|
||||
) {
|
||||
$tokens = $payment_token_repository->all_for_user_id( get_current_user_id() );
|
||||
if ( ! $tokens || ! $payment_token_repository->tokens_contains_paypal( $tokens ) ) {
|
||||
return esc_html__(
|
||||
'No PayPal payments saved, in order to use a saved payment you first need to create it through a purchase.',
|
||||
'woocommerce-paypal-payments'
|
||||
);
|
||||
}
|
||||
$tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), PayPalGateway::ID );
|
||||
|
||||
$output = sprintf(
|
||||
'<p class="form-row form-row-wide"><label>%1$s</label><select id="saved-paypal-payment" name="saved_paypal_payment">',
|
||||
esc_html__( 'Select a saved PayPal payment', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
$output = '<ul class="wc-saved-payment-methods">';
|
||||
foreach ( $tokens as $token ) {
|
||||
if ( isset( $token->source()->paypal ) ) {
|
||||
$output .= sprintf(
|
||||
'<option value="%1$s">%2$s</option>',
|
||||
$token->id(),
|
||||
$token->source()->paypal->payer->email_address
|
||||
);
|
||||
}
|
||||
$output .= '<li>';
|
||||
$output .= sprintf( '<input name="saved_paypal_payment" type="radio" value="%s" style="width:auto;" checked="checked">', $token->get_id() );
|
||||
$output .= sprintf( '<label for="saved_paypal_payment">%s</label>', $token->get_meta( 'email' ) ?? '' );
|
||||
$output .= '</li>';
|
||||
}
|
||||
$output .= '</select></p>';
|
||||
$output .= '</ul>';
|
||||
|
||||
return $output;
|
||||
return $output;
|
||||
}
|
||||
|
||||
return $description;
|
||||
|
@ -271,33 +299,23 @@ class WcSubscriptionsModule implements ModuleInterface {
|
|||
array $default_fields,
|
||||
SubscriptionHelper $subscription_helper
|
||||
) {
|
||||
|
||||
if ( $settings->has( 'vault_enabled_dcc' )
|
||||
&& $settings->get( 'vault_enabled_dcc' )
|
||||
&& $subscription_helper->is_subscription_change_payment()
|
||||
&& CreditCardGateway::ID === $id
|
||||
) {
|
||||
$tokens = $payment_token_repository->all_for_user_id( get_current_user_id() );
|
||||
if ( ! $tokens || ! $payment_token_repository->tokens_contains_card( $tokens ) ) {
|
||||
$default_fields = array();
|
||||
$default_fields['saved-credit-card'] = esc_html__(
|
||||
'No Credit Card saved, in order to use a saved Credit Card you first need to create it through a purchase.',
|
||||
'woocommerce-paypal-payments'
|
||||
);
|
||||
return $default_fields;
|
||||
}
|
||||
|
||||
$tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), CreditCardGateway::ID );
|
||||
$output = sprintf(
|
||||
'<p class="form-row form-row-wide"><label>%1$s</label><select id="saved-credit-card" name="saved_credit_card">',
|
||||
esc_html__( 'Select a saved Credit Card payment', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
foreach ( $tokens as $token ) {
|
||||
if ( isset( $token->source()->card ) ) {
|
||||
if ( $token instanceof WC_Payment_Token_CC ) {
|
||||
$output .= sprintf(
|
||||
'<option value="%1$s">%2$s ...%3$s</option>',
|
||||
$token->id(),
|
||||
$token->source()->card->brand,
|
||||
$token->source()->card->last_digits
|
||||
$token->get_id(),
|
||||
$token->get_card_type(),
|
||||
$token->get_last4()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue