Skip to content
Open
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
154 changes: 96 additions & 58 deletions includes/class-coingate-for-woocommerce-payment-gateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ public function validate_api_auth_token_field( $key, $value ) {
* @throws Exception Unknown exception type.
*/
public function process_payment( $order_id ) {
global $woocommerce, $page, $paged;
$logger = wc_get_logger();
$order = wc_get_order( $order_id );

$client = $this->init_coingate();
Expand Down Expand Up @@ -247,7 +247,14 @@ public function process_payment( $order_id ) {
$response['redirect'] = $gateway_order->payment_url;
}
} catch ( ApiErrorException $exception ) {
error_log( $exception );
$logger->error(
'Failed to create CoinGate order for #' . $order->get_id() . ': ' . $exception->getMessage(),
array(
'source' => 'coingate-for-woocommerce',
'params' => $params,
'backtrace' => true,
)
);
}

return $response;
Expand All @@ -259,74 +266,105 @@ public function process_payment( $order_id ) {
* @throws Exception Unknown exception type.
*/
public function payment_callback() {
$logger = wc_get_logger();
$request = $_POST;
$order = wc_get_order( sanitize_text_field( $request['order_id'] ) );

if ( ! $this->is_token_valid( $order, preg_replace( '/\s+/', '', $request['token'] ) ) ) {
throw new Exception( 'CoinGate callback token does not match' );
$order = wc_get_order( sanitize_text_field( $request['order_id'] ) );
if ( ! $order ) {
// Set HTTP status code to Bad Request (400)
wp_send_json_error( array(
'message' => 'Invalid order ID: ' . $request['order_id'],
), 400 );
}

if ( ! $order || ! $order->get_id() ) {
throw new Exception( 'Order #' . $order->get_id() . ' does not exists' );
}
try {
if ( ! $this->is_token_valid( $order, preg_replace( '/\s+/', '', $request['token'] ) ) ) {
throw new Exception( 'CoinGate callback token does not match' );
}

if ( $order->get_payment_method() !== $this->id ) {
throw new Exception( 'Order #' . $order->get_id() . ' payment method is not ' . $this->method_title );
}
if ( $order->get_payment_method() !== $this->id ) {
throw new Exception( 'Order #' . $order->get_id() . ' payment method is not ' . $this->method_title );
}

// Get payment data from request due to security reason.
$client = $this->init_coingate();
$cg_order = $client->order->get( (int) sanitize_key( $request['id'] ) );
if ( ! $cg_order || $order->get_id() !== (int) $cg_order->order_id ) {
throw new Exception( 'CoinGate Order #' . $order->get_id() . ' does not exists.' );
}
// Get payment data from request due to security reason.
$client = $this->init_coingate();
$cg_order = $client->order->get( (int) sanitize_key( $request['id'] ) );
if ( ! $cg_order || $order->get_id() !== (int) $cg_order->order_id ) {
throw new Exception( 'CoinGate Order #' . $order->get_id() . ' does not exists.' );
}

$callback_order_status = sanitize_text_field( $cg_order->status );
$callback_order_status = sanitize_text_field( $cg_order->status );

$order_statuses = $this->get_option( 'order_statuses' );
$wc_order_status = isset( $order_statuses[ $callback_order_status ] ) ? $order_statuses[ $callback_order_status ] : null;
if ( ! $wc_order_status ) {
return;
}
$order_statuses = $this->get_option( 'order_statuses' );
$wc_order_status = isset( $order_statuses[ $callback_order_status ] ) ? $order_statuses[ $callback_order_status ] : null;
if ( ! $wc_order_status ) {
return;
}

switch ( $callback_order_status ) {
case 'paid':
$status_was = 'wc-' . $order->get_status();
switch ( $callback_order_status ) {
case 'paid':
$status_was = 'wc-' . $order->get_status();

$this->handle_order_status( $order, $wc_order_status );
$order->add_order_note( __( 'Payment is confirmed on the network, and has been credited to the merchant. Purchased goods/services can be securely delivered to the buyer.', 'coingate' ) );
$order->payment_complete();
$this->handle_order_status( $order, $wc_order_status );
$order->add_order_note( __( 'Payment is confirmed on the network, and has been credited to the merchant. Purchased goods/services can be securely delivered to the buyer.', 'coingate' ) );
$order->payment_complete();

$wc_expired_status = $order_statuses['expired'];
$wc_canceled_status = $order_statuses['canceled'];
$wc_expired_status = $order_statuses['expired'];
$wc_canceled_status = $order_statuses['canceled'];

if ( 'processing' === $order->status && ( $status_was === $wc_expired_status || $status_was === $wc_canceled_status ) ) {
WC()->mailer()->emails['WC_Email_Customer_Processing_Order']->trigger( $order->get_id() );
}
if ( ( 'processing' === $order->status || 'completed' === $order->status ) && ( $status_was === $wc_expired_status || $status_was === $wc_canceled_status ) ) {
WC()->mailer()->emails['WC_Email_New_Order']->trigger( $order->get_id() );
}
break;
case 'confirming':
$this->handle_order_status( $order, $wc_order_status );
$order->add_order_note( __( 'Shopper transferred the payment for the invoice. Awaiting blockchain network confirmation.', 'coingate' ) );
break;
case 'invalid':
$this->handle_order_status( $order, $wc_order_status );
$order->add_order_note( __( 'Payment rejected by the network or did not confirm within 7 days.', 'coingate' ) );
break;
case 'expired':
$this->handle_order_status( $order, $wc_order_status );
$order->add_order_note( __( 'Buyer did not pay within the required time and the invoice expired.', 'coingate' ) );
break;
case 'canceled':
$this->handle_order_status( $order, $wc_order_status );
$order->add_order_note( __( 'Buyer canceled the invoice.', 'coingate' ) );
break;
case 'refunded':
$this->handle_order_status( $order, $wc_order_status );
$order->add_order_note( __( 'Payment was refunded to the buyer.', 'coingate' ) );
break;
if ( 'processing' === $order->status && ( $status_was === $wc_expired_status || $status_was === $wc_canceled_status ) ) {
WC()->mailer()->emails['WC_Email_Customer_Processing_Order']->trigger( $order->get_id() );
}
if ( ( 'processing' === $order->status || 'completed' === $order->status ) && ( $status_was === $wc_expired_status || $status_was === $wc_canceled_status ) ) {
WC()->mailer()->emails['WC_Email_New_Order']->trigger( $order->get_id() );
}
break;
case 'confirming':
$this->handle_order_status( $order, $wc_order_status );
$order->add_order_note( __( 'Shopper transferred the payment for the invoice. Awaiting blockchain network confirmation.', 'coingate' ) );
break;
case 'invalid':
$this->handle_order_status( $order, $wc_order_status );
$order->add_order_note( __( 'Payment rejected by the network or did not confirm within 7 days.', 'coingate' ) );
break;
case 'expired':
$this->handle_order_status( $order, $wc_order_status );
$order->add_order_note( __( 'Buyer did not pay within the required time and the invoice expired.', 'coingate' ) );
break;
case 'canceled':
$this->handle_order_status( $order, $wc_order_status );
$order->add_order_note( __( 'Buyer canceled the invoice.', 'coingate' ) );
break;
case 'refunded':
$this->handle_order_status( $order, $wc_order_status );
$order->add_order_note( __( 'Payment was refunded to the buyer.', 'coingate' ) );
break;
}

$logger->info(
'Callback processed for #' . $order->get_id(),
array(
'source' => 'coingate-for-woocommerce',
'request' => $request,
)
);
} catch ( Exception $e ) {
$logger->error(
'Failed to process callback for #' . $order->get_id() . ': ' . $e->getMessage(),
array(
'source' => 'coingate-for-woocommerce',
'request' => $request,
'order_token' => $order->get_meta( static::ORDER_TOKEN_META_KEY ),
'backtrace' => true,
)
);

// Useful for debugging on CoinGate side
wp_send_json_error( array(
'order_id' => $order->get_id(),
'has_token' => ! empty( $order->get_meta( static::ORDER_TOKEN_META_KEY ) ),
'message' => $e->getMessage(),
), 500 );
}
}

Expand Down