Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Do not validate ACDC card brand keys locally but via Confirm Payment Source API #2942

Draft
wants to merge 1 commit into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 17 additions & 16 deletions modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -601,30 +601,23 @@ public function patch( string $order_id, PatchCollection $patches ): void {
*
* @param string $id The PayPal order ID.
* @param array $payment_source The payment source.
* @return stdClass
* @return \stdClass
* @throws PayPalApiException If the request fails.
* @throws RuntimeException If something unexpected happens.
*/
public function confirm_payment_source( string $id, array $payment_source ): stdClass {
public function confirm_payment_source( string $id, array $request_body ): stdClass {
$bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v2/checkout/orders/' . $id . '/confirm-payment-source';

$data = array(
'payment_source' => $payment_source,
'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL',
'application_context' => array(
'locale' => 'es-MX',
),
);

$args = array(
'method' => 'POST',
'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json',
'Prefer' => 'return=representation',
'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json',
'Prefer' => 'return=representation',
'PayPal-Request-Id' => uniqid( 'ppcp-', true ),
),
'body' => wp_json_encode( $data ),
'body' => wp_json_encode( $request_body ),
);

$response = $this->request( $url, $args );
Expand All @@ -634,8 +627,16 @@ public function confirm_payment_source( string $id, array $payment_source ): std

$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( 200 !== $status_code ) {
throw new PayPalApiException( $json, $status_code );
if ( $status_code !== 200 ) {
$message = $json->details[0]->description ?? '';
if ( $message ) {
throw new RuntimeException( $message );
}

throw new PayPalApiException(
$json,
$status_code
);
}

return $json;
Expand Down
16 changes: 8 additions & 8 deletions modules/ppcp-api-client/src/Endpoint/Orders.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,13 @@ public function create( array $request_body, array $headers = array() ): array {
*
* @link https://developer.paypal.com/docs/api/orders/v2/#orders_confirm
*
* @param array $request_body The request body.
* @param string $id PayPal order ID.
* @return array
* @param array $request_body The request body.
* @return \stdClass
* @throws RuntimeException If something went wrong with the request.
* @throws PayPalApiException If something went wrong with the PayPal API request.
*/
public function confirm_payment_source( array $request_body, string $id ): array {
public function confirm_payment_source( string $id, array $request_body ): \stdClass {
$bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v2/checkout/orders/' . $id . '/confirm-payment-source';

Expand All @@ -133,6 +133,7 @@ public function confirm_payment_source( array $request_body, string $id ): array
'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json',
'Prefer' => 'return=representation',
'PayPal-Request-Id' => uniqid( 'ppcp-', true ),
),
'body' => wp_json_encode( $request_body ),
Expand All @@ -143,22 +144,21 @@ public function confirm_payment_source( array $request_body, string $id ): array
throw new RuntimeException( $response->get_error_message() );
}

$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( $status_code !== 200 ) {
$body = json_decode( $response['body'] );

$message = $body->details[0]->description ?? '';
$message = $json->details[0]->description ?? '';
if ( $message ) {
throw new RuntimeException( $message );
}

throw new PayPalApiException(
$body,
$json,
$status_code
);
}

return $response;
return $json;
}

/**
Expand Down
6 changes: 6 additions & 0 deletions modules/ppcp-api-client/src/Entity/PaymentSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,10 @@ public function name(): string {
public function properties(): object {
return $this->properties;
}

public function to_array(): array {
return array(
$this->name => (array) $this->properties
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,10 @@ public function process_payment( $order_id ) {
),
);

$response = $this->orders_endpoint->confirm_payment_source( $request_body, $body->id );
$body = json_decode( $response['body'] );
$response = $this->orders_endpoint->confirm_payment_source( $body->id, $request_body );

$payer_action = '';
foreach ( $body->links as $link ) {
foreach ( $response->links as $link ) {
if ( $link->rel === 'payer-action' ) {
$payer_action = $link->href;
}
Expand Down
10 changes: 9 additions & 1 deletion modules/ppcp-wc-gateway/src/Gateway/OXXO/OXXOGateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,15 @@ public function process_payment( $order_id ) {
'country_code' => $wc_order->get_billing_country(),
),
);
$payment_method = $this->order_endpoint->confirm_payment_source( $order->id(), $payment_source );
$request_body = array(
'payment_source' => $payment_source,
'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL',
'application_context' => array(
'locale' => 'es-MX',
),
);

$payment_method = $this->order_endpoint->confirm_payment_source( $order->id(), $request_body );
foreach ( $payment_method->links as $link ) {
if ( $link->rel === 'payer-action' ) {
$payer_action = $link->href;
Expand Down
21 changes: 19 additions & 2 deletions modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\ApiClient\Factory\OrderFactory;
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
Expand Down Expand Up @@ -196,11 +197,11 @@ public function __construct(
* Processes a given WooCommerce order and captured/authorizes the connected PayPal orders.
*
* @param WC_Order $wc_order The WooCommerce order.
*
* @return \stdClass PayPal order details of confirmed Order
* @throws PayPalOrderMissingException If no PayPal order.
* @throws Exception If processing fails.
*/
public function process( WC_Order $wc_order ): void {
public function process( WC_Order $wc_order ): \stdClass {
$order = $this->session_handler->order();
if ( ! $order ) {
// phpcs:ignore WordPress.Security.NonceVerification
Expand Down Expand Up @@ -228,6 +229,20 @@ public function process( WC_Order $wc_order ): void {
}
}

$request_body = apply_filters(
'woocommerce_paypal_payments_confirm_payment_source_request_body',
array(
'payment_source' => $order->payment_source() !== null ? $order->payment_source()->to_array() : null,
'application_context' => $order->application_context() !== null ? $order->application_context()->to_array() : null,
)
);

if ( ! empty( $request_body[ 'payment_source' ] ) ) {
$confirm_payment_result = $this->order_endpoint->confirm_payment_source( $order->id(), $request_body );
} else {
$confirm_payment_result = new \stdClass();
}

$this->add_paypal_meta( $wc_order, $order, $this->environment );

if ( $this->order_helper->contains_physical_goods( $order ) && ! $this->order_is_ready_for_process( $order ) ) {
Expand Down Expand Up @@ -268,6 +283,8 @@ public function process( WC_Order $wc_order ): void {
}

do_action( 'woocommerce_paypal_payments_after_order_processor', $wc_order, $order );

return $confirm_payment_result;
}

/**
Expand Down
Loading