mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-04 08:47:23 +08:00
Add create payment token for credit card (work in progress)
This commit is contained in:
parent
da4388c507
commit
1783467af4
5 changed files with 157 additions and 3 deletions
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -636,6 +636,7 @@ return array(
|
|||
'type' => 'checkbox',
|
||||
'desc_tip' => true,
|
||||
'label' => sprintf(
|
||||
// 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"
|
||||
|
|
|
@ -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 ) );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue