Add create payment token for credit card (work in progress)

This commit is contained in:
dinamiko 2021-05-17 11:00:57 +02:00
parent da4388c507
commit 1783467af4
5 changed files with 157 additions and 3 deletions

View file

@ -200,4 +200,69 @@ class PaymentTokenEndpoint {
return wp_remote_retrieve_response_code( $response ) === 204;
}
/**
* Creates a payment token for a user.
*
* @param int $customer_id The customer Id.
* @param array $source The payment source.
* @return PaymentToken
* @throws RuntimeException If the request fails.
*/
public function create( $customer_id, $source ): PaymentToken {
$data = array(
'customer_id' => $this->prefix . $customer_id,
'source' => array(
'card' => array(
'number' => $source['credit_card_number'],
'expiry' => $source['credit_card_expiry'],
'security_code' => $source['credit_card_cvc'],
),
),
);
$bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v2/vault/payment-tokens';
$args = array(
'method' => 'POST',
'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json',
'PayPal-Request-Id' => uniqid( 'ppcp-', true ),
'body' => wp_json_encode( $data ),
),
);
$response = $this->request( $url, $args );
if ( is_wp_error( $response ) ) {
$error = new RuntimeException(
sprintf(
// translators: %s is the error message.
__( 'Could not create payment token: %s', 'woocommerce-paypal-payments' ),
$response->get_error_message()
)
);
$this->logger->log( 'error', $error->getMessage() );
throw $error;
}
$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( 200 !== $status_code ) {
$error = new RuntimeException(
sprintf(
// translators: %s is the error message.
__( 'Could not create payment token: %s', 'woocommerce-paypal-payments' ),
$json->message
)
);
$this->logger->log( 'error', $error->getMessage() );
throw $error;
}
return $this->factory->from_paypal_response( $json );
}
}

View file

@ -101,6 +101,22 @@ class PaymentTokenRepository {
return $this->endpoint->delete_token( $token );
}
/**
* Create payment token for customer.
*
* @param int $customer_id The customer Id.
* @param array $source The payment source.
* @return PaymentToken
* @throws RuntimeException If the request fails.
*/
public function create( $customer_id, $source ): PaymentToken {
try {
return $this->endpoint->create( $customer_id, $source );
} catch ( RuntimeException $exception ) {
throw new RuntimeException( $exception->getMessage() );
}
}
/**
* Fetch PaymentToken from PayPal for a user.
*

View file

@ -111,7 +111,7 @@ class SubscriptionModule implements ModuleInterface {
$tokens = $payment_token_repository->all_for_user_id( $subscription->get_customer_id() );
if ( $tokens ) {
$subscription_id = $subscription->get_id();
$latest_token_id = end( $tokens )->id() ?: '';
$latest_token_id = end( $tokens )->id() ? end( $tokens )->id() : '';
update_post_meta( $subscription_id, 'payment_token_id', $latest_token_id, true );
}
} catch ( RuntimeException $error ) {

View file

@ -636,7 +636,8 @@ return array(
'type' => 'checkbox',
'desc_tip' => true,
'label' => sprintf(
__('To use vaulting features, you must %1$senable vaulting on your account%2$s.', 'woocommerce-paypal-payments'),
// translators: %1$s and %2$s are the opening and closing href link tags.
__( 'To use vaulting features, you must %1$senable vaulting on your account%2$s.', 'woocommerce-paypal-payments' ),
'<a
href="https://docs.woocommerce.com/document/woocommerce-paypal-payments/#enable-vaulting-on-your-live-account"
target="_blank"

View file

@ -92,6 +92,57 @@ trait ProcessPaymentTrait {
}
}
/**
* If customer has chosen change Subscription payment.
*/
if ( $this->has_subscription( $order_id ) && $this->is_subscription_change_payment() ) {
if ( $saved_credit_card ) {
update_post_meta( $order_id, 'payment_token_id', $saved_credit_card );
$this->session_handler->destroy_session_data();
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $wc_order ),
);
}
$credit_card_number = filter_input( INPUT_POST, 'ppcp-credit-card-gateway-card-number', FILTER_SANITIZE_STRING );
$credit_card_expiry = filter_input( INPUT_POST, 'ppcp-credit-card-gateway-card-expiry', FILTER_SANITIZE_STRING );
$credit_card_cvc = filter_input( INPUT_POST, 'ppcp-credit-card-gateway-card-cvc', FILTER_SANITIZE_STRING );
if ( $credit_card_number && $credit_card_expiry && $credit_card_cvc ) {
try {
$token = $this->payment_token_repository->create(
$wc_order->get_customer_id(),
array(
'credit_card_number' => $credit_card_number,
'credit_card_expiry' => $credit_card_expiry,
'credit_card_cvc' => $credit_card_cvc,
)
);
update_post_meta( $order_id, 'payment_token_id', $token->id() );
$this->session_handler->destroy_session_data();
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $wc_order ),
);
} catch ( RuntimeException $exception ) {
wc_add_notice(
$exception->getMessage(),
'error'
);
$this->session_handler->destroy_session_data();
return array(
'result' => 'failure',
'redirect' => $this->get_return_url( $wc_order ),
);
}
}
}
/**
* If the WC_Order is payed through the approved webhook.
*/
@ -175,4 +226,25 @@ trait ProcessPaymentTrait {
}
return false;
}
/**
* Is $order_id a subscription?
*
* @param int $order_id The order Id.
* @return boolean Whether order is a subscription or not.
*/
private function has_subscription( $order_id ): bool {
return ( function_exists( 'wcs_order_contains_subscription' ) && ( wcs_order_contains_subscription( $order_id ) || wcs_is_subscription( $order_id ) || wcs_order_contains_renewal( $order_id ) ) );
}
/**
* Checks if page is pay for order and change subscription payment page.
*
* @return bool
*/
private function is_subscription_change_payment(): bool {
$pay_for_order = filter_input( INPUT_GET, 'pay_for_order', FILTER_SANITIZE_STRING );
$change_payment_method = filter_input( INPUT_GET, 'change_payment_method', FILTER_SANITIZE_STRING );
return ( isset( $pay_for_order ) && isset( $change_payment_method ) );
}
}