From 9d291d61dc02fa2d07849e9da1e833f5484c343a Mon Sep 17 00:00:00 2001 From: Razorpay Date: Tue, 12 Dec 2023 13:48:00 +0530 Subject: [PATCH 01/91] webhook conflict error message as info --- includes/razorpay-webhook.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/razorpay-webhook.php b/includes/razorpay-webhook.php index ae836493..58530883 100644 --- a/includes/razorpay-webhook.php +++ b/includes/razorpay-webhook.php @@ -159,18 +159,18 @@ public function process() update_post_meta($orderId, "rzp_webhook_notified_at", time()); } - error_log("ORDER NUMBER $orderId:webhook conflict due to early execution for razorpay order: $razorpayOrderId "); + rzpLogInfo("ORDER NUMBER $orderId:webhook conflict due to early execution for razorpay order: $razorpayOrderId "); header('Status: ' . static::HTTP_CONFLICT_STATUS . ' Webhook conflicts due to early execution.', true, static::HTTP_CONFLICT_STATUS);// nosemgrep : php.lang.security.non-literal-header.non-literal-header return; } elseif ((time() - $rzpWebhookNotifiedAt) < static::WEBHOOK_NOTIFY_WAIT_TIME) { - error_log("ORDER NUMBER $orderId:webhook conflict due to early execution for razorpay order: $razorpayOrderId "); + rzpLogInfo("ORDER NUMBER $orderId:webhook conflict due to early execution for razorpay order: $razorpayOrderId "); header('Status: ' . static::HTTP_CONFLICT_STATUS . ' Webhook conflicts due to early execution.', true, static::HTTP_CONFLICT_STATUS);// nosemgrep : php.lang.security.non-literal-header.non-literal-header return; } - error_log("ORDER NUMBER $orderId:webhook conflict over for razorpay order: $razorpayOrderId"); + rzpLogInfo("ORDER NUMBER $orderId:webhook conflict over for razorpay order: $razorpayOrderId"); rzpLogInfo("Woocommerce orderId: $orderId webhook process intitiated"); From 174b706b63ad495eda9af49e2079253bf88c8e36 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Tue, 26 Dec 2023 18:04:26 +0530 Subject: [PATCH 02/91] Add option fix for 1cc address pull cron job script --- includes/cron/one-click-checkout/one-cc-address-sync.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/cron/one-click-checkout/one-cc-address-sync.php b/includes/cron/one-click-checkout/one-cc-address-sync.php index 74ebb9ad..babc3fae 100644 --- a/includes/cron/one-click-checkout/one-cc-address-sync.php +++ b/includes/cron/one-click-checkout/one-cc-address-sync.php @@ -426,7 +426,7 @@ function createOneCCAddressSyncCron() rzpLogInfo("createOneCCAddressSyncCron:426 - Adding option: ONE_CC_ADDRESS_SYNC_CRON_HOOK"); add_option( Constants::ONE_CC_ADDRESS_SYNC_CRON_HOOK, - $data, + $data ); rzpLogInfo("createOneCCAddressSyncCron:432 - Successfully Added option: ONE_CC_ADDRESS_SYNC_CRON_HOOK"); } From 5e9fd82b00b2f596da6d1f2e7bb378205858904f Mon Sep 17 00:00:00 2001 From: yashgit891 <56789472+yashgit891@users.noreply.github.com> Date: Thu, 28 Dec 2023 20:47:16 +0530 Subject: [PATCH 03/91] PO-54 : PHP 7 Webhook issue (#521) --- includes/razorpay-webhook.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/razorpay-webhook.php b/includes/razorpay-webhook.php index 58530883..3a0f3507 100644 --- a/includes/razorpay-webhook.php +++ b/includes/razorpay-webhook.php @@ -12,12 +12,12 @@ class RZP_Webhook /** * @var HTTP CONFLICT Request */ - protected const HTTP_CONFLICT_STATUS = 409; + const HTTP_CONFLICT_STATUS = 409; /** * @var Webhook Notify Wait Time */ - protected const WEBHOOK_NOTIFY_WAIT_TIME = (5 * 60); + const WEBHOOK_NOTIFY_WAIT_TIME = (5 * 60); /** * Instance of the razorpay payments class From 66a26a099172bdabd8ee0919b5011ccdbd6f54f6 Mon Sep 17 00:00:00 2001 From: yashgit891 <56789472+yashgit891@users.noreply.github.com> Date: Tue, 2 Jan 2024 11:59:45 +0530 Subject: [PATCH 04/91] Version bump 4.5.8 (#522) * Version bump 4.5.8 --- readme.txt | 7 ++++++- woo-razorpay.php | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/readme.txt b/readme.txt index 80d38614..bd13e256 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: razorpay Tags: razorpay, payments, india, woocommerce, curlec, malaysia, ecommerce, international, cross border Requires at least: 3.9.2 Tested up to: 6.3.1 -Stable tag: 4.5.7 +Stable tag: 4.5.8 Requires PHP: 7.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -69,6 +69,11 @@ Razorpay is available for Store Owners and Merchants in == Changelog == += 4.5.8 = +* Bug fix, plugin not activating in php 7.0. +* Add option fix for 1cc address pull cron job script. +* Webhook conflict error message as info + = 4.5.7 = * Added nonce and user capability check for route * Blocked currencies KWD, OMR, BHD. diff --git a/woo-razorpay.php b/woo-razorpay.php index dd7ac522..5779bc94 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -3,8 +3,8 @@ * Plugin Name: Razorpay for WooCommerce * Plugin URI: https://razorpay.com * Description: Razorpay Payment Gateway Integration for WooCommerce - * Version: 4.5.7 - * Stable tag: 4.5.7 + * Version: 4.5.8 + * Stable tag: 4.5.8 * Author: Team Razorpay * WC tested up to: 7.9.0 * Author URI: https://razorpay.com From 3f264cd52254c0c0bde1bdd74942e06b2e5ab95d Mon Sep 17 00:00:00 2001 From: yashgit891 <56789472+yashgit891@users.noreply.github.com> Date: Mon, 15 Jan 2024 12:18:18 +0530 Subject: [PATCH 05/91] Plugin name update (#523) --- woo-razorpay.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index 5779bc94..12bb194d 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -1,8 +1,8 @@ Date: Mon, 15 Jan 2024 12:26:21 +0530 Subject: [PATCH 06/91] Version bump 4.5.9 (#525) --- readme.txt | 5 ++++- woo-razorpay.php | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/readme.txt b/readme.txt index bd13e256..fe7f0a1b 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: razorpay Tags: razorpay, payments, india, woocommerce, curlec, malaysia, ecommerce, international, cross border Requires at least: 3.9.2 Tested up to: 6.3.1 -Stable tag: 4.5.8 +Stable tag: 4.5.9 Requires PHP: 7.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -69,6 +69,9 @@ Razorpay is available for Store Owners and Merchants in == Changelog == += 4.5.9 = +* Plugin name and description updated. + = 4.5.8 = * Bug fix, plugin not activating in php 7.0. * Add option fix for 1cc address pull cron job script. diff --git a/woo-razorpay.php b/woo-razorpay.php index 12bb194d..50bdca76 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -3,8 +3,8 @@ * Plugin Name: 1 Razorpay: Signup for FREE PG * Plugin URI: https://razorpay.com * Description: Razorpay Payment Gateway Integration for WooCommerce.Razorpay Welcome Back Offer: New to Razorpay? Sign up to enjoy FREE payments* of INR 2 lakh till March 31st! Transact before January 10th to grab the offer. - * Version: 4.5.8 - * Stable tag: 4.5.8 + * Version: 4.5.9 + * Stable tag: 4.5.9 * Author: Team Razorpay * WC tested up to: 7.9.0 * Author URI: https://razorpay.com From ecfadea0ed2811d9047d7966c4d8accbe5343e95 Mon Sep 17 00:00:00 2001 From: Anantha-Perumal Date: Mon, 22 Jan 2024 09:39:12 +0530 Subject: [PATCH 07/91] feat: TerraWallet --- includes/api/cart.php | 43 ++++++++++++++--- woo-razorpay.php | 108 +++++++++++++++++++++++++++++------------- 2 files changed, 112 insertions(+), 39 deletions(-) diff --git a/includes/api/cart.php b/includes/api/cart.php index c3c70d33..e09986d8 100644 --- a/includes/api/cart.php +++ b/includes/api/cart.php @@ -5,7 +5,7 @@ // Fetch cart data on cart and mini cart page -use Automattic\WooCommerce\Utilities\OrderUtil; +use Automattic\WooCommerce\Utilities\OrderUtil; function fetchCartData(WP_REST_Request $request) { @@ -39,6 +39,10 @@ function fetchCartData(WP_REST_Request $request) $response = cartResponse($couponCode); + $response['user'] = getCartUserObject(); + + $response['plugins'] = getPluginsDetails(); + return new WP_REST_Response($response, 200); } @@ -90,9 +94,34 @@ function createCartData(WP_REST_Request $request) $response = cartResponse($couponCode); + $response['user'] = getCartUserObject(); + + $response['plugins'] = getPluginsDetails(); + return new WP_REST_Response($response, 200); } +function getCartUserObject(): array { + $user = [ + "logged_in" => false, + ]; + if (is_user_logged_in()) { + $current_user = wp_get_current_user(); + $user['logged_in'] = true; + $user['email'] = $current_user->user_email; + } + return $user; +} + +function getPluginsDetails(): array { + $pluginData = []; + if (is_plugin_active('woo-wallet/woo-wallet.php')) + { + $pluginData['terra-wallet'] = ['active' => true]; + } + return $pluginData; +} + /** * Create the cart object for the line items exist in order */ @@ -134,8 +163,8 @@ function getCartLineItem() $cart = WC()->cart->get_cart(); $i = 0; - foreach($cart as $item_id => $item) { - $product = wc_get_product( $item['product_id']); + foreach($cart as $item_id => $item) { + $product = wc_get_product( $item['product_id']); $price = round($item['line_subtotal']*100) + round($item['line_subtotal_tax']*100); $type = "e-commerce"; @@ -146,7 +175,7 @@ function getCartLineItem() if($product->is_type('variation')){ $parentProductId = $product->get_parent_id(); $parentProduct = wc_get_product($parentProductId); - + if($parentProduct->get_type() == 'pw-gift-card' || $parentProduct->get_type() == 'gift-card'){ $type = 'gift_card'; } @@ -154,7 +183,7 @@ function getCartLineItem() }else{ if($product->get_type() == 'pw-gift-card' || $product->get_type() == 'gift-card'){ - $type = 'gift_card'; + $type = 'gift_card'; } } } @@ -172,7 +201,7 @@ function getCartLineItem() $data[$i]['variant_id'] = $item['variation_id']; $data[$i]['offer_price'] = (empty($productDetails['sale_price'])=== false) ? (int) $productDetails['sale_price']*100 : $price/$item['quantity']; $i++; - } + } return $data; } @@ -220,7 +249,7 @@ function cartResponse($couponCode){ $response['enable_ga_analytics'] = get_option('woocommerce_razorpay_settings')['enable_1cc_ga_analytics'] === 'yes' ? true : false; $response['enable_fb_analytics'] = get_option('woocommerce_razorpay_settings')['enable_1cc_fb_analytics'] === 'yes' ? true : false; - + $response += ['redirect' => true, 'one_click_checkout' => true, 'mandatory_login' => false, 'key' => get_option('woocommerce_razorpay_settings')['key_id'], 'name' => html_entity_decode(get_bloginfo('name'), ENT_QUOTES), 'currency' => 'INR']; return $response; diff --git a/woo-razorpay.php b/woo-razorpay.php index dd7ac522..c3ef160d 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -228,7 +228,7 @@ public function __construct($hooks = true) // file added in woocommerce v7.1.0, maybe removed later if (class_exists('Automattic\WooCommerce\Utilities\OrderUtil') and - OrderUtil::custom_orders_table_usage_is_enabled()) + OrderUtil::custom_orders_table_usage_is_enabled()) { $this->isHposEnabled = true; } @@ -237,7 +237,7 @@ public function __construct($hooks = true) // 1cc flags should be enabled only if merchant has access to 1cc feature $is1ccAvailable = false; $isAccCreationAvailable = false; - + // Load preference API call only for administrative interface page. if (current_user_can('administrator')) { @@ -673,15 +673,15 @@ public function pluginInstrumentation() $orderTable = $wpdb->prefix . 'wc_orders'; - if($this->isHposEnabled) + if($this->isHposEnabled) { $rzpTrancationData = $wpdb->get_row($wpdb->prepare("SELECT id FROM $orderTable AS P WHERE payment_method = %s", "razorpay")); - } - else + } + else { $rzpTrancationData = $wpdb->get_row($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta AS P WHERE meta_key = %s AND meta_value = %s", "_payment_method", "razorpay")); - } - + } + $arrayPost = json_decode(json_encode($rzpTrancationData), true); if (empty($arrayPost) === false and @@ -1144,7 +1144,7 @@ protected function createRazorpayOrderId($orderId, $sessionKey) { throw new Exception($data['currency'] . " currency is not supported at the moment."); } - + $razorpayOrder = $api->order->create($data); } catch (Exception $e) @@ -1234,7 +1234,7 @@ protected function verifyOrderAmount($razorpayOrderId, $orderId, $is1ccCheckout private function getOrderCreationData($orderId) { global $wpdb; - + rzpLogInfo("Called getOrderCreationData with params orderId $orderId"); $order = wc_get_order($orderId); @@ -1496,7 +1496,7 @@ public function process_refund($orderId, $amount = null, $reason = '') } // process refund for gift card - function processGiftCardRefund($orderId, $razorpayPaymentId, $amount = null, $reason = '') + function processRefund($orderId, $razorpayPaymentId, $amount = null, $reason = '') { $order = wc_get_order($orderId); @@ -1632,27 +1632,27 @@ function check_razorpay_response() $orderOperationalDataTable = $wpdb->prefix . 'wc_order_operational_data'; $orderTable = $wpdb->prefix . 'wc_orders'; - if ($this->isHposEnabled) + if ($this->isHposEnabled) { $orderOperationalData = $wpdb->get_row($wpdb->prepare("SELECT order_id FROM $orderOperationalDataTable AS P WHERE order_key = %s", $post_password)); - + $orderData = $wpdb->get_row($wpdb->prepare("SELECT status FROM $orderTable AS P WHERE id = %s", $orderOperationalData->order_id)); - } else + } else { $orderOperationalData = $wpdb->get_row($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta AS P WHERE meta_key = %s AND meta_value = %s", $meta_key, $post_password)); $orderData = $wpdb->get_row($wpdb->prepare("SELECT post_status FROM $wpdb->posts AS P WHERE post_type=%s and ID=%s", $post_type, $orderOperationalData->post_id)); } - + $arrayPost = json_decode(json_encode($orderOperationalData), true); if (!empty($arrayPost) and $arrayPost != null) { - if ($this->isHposEnabled) + if ($this->isHposEnabled) { $orderId = $orderOperationalData->order_id; - + $order = wc_get_order($orderId); if ($orderData->status === 'wc-checkout-draft') @@ -1662,7 +1662,7 @@ function check_razorpay_response() } $orderStatus = $order->get_status(); rzpLogInfo("HPOS is enabled and order status: $orderStatus"); - } + } else { $orderId = $orderOperationalData->post_id; @@ -1676,7 +1676,7 @@ function check_razorpay_response() $orderStatus = $order->get_status(); rzpLogInfo("HPOS is disabled and order status: $orderStatus"); } - + rzpLogInfo("Get order id in check_razorpay_response: orderId $orderId"); } @@ -1697,12 +1697,12 @@ function check_razorpay_response() // If the order has already been paid for // redirect user to success page - if (($order->needs_payment() === false) and - ($orderStatus != 'draft') and + if (($order->needs_payment() === false) and + ($orderStatus != 'draft') and ($orderStatus != 'wc-checkout-draft')) { rzpLogInfo("Order payment is already done for the orderId: " . $orderId . " order status " . $orderStatus); - + $cartHash = get_transient(RZP_1CC_CART_HASH.$orderId); if ($cartHash != false) @@ -2025,7 +2025,7 @@ public function update1ccOrderWC(& $order, $wcOrderId, $razorpayPaymentId) } // update gift card and coupons - $rzpPromotionAmount = $this->updateGiftAndCoupon($razorpayData, $order, $wcOrderId, $razorpayPaymentId); + $rzpPromotionAmount = $this->handlePromotions($razorpayData, $order, $wcOrderId, $razorpayPaymentId); //Apply shipping charges to woo-order if(isset($razorpayData['shipping_fee']) === true) @@ -2053,7 +2053,7 @@ public function update1ccOrderWC(& $order, $wcOrderId, $razorpayPaymentId) else { $isStoreShippingEnabled = ""; - if ($this->isHposEnabled) + if ($this->isHposEnabled) { $shippingData = $order->get_meta('1cc_shippinginfo'); @@ -2139,7 +2139,7 @@ public function update1ccOrderWC(& $order, $wcOrderId, $razorpayPaymentId) $paymentDoneBy = $razorpayPaymentData['method']; - $codFee = 0; + $codFee = 0; if (($paymentDoneBy === 'cod') && isset($razorpayData['cod_fee']) == true) { $codFee = $razorpayData['cod_fee']/100; @@ -2213,7 +2213,7 @@ public function update1ccOrderWC(& $order, $wcOrderId, $razorpayPaymentId) } } - public function updateGiftAndCoupon($razorpayData, $order, $orderId, $razorpayPaymentId) + public function handlePromotions($razorpayData, $order, $orderId, $razorpayPaymentId) { global $woocommerce; global $wpdb; @@ -2238,7 +2238,7 @@ public function updateGiftAndCoupon($razorpayData, $order, $orderId, $razorpayPa if($giftCardBalance == null && $giftCardBalance >= 0 && $usedAmt > $giftCardBalance && 'trash' == $status && !$yithCard->exists()){ // initiate refund in case gift card faliure - $this->processGiftCardRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); + $this->processRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); }else{ //Deduct amount of gift card $yithCard->update_balance( $yithCard->get_balance() - $usedAmt ); @@ -2274,21 +2274,53 @@ public function updateGiftAndCoupon($razorpayData, $order, $orderId, $razorpayPa if($balance == null && $balance >= 0 && $usedAmt > $balance ){ // initiate refund in case gift card faliure - $this->processGiftCardRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); + $this->processRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); }else{ //Deduct amount of gift card $this->debitGiftCards($orderId, $order, "order_id: $orderId checkout_update_order_meta", $usedAmt, $giftCode); } }else{ - $this->processGiftCardRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); + $this->processRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); } }else{ - $this->processGiftCardRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); + $this->processRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); } - }else{ + }else if($promotion['type'] == 'terra_wallet') { + if (!is_plugin_active('woo-wallet/woo-wallet.php')) { + $this->processRefund( + $orderId, + $razorpayPaymentId, + $razorpayData['amount_paid'], + 'Terra Wallet Plugin is not active'); + } + $viaWalletAmount = $promotion['value']/100; + $walletBalance = woo_wallet()->wallet->get_wallet_balance($order->get_user_id(), 'edit'); + if ($walletBalance < $viaWalletAmount) + { + $this->processRefund( + $orderId, + $razorpayPaymentId, + $razorpayData['amount_paid'], + 'Terra Wallet Insufficient Balance'); + } + $this->addTerraWalletAmountAsPartialPaymentFee($viaWalletAmount, $order); + woo_wallet()->wallet->wallet_partial_payment($orderId); + $terraWalletTransactionID = get_post_meta( $orderId, '_partial_pay_through_wallet_compleate', true ); + if(!$terraWalletTransactionID) { + $this->processRefund( + $orderId, + $razorpayPaymentId, + $razorpayData['amount_paid'], + 'Terra Wallet Transaction Failed'); + }else { + rzpLogInfo("TerraWallet TransactionID for order id $orderId is $terraWalletTransactionID"); + } + } + else{ + $couponKey = $promotion['code']; @@ -2303,6 +2335,18 @@ public function updateGiftAndCoupon($razorpayData, $order, $orderId, $razorpayPa return $rzpGiftAndCouponAmount; } + private function addTerraWalletAmountAsPartialPaymentFee($amount, $order) { + if ( $amount > 0 ) { + $itemFee = new WC_Order_Item_Fee(); + $itemFee->set_name(__( 'Via wallet', 'woo-wallet' )); + $itemFee->set_amount(-1.0 * $amount); + $itemFee->set_tax_status('none'); + $itemFee->set_total(-1.0 * $amount); + $order->add_item($itemFee); + $order->save(); + } + } + protected function debitGiftCards( $orderId, $order, $note, $usedAmt, $giftCardNo) { global $woocommerce; @@ -2542,7 +2586,7 @@ protected function updateRecoverCartInfo($wcOrderId) }else{ $userId = get_post_meta($wcOrderId, 'abandoned_user_id', true); } - + } $results = $wpdb->get_results( // phpcs:ignore @@ -2564,7 +2608,7 @@ protected function updateRecoverCartInfo($wcOrderId) } $abandonedOrderId = wcal_common::wcal_get_cart_session('abandoned_cart_id_lite'); - + if ($this->isHposEnabled) { $order->update_meta_data( 'abandoned_id', $abandonedOrderId); $order->save(); From 7788cf47c60c3584adf111f5e7ed1c6398fc1111 Mon Sep 17 00:00:00 2001 From: yashgit891 <56789472+yashgit891@users.noreply.github.com> Date: Tue, 23 Jan 2024 17:25:31 +0530 Subject: [PATCH 08/91] Instant refund speed addition (#530) * Instant refund speed addition * Added object availability check --- woo-razorpay.php | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index 50bdca76..b9c098aa 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -1465,6 +1465,7 @@ public function process_refund($orderId, $amount = null, $reason = '') $data = array( 'amount' => (int) round($amount * 100), + 'speed' => "optimum", 'notes' => array( 'reason' => $reason, 'order_id' => $orderId, @@ -1479,13 +1480,20 @@ public function process_refund($orderId, $amount = null, $reason = '') ->fetch( $paymentId ) ->refund( $data ); - $order->add_order_note( __( 'Refund Id: ' . $refund->id, 'woocommerce' ) ); - /** - * @var $refund ->id -- Provides the RazorPay Refund ID - * @var $orderId -> Refunded Order ID - * @var $refund -> WooCommerce Refund Instance. - */ - do_action( 'woo_razorpay_refund_success', $refund->id, $orderId, $refund ); + if (isset($refund) === true) + { + $order->add_order_note( __( 'Refund Id: ' . $refund->id, 'woocommerce' ) ); + /** + * @var $refund ->id -- Provides the RazorPay Refund ID + * @var $orderId -> Refunded Order ID + * @var $refund -> WooCommerce Refund Instance. + */ + do_action( 'woo_razorpay_refund_success', $refund->id, $orderId, $refund ); + + rzpLogInfo( 'Refund ID = ' . $refund->id . + ' , Refund speed requested = ' . $refund->speed_requested . + ' , Refund speed processed = ' . $refund->speed_processed); + } return true; } From 16a671e52d6cbd5e4de3464dbbbdc1c5d9e6e91e Mon Sep 17 00:00:00 2001 From: yashgit891 <56789472+yashgit891@users.noreply.github.com> Date: Tue, 23 Jan 2024 17:27:10 +0530 Subject: [PATCH 09/91] Rtb widget (#528) * Razorpay Trusted Badge Widget --- woo-razorpay.php | 96 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/woo-razorpay.php b/woo-razorpay.php index b9c098aa..852b0a24 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -396,6 +396,15 @@ public function init_form_fields() } } + $this->form_fields['rtb_widget_title'] = array( + 'title' => '' . __('Razorpay Trusted Business'). '', + 'type' => 'title' + ); + + $this->form_fields['enable_rtb_widget'] = array( + 'title' => '' . __('Sorry, your business is currently not eligible for RTB.') . '', + 'type' => 'title' + ); //Affordability Widget Code if (is_admin()) { @@ -406,10 +415,12 @@ public function init_form_fields() isset($_POST['woocommerce_razorpay_key_secret']) and empty($_POST['woocommerce_razorpay_key_secret']) === false) { + $key_id = $_POST['woocommerce_razorpay_key_id']; $api = new Api($_POST['woocommerce_razorpay_key_id'], $_POST['woocommerce_razorpay_key_secret']); } else { + $key_id = $this->getSetting('key_id'); $api = $this->getRazorpayApiInstance(); } @@ -421,6 +432,8 @@ public function init_form_fields() } update_option('rzp_afd_enable', 'no'); + update_option('rzp_rtb_enable', 'no'); + foreach ($merchantPreferences['assigned_features'] as $preference) { if ($preference['name'] === 'affordability_widget' or @@ -434,7 +447,31 @@ public function init_form_fields() } } + foreach ($merchantPreferences['assigned_features'] as $preference) + { + if ($preference['name'] === 'rtb_widget_enabled') + { + $rtbActivationStatus = $api->request->request('GET', 'rtb?key_id=' . $key_id); + + if (isset($rtbActivationStatus['widget_enabled']) and + $rtbActivationStatus['widget_enabled'] === true) + { + $this->form_fields['enable_rtb_widget'] = array( + 'title' => __('RTB Widget Enable/Disable'), + 'type' => 'checkbox', + 'desc' => __('Enable RTB Widget?'), + 'default' => 'no', + 'id' => 'rzp_rtb_enable' + ); + update_option('rzp_rtb_enable', 'yes'); + } + + break; + } + } + update_option('rzp_afd_feature_checked', 'yes'); + update_option('rzp_rtb_feature_checked', 'yes'); } catch (\Exception $e) { @@ -2768,6 +2805,8 @@ function razorpay_woo_plugin_links($links) add_action( 'woocommerce_before_single_product', 'trigger_affordability_widget', 10 ); + add_action( 'woocommerce_after_add_to_cart_button', 'trigger_rtb_widget', 10 ); + function trigger_affordability_widget() { if (empty(get_option('rzp_afd_enable')) === false and @@ -2813,6 +2852,63 @@ function trigger_affordability_widget() } } } + + function trigger_rtb_widget() + { + if (empty(get_option('rzp_rtb_feature_checked')) === true or + get_option('rzp_rtb_feature_checked') === 'no') + { + try + { + $api = new Api(get_option('woocommerce_razorpay_settings')['key_id'], get_option('woocommerce_razorpay_settings')['key_secret']); + $merchantPreferences = $api->request->request('GET', 'accounts/me/features'); + if (isset($merchantPreferences) === false or + isset($merchantPreferences['assigned_features']) === false) + { + throw new Exception("Error in Api call."); + } + + update_option('rzp_rtb_enable', 'no'); + foreach ($merchantPreferences['assigned_features'] as $preference) + { + if ($preference['name'] === 'rtb_widget_enabled') + { + $rtbActivationStatus = $api->request->request('GET', 'rtb?key_id=' . get_option('woocommerce_razorpay_settings')['key_id']); + + if (isset($rtbActivationStatus['widget_enabled']) and + $rtbActivationStatus['widget_enabled'] === true) + { + update_option('rzp_rtb_enable', 'yes'); + } + + break; + } + } + + update_option('rzp_rtb_feature_checked', 'yes'); + } + catch(\Exception $e) + { + rzpLogError($e->getMessage()); + return; + } + } + + if (empty(get_option('woocommerce_razorpay_settings')) === false and + get_option('woocommerce_razorpay_settings')['enable_rtb_widget'] === 'yes' and + empty(get_option('rzp_rtb_enable')) === false and + get_option('rzp_rtb_enable') === 'yes') + { + $key_id = get_option('woocommerce_razorpay_settings')['key_id']; + echo ' + +
+ + +
'; + + } + } } // This is set to a priority of 10 From 06ce6a9e10e3bcd760f7905aa7120afeab6593b3 Mon Sep 17 00:00:00 2001 From: Anantha-Perumal Date: Wed, 24 Jan 2024 19:42:07 +0530 Subject: [PATCH 10/91] fix: order amount not updated while applying wallet amount --- woo-razorpay.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index c3ef160d..3f176969 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -2337,12 +2337,14 @@ public function handlePromotions($razorpayData, $order, $orderId, $razorpayPayme private function addTerraWalletAmountAsPartialPaymentFee($amount, $order) { if ( $amount > 0 ) { + $walletAmount = -1.0 * $amount; $itemFee = new WC_Order_Item_Fee(); $itemFee->set_name(__( 'Via wallet', 'woo-wallet' )); - $itemFee->set_amount(-1.0 * $amount); + $itemFee->set_amount($walletAmount); $itemFee->set_tax_status('none'); - $itemFee->set_total(-1.0 * $amount); + $itemFee->set_total($walletAmount); $order->add_item($itemFee); + $order->set_total($order->get_total() - $amount); $order->save(); } } From 1642295ddd6306b95b480cbf26b1e729fd80b07f Mon Sep 17 00:00:00 2001 From: Anantha-Perumal Date: Sun, 28 Jan 2024 12:52:03 +0530 Subject: [PATCH 11/91] fix: terrawallet not working properly with shipping fee and refactor: review changes and added comments --- woo-razorpay.php | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index 3f176969..483264ed 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -1495,8 +1495,8 @@ public function process_refund($orderId, $amount = null, $reason = '') } } - // process refund for gift card - function processRefund($orderId, $razorpayPaymentId, $amount = null, $reason = '') + // process refund for rzp payment and WC gift card + function processRefundForOrdersWithGiftCard($orderId, $razorpayPaymentId, $amount = null, $reason = '') { $order = wc_get_order($orderId); @@ -2024,9 +2024,6 @@ public function update1ccOrderWC(& $order, $wcOrderId, $razorpayPaymentId) $order->add_order_note( "Order Instructions: ". $orderInstructions); } - // update gift card and coupons - $rzpPromotionAmount = $this->handlePromotions($razorpayData, $order, $wcOrderId, $razorpayPaymentId); - //Apply shipping charges to woo-order if(isset($razorpayData['shipping_fee']) === true) { @@ -2172,7 +2169,10 @@ public function update1ccOrderWC(& $order, $wcOrderId, $razorpayPaymentId) $order->save(); } - if(!empty($razorpayData['offers'])) + // handle promotions in order which include handling coupons, gift cards and terra wallet if applicable + $rzpPromotionAmount = $this->handlePromotions($razorpayData, $order, $wcOrderId, $razorpayPaymentId); + + if(!empty($razorpayData['offers'])) { $offerDiff = $razorpayData['line_items_total'] + $razorpayData['shipping_fee'] + $codFee*100 - $razorpayPaymentData['amount'] - $rzpPromotionAmount; @@ -2238,7 +2238,7 @@ public function handlePromotions($razorpayData, $order, $orderId, $razorpayPayme if($giftCardBalance == null && $giftCardBalance >= 0 && $usedAmt > $giftCardBalance && 'trash' == $status && !$yithCard->exists()){ // initiate refund in case gift card faliure - $this->processRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); + $this->processRefundForOrdersWithGiftCard($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); }else{ //Deduct amount of gift card $yithCard->update_balance( $yithCard->get_balance() - $usedAmt ); @@ -2274,23 +2274,23 @@ public function handlePromotions($razorpayData, $order, $orderId, $razorpayPayme if($balance == null && $balance >= 0 && $usedAmt > $balance ){ // initiate refund in case gift card faliure - $this->processRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); + $this->processRefundForOrdersWithGiftCard($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); }else{ //Deduct amount of gift card $this->debitGiftCards($orderId, $order, "order_id: $orderId checkout_update_order_meta", $usedAmt, $giftCode); } }else{ - $this->processRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); + $this->processRefundForOrdersWithGiftCard($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); } }else{ - $this->processRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); + $this->processRefundForOrdersWithGiftCard($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); } }else if($promotion['type'] == 'terra_wallet') { if (!is_plugin_active('woo-wallet/woo-wallet.php')) { - $this->processRefund( + $this->processRefundForOrdersWithGiftCard( $orderId, $razorpayPaymentId, $razorpayData['amount_paid'], @@ -2300,7 +2300,7 @@ public function handlePromotions($razorpayData, $order, $orderId, $razorpayPayme $walletBalance = woo_wallet()->wallet->get_wallet_balance($order->get_user_id(), 'edit'); if ($walletBalance < $viaWalletAmount) { - $this->processRefund( + $this->processRefundForOrdersWithGiftCard( $orderId, $razorpayPaymentId, $razorpayData['amount_paid'], @@ -2310,7 +2310,7 @@ public function handlePromotions($razorpayData, $order, $orderId, $razorpayPayme woo_wallet()->wallet->wallet_partial_payment($orderId); $terraWalletTransactionID = get_post_meta( $orderId, '_partial_pay_through_wallet_compleate', true ); if(!$terraWalletTransactionID) { - $this->processRefund( + $this->processRefundForOrdersWithGiftCard( $orderId, $razorpayPaymentId, $razorpayData['amount_paid'], From 4e909c8f96ce79f4bbcdff9611979c6c651288ad Mon Sep 17 00:00:00 2001 From: yashgit891 <56789472+yashgit891@users.noreply.github.com> Date: Mon, 29 Jan 2024 11:41:55 +0530 Subject: [PATCH 12/91] PO-55 : Webhook secret fetch fix (#531) * PO-55 : Webhook secret fetch fix --- woo-razorpay.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index 852b0a24..32ff5756 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -510,7 +510,9 @@ public function autoEnableWebhook() $key_id = $this->getSetting('key_id'); $key_secret = $this->getSetting('key_secret'); $enabled = true; - $secret = empty($this->getSetting('webhook_secret')) ? $this->generateSecret() : $this->getSetting('webhook_secret'); + $secret = (empty($this->getSetting('webhook_secret')) === true) ? get_option('webhook_secret') : $this->getSetting('webhook_secret'); + + $secret = (empty($secret) === false) ? $secret : $this->generateSecret(); update_option('webhook_secret', $secret); $getWebhookFlag = get_option('webhook_enable_flag'); From 475195a7b5955d8a6e476b378185f1075e73bf2e Mon Sep 17 00:00:00 2001 From: Anantha-Perumal Date: Fri, 2 Feb 2024 18:14:34 +0530 Subject: [PATCH 13/91] handled plugin uninstalled case --- test.php | 3004 ++++++++++++++++++++++++++++++++++++++++++++++ woo-razorpay.php | 46 +- 2 files changed, 3027 insertions(+), 23 deletions(-) create mode 100644 test.php diff --git a/test.php b/test.php new file mode 100644 index 00000000..ac81612d --- /dev/null +++ b/test.php @@ -0,0 +1,3004 @@ +getSetting('key_id'); + $trackObject = $rzp->newTrackPluginInstrumentation($key_id, ''); + $properties = [ + 'isHposEnabled' => true + ]; + + $response = $trackObject->rzpTrackSegment('hpos.interacted', $properties); + $trackObject->rzpTrackDataLake('hpos.interacted', $properties); + + update_option('rzp_hpos', 'yes'); + } + else if(class_exists('Automattic\WooCommerce\Utilities\OrderUtil') and + OrderUtil::custom_orders_table_usage_is_enabled() === false and + get_option('rzp_hpos') === 'yes') + { + $key_id = $rzp->getSetting('key_id'); + $trackObject = $rzp->newTrackPluginInstrumentation($key_id, ''); + $properties = [ + 'isHposEnabled' => false + ]; + + $response = $trackObject->rzpTrackSegment('hpos.interacted', $properties); + $trackObject->rzpTrackDataLake('hpos.interacted', $properties); + + update_option('rzp_hpos', 'no'); + } + } + + if (!class_exists('WC_Payment_Gateway') || class_exists('WC_Razorpay')) + { + return; + } + + class WC_Razorpay extends WC_Payment_Gateway + { + // This one stores the WooCommerce Order Id + const SESSION_KEY = 'razorpay_wc_order_id'; + const RAZORPAY_PAYMENT_ID = 'razorpay_payment_id'; + const RAZORPAY_ORDER_ID = 'razorpay_order_id'; + const RAZORPAY_ORDER_ID_1CC = 'razorpay_order_id_1cc'; + const RAZORPAY_SIGNATURE = 'razorpay_signature'; + const RAZORPAY_WC_FORM_SUBMIT = 'razorpay_wc_form_submit'; + + const INR = 'INR'; + const CAPTURE = 'capture'; + const AUTHORIZE = 'authorize'; + const WC_ORDER_ID = 'woocommerce_order_id'; + const WC_ORDER_NUMBER = 'woocommerce_order_number'; + + const DEFAULT_LABEL = 'Credit Card/Debit Card/NetBanking'; + const DEFAULT_DESCRIPTION = 'Pay securely by Credit or Debit card or Internet Banking through Razorpay.'; + const DEFAULT_SUCCESS_MESSAGE = 'Thank you for shopping with us. Your account has been charged and your transaction is successful. We will be processing your order soon.'; + + const PREPAY_COD_URL = '1cc/orders/cod/convert'; + + protected $supportedWebhookEvents = array( + 'payment.authorized', + 'payment.pending', + 'refund.created', + 'virtual_account.credited', + 'subscription.cancelled', + 'subscription.paused', + 'subscription.resumed', + 'subscription.charged' + ); + + protected $defaultWebhookEvents = array( + 'payment.authorized' => true, + 'refund.created' => true + ); + + protected $visibleSettings = array( + 'enabled', + 'title', + 'description', + 'key_id', + 'key_secret', + 'payment_action', + 'order_success_message', + 'route_enable', + 'enable_1cc_debug_mode', + ); + + public $form_fields = array(); + + public $supports = array( + 'products', + 'refunds' + ); + + /** + * Can be set to true if you want payment fields + * to show on the checkout (if doing a direct integration). + * @var boolean + */ + public $has_fields = false; + + /** + * Unique ID for the gateway + * @var string + */ + public $id = 'razorpay'; + + /** + * Title of the payment method shown on the admin page. + * @var string + */ + public $method_title = 'Razorpay'; + + + /** + * Description of the payment method shown on the admin page. + * @var string + */ + public $method_description = 'Allow customers to securely pay via Razorpay (Credit/Debit Cards, NetBanking, UPI, Wallets)'; + + /** + * Icon URL, set in constructor + * @var string + */ + public $icon; + + /** + * TODO: Remove usage of $this->msg + */ + protected $msg = array( + 'message' => '', + 'class' => '', + ); + + /** + * hpos enabled check + * @var bool + */ + public $isHposEnabled; + + /** + * Return Wordpress plugin settings + * @param string $key setting key + * @return mixed setting value + */ + public function getSetting($key) + { + return $this->get_option($key); + } + + public function getCustomOrdercreationMessage($thank_you_title, $order) + { + $message = $this->getSetting('order_success_message'); + if (isset($message) === false) + { + $message = static::DEFAULT_SUCCESS_MESSAGE; + } + return $message; + } + + /** + * @param boolean $hooks Whether or not to + * setup the hooks on + * calling the constructor + */ + public function __construct($hooks = true) + { + + $this->isHposEnabled = false; + + // file added in woocommerce v7.1.0, maybe removed later + if (class_exists('Automattic\WooCommerce\Utilities\OrderUtil') and + OrderUtil::custom_orders_table_usage_is_enabled()) + { + $this->isHposEnabled = true; + } + + $this->icon = "https://cdn.razorpay.com/static/assets/logo/rzp_payment_icon.svg"; + // 1cc flags should be enabled only if merchant has access to 1cc feature + $is1ccAvailable = false; + $isAccCreationAvailable = false; + + // Load preference API call only for administrative interface page. + if (current_user_can('administrator')) + { + if (!empty($this->getSetting('key_id')) && !empty($this->getSetting('key_secret'))) + { + try { + + $api = $this->getRazorpayApiInstance(); + $merchantPreferences = $api->request->request('GET', 'merchant/1cc_preferences'); + + if (!empty($merchantPreferences['features']['one_click_checkout'])) { + $is1ccAvailable = true; + } + + if (!empty($merchantPreferences['features']['one_cc_store_account'])) { + $isAccCreationAvailable = true; + } + + } catch (\Exception $e) { + rzpLogError($e->getMessage()); + } + + } + } + + if ($is1ccAvailable) { + $this->visibleSettings = array_merge($this->visibleSettings, array( + 'enable_1cc', + 'enable_1cc_mandatory_login', + 'enable_1cc_test_mode', + 'enable_1cc_pdp_checkout', + 'enable_1cc_mini_cart_checkout', + 'enable_1cc_ga_analytics', + 'enable_1cc_fb_analytics', + '1cc_min_cart_amount', + '1cc_min_COD_slab_amount', + '1cc_max_COD_slab_amount', + )); + + if ($isAccCreationAvailable) { + $this->visibleSettings = array_merge($this->visibleSettings, array( + '1cc_account_creation', + )); + } + + } + + $this->init_form_fields(); + $this->init_settings(); + + // TODO: This is hacky, find a better way to do this + // See mergeSettingsWithParentPlugin() in subscriptions for more details. + if ($hooks) + { + $this->initHooks(); + } + + $this->title = $this->getSetting('title'); + } + + protected function initHooks() + { + add_action('woocommerce_receipt_' . $this->id, array($this, 'receipt_page')); + + add_action('woocommerce_api_' . $this->id, array($this, 'check_razorpay_response')); + + $cb = array($this, 'process_admin_options'); + + if (version_compare(WOOCOMMERCE_VERSION, '2.0.0', '>=')) + { + add_action( "woocommerce_update_options_payment_gateways_{$this->id}", array($this, 'pluginInstrumentation')); + add_action("woocommerce_update_options_payment_gateways_{$this->id}", $cb); + add_action( "woocommerce_update_options_payment_gateways_{$this->id}", array($this, 'autoEnableWebhook')); + add_action( "woocommerce_update_options_payment_gateways_{$this->id}", array($this, 'addAdminCheckoutSettingsAlert')); + add_action( "woocommerce_update_options_payment_gateways_{$this->id}", 'createOneCCAddressSyncCron'); + add_action( "woocommerce_update_options_payment_gateways_{$this->id}", 'syncPluginFetchCron'); + } + else + { + add_action( "woocommerce_update_options_payment_gateways", array($this, 'pluginInstrumentation')); + add_action('woocommerce_update_options_payment_gateways', $cb); + add_action( "woocommerce_update_options_payment_gateways", array($this, 'autoEnableWebhook')); + add_action( "woocommerce_update_options_payment_gateways", array($this, 'addAdminCheckoutSettingsAlert')); + add_action( "woocommerce_update_options_payment_gateways", 'createOneCCAddressSyncCron'); + add_action( "woocommerce_update_options_payment_gateways_{$this->id}", 'syncPluginFetchCron'); + } + + add_filter( 'woocommerce_thankyou_order_received_text', array($this, 'getCustomOrdercreationMessage'), 20, 2 ); + } + + public function init_form_fields() + { + $webhookUrl = esc_url(admin_url('admin-post.php')) . '?action=rzp_wc_webhook'; + + $defaultFormFields = array( + 'enabled' => array( + 'title' => __('Enable/Disable', $this->id), + 'type' => 'checkbox', + 'label' => __('Enable this module?', $this->id), + 'default' => 'yes' + ), + 'title' => array( + 'title' => __('Title', $this->id), + 'type'=> 'text', + 'description' => __('This controls the title which the user sees during checkout.', $this->id), + 'default' => __(static::DEFAULT_LABEL, $this->id) + ), + 'description' => array( + 'title' => __('Description', $this->id), + 'type' => 'textarea', + 'description' => __('This controls the description which the user sees during checkout.', $this->id), + 'default' => __(static::DEFAULT_DESCRIPTION, $this->id) + ), + 'key_id' => array( + 'title' => __('Key ID', $this->id), + 'type' => 'text', + 'description' => __('The key Id and key secret can be generated from "API Keys" section of Razorpay Dashboard. Use test or live for test or live mode.', $this->id) + ), + 'key_secret' => array( + 'title' => __('Key Secret', $this->id), + 'type' => 'text', + 'description' => __('The key Id and key secret can be generated from "API Keys" section of Razorpay Dashboard. Use test or live for test or live mode.', $this->id) + ), + 'payment_action' => array( + 'title' => __('Payment Action', $this->id), + 'type' => 'select', + 'description' => __('Payment action on order compelete', $this->id), + 'default' => self::CAPTURE, + 'options' => array( + self::AUTHORIZE => 'Authorize', + self::CAPTURE => 'Authorize and Capture' + ) + ), + 'order_success_message' => array( + 'title' => __('Order Completion Message', $this->id), + 'type' => 'textarea', + 'description' => __('Message to be displayed after a successful order', $this->id), + 'default' => __(STATIC::DEFAULT_SUCCESS_MESSAGE, $this->id), + ), + 'enable_1cc_debug_mode' => array( //Added this config for both native and 1cc merchants + 'title' => __('Activate debug mode'), + 'type' => 'checkbox', + 'description' => 'When debug mode is active, API logs and errors are collected and stored in your Woocommerce dashboard. It is recommended to keep this activated.', + 'label' => __('Enable debug mode'), + 'default' => 'yes', + ), + ); + + do_action_ref_array( 'setup_extra_setting_fields', array( &$defaultFormFields ) ); + + foreach ($defaultFormFields as $key => $value) + { + if (in_array($key, $this->visibleSettings, true)) + { + $this->form_fields[$key] = $value; + } + } + + //Affordability Widget Code + if (is_admin()) + { + try + { + if (isset($_POST['woocommerce_razorpay_key_id']) and + empty($_POST['woocommerce_razorpay_key_id']) === false and + isset($_POST['woocommerce_razorpay_key_secret']) and + empty($_POST['woocommerce_razorpay_key_secret']) === false) + { + $api = new Api($_POST['woocommerce_razorpay_key_id'], $_POST['woocommerce_razorpay_key_secret']); + } + else + { + $api = $this->getRazorpayApiInstance(); + } + + $merchantPreferences = $api->request->request('GET', 'accounts/me/features'); + if (isset($merchantPreferences) === false or + isset($merchantPreferences['assigned_features']) === false) + { + throw new Exception("Error in Api call."); + } + + update_option('rzp_afd_enable', 'no'); + foreach ($merchantPreferences['assigned_features'] as $preference) + { + if ($preference['name'] === 'affordability_widget' or + $preference['name'] === 'affordability_widget_set') + { + add_action('woocommerce_sections_checkout', 'addSubSection'); + add_action('woocommerce_settings_tabs_checkout', 'displayAffordabilityWidgetSettings'); + add_action('woocommerce_update_options_checkout', 'updateAffordabilityWidgetSettings'); + update_option('rzp_afd_enable', 'yes'); + break; + } + } + + update_option('rzp_afd_feature_checked', 'yes'); + } + catch (\Exception $e) + { + rzpLogError($e->getMessage()); + return; + } + } + } + + protected function getWebhookUrl() + { + return esc_url(admin_url('admin-post.php')) . '?action=rzp_wc_webhook'; + } + + protected function triggerValidationInstrumentation($data) + { + $properties = [ + 'page_url' => $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], + 'field_type' => 'text', + 'field_name' => 'key_id or key_secret', + 'is_plugin_activated' => ($this->getSetting('enabled') === 'yes') ? true : false + ]; + + $properties = array_merge($properties, $data); + + $trackObject = $this->newTrackPluginInstrumentation($this->getSetting('key_id'), ''); + $response = $trackObject->rzpTrackSegment('formfield.validation.error', $properties); + $trackObject->rzpTrackDataLake('formfield.validation.error', $properties); + } + + public function autoEnableWebhook() + { + $webhookExist = false; + $webhookUrl = $this->getWebhookUrl(); + + $key_id = $this->getSetting('key_id'); + $key_secret = $this->getSetting('key_secret'); + $enabled = true; + $secret = empty($this->getSetting('webhook_secret')) ? $this->generateSecret() : $this->getSetting('webhook_secret'); + + update_option('webhook_secret', $secret); + $getWebhookFlag = get_option('webhook_enable_flag'); + $time = time(); + + if (empty($getWebhookFlag)) + { + add_option('webhook_enable_flag', $time); + } + else + { + update_option('webhook_enable_flag', $time); + } + //validating the key id and key secret set properly or not. + if($key_id == null || $key_secret == null) + { + $validationErrorProperties = $this->triggerValidationInstrumentation( + ['error_message' => 'Key Id and or Key Secret is null']); + ?> +
+

+
+ getRazorpayApiInstance(); + $validateKeySecret = $api->request->request("GET", "orders"); + } + catch (Exception $e) + { + $validationErrorProperties = $this->triggerValidationInstrumentation( + ['error_message' => 'Invalid Key Id and Key Secret']); + ?> +
+

+
+ $e->getMessage(), + ); + rzpLogError(json_encode($log)); + + return; + } + + $domain = parse_url($webhookUrl, PHP_URL_HOST); + + $domain_ip = gethostbyname($domain); + + if (!filter_var($domain_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) + { + ?> +
+

+
+ webhookAPI("GET", "webhooks?count=".$count."&skip=".$skip); + $skip += 10; + if ($webhook['count'] > 0) + { + foreach ($webhook['items'] as $key => $value) + { + $webhookItems[] = $value; + } + } + } while ( $webhook['count'] === $count); + + $subscriptionWebhookFlag = get_option('rzp_subscription_webhook_enable_flag'); + + if ($subscriptionWebhookFlag) + { + $this->defaultWebhookEvents += array( + 'subscription.cancelled' => true, + 'subscription.resumed' => true, + 'subscription.paused' => true, + 'subscription.charged' => true + ); + } + + $data = [ + 'url' => $webhookUrl, + 'active' => $enabled, + 'events' => $this->defaultWebhookEvents, + 'secret' => $secret, + ]; + + if (count($webhookItems) > 0) + { + foreach ($webhookItems as $key => $value) + { + if ($value['url'] === $webhookUrl) + { + foreach ($value['events'] as $evntkey => $evntval) + { + if (($evntval == 1) and + (in_array($evntkey, $this->supportedWebhookEvents) === true)) + { + $this->defaultWebhookEvents[$evntkey] = true; + } + } + + if (!$subscriptionWebhookFlag) + { + unset($this->defaultWebhookEvents['subscription.cancelled']); + unset($this->defaultWebhookEvents['subscription.resumed']); + unset($this->defaultWebhookEvents['subscription.paused']); + unset($this->defaultWebhookEvents['subscription.charged']); + } + + $data = [ + 'url' => $webhookUrl, + 'active' => $enabled, + 'events' => $this->defaultWebhookEvents, + 'secret' => $secret, + ]; + $webhookExist = true; + $webhookId = $value['id']; + } + } + } + + $webhookProperties = [ + 'page_url' => $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], + 'prev_page_url' => $_SERVER['HTTP_REFERER'], + 'is_plugin_activated' => ($this->getSetting('enabled') === 'yes') ? true : false, + 'events_selected' => $this->defaultWebhookEvents, + ]; + + if ($webhookExist) + { + $trackObject = $this->newTrackPluginInstrumentation($this->getSetting('key_id'), ''); + $response = $trackObject->rzpTrackSegment('autowebhook.updated', $webhookProperties); + $trackObject->rzpTrackDataLake('autowebhook.updated', $webhookProperties); + + rzpLogInfo('Updating razorpay webhook'); + return $this->webhookAPI('PUT', "webhooks/" . $webhookId, $data); + } + else + { + $trackObject = $this->newTrackPluginInstrumentation($this->getSetting('key_id'), ''); + $response = $trackObject->rzpTrackSegment('autowebhook.created', $webhookProperties); + $trackObject->rzpTrackDataLake('autowebhook.created', $webhookProperties); + + rzpLogInfo('Creating razorpay webhook'); + return $this->webhookAPI('POST', "webhooks/", $data); + } + } + + public function newTrackPluginInstrumentation($key, $secret) + { + $api = $this->getRazorpayApiInstance($key, $secret); + + return new TrackPluginInstrumentation($api, $key); + } + + public function pluginInstrumentation() + { + if (empty($_POST['woocommerce_razorpay_key_id']) or + empty($_POST['woocommerce_razorpay_key_secret'])) + { + error_log('Key Id and Key Secret are required.'); + return; + } + + $trackObject = $this->newTrackPluginInstrumentation($_POST['woocommerce_razorpay_key_id'], $_POST['woocommerce_razorpay_key_secret']); + + $existingVersion = get_option('rzp_woocommerce_current_version'); + + if(isset($existingVersion)) + { + update_option('rzp_woocommerce_current_version', get_plugin_data(__FILE__)['Version']); + } + else + { + add_option('rzp_woocommerce_current_version', get_plugin_data(__FILE__)['Version']); + } + + try + { + global $wpdb; + $isTransactingUser = false; + + $orderTable = $wpdb->prefix . 'wc_orders'; + + if($this->isHposEnabled) + { + $rzpTrancationData = $wpdb->get_row($wpdb->prepare("SELECT id FROM $orderTable AS P WHERE payment_method = %s", "razorpay")); + } + else + { + $rzpTrancationData = $wpdb->get_row($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta AS P WHERE meta_key = %s AND meta_value = %s", "_payment_method", "razorpay")); + } + + $arrayPost = json_decode(json_encode($rzpTrancationData), true); + + if (empty($arrayPost) === false and + ($arrayPost == null) === false) + { + $isTransactingUser = true; + } + } + catch (\Razorpay\Api\Errors\Error $e) + { + ?> +
+

+
+ +
+

+
+ getMessage()); + return; + } + + $authEvent = ''; + $pluginStatusEvent = ''; + + $authProperties = [ + 'is_key_id_populated' => true, + 'is_key_secret_populated' => true, + 'page_url' => $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], + 'auth_successful_status' => true, + 'is_plugin_activated' => (isset($_POST['woocommerce_razorpay_enabled'])) ? true :false + ]; + + // for enable and disable plugin + $pluginStatusProperties = [ + 'current_status' => ($this->getSetting('enabled')==='yes') ? 'enabled' :'disabled', + 'is_transacting_user' => $isTransactingUser + ]; + + if (empty($this->getSetting('key_id')) and + empty($this->getSetting('key_secret'))) + { + $authEvent = 'saving auth details'; + + if(empty($_POST['woocommerce_razorpay_enabled']) === false) + { + $pluginStatusEvent = 'plugin enabled'; + } + } + else + { + $authEvent = 'updating auth details'; + } + + $response = $trackObject->rzpTrackSegment($authEvent, $authProperties); + + $trackObject->rzpTrackDataLake($authEvent, $authProperties); + + if ((empty($_POST['woocommerce_razorpay_enabled']) === false) and + ($this->getSetting('enabled') === 'no')) + { + $pluginStatusEvent = 'plugin enabled'; + } + elseif ((empty($_POST['woocommerce_razorpay_enabled']) === true) and + ($this->getSetting('enabled') === 'yes')) + { + $pluginStatusEvent = 'plugin disabled'; + } + + if ($pluginStatusEvent !== '') + { + $response = $trackObject->rzpTrackSegment($pluginStatusEvent, $pluginStatusProperties); + + $trackObject->rzpTrackDataLake($pluginStatusEvent, $pluginStatusProperties); + } + } + + public function generateSecret() + { + $alphanumericString = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-=~!@#$%^&*()_+,./<>?;:[]{}|abcdefghijklmnopqrstuvwxyz'; + $secret = substr(str_shuffle($alphanumericString), 0, 20); + + return $secret; + } + + // showing notice : status of 1cc active / inactive message in admin dashboard + function addAdminCheckoutSettingsAlert() { + $enable_1cc = $this->getSetting('enable_1cc'); + if($enable_1cc == 'no') + { + ?> +
+

+
+ +
+

+
+ getRazorpayApiInstance(); + + $webhook = $api->request->request($method, $url, $data); + } + catch(Exception $e) + { + $log = array( + 'message' => $e->getMessage(), + ); + + error_log(json_encode($log)); + rzpLogError(json_encode($log)); + } + + return $webhook; + } + + public function admin_options() + { + echo '

'.__('Razorpay Payment Gateway', $this->id) . '

'; + echo '

'.__('Allows payments by Credit/Debit Cards, NetBanking, UPI, and multiple Wallets') . '

'; + echo '

'.__('First signup for a Razorpay account or + login if you have an existing account.'). '

'; + echo ''; + + // Generate the HTML For the settings form. + $this->generate_settings_html(); + echo '
'; + } + + public function get_description() + { + return $this->getSetting('description'); + } + + /** + * Receipt Page + * @param string $orderId WC Order Id + **/ + function receipt_page($orderId) + { + foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $value) + { + if ($value['function'] === 'output' and + stripos($value['file'], 'themes/divi') !== false and + basename($value['file'], ".php") !== 'CheckoutPaymentInfo') + { + return; + } + } + + echo $this->generate_razorpay_form($orderId); + } + + /** + * Returns key to use in session for storing Razorpay order Id + * @param string $orderId Razorpay Order Id + * @return string Session Key + */ + protected function getOrderSessionKey($orderId) + { + if ($this->isHposEnabled) { + $order = wc_get_order($orderId); + $is1ccOrder = $order->get_meta('is_magic_checkout_order'); + }else{ + $is1ccOrder = get_post_meta( $orderId, 'is_magic_checkout_order', true ); + } + + if($is1ccOrder == 'yes') + { + return self::RAZORPAY_ORDER_ID_1CC . $orderId; + } + return self::RAZORPAY_ORDER_ID . $orderId; + } + + /** + * Given a order Id, find the associated + * Razorpay Order from the session and verify + * that is is still correct. If not found + * (or incorrect), create a new Razorpay Order + * + * @param string $orderId Order Id + * @return mixed Razorpay Order Id or Exception + */ + public function createOrGetRazorpayOrderId($order, $orderId, $is1ccCheckout = 'no') + { + global $woocommerce; + rzpLogInfo("createOrGetRazorpayOrderId $orderId and is1ccCheckout is set to $is1ccCheckout"); + + $create = false; + + if($is1ccCheckout == 'no') + { + if ($this->isHposEnabled) { + $order->update_meta_data( 'is_magic_checkout_order', 'no' ); + $order->save(); + }else{ + update_post_meta($orderId, 'is_magic_checkout_order', 'no'); + } + + rzpLogInfo("Called createOrGetRazorpayOrderId with params orderId $orderId and is_magic_checkout_order is set to no"); + } + + $sessionKey = $this->getOrderSessionKey($orderId); + + try + { + $razorpayOrderId = get_transient($sessionKey); + rzpLogInfo("razorpayOrderId $razorpayOrderId | sessionKey $sessionKey"); + // If we don't have an Order + // or the if the order is present in transient but doesn't match what we have saved + if (($razorpayOrderId === false) or + (($razorpayOrderId and ($this->verifyOrderAmount($razorpayOrderId, $orderId, $is1ccCheckout)) === false))) + { + $create = true; + } + else + { + return $razorpayOrderId; + } + } + // Order doesn't exist or verification failed + // So try creating one + catch (Exception $e) + { + $create = true; + } + + if ($create) + { + try + { + return $this->createRazorpayOrderId($orderId, $sessionKey); + } + // For the bad request errors, it's safe to show the message to the customer. + catch (Errors\BadRequestError $e) + { + return $e; + } + // For any other exceptions, we make sure that the error message + // does not propagate to the front-end. + catch (Exception $e) + { + return new Exception("Payment failed"); + } + } + } + + /** + * Returns redirect URL post payment processing + * @return string redirect URL + */ + private function getRedirectUrl($orderId) + { + $order = wc_get_order($orderId); + + $query = [ + 'wc-api' => $this->id, + 'order_key' => $order->get_order_key(), + ]; + + return add_query_arg($query, trailingslashit(get_home_url())); + } + + /** + * Specific payment parameters to be passed to checkout + * for payment processing + * @param string $orderId WC Order Id + * @return array payment params + */ + protected function getRazorpayPaymentParams($order, $orderId) + { + $getWebhookFlag = get_option('webhook_enable_flag'); + $time = time(); + if (empty($getWebhookFlag) == false) + { + if ($getWebhookFlag + 86400 < time()) + { + $this->autoEnableWebhook(); + } + } + else + { + update_option('webhook_enable_flag', $time); + $this->autoEnableWebhook(); + } + + rzpLogInfo("getRazorpayPaymentParams $orderId"); + $razorpayOrderId = $this->createOrGetRazorpayOrderId($order, $orderId); + + if ($razorpayOrderId === null) + { + throw new Exception('RAZORPAY ERROR: Razorpay API could not be reached'); + } + else if ($razorpayOrderId instanceof Exception) + { + $message = $razorpayOrderId->getMessage(); + + throw new Exception("RAZORPAY ERROR: Order creation failed with the message: '$message'."); + } + + return [ + 'order_id' => $razorpayOrderId + ]; + } + + /** + * Generate razorpay button link + * @param string $orderId WC Order Id + **/ + public function generate_razorpay_form($orderId) + { + $order = wc_get_order($orderId); + + try + { + $params = $this->getRazorpayPaymentParams($order, $orderId); + } + catch (Exception $e) + { + return $e->getMessage(); + } + + $checkoutArgs = $this->getCheckoutArguments($order, $params); + + $html = '

'.__('Thank you for your order, please click the button below to pay with Razorpay.', $this->id).'

'; + + $html .= $this->generateOrderForm($checkoutArgs); + + return $html; + } + + /** + * default parameters passed to checkout + * @param WC_Order $order WC Order + * @return array checkout params + */ + public function getDefaultCheckoutArguments($order) + { + global $woocommerce; + + $orderId = $order->get_order_number(); + + $wcOrderId = $order->get_id(); + + $callbackUrl = $this->getRedirectUrl($wcOrderId); + + $sessionKey = $this->getOrderSessionKey($wcOrderId); + + $razorpayOrderId = get_transient($sessionKey); + + $productinfo = "Order $orderId"; + + return array( + 'key' => $this->getSetting('key_id'), + 'name' => html_entity_decode(get_bloginfo('name'), ENT_QUOTES), + 'currency' => self::INR, + 'description' => $productinfo, + 'notes' => array( + self::WC_ORDER_ID => $orderId, + self::WC_ORDER_NUMBER => $wcOrderId + ), + 'order_id' => $razorpayOrderId, + 'callback_url' => $callbackUrl, + 'prefill' => $this->getCustomerInfo($order) + ); + } + + /** + * @param WC_Order $order + * @return string currency + */ + private function getOrderCurrency($order) + { + if (version_compare(WOOCOMMERCE_VERSION, '2.7.0', '>=')) + { + return $order->get_currency(); + } + + return $order->get_order_currency(); + } + + /** + * Returns array of checkout params + */ + private function getCheckoutArguments($order, $params) + { + $args = $this->getDefaultCheckoutArguments($order); + + $currency = $this->getOrderCurrency($order); + + // The list of valid currencies is at https://razorpay.freshdesk.com/support/solutions/articles/11000065530-what-currencies-does-razorpay-support- + + $args = array_merge($args, $params); + + return $args; + } + + public function getCustomerInfo($order) + { + if (version_compare(WOOCOMMERCE_VERSION, '2.7.0', '>=')) + { + $args = array( + 'name' => $order->get_billing_first_name() . ' ' . $order->get_billing_last_name(), + 'email' => $order->get_billing_email(), + 'contact' => $order->get_billing_phone(), + ); + } + else + { + $args = array( + 'name' => $order->billing_first_name . ' ' . $order->billing_last_name, + 'email' => $order->billing_email, + 'contact' => $order->billing_phone, + ); + } + + return $args; + } + + protected function createRazorpayOrderId($orderId, $sessionKey) + { + rzpLogInfo("Called createRazorpayOrderId with params orderId $orderId and sessionKey $sessionKey"); + + + // Calls the helper function to create order data + global $woocommerce; + + $api = $this->getRazorpayApiInstance(); + + $data = $this->getOrderCreationData($orderId); + rzpLogInfo('For order ' . $orderId); + rzpLogInfo(json_encode($data)); + try + { + if ($data['currency'] === "KWD" or + $data['currency'] === "OMR" or + $data['currency'] === "BHD") + { + throw new Exception($data['currency'] . " currency is not supported at the moment."); + } + + $razorpayOrder = $api->order->create($data); + } + catch (Exception $e) + { + rzpLogInfo("rzp order error " . $e->getMessage()); + return $e; + } + + $getWebhookFlag = get_option('webhook_enable_flag'); + $time = time(); + + if (empty($getWebhookFlag) == false) + { + if ($getWebhookFlag + 43200 < time()) + { + $this->autoEnableWebhook(); + } + } + else + { + update_option('webhook_enable_flag', $time); + $this->autoEnableWebhook(); + } + + $razorpayOrderId = $razorpayOrder['id']; + + // Storing the razorpay order id in transient for 5 hours time. + set_transient($sessionKey, $razorpayOrderId, 18000); + + // By default woocommerce session TTL is 48 hours. + $woocommerce->session->set($sessionKey, $razorpayOrderId); + + rzpLogInfo('For order session key ' . $sessionKey); + //update it in order comments + $order = wc_get_order($orderId); + + $order->add_order_note("Razorpay OrderId: $razorpayOrderId"); + + return $razorpayOrderId; + } + + protected function verifyOrderAmount($razorpayOrderId, $orderId, $is1ccCheckout = 'no') + { + rzpLogInfo("Called verifyOrderAmount with params orderId $orderId and rzporderId $razorpayOrderId"); + $order = wc_get_order($orderId); + + $api = $this->getRazorpayApiInstance(); + + try + { + $razorpayOrder = $api->order->fetch($razorpayOrderId); + } + catch (Exception $e) + { + $message = $e->getMessage(); + rzpLogInfo("Failed at verifyOrderAmount with $message"); + return "RAZORPAY ERROR: Order fetch failed with the message '$message'"; + } + + $orderCreationData = $this->getOrderCreationData($orderId); + + $razorpayOrderArgs = array( + 'id' => $razorpayOrderId, + 'currency' => $orderCreationData['currency'], + 'receipt' => (string) $orderId, + ); + + if($is1ccCheckout == 'no'){ + $razorpayOrderArgs['amount'] = $orderCreationData['amount']; + }else{ + $razorpayOrderArgs['line_items_total'] = $orderCreationData['amount']; + } + + $orderKeys = array_keys($razorpayOrderArgs); + + foreach ($orderKeys as $key) + { + if ($razorpayOrderArgs[$key] !== $razorpayOrder[$key]) + { + return false; + } + } + + return true; + } + + private function getOrderCreationData($orderId) + { + global $wpdb; + + rzpLogInfo("Called getOrderCreationData with params orderId $orderId"); + $order = wc_get_order($orderId); + + $orderMetaTable = $wpdb->prefix . 'wc_orders_meta'; + + if ($this->isHposEnabled) { + $is1ccOrder = $order->get_meta('is_magic_checkout_order'); + }else{ + $is1ccOrder = get_post_meta( $orderId, 'is_magic_checkout_order', true ); + } + + $data = array( + 'receipt' => (string)$orderId, + 'amount' => (int) round($order->get_total() * 100), + 'currency' => $this->getOrderCurrency($order), + 'payment_capture' => ($this->getSetting('payment_action') === self::AUTHORIZE) ? 0 : 1, + 'app_offer' => ($order->get_discount_total() > 0) ? 1 : 0, + 'notes' => array( + self::WC_ORDER_NUMBER => (string) $orderId, + ), + ); + + if ($this->getSetting('route_enable') == 'yes') + { + $razorpayRoute = new RZP_Route_Action(); + $orderTransferArr = $razorpayRoute->getOrderTransferData($orderId); + + if(isset($orderTransferArr) && !empty($orderTransferArr)){ + + $transferData = array( + 'transfers' => $orderTransferArr + ); + $data = array_merge($data,$transferData); + } + } + + rzpLogInfo("Called getOrderCreationData with params orderId $orderId and is1ccOrder is set to $is1ccOrder"); + + if (is1ccEnabled() && !empty($is1ccOrder) && $is1ccOrder == 'yes') + { + $data = $this->orderArg1CC($data, $order); + rzpLogInfo("Called getOrderCreationData with params orderId $orderId and adding line_items_total"); + } + + return $data; + } + + public function orderArg1CC($data, $order) + { + // TODO: trim to 2 deciamls + $data['line_items_total'] = $order->get_total()*100; + + $i = 0; + // Get and Loop Over Order Items + $type = "e-commerce"; + foreach ( $order->get_items() as $item_id => $item ) + { + $product = $item->get_product(); + + $productDetails = $product->get_data(); + + // check product type for gift card plugin + if(is_plugin_active('pw-woocommerce-gift-cards/pw-gift-cards.php') || is_plugin_active('yith-woocommerce-gift-cards/init.php')){ + if($product->is_type('variation')){ + $parentProductId = $product->get_parent_id(); + $parentProduct = wc_get_product($parentProductId); + + if($parentProduct->get_type() == 'pw-gift-card' || $parentProduct->get_type() == 'gift-card'){ + $type = 'gift_card'; + } + + }else{ + + if($product->get_type() == 'pw-gift-card' || $product->get_type() == 'gift-card'){ + $type = 'gift_card'; + } + } + + } + + $data['line_items'][$i]['type'] = $type; + $data['line_items'][$i]['sku'] = $product->get_sku(); + $data['line_items'][$i]['variant_id'] = (string)$item->get_variation_id(); + $data['line_items'][$i]['product_id'] = (string)$product->get_parent_id(); + $data['line_items'][$i]['price'] = (empty($productDetails['price'])=== false) ? round(wc_get_price_excluding_tax($product)*100) + round($item->get_subtotal_tax()*100 / $item->get_quantity()) : 0; + $data['line_items'][$i]['offer_price'] = (empty($productDetails['sale_price'])=== false) ? (int) $productDetails['sale_price']*100 : $productDetails['price']*100; + $data['line_items'][$i]['quantity'] = (int)$item->get_quantity(); + $data['line_items'][$i]['name'] = mb_substr($item->get_name(), 0, 125, "UTF-8"); + $data['line_items'][$i]['description'] = mb_substr($item->get_name(), 0, 250,"UTF-8"); + $productImage = $product->get_image_id()?? null; + $data['line_items'][$i]['image_url'] = (string)($productImage? wp_get_attachment_url( $productImage ) : ""); + $data['line_items'][$i]['product_url'] = (string)$product->get_permalink(); + + $i++; + } + + return $data; + } + + public function enqueueCheckoutScripts($data) + { + if($data === 'checkoutForm' || $data === 'routeAnalyticsForm') + { + wp_register_script('razorpay_wc_script', plugin_dir_url(__FILE__) . 'script.js', + null, null); + $data = array($data); + } + else + { + wp_register_script('razorpay_wc_script', plugin_dir_url(__FILE__) . 'script.js', + array('razorpay_checkout')); + + wp_register_script('razorpay_checkout', + 'https://checkout.razorpay.com/v1/checkout.js', + null, null); + } + + wp_localize_script('razorpay_wc_script', + 'razorpay_wc_checkout_vars', + $data + ); + + wp_enqueue_script('razorpay_wc_script'); + } + + private function hostCheckoutScripts($data) + { + $url = Api::getFullUrl("checkout/embedded"); + + $formFields = ""; + foreach ($data as $fieldKey => $val) { + if(in_array($fieldKey, array('notes', 'prefill', '_'))) + { + foreach ($data[$fieldKey] as $field => $fieldVal) { + $formFields .= " \n"; + } + } + } + + return '
+ + + + + + + + '. $formFields .' +
'; + + } + + + /** + * Generates the order form + **/ + function generateOrderForm($data) + { + $data["_"] = $this->getVersionMetaInfo($data); + + $wooOrderId = $data['notes']['woocommerce_order_number']; + + $redirectUrl = $this->getRedirectUrl($wooOrderId); + + $data['cancel_url'] = wc_get_checkout_url(); + + $api = $this->getRazorpayApiPublicInstance(); + + $merchantPreferences = $api->request->request("GET", "preferences"); + + if(isset($merchantPreferences['options']['redirect']) && $merchantPreferences['options']['redirect'] === true) + { + $this->enqueueCheckoutScripts('checkoutForm'); + + $data['preference']['image'] = $merchantPreferences['options']['image']; + + return $this->hostCheckoutScripts($data); + + } else { + $this->enqueueCheckoutScripts($data); + + return << + + + + + + +

+ + +

+EOT; + } + } + + /** + * Gets the Order Key from the Order + * for all WC versions that we suport + */ + protected function getOrderKey($order) + { + $orderKey = null; + + if (version_compare(WOOCOMMERCE_VERSION, '3.0.0', '>=')) + { + return $order->get_order_key(); + } + + return $order->order_key; + } + + public function process_refund($orderId, $amount = null, $reason = '') + { + $order = wc_get_order($orderId); + + if (! $order or ! $order->get_transaction_id()) + { + return new WP_Error('error', __('Refund failed: No transaction ID', 'woocommerce')); + } + + $client = $this->getRazorpayApiInstance(); + + $paymentId = $order->get_transaction_id(); + + $data = array( + 'amount' => (int) round($amount * 100), + 'notes' => array( + 'reason' => $reason, + 'order_id' => $orderId, + 'refund_from_website' => true, + 'source' => 'woocommerce', + ) + ); + + try + { + $refund = $client->payment + ->fetch( $paymentId ) + ->refund( $data ); + + $order->add_order_note( __( 'Refund Id: ' . $refund->id, 'woocommerce' ) ); + /** + * @var $refund ->id -- Provides the RazorPay Refund ID + * @var $orderId -> Refunded Order ID + * @var $refund -> WooCommerce Refund Instance. + */ + do_action( 'woo_razorpay_refund_success', $refund->id, $orderId, $refund ); + + return true; + } + catch(Exception $e) + { + return new WP_Error('error', __($e->getMessage(), 'woocommerce')); + } + } + + // process refund for gift card + function processGiftCardRefund($orderId, $razorpayPaymentId, $amount = null, $reason = '') + { + $order = wc_get_order($orderId); + + if (! $order or ! $razorpayPaymentId) + { + return new WP_Error('error', __('Refund failed: No transaction ID', 'woocommerce')); + } + + $client = $this->getRazorpayApiInstance(); + + $data = array( + 'amount' => (int) round($amount), + 'notes' => array( + 'reason' => $reason, + 'order_id' => $orderId, + 'refund_from_website' => true, + 'source' => 'woocommerce', + ) + ); + + try + { + $refund = $client->payment->fetch( $razorpayPaymentId )->refund( $data ); + + wc_create_refund(array( + 'amount' => $amount, + 'reason' => $reason, + 'order_id' => $orderId, + 'refund_id' => $refund->id, + 'line_items' => array(), + 'refund_payment' => false, + )); + + $order->add_order_note( __( 'Refund Id: ' . $refund->id, 'woocommerce' ) ); + /** + * @var $refund ->id -- Provides the RazorPay Refund ID + * @var $orderId -> Refunded Order ID + * @var $refund -> WooCommerce Refund Instance. + */ + //do_action( 'woo_razorpay_refund_success', $refund->id, $orderId, $refund ); + $this->add_notice("Payment refunded", "error"); + + } + catch(Exception $e) + { + rzpLogInfo('failure message for refund:' . $e->getMessage()); + } + + wp_redirect(wc_get_cart_url()); + exit; + } + + /** + * Process the payment and return the result + **/ + function process_payment($order_id) + { + rzpLogInfo("Called process_payment with params order_id $order_id"); + + global $woocommerce; + + $order = wc_get_order($order_id); + + set_transient(self::SESSION_KEY, $order_id, 3600); + rzpLogInfo("Set transient with key " . self::SESSION_KEY . " params order_id $order_id"); + + $orderKey = $this->getOrderKey($order); + + if (version_compare(WOOCOMMERCE_VERSION, '2.1', '>=')) + { + return array( + 'result' => 'success', + 'redirect' => add_query_arg('key', $orderKey, $order->get_checkout_payment_url(true)) + ); + } + else if (version_compare(WOOCOMMERCE_VERSION, '2.0.0', '>=')) + { + return array( + 'result' => 'success', + 'redirect' => add_query_arg('order', $order->get_id(), + add_query_arg('key', $orderKey, $order->get_checkout_payment_url(true))) + ); + } + else + { + return array( + 'result' => 'success', + 'redirect' => add_query_arg('order', $order->get_id(), + add_query_arg('key', $orderKey, get_permalink(get_option('woocommerce_pay_page_id')))) + ); + } + } + + public function getRazorpayApiInstance($key = '', $secret = '') + { + if ($key === '') + { + $key = $this->getSetting('key_id'); + } + + if ($secret === '') + { + $secret = $this->getSetting('key_secret'); + } + + return new Api($key, $secret); + } + + public function getRazorpayApiPublicInstance() + { + return new Api($this->getSetting('key_id'), ""); + } + + /** + * Check for valid razorpay server callback + * Called once payment is completed using redirect method + */ + function check_razorpay_response() + { + global $woocommerce; + global $wpdb; + + $order = false; + + $post_type = 'shop_order'; + + $post_password = sanitize_text_field($_GET['order_key']); + + rzpLogInfo("Called check_razorpay_response: $post_password"); + + $meta_key = '_order_key'; + + $orderOperationalDataTable = $wpdb->prefix . 'wc_order_operational_data'; + $orderTable = $wpdb->prefix . 'wc_orders'; + + if ($this->isHposEnabled) + { + $orderOperationalData = $wpdb->get_row($wpdb->prepare("SELECT order_id FROM $orderOperationalDataTable AS P WHERE order_key = %s", $post_password)); + + $orderData = $wpdb->get_row($wpdb->prepare("SELECT status FROM $orderTable AS P WHERE id = %s", $orderOperationalData->order_id)); + } else + { + $orderOperationalData = $wpdb->get_row($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta AS P WHERE meta_key = %s AND meta_value = %s", $meta_key, $post_password)); + + $orderData = $wpdb->get_row($wpdb->prepare("SELECT post_status FROM $wpdb->posts AS P WHERE post_type=%s and ID=%s", $post_type, $orderOperationalData->post_id)); + } + + $arrayPost = json_decode(json_encode($orderOperationalData), true); + + if (!empty($arrayPost) and + $arrayPost != null) + { + if ($this->isHposEnabled) + { + $orderId = $orderOperationalData->order_id; + + $order = wc_get_order($orderId); + + if ($orderData->status === 'wc-checkout-draft') + { + $order->set_status('wc-pending'); + $order->save(); + } + $orderStatus = $order->get_status(); + rzpLogInfo("HPOS is enabled and order status: $orderStatus"); + } + else + { + $orderId = $orderOperationalData->post_id; + + $order = wc_get_order($orderId); + + if ($orderData->post_status === 'draft') + { + updateOrderStatus($orderId, 'wc-pending'); + } + $orderStatus = $order->get_status(); + rzpLogInfo("HPOS is disabled and order status: $orderStatus"); + } + + rzpLogInfo("Get order id in check_razorpay_response: orderId $orderId"); + } + + // TODO: Handle redirect + if ($order === false) + { + // TODO: Add test mode condition + if (is1ccEnabled()) + { + rzpLogInfo("Order details not found for the orderId: $orderId"); + + wp_redirect(wc_get_cart_url()); + exit; + } + wp_redirect(wc_get_checkout_url()); + exit; + } + + // If the order has already been paid for + // redirect user to success page + if (($order->needs_payment() === false) and + ($orderStatus != 'draft') and + ($orderStatus != 'wc-checkout-draft')) + { + rzpLogInfo("Order payment is already done for the orderId: " . $orderId . " order status " . $orderStatus); + + $cartHash = get_transient(RZP_1CC_CART_HASH.$orderId); + + if ($cartHash != false) + { + // Need to delete the cart hash stored in transient. + // Becuase the cart hash will be depending on the cart items so this will cause the issue when order api triggers. + $woocommerce->session->__unset(RZP_1CC_CART_HASH.$cartHash); + } + + $this->redirectUser($order); + } + + $razorpayPaymentId = null; + + if ($orderId and !empty($_POST[self::RAZORPAY_PAYMENT_ID])) + { + $error = ""; + $success = false; + + try + { + $this->verifySignature($orderId); + $success = true; + $razorpayPaymentId = sanitize_text_field($_POST[self::RAZORPAY_PAYMENT_ID]); + + $cartHash = get_transient(RZP_1CC_CART_HASH.$orderId); + + if ($cartHash != false) + { + // Need to delete the cart hash stored in transient. + // Becuase the cart hash will be depending on the cart items so this will cause the issue when order api triggers. + $woocommerce->session->__unset(RZP_1CC_CART_HASH.$cartHash); + } + } + catch (Errors\SignatureVerificationError $e) + { + $error = 'WOOCOMMERCE_ERROR: Payment to Razorpay Failed. ' . $e->getMessage(); + } + } + else + { + if(isset($_POST[self::RAZORPAY_WC_FORM_SUBMIT]) && $_POST[self::RAZORPAY_WC_FORM_SUBMIT] ==1) + { + $success = false; + $error = 'Customer cancelled the payment'; + } + else + { + $success = false; + $error = "Payment Failed."; + } + + if ($this->isHposEnabled) { + $is1ccOrder = $order->get_meta('is_magic_checkout_order'); + }else{ + $is1ccOrder = get_post_meta( $orderId, 'is_magic_checkout_order', true ); + } + + if (is1ccEnabled() && !empty($is1ccOrder) && $is1ccOrder == 'yes') + { + $api = $this->getRazorpayApiInstance(); + $sessionKey = $this->getOrderSessionKey($orderId); + + //Check the transient data for razorpay order id, if it's not available then look into session data. + if(get_transient($sessionKey)) + { + $razorpayOrderId = get_transient($sessionKey); + } + else + { + $razorpayOrderId = $woocommerce->session->get($sessionKey); + } + + $razorpayData = $api->order->fetch($razorpayOrderId); + + $this->UpdateOrderAddress($razorpayData, $order); + } + + $this->handleErrorCase($order); + $this->updateOrder($order, $success, $error, $razorpayPaymentId, null); + + if (is1ccEnabled()) + { + wp_redirect(wc_get_cart_url()); + exit; + } + + wp_redirect(wc_get_checkout_url()); + exit; + } + + $this->updateOrder($order, $success, $error, $razorpayPaymentId, null); + + $this->redirectUser($order); + } + + protected function redirectUser($order) + { + $redirectUrl = $this->get_return_url($order); + + wp_redirect($redirectUrl); + exit; + } + + protected function verifySignature($orderId) + { + rzpLogInfo("verifySignature orderId: $orderId"); + + global $woocommerce; + + $api = $this->getRazorpayApiInstance(); + + $attributes = array( + self::RAZORPAY_PAYMENT_ID => $_POST[self::RAZORPAY_PAYMENT_ID], + self::RAZORPAY_SIGNATURE => $_POST[self::RAZORPAY_SIGNATURE], + ); + + $sessionKey = $this->getOrderSessionKey($orderId); + //Check the transient data for razorpay order id, if it's not available then look into session data. + if(get_transient($sessionKey)) + { + $razorpayOrderId = get_transient($sessionKey); + } + else + { + $razorpayOrderId = $woocommerce->session->get($sessionKey); + } + + $attributes[self::RAZORPAY_ORDER_ID] = $razorpayOrderId?? ''; + rzpLogInfo("verifySignature attr"); + rzpLogInfo(json_encode($attributes)); + $api->utility->verifyPaymentSignature($attributes); + } + + public function rzpThankYouMessage( $thank_you_title, $order ) + { + return self::DEFAULT_SUCCESS_MESSAGE; + } + + protected function getErrorMessage($orderId) + { + // We don't have a proper order id + rzpLogInfo("getErrorMessage orderId: $orderId"); + + if ($orderId !== null) + { + $message = 'An error occured while processing this payment'; + } + if (isset($_POST['error']) === true && is_array($_POST['error'])) + { + $error = $_POST['error']; + + $description = htmlentities($error['description']); + $code = htmlentities($error['code']); + + $message = 'An error occured. Description : ' . $description . '. Code : ' . $code; + + if (isset($error['field']) === true) + { + $fieldError = htmlentities($error['field']); + $message .= 'Field : ' . $fieldError; + } + } + else + { + $message = 'An error occured. Please contact administrator for assistance'; + } + rzpLogInfo("returning $message"); + return $message; + } + + /** + * Modifies existing order and handles success case + * + * @param $success, & $order + */ + public function updateOrder(& $order, $success, $errorMessage, $razorpayPaymentId, $virtualAccountId = null, $webhook = false) + { + global $woocommerce; + + $orderId = $order->get_order_number(); + + rzpLogInfo("updateOrder orderId: $orderId , razorpayPaymentId: $razorpayPaymentId , success: $success"); + + if ($success === true) + { + try + { + $wcOrderId = $order->get_id(); + + if ($this->isHposEnabled) { + $is1ccOrder = $order->get_meta('is_magic_checkout_order'); + }else{ + $is1ccOrder = get_post_meta( $orderId, 'is_magic_checkout_order', true ); + } + + rzpLogInfo("Order details check initiated step 1 for the orderId: $wcOrderId"); + + if (is1ccEnabled() && !empty($is1ccOrder) && $is1ccOrder == 'yes') + { + rzpLogInfo("Order details update initiated step 1 for the orderId: $wcOrderId"); + + //To verify whether the 1cc update order function already under execution or not + if(get_transient('wc_order_under_process_'.$wcOrderId) === false) + { + rzpLogInfo("Order details update initiated step 2 for the orderId: $wcOrderId"); + + $this->update1ccOrderWC($order, $wcOrderId, $razorpayPaymentId); + } + + } + } catch (Exception $e) { + $message = $e->getMessage(); + rzpLogError("Failed to update 1cc flow with error : $message"); + } + + $payment_method=$order->get_payment_method(); + + // Need to set the status manually to processing incase of COD payment method. + if ($payment_method == "cod") + { + $order->update_status( 'processing' ); + } + else + { + $order->payment_complete($razorpayPaymentId); + } + + if(is1ccEnabled() && !empty($is1ccOrder) && $is1ccOrder == 'yes' && is_plugin_active('woo-save-abandoned-carts/cartbounty-abandoned-carts.php')){ + handleCBRecoveredOrder($orderId); + } + + // Check Wati.io retargetting plugin is active or not + if (is1ccEnabled() && !empty($is1ccOrder) && $is1ccOrder == 'yes' && is_plugin_active('wati-chat-and-notification/wati-chat-and-notification.php')){ + handleWatiRecoveredOrder($orderId); + } + + $order->add_order_note("Razorpay payment successful
Razorpay Id: $razorpayPaymentId"); + + if($this->getSetting('route_enable') == 'yes') + { + $razorpayRoute = new RZP_Route_Action(); + + $wcOrderId = $order->get_id(); + + $razorpayRoute->transferFromPayment($wcOrderId, $razorpayPaymentId); // creates transfers from payment + } + + if($virtualAccountId != null) + { + $order->add_order_note("Virtual Account Id: $virtualAccountId"); + } + + if (isset($woocommerce->cart) === true) + { + $woocommerce->cart->empty_cart(); + } + } + else + { + $this->msg['class'] = 'error'; + $this->msg['message'] = $errorMessage; + + if ($razorpayPaymentId) + { + $order->add_order_note("Payment Failed. Please check Razorpay Dashboard.
Razorpay Id: $razorpayPaymentId"); + } + + $order->add_order_note("Transaction Failed: $errorMessage
"); + $order->update_status('failed'); + } + + if ($webhook === false) + { + $this->add_notice($this->msg['message'], $this->msg['class']); + + rzpLogInfo("Woocommerce orderId: $orderId processed through callback"); + } + else + { + rzpLogInfo("Woocommerce orderId: $orderId processed through webhook"); + } + } + + public function update1ccOrderWC(& $order, $wcOrderId, $razorpayPaymentId) + { + global $woocommerce; + + $logObj = array(); + rzpLogInfo("update1ccOrderWC wcOrderId: $wcOrderId, razorpayPaymentId: $razorpayPaymentId"); + + //To avoid the symultanious update from callback and webhook + set_transient('wc_order_under_process_'.$wcOrderId, true, 300); + + $api = $this->getRazorpayApiInstance(); + $sessionKey = $this->getOrderSessionKey($wcOrderId); + + //Check the transient data for razorpay order id, if it's not available then look into session data. + if(get_transient($sessionKey)) + { + $razorpayOrderId = get_transient($sessionKey); + } + else + { + $razorpayOrderId = $woocommerce->session->get($sessionKey); + } + + $razorpayData = $api->order->fetch($razorpayOrderId); + + $this->UpdateOrderAddress($razorpayData, $order); + + $gstNo = $razorpayData['notes']['gstin']??''; + $orderInstructions = $razorpayData['notes']['order_instructions']??''; + + if($gstNo != ''){ + $order->add_order_note( "GSTIN No. : ". $gstNo ); + } + if($orderInstructions != ''){ + $order->add_order_note( "Order Instructions: ". $orderInstructions); + } + + // update gift card and coupons + $rzpPromotionAmount = $this->updateGiftAndCoupon($razorpayData, $order, $wcOrderId, $razorpayPaymentId); + + //Apply shipping charges to woo-order + if(isset($razorpayData['shipping_fee']) === true) + { + + //To remove by default shipping method added on order. + $existingItems = (array) $order->get_items('shipping'); + rzpLogInfo("Shipping details updated for orderId: $wcOrderId is".json_encode($existingItems)); + + if (sizeof($existingItems) != 0) { + // Loop through shipping items + foreach ($existingItems as $existingItemKey => $existingItemVal) { + $order->remove_item($existingItemKey); + } + } + + // Get a new instance of the WC_Order_Item_Shipping Object + $item = new WC_Order_Item_Shipping(); + + // if shipping charges zero + if($razorpayData['shipping_fee'] == 0) + { + $item->set_method_title( 'Free Shipping' ); + } + else + { + $isStoreShippingEnabled = ""; + if ($this->isHposEnabled) + { + $shippingData = $order->get_meta('1cc_shippinginfo'); + + }else{ + $shippingData = get_post_meta( $wcOrderId, '1cc_shippinginfo', true ); + } + + if (class_exists('WCFMmp')) + { + $shippingOptions = get_option( 'wcfm_shipping_options', array()); + // By default store shipping should be consider enable + $isStoreShippingEnabled = isset( $shippingOptions['enable_store_shipping'] ) ? $shippingOptions['enable_store_shipping'] : 'yes'; + } + + if ($isStoreShippingEnabled == 'yes') + { + foreach ($shippingData as $key => $value) + { + $item = new WC_Order_Item_Shipping(); + //$item->set_method_id($test[$key]['rate_id']); + $item->set_method_title($shippingData[$key]['name']); + $item->set_total($shippingData[$key]['price']/100 ); + $order->add_item($item); + $item->save(); + $itemId = $item->get_id(); + + $wcfmCommissionOptions = get_option( 'wcfm_commission_options', array() ); + + $vendorGetShipping = isset( $wcfmCommissionOptions['get_shipping'] ) ? $wcfmCommissionOptions['get_shipping'] : 'yes'; + + if (isset($shippingData[$key]['vendor_id']) && $vendorGetShipping == 'yes') + { + $itemData = array( + 'method_id' => $shippingData[$key]['method_id'], + 'instance_id' => $shippingData[$key]['instance_id'], + 'vendor_id' => $shippingData[$key]['vendor_id'], + 'Items' => $shippingData[$key]['meta_data'][0]['value'] + ); + updateVendorDetails($shippingData[$key]['price']/100, $shippingData[$key]['vendor_id'], $wcOrderId); + + foreach ($itemData as $itemkey => $itemval) + { + wc_update_order_item_meta( $itemId, $itemkey, $itemval); + } + } + + } + } + else + { + $item = new WC_Order_Item_Shipping(); + + // if shipping charges zero + if ($razorpayData['shipping_fee'] == 0) + { + $item->set_method_title( 'Free Shipping' ); + } + else + { + $item->set_method_title($shippingData??[0]['name']); + } + + // set an non existing Shipping method rate ID will mark the order as completed instead of processing status + // $item->set_method_id( "flat_rate:1" ); + $item->set_total( $razorpayData['shipping_fee']/100 ); + + $order->add_item( $item ); + + $item->save(); + } + // Calculate totals and save + $order->calculate_totals(); + + } + } + + // set default payment method + $payment_method = $this->id; + $payment_method_title = $this->title; + + // To verify the payment method for particular payment id. + $razorpayPaymentData = $api->payment->fetch($razorpayPaymentId); + + $paymentDoneBy = $razorpayPaymentData['method']; + + $codFee = 0; + if (($paymentDoneBy === 'cod') && isset($razorpayData['cod_fee']) == true) + { + $codFee = $razorpayData['cod_fee']/100; + $payment_method = 'cod'; + $payment_method_title = 'Cash on delivery'; + } + + //update payment method title + $order->set_payment_method($payment_method); + $order->set_payment_method_title($payment_method_title); + $order->save(); + + if (($paymentDoneBy === 'cod') && isset($razorpayData['cod_fee']) == true) + { + // Get a new instance of the WC_Order_Item_Fee Object + $itemFee = new WC_Order_Item_Fee(); + + $itemFee->set_name('COD Fee'); // Generic fee name + $itemFee->set_amount($codFee); // Fee amount + // $itemFee->set_tax_class(''); // default for '' + $itemFee->set_tax_status( 'none' ); // If we don't set tax status then it will consider by dafalut tax class. + $itemFee->set_total($codFee); // Fee amount + + // Calculating Fee taxes + // $itemFee->calculate_taxes( $calculateTaxFor ); + + // Add Fee item to the order + $order->add_item($itemFee); + $order->calculate_totals(); + $order->save(); + } + + if(!empty($razorpayData['offers'])) + { + $offerDiff = $razorpayData['line_items_total'] + $razorpayData['shipping_fee'] + $codFee*100 - $razorpayPaymentData['amount'] - $rzpPromotionAmount; + + if($offerDiff > 0){ + $offerDiscount = ($offerDiff/100); + $title = 'Razorpay_offers_'. $wcOrderId .'(₹'. $offerDiscount .')'; + + $this->createRzpOfferCoupon($title, $offerDiscount); + $this->applyCoupon($order, $title, $offerDiff); + + } + + } + + + //For abandon cart Lite recovery plugin recovery function + if(is_plugin_active( 'woocommerce-abandoned-cart/woocommerce-ac.php')) + { + $this->updateRecoverCartInfo($wcOrderId); + } + + $note = __('Order placed through Razorpay Magic Checkout'); + $order->add_order_note( $note ); + if ($paymentDoneBy === 'cod') + { + try + { + $body = ['order_id' => $razorpayOrderId]; + rzpLogInfo("making prepay API Call for order : $razorpayOrderId"); + $response = $api->request->request('POST', self::PREPAY_COD_URL , $body); + rzpLogInfo("makeAPICall: url: ". self::PREPAY_COD_URL . " is success"); + } + catch (\Razorpay\Api\Errors\Error $e) + { + $statusCode = $e->getHttpStatusCode(); + rzpLogError("make prepayAPICall failed: message:" . $e->getMessage() . ", url: " . self::PREPAY_COD_URL . ", statusCode : " . $statusCode . ", stacktrace : " . $e->getTraceAsString()); + } + } + } + + public function updateGiftAndCoupon($razorpayData, $order, $orderId, $razorpayPaymentId) + { + global $woocommerce; + global $wpdb; + + foreach($razorpayData['promotions'] as $promotion) + { + $rzpGiftAndCouponAmount += $promotion['value']; + + if($promotion['type'] == 'gift_card'){ + + $usedAmt = $promotion['value']/100; + $giftCode = $promotion['code']; + if(is_plugin_active('yith-woocommerce-gift-cards/init.php')){ + + $yithCard = new YITH_YWGC_Gift_Card( $args = array('gift_card_number'=> $giftCode)); + + //Get GC status + $post = get_post($yithCard->ID); + $status = $post->post_status; + + $giftCardBalance = $yithCard->get_balance(); + + if($giftCardBalance == null && $giftCardBalance >= 0 && $usedAmt > $giftCardBalance && 'trash' == $status && !$yithCard->exists()){ + // initiate refund in case gift card faliure + $this->processGiftCardRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); + }else{ + //Deduct amount of gift card + $yithCard->update_balance( $yithCard->get_balance() - $usedAmt ); + $yithCard->register_order($orderId); + + $code = "Gift Card ($giftCode)"; + + $wpdb->query( // phpcs:ignore + $wpdb->prepare( + 'INSERT INTO `' . $wpdb->prefix . 'woocommerce_order_items`( order_item_name, order_item_type, order_id ) VALUES ( %s, %s, %s)', + $code, + 'fee', + $orderId + ) + ); + + $itemId = $wpdb->insert_id; + wc_add_order_item_meta( $itemId, '_line_total', -$usedAmt ); + + $order->add_order_note( sprintf( esc_html__( 'Order paid with gift cards for a total amount of %s.', 'yith-woocommerce-gift-cards' ), wc_price( $usedAmt ) ) ); + + $orderTotal = $order->get_total() - $usedAmt; + $order->set_total($orderTotal); + $order->save(); + } + + } + else if(is_plugin_active('pw-woocommerce-gift-cards/pw-gift-cards.php')) + { + $result = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM `{$wpdb->pimwick_gift_card}` WHERE `number` = %s", $promotion['code'] ) ); + if($result != null){ + $balance = $wpdb->get_var( $wpdb->prepare( "SELECT SUM(amount) FROM {$wpdb->pimwick_gift_card_activity} WHERE pimwick_gift_card_id = %d", $result->pimwick_gift_card_id ) ); + + if($balance == null && $balance >= 0 && $usedAmt > $balance ){ + // initiate refund in case gift card faliure + $this->processGiftCardRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); + }else{ + //Deduct amount of gift card + $this->debitGiftCards($orderId, $order, "order_id: $orderId checkout_update_order_meta", $usedAmt, $giftCode); + } + + }else{ + $this->processGiftCardRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); + } + + }else{ + $this->processGiftCardRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); + } + + }else{ + + $couponKey = $promotion['code']; + + if (empty($couponKey) === false) + { + $this->applyCoupon($order, $couponKey, $promotion['value']); + rzpLogInfo("Coupon details updated for orderId: $orderId"); + } + } + + } + return $rzpGiftAndCouponAmount; + } + + protected function debitGiftCards( $orderId, $order, $note, $usedAmt, $giftCardNo) { + + global $woocommerce; + global $wpdb; + + if ( ! is_a( $order, 'WC_Order' ) ) { + return; + } + + // insert GC in orderitems + $wpdb->query( // phpcs:ignore + $wpdb->prepare( + 'INSERT INTO `' . $wpdb->prefix . 'woocommerce_order_items`( order_item_name, order_item_type, order_id ) VALUES ( %s, %s, %s)', + $code, + 'pw_gift_card', + $orderId + ) + ); + + $itemId = $wpdb->insert_id; + wc_add_order_item_meta( $itemId, 'card_number', $giftCardNo ); + wc_add_order_item_meta( $itemId, 'amount', $usedAmt ); + + foreach( $order->get_items( 'pw_gift_card' ) as $order_item_id => $line ) { + $gift_card = new PW_Gift_Card( $giftCardNo ); + + if ( $gift_card->get_id() ) { + if ( !$line->meta_exists( '_pw_gift_card_debited' ) ) { + if ( $line->get_amount() != 0 ) { + $gift_card->debit( ( $line->get_amount() * -1 ), "$note, order_item_id: $order_item_id" ); + } + + $line->add_meta_data( '_pw_gift_card_debited', true ); + $line->save(); + } + } + } + } + + //To update customer address info to wc order. + public function updateOrderAddress($razorpayData, $order) + { + $this->newUserAccount($razorpayData, $order); + rzpLogInfo("updateOrderAddress function called"); + $receipt = $razorpayData['receipt']; + + if (isset($razorpayData['customer_details']['shipping_address'])) + { + $shippingAddressKey = $razorpayData['customer_details']['shipping_address']; + + $shippingAddress = []; + + $shippingAddress['first_name'] = $shippingAddressKey['name']; + $shippingAddress['address_1'] = $shippingAddressKey['line1']; + $shippingAddress['address_2'] = $shippingAddressKey['line2']; + $shippingAddress['city'] = $shippingAddressKey['city']; + $shippingAddress['country'] = strtoupper($shippingAddressKey['country']); + $shippingAddress['postcode'] = $shippingAddressKey['zipcode']; + $shippingAddress['email'] = $razorpayData['customer_details']['email']; + $shippingAddress['phone'] = $shippingAddressKey['contact']; + + $order->set_address( $shippingAddress, 'shipping' ); + + $shippingState = strtoupper($shippingAddressKey['state']); + $shippingStateName = str_replace(" ", '', $shippingState); + $shippingStateCode = getWcStateCodeFromName($shippingStateName); + $order->set_shipping_state($shippingStateCode); + + $this->updateUserAddressInfo('shipping_', $shippingAddress, $shippingStateCode, $order); + rzpLogInfo('shipping details for receipt id: '.$receipt .' is '. json_encode($shippingAddress)); + + if (empty($razorpayData['customer_details']['billing_address']) == false) + { + $billingAddress['first_name'] = $razorpayData['customer_details']['billing_address']['name']; + $billingAddress['address_1'] = $razorpayData['customer_details']['billing_address']['line1']; + $billingAddress['address_2'] = $razorpayData['customer_details']['billing_address']['line2']; + $billingAddress['city'] = $razorpayData['customer_details']['billing_address']['city']; + $billingAddress['country'] = strtoupper($razorpayData['customer_details']['billing_address']['country']); + $billingAddress['postcode'] = $razorpayData['customer_details']['billing_address']['zipcode']; + $billingAddress['email'] = $razorpayData['customer_details']['email']; + $billingAddress['phone'] = $razorpayData['customer_details']['billing_address']['contact']; + $order->set_address( $billingAddress, 'billing' ); + + $billingState = strtoupper($razorpayData['customer_details']['billing_address']['state']); + $billingStateName = str_replace(" ", '', $billingState); + $billingStateCode = getWcStateCodeFromName($billingStateName); + $order->set_billing_state($billingStateCode); + + $this->updateUserAddressInfo('billing_', $billingAddress, $billingStateCode, $order); + rzpLogInfo('billing details for receipt id: '.$receipt .' is '. json_encode($billingAddress)); + } + else + { + $order->set_address( $shippingAddress, 'billing' ); + $order->set_billing_state($shippingStateCode); + + $this->updateUserAddressInfo('billing_', $shippingAddress, $shippingStateCode, $order); + } + + rzpLogInfo("updateOrderAddress function executed"); + + $order->save(); + } + } + + //Create new user account + public function newUserAccount($razorpayData, $order) + { + global $woocommerce; + + if (!email_exists($razorpayData['customer_details']['email']) && isMandatoryAccCreationEnabled()) { + + $contact = $razorpayData['customer_details']['contact']; + + $email = $razorpayData['customer_details']['email']; + $random_password = wp_generate_password(8, false); + + //create user name with the help default woocommerce function + $username = wc_create_new_customer_username( $email ); + $userId = wp_create_user( $username, $random_password, $email ); + $user = get_user_by('id', $userId); + + $order->set_customer_id( $userId ); + $order->save(); + + // Get all WooCommerce emails Objects from WC_Emails Object instance + $emails = wc()->mailer()->emails; + + // Send WooCommerce "Customer New Account" email notification with the password + $emails['WC_Email_Customer_New_Account']->trigger( $userId, $random_password, true ); + + update_user_meta( $userId, 'shipping_email', $email); + update_user_meta( $userId, 'shipping_phone', $contact ); + + if (isset($razorpayData['customer_details']['shipping_address'])) + { + $shpping = $razorpayData['customer_details']['shipping_address']; + + //extract data + if (empty($razorpayData['customer_details']['billing_address']) == false) + { + $billing = $razorpayData['customer_details']['billing_address']; + } + else + { + $billing = $razorpayData['customer_details']['shipping_address']; + } + + $shippingState = strtoupper($shpping->state); + $shippingStateName = str_replace(" ", '', $shippingState); + $shippingStateCode = getWcStateCodeFromName($shippingStateName); + + $billingState = strtoupper($billing->state); + $billingStateName = str_replace(" ", '', $billingState); + $billingStateCode = getWcStateCodeFromName($billingStateName); + + // user's shipping data + update_user_meta( $userId, 'shipping_first_name', $shpping->name ); + update_user_meta( $userId, 'shipping_address_1', $shpping->line1); + update_user_meta( $userId, 'shipping_address_2', $shpping->line2); + update_user_meta( $userId, 'shipping_city', $shpping->city); + update_user_meta( $userId, 'shipping_country', strtoupper($shpping->country)); + update_user_meta( $userId, 'shipping_postcode', $shpping->zipcode); + update_user_meta( $userId, 'shipping_state', $shippingStateCode); + + // user's billing data + update_user_meta( $userId, 'billing_first_name', $shpping->name); + update_user_meta( $userId, 'billing_phone', $contact); + update_user_meta( $userId, 'billing_address_1', $billing->line1); + update_user_meta( $userId, 'billing_address_2', $billing->line2); + update_user_meta( $userId, 'billing_city', $billing->city); + update_user_meta( $userId, 'billing_country', strtoupper($billing->country)); + update_user_meta( $userId, 'billing_postcode', $billing->zipcode); + update_user_meta( $userId, 'billing_state', $billingStateCode); + } + } + } + + /** + * Retrieve a Shipping Zone by it's ID. + * + * @param int $zone_id Shipping Zone ID. + * @return WC_Shipping_Zone|WP_Error + */ + // TODO: can't we directly return the statement? + protected function getShippingZone($zoneId) + { + $zone = WC_Shipping_Zones::get_zone_by('zone_id', $zoneId); + + return $zone; + } + + // Update user billing and shipping information + protected function updateUserAddressInfo($addressKeyPrefix, $addressValue, $stateValue, $order) + { + foreach ($addressValue as $key => $value) + { + $metaKey = $addressKeyPrefix; + $metaKey .= $key; + + update_user_meta($order->get_user_id(), $metaKey, $value); + } + + update_user_meta($order->get_user_id(), $addressKeyPrefix . 'state', $stateValue); + } + + // Update Abandonment cart plugin table for recovered cart. + protected function updateRecoverCartInfo($wcOrderId) + { + global $woocommerce; + global $wpdb; + + $order = wc_get_order($wcOrderId); + $userId = $order->get_customer_id(); + $currentTime = current_time('timestamp'); // phpcs:ignore + $cutOffTime = get_option('ac_lite_cart_abandoned_time'); + + if (isset($cut_off_time)) + { + $cartCutOffTime = intval($cutOffTime) * 60; + } + else + { + $cartCutOffTime = 60 * 60; + } + + $compareTime = $currentTime - $cutOffTime; + if($userId > 0) + { + $userType = 'REGISTERED'; + } + else + { + $userType = 'GUEST'; + if ($this->isHposEnabled) { + $userId = $order->get_meta('abandoned_user_id'); + }else{ + $userId = get_post_meta($wcOrderId, 'abandoned_user_id', true); + } + + } + + $results = $wpdb->get_results( // phpcs:ignore + $wpdb->prepare( + 'SELECT * FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE user_id = %s AND cart_ignored = %s AND recovered_cart = %s AND user_type = %s', + $userId, + 0, + 0, + $userType + ) + ); + + if(count($results) > 0) + { + if(isset($results[0]->abandoned_cart_time) && $compareTime > $results[0]->abandoned_cart_time) + { + wcal_common::wcal_set_cart_session('abandoned_cart_id_lite', $results[0]->id); + } + } + + $abandonedOrderId = wcal_common::wcal_get_cart_session('abandoned_cart_id_lite'); + + if ($this->isHposEnabled) { + $order->update_meta_data( 'abandoned_id', $abandonedOrderId); + $order->save(); + }else{ + add_post_meta($wcOrderId, 'abandoned_id', $abandonedOrderId); + } + $wpdb->query( // phpcS:ignore + $wpdb->prepare( + 'UPDATE `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET recovered_cart = %s, cart_ignored = %s WHERE id = %s', + $wcOrderId, + '1', + $abandonedOrderId + ) + ); + } + + protected function handleErrorCase($order) + { + $orderId = $order->get_order_number(); + rzpLogInfo('handleErrorCase'); + $this->msg['class'] = 'error'; + $this->msg['message'] = $this->getErrorMessage($orderId); + } + + /** + * Add a woocommerce notification message + * + * @param string $message Notification message + * @param string $type Notification type, default = notice + */ + protected function add_notice($message, $type = 'notice') + { + global $woocommerce; + $type = in_array($type, array('notice','error','success'), true) ? $type : 'notice'; + // Check for existence of new notification api. Else use previous add_error + if (function_exists('wc_add_notice')) + { + wc_add_notice($message, $type); + } + else + { + // Retrocompatibility WooCommerce < 2.1 + switch ($type) + { + case "error" : + $woocommerce->add_error($message); + break; + default : + $woocommerce->add_message($message); + break; + } + } + } + + /** + * Fetching version info for woo-razorpay and woo-razorpay-subscription + * Which will be sent through checkout as meta info + * @param $data + * @return array + */ + public function getVersionMetaInfo($data = array()) + { + if (isset($data['subscription_id']) && isset($data['recurring'])) { + $pluginRoot = WP_PLUGIN_DIR . '/razorpay-subscriptions-for-woocommerce'; + return array( + 'integration' => 'woocommerce-subscription', + 'integration_version' => get_plugin_data($pluginRoot . '/razorpay-subscriptions.php')['Version'], + 'integration_woo_razorpay_version' => get_plugin_data(plugin_dir_path(__FILE__) . 'woo-razorpay.php')['Version'], + 'integration_parent_version' => WOOCOMMERCE_VERSION, + 'integration_type' => 'plugin', + ); + } else { + return array( + 'integration' => 'woocommerce', + 'integration_version' => get_plugin_data(plugin_dir_path(__FILE__) . 'woo-razorpay.php')['Version'], + 'integration_parent_version' => WOOCOMMERCE_VERSION, + 'integration_type' => 'plugin', + ); + } + } + + public function applyCoupon($order, $couponKey, $couponValue) { + // Remove the same coupon, if already being added to order. + $order->remove_coupon($couponKey); + + //TODO: Convert all razorpay amount in paise to rupees + $discount_total = $couponValue/100; + + //TODO: Verify source code implementation + // Loop through products and apply the coupon discount + foreach($order->get_items() as $order_item) + { + $total = $order_item->get_total(); + $order_item->set_total($total - $discount_total); + $order_item->save(); + } + // TODO: Test if individual use coupon fails by hardcoding here + $isApplied = $order->apply_coupon($couponKey); + $order->save(); + } + + //TODO: create a common function to create a coupon functionality + public function createRzpOfferCoupon($couponCode, $amount) : bool { + + $coupon = array( + 'post_title' => $couponCode, + 'post_content' => '', + 'post_status' => 'publish', + 'post_author' => 1, + 'post_type' => 'shop_coupon'); + + $newCouponId = wp_insert_post( $coupon ); + + if( $newCouponId === 0) { + return false; + } + + $input = [ + 'discount_type' => 'fixed_cart', + 'coupon_amount' => $amount, + 'usage_limit' => 1, + 'minimum_amount' => $amount, + ]; + + foreach ($input as $key => $value) { + $isSuccess = update_post_meta($newCouponId, $key, $value); + if($isSuccess === false) { + rzpLogError("rzp offer create coupon : update post meta error, key : " . $key . ", value : " . $value); + return false; + } + } + return true; + } + + } + + //update vendor data into wp_wcfm_marketplace_orders + function updateVendorDetails($shippingFee, $vendorId, $orderId) + { + global $woocommerce; + global $wpdb; + $commission = $wpdb->get_results( + $wpdb->prepare( + 'SELECT * FROM `' . $wpdb->prefix . 'wcfm_marketplace_orders` WHERE vendor_id = %d AND order_id = %d', + $vendorId, + $orderId + ) + ); + + if (count($commission) > 0) + { + $totalComm = $commission[0]->total_commission+$shippingFee; + $wpdb->query( + $wpdb->prepare( + 'UPDATE `' . $wpdb->prefix . 'wcfm_marketplace_orders` SET shipping = %d, total_commission = %d WHERE vendor_id = %d AND order_id = %d', + $shippingFee, + $totalComm, + $vendorId, + $orderId + ) + ); + } + } + + /** + * Add the Gateway to WooCommerce + **/ + function woocommerce_add_razorpay_gateway($methods) + { + $methods[] = 'WC_Razorpay'; + return $methods; + } + + add_filter('woocommerce_payment_gateways', 'woocommerce_add_razorpay_gateway'); + + /** + * Creating the settings link from the plugins page + **/ + function razorpay_woo_plugin_links($links) + { + $pluginLinks = array( + 'settings' => 'Settings', + 'docs' => 'Docs', + 'support' => 'Support' + ); + + $links = array_merge($links, $pluginLinks); + + return $links; + } + + add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'razorpay_woo_plugin_links'); + + add_action( 'woocommerce_before_single_product', 'trigger_affordability_widget', 10 ); + + function trigger_affordability_widget() + { + if (empty(get_option('rzp_afd_enable')) === false and + get_option('rzp_afd_enable') === 'yes') + { + if (empty(get_option('rzp_afd_feature_checked')) === true or + get_option('rzp_afd_feature_checked') === 'no') + { + try + { + $api = new Api(get_option('woocommerce_razorpay_settings')['key_id'], get_option('woocommerce_razorpay_settings')['key_secret']); + $merchantPreferences = $api->request->request('GET', 'accounts/me/features'); + if (isset($merchantPreferences) === false or + isset($merchantPreferences['assigned_features']) === false) + { + throw new Exception("Error in Api call."); + } + + update_option('rzp_afd_enable', 'no'); + foreach ($merchantPreferences['assigned_features'] as $preference) + { + if ($preference['name'] === 'affordability_widget' or + $preference['name'] === 'affordability_widget_set') + { + update_option('rzp_afd_enable', 'yes'); + break; + } + } + + update_option('rzp_afd_feature_checked', 'yes'); + } + catch(\Exception $e) + { + rzpLogError($e->getMessage()); + return; + } + } + + if (empty(get_option('rzp_afd_enable')) === false and + get_option('rzp_afd_enable') === 'yes') + { + add_action ('woocommerce_before_add_to_cart_form', 'addAffordabilityWidgetHTML'); + } + } + } +} + +// This is set to a priority of 10 +function razorpay_webhook_init() +{ + $rzpWebhook = new RZP_Webhook(); + + $rzpWebhook->process(); +} + +define('RZP_PATH', plugin_dir_path( __FILE__ )); +define('RZP_CHECKOUTJS_URL', 'https://checkout.razorpay.com/v1/magic-checkout.js'); +define('BTN_CHECKOUTJS_URL', 'https://cdn.razorpay.com/static/wooc/magic-rzp.js'); +define('RZP_1CC_CSS_SCRIPT', 'RZP_1CC_CSS_SCRIPT'); + + +function enqueueScriptsFor1cc() +{ + $siteurl = get_option('siteurl'); + $pluginData = get_plugin_data( __FILE__ ); + + $domain = parse_url($siteurl, PHP_URL_HOST); + $domain_ip = gethostbyname($domain); + + //Consider https if site url is not localhost server. + if (filter_var($domain_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) + { + $siteurl = str_replace('http://', 'https://', $siteurl); + } + + wp_register_script( '1cc_razorpay_config', '' ); + wp_enqueue_script( '1cc_razorpay_config' ); + wp_add_inline_script( '1cc_razorpay_config', '!function(){var o=document.querySelector("meta[name=rzp_merchant_key]");o&&(window.Razorpay||(window.Razorpay={}),"object"==typeof window.Razorpay&&(window.Razorpay.config||(window.Razorpay.config={}),window.Razorpay.config.merchant_key=o.getAttribute("value")))}();'); + + wp_register_script('1cc_razorpay_checkout', RZP_CHECKOUTJS_URL, null, null); + wp_enqueue_script('1cc_razorpay_checkout'); + wp_register_style(RZP_1CC_CSS_SCRIPT, plugin_dir_url(__FILE__) . 'public/css/1cc-product-checkout.css', null, null); + wp_enqueue_style(RZP_1CC_CSS_SCRIPT); + + wp_register_script('btn_1cc_checkout', BTN_CHECKOUTJS_URL, null, null); + wp_localize_script('btn_1cc_checkout', 'rzp1ccCheckoutData', array( + 'nonce' => wp_create_nonce("wp_rest"), + 'siteurl' => $siteurl, + 'blogname' => get_bloginfo('name'), + 'cookies' => $_COOKIE, + 'requestData' => $_REQUEST, + 'version' => $pluginData['Version'], + ) ); + wp_enqueue_script('btn_1cc_checkout'); +} + +//To add 1CC button on cart page. +add_action( 'woocommerce_proceed_to_checkout', 'addCheckoutButton'); + +if(isRazorpayPluginEnabled() && is1ccEnabled()) { + add_action('wp_head', 'injectMerchantKeyMeta', 1); + add_action('wp_head', 'addRzpSpinner'); +} + +function addCheckoutButton() +{ + add_action('wp_enqueue_scripts', 'enqueueScriptsFor1cc', 0); + + if (isRazorpayPluginEnabled() && is1ccEnabled() ) + { + if (isTestModeEnabled()) { + $current_user = wp_get_current_user(); + if ($current_user->has_cap( 'administrator' ) || preg_match( '/@razorpay.com$/i', $current_user->user_email )) { + $tempTest = RZP_PATH . 'templates/rzp-cart-checkout-btn.php'; + load_template( $tempTest, false, array() ); + } + } else { + $tempTest = RZP_PATH . 'templates/rzp-cart-checkout-btn.php'; + load_template( $tempTest, false, array() ); + } + } + else + { + return; + } +} + +//To add 1CC Mini cart checkout button +if(isRazorpayPluginEnabled() && is1ccEnabled() && isMiniCartCheckoutEnabled()) +{ + + add_action( 'woocommerce_widget_shopping_cart_buttons', function() + { + // Removing Buttons + remove_action( 'woocommerce_widget_shopping_cart_buttons', 'woocommerce_widget_shopping_cart_proceed_to_checkout', 20 ); + + add_action('woocommerce_cart_updated', 'enqueueScriptsFor1cc', 10); + + add_action( 'woocommerce_widget_shopping_cart_buttons', 'addMiniCheckoutButton', 20 ); + + }, 1 ); +} + +function addMiniCheckoutButton() +{ + add_action('wp_enqueue_scripts', 'enqueueScriptsFor1cc', 0); + + if (isTestModeEnabled()) { + $current_user = wp_get_current_user(); + if ($current_user->has_cap( 'administrator' ) || preg_match( '/@razorpay.com$/i', $current_user->user_email )) { + $tempTest = RZP_PATH . 'templates/rzp-mini-checkout-btn.php'; + load_template( $tempTest, false, array() ); + } + } else { + $tempTest = RZP_PATH . 'templates/rzp-mini-checkout-btn.php'; + load_template( $tempTest, false, array() ); + } + +} + +//To add 1CC button on product page. +if(isRazorpayPluginEnabled() && is1ccEnabled() && isPdpCheckoutEnabled()) +{ + add_action( 'woocommerce_after_add_to_cart_button', 'addPdpCheckoutButton'); +} + +function injectMerchantKeyMeta(){ + echo ""; +} + +function addRzpSpinner() +{ + if (isTestModeEnabled()) { + $current_user = wp_get_current_user(); + if ($current_user->has_cap( 'administrator' ) || preg_match( '/@razorpay.com$/i', $current_user->user_email )) { + $tempTest = RZP_PATH . 'templates/rzp-spinner.php'; + load_template( $tempTest, false, array() ); + } + } else { + $tempTest = RZP_PATH . 'templates/rzp-spinner.php'; + load_template( $tempTest, false, array() ); + } +} + +function addPdpCheckoutButton() +{ + add_action('wp_enqueue_scripts', 'enqueueScriptsFor1cc', 0); + + if (isTestModeEnabled()) { + $current_user = wp_get_current_user(); + if ($current_user->has_cap( 'administrator' ) || preg_match( '/@razorpay.com$/i', $current_user->user_email )) { + $tempTest = RZP_PATH . 'templates/rzp-pdp-checkout-btn.php'; + load_template( $tempTest, false, array() ); + } + } else { + $tempTest = RZP_PATH . 'templates/rzp-pdp-checkout-btn.php'; + load_template( $tempTest, false, array() ); + } +} + +// for admin panel custom alerts +function addAdminSettingsAlertScript() +{ + if (isRazorpayPluginEnabled()) { + wp_enqueue_script('rzpAdminSettingsScript', plugin_dir_url(__FILE__) .'public/js/admin-rzp-settings.js'); + } +} + +add_action('admin_enqueue_scripts', 'addAdminSettingsAlertScript'); + +function disable_coupon_field_on_cart($enabled) +{ + if (isTestModeEnabled()) { + $current_user = wp_get_current_user(); + if ($current_user->has_cap( 'administrator' ) || preg_match( '/@razorpay.com$/i', $current_user->user_email )) { + if (is_cart()) { + $enabled = false; + } + } + } else { + if (is_cart()) { + $enabled = false; + } + } + return $enabled; +} + +if(is1ccEnabled()) +{ + add_filter('woocommerce_coupons_enabled', 'disable_coupon_field_on_cart'); + add_action('woocommerce_cart_updated', 'enqueueScriptsFor1cc', 10); + add_filter('woocommerce_order_needs_shipping_address', '__return_true'); +} + +//Changes Recovery link URL to Magic cart URL to avoid redirection to checkout page +function cartbounty_alter_automation_button( $button ){ + return str_replace("cartbounty=","cartbounty=magic_",$button); +} + +if(is_plugin_active('woo-save-abandoned-carts/cartbounty-abandoned-carts.php')){ + add_filter( 'cartbounty_automation_button_html', 'cartbounty_alter_automation_button' ); +} diff --git a/woo-razorpay.php b/woo-razorpay.php index 483264ed..4c9f06a9 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -2289,35 +2289,35 @@ public function handlePromotions($razorpayData, $order, $orderId, $razorpayPayme } }else if($promotion['type'] == 'terra_wallet') { - if (!is_plugin_active('woo-wallet/woo-wallet.php')) { + if (is_plugin_active('woo-wallet/woo-wallet.php')) { + $viaWalletAmount = $promotion['value'] / 100; + $walletBalance = woo_wallet()->wallet->get_wallet_balance($order->get_user_id(), 'edit'); + if ($walletBalance < $viaWalletAmount) { + $this->processRefundForOrdersWithGiftCard( + $orderId, + $razorpayPaymentId, + $razorpayData['amount_paid'], + 'Terra Wallet Insufficient Balance'); + } + $this->addTerraWalletAmountAsPartialPaymentFee($viaWalletAmount, $order); + woo_wallet()->wallet->wallet_partial_payment($orderId); + $terraWalletTransactionID = get_post_meta($orderId, '_partial_pay_through_wallet_compleate', true); + if (!$terraWalletTransactionID) { + $this->processRefundForOrdersWithGiftCard( + $orderId, + $razorpayPaymentId, + $razorpayData['amount_paid'], + 'Terra Wallet Transaction Failed'); + } else { + rzpLogInfo("TerraWallet TransactionID for order id $orderId is $terraWalletTransactionID"); + } + } else { $this->processRefundForOrdersWithGiftCard( $orderId, $razorpayPaymentId, $razorpayData['amount_paid'], 'Terra Wallet Plugin is not active'); } - $viaWalletAmount = $promotion['value']/100; - $walletBalance = woo_wallet()->wallet->get_wallet_balance($order->get_user_id(), 'edit'); - if ($walletBalance < $viaWalletAmount) - { - $this->processRefundForOrdersWithGiftCard( - $orderId, - $razorpayPaymentId, - $razorpayData['amount_paid'], - 'Terra Wallet Insufficient Balance'); - } - $this->addTerraWalletAmountAsPartialPaymentFee($viaWalletAmount, $order); - woo_wallet()->wallet->wallet_partial_payment($orderId); - $terraWalletTransactionID = get_post_meta( $orderId, '_partial_pay_through_wallet_compleate', true ); - if(!$terraWalletTransactionID) { - $this->processRefundForOrdersWithGiftCard( - $orderId, - $razorpayPaymentId, - $razorpayData['amount_paid'], - 'Terra Wallet Transaction Failed'); - }else { - rzpLogInfo("TerraWallet TransactionID for order id $orderId is $terraWalletTransactionID"); - } } else{ From 4127b2a619dd9130771dfe1af668cacc7c0a8f7c Mon Sep 17 00:00:00 2001 From: Anantha-Perumal Date: Fri, 2 Feb 2024 18:15:30 +0530 Subject: [PATCH 14/91] delete unwanted files --- test.php | 3004 ------------------------------------------------------ 1 file changed, 3004 deletions(-) delete mode 100644 test.php diff --git a/test.php b/test.php deleted file mode 100644 index ac81612d..00000000 --- a/test.php +++ /dev/null @@ -1,3004 +0,0 @@ -getSetting('key_id'); - $trackObject = $rzp->newTrackPluginInstrumentation($key_id, ''); - $properties = [ - 'isHposEnabled' => true - ]; - - $response = $trackObject->rzpTrackSegment('hpos.interacted', $properties); - $trackObject->rzpTrackDataLake('hpos.interacted', $properties); - - update_option('rzp_hpos', 'yes'); - } - else if(class_exists('Automattic\WooCommerce\Utilities\OrderUtil') and - OrderUtil::custom_orders_table_usage_is_enabled() === false and - get_option('rzp_hpos') === 'yes') - { - $key_id = $rzp->getSetting('key_id'); - $trackObject = $rzp->newTrackPluginInstrumentation($key_id, ''); - $properties = [ - 'isHposEnabled' => false - ]; - - $response = $trackObject->rzpTrackSegment('hpos.interacted', $properties); - $trackObject->rzpTrackDataLake('hpos.interacted', $properties); - - update_option('rzp_hpos', 'no'); - } - } - - if (!class_exists('WC_Payment_Gateway') || class_exists('WC_Razorpay')) - { - return; - } - - class WC_Razorpay extends WC_Payment_Gateway - { - // This one stores the WooCommerce Order Id - const SESSION_KEY = 'razorpay_wc_order_id'; - const RAZORPAY_PAYMENT_ID = 'razorpay_payment_id'; - const RAZORPAY_ORDER_ID = 'razorpay_order_id'; - const RAZORPAY_ORDER_ID_1CC = 'razorpay_order_id_1cc'; - const RAZORPAY_SIGNATURE = 'razorpay_signature'; - const RAZORPAY_WC_FORM_SUBMIT = 'razorpay_wc_form_submit'; - - const INR = 'INR'; - const CAPTURE = 'capture'; - const AUTHORIZE = 'authorize'; - const WC_ORDER_ID = 'woocommerce_order_id'; - const WC_ORDER_NUMBER = 'woocommerce_order_number'; - - const DEFAULT_LABEL = 'Credit Card/Debit Card/NetBanking'; - const DEFAULT_DESCRIPTION = 'Pay securely by Credit or Debit card or Internet Banking through Razorpay.'; - const DEFAULT_SUCCESS_MESSAGE = 'Thank you for shopping with us. Your account has been charged and your transaction is successful. We will be processing your order soon.'; - - const PREPAY_COD_URL = '1cc/orders/cod/convert'; - - protected $supportedWebhookEvents = array( - 'payment.authorized', - 'payment.pending', - 'refund.created', - 'virtual_account.credited', - 'subscription.cancelled', - 'subscription.paused', - 'subscription.resumed', - 'subscription.charged' - ); - - protected $defaultWebhookEvents = array( - 'payment.authorized' => true, - 'refund.created' => true - ); - - protected $visibleSettings = array( - 'enabled', - 'title', - 'description', - 'key_id', - 'key_secret', - 'payment_action', - 'order_success_message', - 'route_enable', - 'enable_1cc_debug_mode', - ); - - public $form_fields = array(); - - public $supports = array( - 'products', - 'refunds' - ); - - /** - * Can be set to true if you want payment fields - * to show on the checkout (if doing a direct integration). - * @var boolean - */ - public $has_fields = false; - - /** - * Unique ID for the gateway - * @var string - */ - public $id = 'razorpay'; - - /** - * Title of the payment method shown on the admin page. - * @var string - */ - public $method_title = 'Razorpay'; - - - /** - * Description of the payment method shown on the admin page. - * @var string - */ - public $method_description = 'Allow customers to securely pay via Razorpay (Credit/Debit Cards, NetBanking, UPI, Wallets)'; - - /** - * Icon URL, set in constructor - * @var string - */ - public $icon; - - /** - * TODO: Remove usage of $this->msg - */ - protected $msg = array( - 'message' => '', - 'class' => '', - ); - - /** - * hpos enabled check - * @var bool - */ - public $isHposEnabled; - - /** - * Return Wordpress plugin settings - * @param string $key setting key - * @return mixed setting value - */ - public function getSetting($key) - { - return $this->get_option($key); - } - - public function getCustomOrdercreationMessage($thank_you_title, $order) - { - $message = $this->getSetting('order_success_message'); - if (isset($message) === false) - { - $message = static::DEFAULT_SUCCESS_MESSAGE; - } - return $message; - } - - /** - * @param boolean $hooks Whether or not to - * setup the hooks on - * calling the constructor - */ - public function __construct($hooks = true) - { - - $this->isHposEnabled = false; - - // file added in woocommerce v7.1.0, maybe removed later - if (class_exists('Automattic\WooCommerce\Utilities\OrderUtil') and - OrderUtil::custom_orders_table_usage_is_enabled()) - { - $this->isHposEnabled = true; - } - - $this->icon = "https://cdn.razorpay.com/static/assets/logo/rzp_payment_icon.svg"; - // 1cc flags should be enabled only if merchant has access to 1cc feature - $is1ccAvailable = false; - $isAccCreationAvailable = false; - - // Load preference API call only for administrative interface page. - if (current_user_can('administrator')) - { - if (!empty($this->getSetting('key_id')) && !empty($this->getSetting('key_secret'))) - { - try { - - $api = $this->getRazorpayApiInstance(); - $merchantPreferences = $api->request->request('GET', 'merchant/1cc_preferences'); - - if (!empty($merchantPreferences['features']['one_click_checkout'])) { - $is1ccAvailable = true; - } - - if (!empty($merchantPreferences['features']['one_cc_store_account'])) { - $isAccCreationAvailable = true; - } - - } catch (\Exception $e) { - rzpLogError($e->getMessage()); - } - - } - } - - if ($is1ccAvailable) { - $this->visibleSettings = array_merge($this->visibleSettings, array( - 'enable_1cc', - 'enable_1cc_mandatory_login', - 'enable_1cc_test_mode', - 'enable_1cc_pdp_checkout', - 'enable_1cc_mini_cart_checkout', - 'enable_1cc_ga_analytics', - 'enable_1cc_fb_analytics', - '1cc_min_cart_amount', - '1cc_min_COD_slab_amount', - '1cc_max_COD_slab_amount', - )); - - if ($isAccCreationAvailable) { - $this->visibleSettings = array_merge($this->visibleSettings, array( - '1cc_account_creation', - )); - } - - } - - $this->init_form_fields(); - $this->init_settings(); - - // TODO: This is hacky, find a better way to do this - // See mergeSettingsWithParentPlugin() in subscriptions for more details. - if ($hooks) - { - $this->initHooks(); - } - - $this->title = $this->getSetting('title'); - } - - protected function initHooks() - { - add_action('woocommerce_receipt_' . $this->id, array($this, 'receipt_page')); - - add_action('woocommerce_api_' . $this->id, array($this, 'check_razorpay_response')); - - $cb = array($this, 'process_admin_options'); - - if (version_compare(WOOCOMMERCE_VERSION, '2.0.0', '>=')) - { - add_action( "woocommerce_update_options_payment_gateways_{$this->id}", array($this, 'pluginInstrumentation')); - add_action("woocommerce_update_options_payment_gateways_{$this->id}", $cb); - add_action( "woocommerce_update_options_payment_gateways_{$this->id}", array($this, 'autoEnableWebhook')); - add_action( "woocommerce_update_options_payment_gateways_{$this->id}", array($this, 'addAdminCheckoutSettingsAlert')); - add_action( "woocommerce_update_options_payment_gateways_{$this->id}", 'createOneCCAddressSyncCron'); - add_action( "woocommerce_update_options_payment_gateways_{$this->id}", 'syncPluginFetchCron'); - } - else - { - add_action( "woocommerce_update_options_payment_gateways", array($this, 'pluginInstrumentation')); - add_action('woocommerce_update_options_payment_gateways', $cb); - add_action( "woocommerce_update_options_payment_gateways", array($this, 'autoEnableWebhook')); - add_action( "woocommerce_update_options_payment_gateways", array($this, 'addAdminCheckoutSettingsAlert')); - add_action( "woocommerce_update_options_payment_gateways", 'createOneCCAddressSyncCron'); - add_action( "woocommerce_update_options_payment_gateways_{$this->id}", 'syncPluginFetchCron'); - } - - add_filter( 'woocommerce_thankyou_order_received_text', array($this, 'getCustomOrdercreationMessage'), 20, 2 ); - } - - public function init_form_fields() - { - $webhookUrl = esc_url(admin_url('admin-post.php')) . '?action=rzp_wc_webhook'; - - $defaultFormFields = array( - 'enabled' => array( - 'title' => __('Enable/Disable', $this->id), - 'type' => 'checkbox', - 'label' => __('Enable this module?', $this->id), - 'default' => 'yes' - ), - 'title' => array( - 'title' => __('Title', $this->id), - 'type'=> 'text', - 'description' => __('This controls the title which the user sees during checkout.', $this->id), - 'default' => __(static::DEFAULT_LABEL, $this->id) - ), - 'description' => array( - 'title' => __('Description', $this->id), - 'type' => 'textarea', - 'description' => __('This controls the description which the user sees during checkout.', $this->id), - 'default' => __(static::DEFAULT_DESCRIPTION, $this->id) - ), - 'key_id' => array( - 'title' => __('Key ID', $this->id), - 'type' => 'text', - 'description' => __('The key Id and key secret can be generated from "API Keys" section of Razorpay Dashboard. Use test or live for test or live mode.', $this->id) - ), - 'key_secret' => array( - 'title' => __('Key Secret', $this->id), - 'type' => 'text', - 'description' => __('The key Id and key secret can be generated from "API Keys" section of Razorpay Dashboard. Use test or live for test or live mode.', $this->id) - ), - 'payment_action' => array( - 'title' => __('Payment Action', $this->id), - 'type' => 'select', - 'description' => __('Payment action on order compelete', $this->id), - 'default' => self::CAPTURE, - 'options' => array( - self::AUTHORIZE => 'Authorize', - self::CAPTURE => 'Authorize and Capture' - ) - ), - 'order_success_message' => array( - 'title' => __('Order Completion Message', $this->id), - 'type' => 'textarea', - 'description' => __('Message to be displayed after a successful order', $this->id), - 'default' => __(STATIC::DEFAULT_SUCCESS_MESSAGE, $this->id), - ), - 'enable_1cc_debug_mode' => array( //Added this config for both native and 1cc merchants - 'title' => __('Activate debug mode'), - 'type' => 'checkbox', - 'description' => 'When debug mode is active, API logs and errors are collected and stored in your Woocommerce dashboard. It is recommended to keep this activated.', - 'label' => __('Enable debug mode'), - 'default' => 'yes', - ), - ); - - do_action_ref_array( 'setup_extra_setting_fields', array( &$defaultFormFields ) ); - - foreach ($defaultFormFields as $key => $value) - { - if (in_array($key, $this->visibleSettings, true)) - { - $this->form_fields[$key] = $value; - } - } - - //Affordability Widget Code - if (is_admin()) - { - try - { - if (isset($_POST['woocommerce_razorpay_key_id']) and - empty($_POST['woocommerce_razorpay_key_id']) === false and - isset($_POST['woocommerce_razorpay_key_secret']) and - empty($_POST['woocommerce_razorpay_key_secret']) === false) - { - $api = new Api($_POST['woocommerce_razorpay_key_id'], $_POST['woocommerce_razorpay_key_secret']); - } - else - { - $api = $this->getRazorpayApiInstance(); - } - - $merchantPreferences = $api->request->request('GET', 'accounts/me/features'); - if (isset($merchantPreferences) === false or - isset($merchantPreferences['assigned_features']) === false) - { - throw new Exception("Error in Api call."); - } - - update_option('rzp_afd_enable', 'no'); - foreach ($merchantPreferences['assigned_features'] as $preference) - { - if ($preference['name'] === 'affordability_widget' or - $preference['name'] === 'affordability_widget_set') - { - add_action('woocommerce_sections_checkout', 'addSubSection'); - add_action('woocommerce_settings_tabs_checkout', 'displayAffordabilityWidgetSettings'); - add_action('woocommerce_update_options_checkout', 'updateAffordabilityWidgetSettings'); - update_option('rzp_afd_enable', 'yes'); - break; - } - } - - update_option('rzp_afd_feature_checked', 'yes'); - } - catch (\Exception $e) - { - rzpLogError($e->getMessage()); - return; - } - } - } - - protected function getWebhookUrl() - { - return esc_url(admin_url('admin-post.php')) . '?action=rzp_wc_webhook'; - } - - protected function triggerValidationInstrumentation($data) - { - $properties = [ - 'page_url' => $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], - 'field_type' => 'text', - 'field_name' => 'key_id or key_secret', - 'is_plugin_activated' => ($this->getSetting('enabled') === 'yes') ? true : false - ]; - - $properties = array_merge($properties, $data); - - $trackObject = $this->newTrackPluginInstrumentation($this->getSetting('key_id'), ''); - $response = $trackObject->rzpTrackSegment('formfield.validation.error', $properties); - $trackObject->rzpTrackDataLake('formfield.validation.error', $properties); - } - - public function autoEnableWebhook() - { - $webhookExist = false; - $webhookUrl = $this->getWebhookUrl(); - - $key_id = $this->getSetting('key_id'); - $key_secret = $this->getSetting('key_secret'); - $enabled = true; - $secret = empty($this->getSetting('webhook_secret')) ? $this->generateSecret() : $this->getSetting('webhook_secret'); - - update_option('webhook_secret', $secret); - $getWebhookFlag = get_option('webhook_enable_flag'); - $time = time(); - - if (empty($getWebhookFlag)) - { - add_option('webhook_enable_flag', $time); - } - else - { - update_option('webhook_enable_flag', $time); - } - //validating the key id and key secret set properly or not. - if($key_id == null || $key_secret == null) - { - $validationErrorProperties = $this->triggerValidationInstrumentation( - ['error_message' => 'Key Id and or Key Secret is null']); - ?> -
-

-
- getRazorpayApiInstance(); - $validateKeySecret = $api->request->request("GET", "orders"); - } - catch (Exception $e) - { - $validationErrorProperties = $this->triggerValidationInstrumentation( - ['error_message' => 'Invalid Key Id and Key Secret']); - ?> -
-

-
- $e->getMessage(), - ); - rzpLogError(json_encode($log)); - - return; - } - - $domain = parse_url($webhookUrl, PHP_URL_HOST); - - $domain_ip = gethostbyname($domain); - - if (!filter_var($domain_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) - { - ?> -
-

-
- webhookAPI("GET", "webhooks?count=".$count."&skip=".$skip); - $skip += 10; - if ($webhook['count'] > 0) - { - foreach ($webhook['items'] as $key => $value) - { - $webhookItems[] = $value; - } - } - } while ( $webhook['count'] === $count); - - $subscriptionWebhookFlag = get_option('rzp_subscription_webhook_enable_flag'); - - if ($subscriptionWebhookFlag) - { - $this->defaultWebhookEvents += array( - 'subscription.cancelled' => true, - 'subscription.resumed' => true, - 'subscription.paused' => true, - 'subscription.charged' => true - ); - } - - $data = [ - 'url' => $webhookUrl, - 'active' => $enabled, - 'events' => $this->defaultWebhookEvents, - 'secret' => $secret, - ]; - - if (count($webhookItems) > 0) - { - foreach ($webhookItems as $key => $value) - { - if ($value['url'] === $webhookUrl) - { - foreach ($value['events'] as $evntkey => $evntval) - { - if (($evntval == 1) and - (in_array($evntkey, $this->supportedWebhookEvents) === true)) - { - $this->defaultWebhookEvents[$evntkey] = true; - } - } - - if (!$subscriptionWebhookFlag) - { - unset($this->defaultWebhookEvents['subscription.cancelled']); - unset($this->defaultWebhookEvents['subscription.resumed']); - unset($this->defaultWebhookEvents['subscription.paused']); - unset($this->defaultWebhookEvents['subscription.charged']); - } - - $data = [ - 'url' => $webhookUrl, - 'active' => $enabled, - 'events' => $this->defaultWebhookEvents, - 'secret' => $secret, - ]; - $webhookExist = true; - $webhookId = $value['id']; - } - } - } - - $webhookProperties = [ - 'page_url' => $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], - 'prev_page_url' => $_SERVER['HTTP_REFERER'], - 'is_plugin_activated' => ($this->getSetting('enabled') === 'yes') ? true : false, - 'events_selected' => $this->defaultWebhookEvents, - ]; - - if ($webhookExist) - { - $trackObject = $this->newTrackPluginInstrumentation($this->getSetting('key_id'), ''); - $response = $trackObject->rzpTrackSegment('autowebhook.updated', $webhookProperties); - $trackObject->rzpTrackDataLake('autowebhook.updated', $webhookProperties); - - rzpLogInfo('Updating razorpay webhook'); - return $this->webhookAPI('PUT', "webhooks/" . $webhookId, $data); - } - else - { - $trackObject = $this->newTrackPluginInstrumentation($this->getSetting('key_id'), ''); - $response = $trackObject->rzpTrackSegment('autowebhook.created', $webhookProperties); - $trackObject->rzpTrackDataLake('autowebhook.created', $webhookProperties); - - rzpLogInfo('Creating razorpay webhook'); - return $this->webhookAPI('POST', "webhooks/", $data); - } - } - - public function newTrackPluginInstrumentation($key, $secret) - { - $api = $this->getRazorpayApiInstance($key, $secret); - - return new TrackPluginInstrumentation($api, $key); - } - - public function pluginInstrumentation() - { - if (empty($_POST['woocommerce_razorpay_key_id']) or - empty($_POST['woocommerce_razorpay_key_secret'])) - { - error_log('Key Id and Key Secret are required.'); - return; - } - - $trackObject = $this->newTrackPluginInstrumentation($_POST['woocommerce_razorpay_key_id'], $_POST['woocommerce_razorpay_key_secret']); - - $existingVersion = get_option('rzp_woocommerce_current_version'); - - if(isset($existingVersion)) - { - update_option('rzp_woocommerce_current_version', get_plugin_data(__FILE__)['Version']); - } - else - { - add_option('rzp_woocommerce_current_version', get_plugin_data(__FILE__)['Version']); - } - - try - { - global $wpdb; - $isTransactingUser = false; - - $orderTable = $wpdb->prefix . 'wc_orders'; - - if($this->isHposEnabled) - { - $rzpTrancationData = $wpdb->get_row($wpdb->prepare("SELECT id FROM $orderTable AS P WHERE payment_method = %s", "razorpay")); - } - else - { - $rzpTrancationData = $wpdb->get_row($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta AS P WHERE meta_key = %s AND meta_value = %s", "_payment_method", "razorpay")); - } - - $arrayPost = json_decode(json_encode($rzpTrancationData), true); - - if (empty($arrayPost) === false and - ($arrayPost == null) === false) - { - $isTransactingUser = true; - } - } - catch (\Razorpay\Api\Errors\Error $e) - { - ?> -
-

-
- -
-

-
- getMessage()); - return; - } - - $authEvent = ''; - $pluginStatusEvent = ''; - - $authProperties = [ - 'is_key_id_populated' => true, - 'is_key_secret_populated' => true, - 'page_url' => $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], - 'auth_successful_status' => true, - 'is_plugin_activated' => (isset($_POST['woocommerce_razorpay_enabled'])) ? true :false - ]; - - // for enable and disable plugin - $pluginStatusProperties = [ - 'current_status' => ($this->getSetting('enabled')==='yes') ? 'enabled' :'disabled', - 'is_transacting_user' => $isTransactingUser - ]; - - if (empty($this->getSetting('key_id')) and - empty($this->getSetting('key_secret'))) - { - $authEvent = 'saving auth details'; - - if(empty($_POST['woocommerce_razorpay_enabled']) === false) - { - $pluginStatusEvent = 'plugin enabled'; - } - } - else - { - $authEvent = 'updating auth details'; - } - - $response = $trackObject->rzpTrackSegment($authEvent, $authProperties); - - $trackObject->rzpTrackDataLake($authEvent, $authProperties); - - if ((empty($_POST['woocommerce_razorpay_enabled']) === false) and - ($this->getSetting('enabled') === 'no')) - { - $pluginStatusEvent = 'plugin enabled'; - } - elseif ((empty($_POST['woocommerce_razorpay_enabled']) === true) and - ($this->getSetting('enabled') === 'yes')) - { - $pluginStatusEvent = 'plugin disabled'; - } - - if ($pluginStatusEvent !== '') - { - $response = $trackObject->rzpTrackSegment($pluginStatusEvent, $pluginStatusProperties); - - $trackObject->rzpTrackDataLake($pluginStatusEvent, $pluginStatusProperties); - } - } - - public function generateSecret() - { - $alphanumericString = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-=~!@#$%^&*()_+,./<>?;:[]{}|abcdefghijklmnopqrstuvwxyz'; - $secret = substr(str_shuffle($alphanumericString), 0, 20); - - return $secret; - } - - // showing notice : status of 1cc active / inactive message in admin dashboard - function addAdminCheckoutSettingsAlert() { - $enable_1cc = $this->getSetting('enable_1cc'); - if($enable_1cc == 'no') - { - ?> -
-

-
- -
-

-
- getRazorpayApiInstance(); - - $webhook = $api->request->request($method, $url, $data); - } - catch(Exception $e) - { - $log = array( - 'message' => $e->getMessage(), - ); - - error_log(json_encode($log)); - rzpLogError(json_encode($log)); - } - - return $webhook; - } - - public function admin_options() - { - echo '

'.__('Razorpay Payment Gateway', $this->id) . '

'; - echo '

'.__('Allows payments by Credit/Debit Cards, NetBanking, UPI, and multiple Wallets') . '

'; - echo '

'.__('First signup for a Razorpay account or - login if you have an existing account.'). '

'; - echo ''; - - // Generate the HTML For the settings form. - $this->generate_settings_html(); - echo '
'; - } - - public function get_description() - { - return $this->getSetting('description'); - } - - /** - * Receipt Page - * @param string $orderId WC Order Id - **/ - function receipt_page($orderId) - { - foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $value) - { - if ($value['function'] === 'output' and - stripos($value['file'], 'themes/divi') !== false and - basename($value['file'], ".php") !== 'CheckoutPaymentInfo') - { - return; - } - } - - echo $this->generate_razorpay_form($orderId); - } - - /** - * Returns key to use in session for storing Razorpay order Id - * @param string $orderId Razorpay Order Id - * @return string Session Key - */ - protected function getOrderSessionKey($orderId) - { - if ($this->isHposEnabled) { - $order = wc_get_order($orderId); - $is1ccOrder = $order->get_meta('is_magic_checkout_order'); - }else{ - $is1ccOrder = get_post_meta( $orderId, 'is_magic_checkout_order', true ); - } - - if($is1ccOrder == 'yes') - { - return self::RAZORPAY_ORDER_ID_1CC . $orderId; - } - return self::RAZORPAY_ORDER_ID . $orderId; - } - - /** - * Given a order Id, find the associated - * Razorpay Order from the session and verify - * that is is still correct. If not found - * (or incorrect), create a new Razorpay Order - * - * @param string $orderId Order Id - * @return mixed Razorpay Order Id or Exception - */ - public function createOrGetRazorpayOrderId($order, $orderId, $is1ccCheckout = 'no') - { - global $woocommerce; - rzpLogInfo("createOrGetRazorpayOrderId $orderId and is1ccCheckout is set to $is1ccCheckout"); - - $create = false; - - if($is1ccCheckout == 'no') - { - if ($this->isHposEnabled) { - $order->update_meta_data( 'is_magic_checkout_order', 'no' ); - $order->save(); - }else{ - update_post_meta($orderId, 'is_magic_checkout_order', 'no'); - } - - rzpLogInfo("Called createOrGetRazorpayOrderId with params orderId $orderId and is_magic_checkout_order is set to no"); - } - - $sessionKey = $this->getOrderSessionKey($orderId); - - try - { - $razorpayOrderId = get_transient($sessionKey); - rzpLogInfo("razorpayOrderId $razorpayOrderId | sessionKey $sessionKey"); - // If we don't have an Order - // or the if the order is present in transient but doesn't match what we have saved - if (($razorpayOrderId === false) or - (($razorpayOrderId and ($this->verifyOrderAmount($razorpayOrderId, $orderId, $is1ccCheckout)) === false))) - { - $create = true; - } - else - { - return $razorpayOrderId; - } - } - // Order doesn't exist or verification failed - // So try creating one - catch (Exception $e) - { - $create = true; - } - - if ($create) - { - try - { - return $this->createRazorpayOrderId($orderId, $sessionKey); - } - // For the bad request errors, it's safe to show the message to the customer. - catch (Errors\BadRequestError $e) - { - return $e; - } - // For any other exceptions, we make sure that the error message - // does not propagate to the front-end. - catch (Exception $e) - { - return new Exception("Payment failed"); - } - } - } - - /** - * Returns redirect URL post payment processing - * @return string redirect URL - */ - private function getRedirectUrl($orderId) - { - $order = wc_get_order($orderId); - - $query = [ - 'wc-api' => $this->id, - 'order_key' => $order->get_order_key(), - ]; - - return add_query_arg($query, trailingslashit(get_home_url())); - } - - /** - * Specific payment parameters to be passed to checkout - * for payment processing - * @param string $orderId WC Order Id - * @return array payment params - */ - protected function getRazorpayPaymentParams($order, $orderId) - { - $getWebhookFlag = get_option('webhook_enable_flag'); - $time = time(); - if (empty($getWebhookFlag) == false) - { - if ($getWebhookFlag + 86400 < time()) - { - $this->autoEnableWebhook(); - } - } - else - { - update_option('webhook_enable_flag', $time); - $this->autoEnableWebhook(); - } - - rzpLogInfo("getRazorpayPaymentParams $orderId"); - $razorpayOrderId = $this->createOrGetRazorpayOrderId($order, $orderId); - - if ($razorpayOrderId === null) - { - throw new Exception('RAZORPAY ERROR: Razorpay API could not be reached'); - } - else if ($razorpayOrderId instanceof Exception) - { - $message = $razorpayOrderId->getMessage(); - - throw new Exception("RAZORPAY ERROR: Order creation failed with the message: '$message'."); - } - - return [ - 'order_id' => $razorpayOrderId - ]; - } - - /** - * Generate razorpay button link - * @param string $orderId WC Order Id - **/ - public function generate_razorpay_form($orderId) - { - $order = wc_get_order($orderId); - - try - { - $params = $this->getRazorpayPaymentParams($order, $orderId); - } - catch (Exception $e) - { - return $e->getMessage(); - } - - $checkoutArgs = $this->getCheckoutArguments($order, $params); - - $html = '

'.__('Thank you for your order, please click the button below to pay with Razorpay.', $this->id).'

'; - - $html .= $this->generateOrderForm($checkoutArgs); - - return $html; - } - - /** - * default parameters passed to checkout - * @param WC_Order $order WC Order - * @return array checkout params - */ - public function getDefaultCheckoutArguments($order) - { - global $woocommerce; - - $orderId = $order->get_order_number(); - - $wcOrderId = $order->get_id(); - - $callbackUrl = $this->getRedirectUrl($wcOrderId); - - $sessionKey = $this->getOrderSessionKey($wcOrderId); - - $razorpayOrderId = get_transient($sessionKey); - - $productinfo = "Order $orderId"; - - return array( - 'key' => $this->getSetting('key_id'), - 'name' => html_entity_decode(get_bloginfo('name'), ENT_QUOTES), - 'currency' => self::INR, - 'description' => $productinfo, - 'notes' => array( - self::WC_ORDER_ID => $orderId, - self::WC_ORDER_NUMBER => $wcOrderId - ), - 'order_id' => $razorpayOrderId, - 'callback_url' => $callbackUrl, - 'prefill' => $this->getCustomerInfo($order) - ); - } - - /** - * @param WC_Order $order - * @return string currency - */ - private function getOrderCurrency($order) - { - if (version_compare(WOOCOMMERCE_VERSION, '2.7.0', '>=')) - { - return $order->get_currency(); - } - - return $order->get_order_currency(); - } - - /** - * Returns array of checkout params - */ - private function getCheckoutArguments($order, $params) - { - $args = $this->getDefaultCheckoutArguments($order); - - $currency = $this->getOrderCurrency($order); - - // The list of valid currencies is at https://razorpay.freshdesk.com/support/solutions/articles/11000065530-what-currencies-does-razorpay-support- - - $args = array_merge($args, $params); - - return $args; - } - - public function getCustomerInfo($order) - { - if (version_compare(WOOCOMMERCE_VERSION, '2.7.0', '>=')) - { - $args = array( - 'name' => $order->get_billing_first_name() . ' ' . $order->get_billing_last_name(), - 'email' => $order->get_billing_email(), - 'contact' => $order->get_billing_phone(), - ); - } - else - { - $args = array( - 'name' => $order->billing_first_name . ' ' . $order->billing_last_name, - 'email' => $order->billing_email, - 'contact' => $order->billing_phone, - ); - } - - return $args; - } - - protected function createRazorpayOrderId($orderId, $sessionKey) - { - rzpLogInfo("Called createRazorpayOrderId with params orderId $orderId and sessionKey $sessionKey"); - - - // Calls the helper function to create order data - global $woocommerce; - - $api = $this->getRazorpayApiInstance(); - - $data = $this->getOrderCreationData($orderId); - rzpLogInfo('For order ' . $orderId); - rzpLogInfo(json_encode($data)); - try - { - if ($data['currency'] === "KWD" or - $data['currency'] === "OMR" or - $data['currency'] === "BHD") - { - throw new Exception($data['currency'] . " currency is not supported at the moment."); - } - - $razorpayOrder = $api->order->create($data); - } - catch (Exception $e) - { - rzpLogInfo("rzp order error " . $e->getMessage()); - return $e; - } - - $getWebhookFlag = get_option('webhook_enable_flag'); - $time = time(); - - if (empty($getWebhookFlag) == false) - { - if ($getWebhookFlag + 43200 < time()) - { - $this->autoEnableWebhook(); - } - } - else - { - update_option('webhook_enable_flag', $time); - $this->autoEnableWebhook(); - } - - $razorpayOrderId = $razorpayOrder['id']; - - // Storing the razorpay order id in transient for 5 hours time. - set_transient($sessionKey, $razorpayOrderId, 18000); - - // By default woocommerce session TTL is 48 hours. - $woocommerce->session->set($sessionKey, $razorpayOrderId); - - rzpLogInfo('For order session key ' . $sessionKey); - //update it in order comments - $order = wc_get_order($orderId); - - $order->add_order_note("Razorpay OrderId: $razorpayOrderId"); - - return $razorpayOrderId; - } - - protected function verifyOrderAmount($razorpayOrderId, $orderId, $is1ccCheckout = 'no') - { - rzpLogInfo("Called verifyOrderAmount with params orderId $orderId and rzporderId $razorpayOrderId"); - $order = wc_get_order($orderId); - - $api = $this->getRazorpayApiInstance(); - - try - { - $razorpayOrder = $api->order->fetch($razorpayOrderId); - } - catch (Exception $e) - { - $message = $e->getMessage(); - rzpLogInfo("Failed at verifyOrderAmount with $message"); - return "RAZORPAY ERROR: Order fetch failed with the message '$message'"; - } - - $orderCreationData = $this->getOrderCreationData($orderId); - - $razorpayOrderArgs = array( - 'id' => $razorpayOrderId, - 'currency' => $orderCreationData['currency'], - 'receipt' => (string) $orderId, - ); - - if($is1ccCheckout == 'no'){ - $razorpayOrderArgs['amount'] = $orderCreationData['amount']; - }else{ - $razorpayOrderArgs['line_items_total'] = $orderCreationData['amount']; - } - - $orderKeys = array_keys($razorpayOrderArgs); - - foreach ($orderKeys as $key) - { - if ($razorpayOrderArgs[$key] !== $razorpayOrder[$key]) - { - return false; - } - } - - return true; - } - - private function getOrderCreationData($orderId) - { - global $wpdb; - - rzpLogInfo("Called getOrderCreationData with params orderId $orderId"); - $order = wc_get_order($orderId); - - $orderMetaTable = $wpdb->prefix . 'wc_orders_meta'; - - if ($this->isHposEnabled) { - $is1ccOrder = $order->get_meta('is_magic_checkout_order'); - }else{ - $is1ccOrder = get_post_meta( $orderId, 'is_magic_checkout_order', true ); - } - - $data = array( - 'receipt' => (string)$orderId, - 'amount' => (int) round($order->get_total() * 100), - 'currency' => $this->getOrderCurrency($order), - 'payment_capture' => ($this->getSetting('payment_action') === self::AUTHORIZE) ? 0 : 1, - 'app_offer' => ($order->get_discount_total() > 0) ? 1 : 0, - 'notes' => array( - self::WC_ORDER_NUMBER => (string) $orderId, - ), - ); - - if ($this->getSetting('route_enable') == 'yes') - { - $razorpayRoute = new RZP_Route_Action(); - $orderTransferArr = $razorpayRoute->getOrderTransferData($orderId); - - if(isset($orderTransferArr) && !empty($orderTransferArr)){ - - $transferData = array( - 'transfers' => $orderTransferArr - ); - $data = array_merge($data,$transferData); - } - } - - rzpLogInfo("Called getOrderCreationData with params orderId $orderId and is1ccOrder is set to $is1ccOrder"); - - if (is1ccEnabled() && !empty($is1ccOrder) && $is1ccOrder == 'yes') - { - $data = $this->orderArg1CC($data, $order); - rzpLogInfo("Called getOrderCreationData with params orderId $orderId and adding line_items_total"); - } - - return $data; - } - - public function orderArg1CC($data, $order) - { - // TODO: trim to 2 deciamls - $data['line_items_total'] = $order->get_total()*100; - - $i = 0; - // Get and Loop Over Order Items - $type = "e-commerce"; - foreach ( $order->get_items() as $item_id => $item ) - { - $product = $item->get_product(); - - $productDetails = $product->get_data(); - - // check product type for gift card plugin - if(is_plugin_active('pw-woocommerce-gift-cards/pw-gift-cards.php') || is_plugin_active('yith-woocommerce-gift-cards/init.php')){ - if($product->is_type('variation')){ - $parentProductId = $product->get_parent_id(); - $parentProduct = wc_get_product($parentProductId); - - if($parentProduct->get_type() == 'pw-gift-card' || $parentProduct->get_type() == 'gift-card'){ - $type = 'gift_card'; - } - - }else{ - - if($product->get_type() == 'pw-gift-card' || $product->get_type() == 'gift-card'){ - $type = 'gift_card'; - } - } - - } - - $data['line_items'][$i]['type'] = $type; - $data['line_items'][$i]['sku'] = $product->get_sku(); - $data['line_items'][$i]['variant_id'] = (string)$item->get_variation_id(); - $data['line_items'][$i]['product_id'] = (string)$product->get_parent_id(); - $data['line_items'][$i]['price'] = (empty($productDetails['price'])=== false) ? round(wc_get_price_excluding_tax($product)*100) + round($item->get_subtotal_tax()*100 / $item->get_quantity()) : 0; - $data['line_items'][$i]['offer_price'] = (empty($productDetails['sale_price'])=== false) ? (int) $productDetails['sale_price']*100 : $productDetails['price']*100; - $data['line_items'][$i]['quantity'] = (int)$item->get_quantity(); - $data['line_items'][$i]['name'] = mb_substr($item->get_name(), 0, 125, "UTF-8"); - $data['line_items'][$i]['description'] = mb_substr($item->get_name(), 0, 250,"UTF-8"); - $productImage = $product->get_image_id()?? null; - $data['line_items'][$i]['image_url'] = (string)($productImage? wp_get_attachment_url( $productImage ) : ""); - $data['line_items'][$i]['product_url'] = (string)$product->get_permalink(); - - $i++; - } - - return $data; - } - - public function enqueueCheckoutScripts($data) - { - if($data === 'checkoutForm' || $data === 'routeAnalyticsForm') - { - wp_register_script('razorpay_wc_script', plugin_dir_url(__FILE__) . 'script.js', - null, null); - $data = array($data); - } - else - { - wp_register_script('razorpay_wc_script', plugin_dir_url(__FILE__) . 'script.js', - array('razorpay_checkout')); - - wp_register_script('razorpay_checkout', - 'https://checkout.razorpay.com/v1/checkout.js', - null, null); - } - - wp_localize_script('razorpay_wc_script', - 'razorpay_wc_checkout_vars', - $data - ); - - wp_enqueue_script('razorpay_wc_script'); - } - - private function hostCheckoutScripts($data) - { - $url = Api::getFullUrl("checkout/embedded"); - - $formFields = ""; - foreach ($data as $fieldKey => $val) { - if(in_array($fieldKey, array('notes', 'prefill', '_'))) - { - foreach ($data[$fieldKey] as $field => $fieldVal) { - $formFields .= " \n"; - } - } - } - - return '
- - - - - - - - '. $formFields .' -
'; - - } - - - /** - * Generates the order form - **/ - function generateOrderForm($data) - { - $data["_"] = $this->getVersionMetaInfo($data); - - $wooOrderId = $data['notes']['woocommerce_order_number']; - - $redirectUrl = $this->getRedirectUrl($wooOrderId); - - $data['cancel_url'] = wc_get_checkout_url(); - - $api = $this->getRazorpayApiPublicInstance(); - - $merchantPreferences = $api->request->request("GET", "preferences"); - - if(isset($merchantPreferences['options']['redirect']) && $merchantPreferences['options']['redirect'] === true) - { - $this->enqueueCheckoutScripts('checkoutForm'); - - $data['preference']['image'] = $merchantPreferences['options']['image']; - - return $this->hostCheckoutScripts($data); - - } else { - $this->enqueueCheckoutScripts($data); - - return << - - - - - - -

- - -

-EOT; - } - } - - /** - * Gets the Order Key from the Order - * for all WC versions that we suport - */ - protected function getOrderKey($order) - { - $orderKey = null; - - if (version_compare(WOOCOMMERCE_VERSION, '3.0.0', '>=')) - { - return $order->get_order_key(); - } - - return $order->order_key; - } - - public function process_refund($orderId, $amount = null, $reason = '') - { - $order = wc_get_order($orderId); - - if (! $order or ! $order->get_transaction_id()) - { - return new WP_Error('error', __('Refund failed: No transaction ID', 'woocommerce')); - } - - $client = $this->getRazorpayApiInstance(); - - $paymentId = $order->get_transaction_id(); - - $data = array( - 'amount' => (int) round($amount * 100), - 'notes' => array( - 'reason' => $reason, - 'order_id' => $orderId, - 'refund_from_website' => true, - 'source' => 'woocommerce', - ) - ); - - try - { - $refund = $client->payment - ->fetch( $paymentId ) - ->refund( $data ); - - $order->add_order_note( __( 'Refund Id: ' . $refund->id, 'woocommerce' ) ); - /** - * @var $refund ->id -- Provides the RazorPay Refund ID - * @var $orderId -> Refunded Order ID - * @var $refund -> WooCommerce Refund Instance. - */ - do_action( 'woo_razorpay_refund_success', $refund->id, $orderId, $refund ); - - return true; - } - catch(Exception $e) - { - return new WP_Error('error', __($e->getMessage(), 'woocommerce')); - } - } - - // process refund for gift card - function processGiftCardRefund($orderId, $razorpayPaymentId, $amount = null, $reason = '') - { - $order = wc_get_order($orderId); - - if (! $order or ! $razorpayPaymentId) - { - return new WP_Error('error', __('Refund failed: No transaction ID', 'woocommerce')); - } - - $client = $this->getRazorpayApiInstance(); - - $data = array( - 'amount' => (int) round($amount), - 'notes' => array( - 'reason' => $reason, - 'order_id' => $orderId, - 'refund_from_website' => true, - 'source' => 'woocommerce', - ) - ); - - try - { - $refund = $client->payment->fetch( $razorpayPaymentId )->refund( $data ); - - wc_create_refund(array( - 'amount' => $amount, - 'reason' => $reason, - 'order_id' => $orderId, - 'refund_id' => $refund->id, - 'line_items' => array(), - 'refund_payment' => false, - )); - - $order->add_order_note( __( 'Refund Id: ' . $refund->id, 'woocommerce' ) ); - /** - * @var $refund ->id -- Provides the RazorPay Refund ID - * @var $orderId -> Refunded Order ID - * @var $refund -> WooCommerce Refund Instance. - */ - //do_action( 'woo_razorpay_refund_success', $refund->id, $orderId, $refund ); - $this->add_notice("Payment refunded", "error"); - - } - catch(Exception $e) - { - rzpLogInfo('failure message for refund:' . $e->getMessage()); - } - - wp_redirect(wc_get_cart_url()); - exit; - } - - /** - * Process the payment and return the result - **/ - function process_payment($order_id) - { - rzpLogInfo("Called process_payment with params order_id $order_id"); - - global $woocommerce; - - $order = wc_get_order($order_id); - - set_transient(self::SESSION_KEY, $order_id, 3600); - rzpLogInfo("Set transient with key " . self::SESSION_KEY . " params order_id $order_id"); - - $orderKey = $this->getOrderKey($order); - - if (version_compare(WOOCOMMERCE_VERSION, '2.1', '>=')) - { - return array( - 'result' => 'success', - 'redirect' => add_query_arg('key', $orderKey, $order->get_checkout_payment_url(true)) - ); - } - else if (version_compare(WOOCOMMERCE_VERSION, '2.0.0', '>=')) - { - return array( - 'result' => 'success', - 'redirect' => add_query_arg('order', $order->get_id(), - add_query_arg('key', $orderKey, $order->get_checkout_payment_url(true))) - ); - } - else - { - return array( - 'result' => 'success', - 'redirect' => add_query_arg('order', $order->get_id(), - add_query_arg('key', $orderKey, get_permalink(get_option('woocommerce_pay_page_id')))) - ); - } - } - - public function getRazorpayApiInstance($key = '', $secret = '') - { - if ($key === '') - { - $key = $this->getSetting('key_id'); - } - - if ($secret === '') - { - $secret = $this->getSetting('key_secret'); - } - - return new Api($key, $secret); - } - - public function getRazorpayApiPublicInstance() - { - return new Api($this->getSetting('key_id'), ""); - } - - /** - * Check for valid razorpay server callback - * Called once payment is completed using redirect method - */ - function check_razorpay_response() - { - global $woocommerce; - global $wpdb; - - $order = false; - - $post_type = 'shop_order'; - - $post_password = sanitize_text_field($_GET['order_key']); - - rzpLogInfo("Called check_razorpay_response: $post_password"); - - $meta_key = '_order_key'; - - $orderOperationalDataTable = $wpdb->prefix . 'wc_order_operational_data'; - $orderTable = $wpdb->prefix . 'wc_orders'; - - if ($this->isHposEnabled) - { - $orderOperationalData = $wpdb->get_row($wpdb->prepare("SELECT order_id FROM $orderOperationalDataTable AS P WHERE order_key = %s", $post_password)); - - $orderData = $wpdb->get_row($wpdb->prepare("SELECT status FROM $orderTable AS P WHERE id = %s", $orderOperationalData->order_id)); - } else - { - $orderOperationalData = $wpdb->get_row($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta AS P WHERE meta_key = %s AND meta_value = %s", $meta_key, $post_password)); - - $orderData = $wpdb->get_row($wpdb->prepare("SELECT post_status FROM $wpdb->posts AS P WHERE post_type=%s and ID=%s", $post_type, $orderOperationalData->post_id)); - } - - $arrayPost = json_decode(json_encode($orderOperationalData), true); - - if (!empty($arrayPost) and - $arrayPost != null) - { - if ($this->isHposEnabled) - { - $orderId = $orderOperationalData->order_id; - - $order = wc_get_order($orderId); - - if ($orderData->status === 'wc-checkout-draft') - { - $order->set_status('wc-pending'); - $order->save(); - } - $orderStatus = $order->get_status(); - rzpLogInfo("HPOS is enabled and order status: $orderStatus"); - } - else - { - $orderId = $orderOperationalData->post_id; - - $order = wc_get_order($orderId); - - if ($orderData->post_status === 'draft') - { - updateOrderStatus($orderId, 'wc-pending'); - } - $orderStatus = $order->get_status(); - rzpLogInfo("HPOS is disabled and order status: $orderStatus"); - } - - rzpLogInfo("Get order id in check_razorpay_response: orderId $orderId"); - } - - // TODO: Handle redirect - if ($order === false) - { - // TODO: Add test mode condition - if (is1ccEnabled()) - { - rzpLogInfo("Order details not found for the orderId: $orderId"); - - wp_redirect(wc_get_cart_url()); - exit; - } - wp_redirect(wc_get_checkout_url()); - exit; - } - - // If the order has already been paid for - // redirect user to success page - if (($order->needs_payment() === false) and - ($orderStatus != 'draft') and - ($orderStatus != 'wc-checkout-draft')) - { - rzpLogInfo("Order payment is already done for the orderId: " . $orderId . " order status " . $orderStatus); - - $cartHash = get_transient(RZP_1CC_CART_HASH.$orderId); - - if ($cartHash != false) - { - // Need to delete the cart hash stored in transient. - // Becuase the cart hash will be depending on the cart items so this will cause the issue when order api triggers. - $woocommerce->session->__unset(RZP_1CC_CART_HASH.$cartHash); - } - - $this->redirectUser($order); - } - - $razorpayPaymentId = null; - - if ($orderId and !empty($_POST[self::RAZORPAY_PAYMENT_ID])) - { - $error = ""; - $success = false; - - try - { - $this->verifySignature($orderId); - $success = true; - $razorpayPaymentId = sanitize_text_field($_POST[self::RAZORPAY_PAYMENT_ID]); - - $cartHash = get_transient(RZP_1CC_CART_HASH.$orderId); - - if ($cartHash != false) - { - // Need to delete the cart hash stored in transient. - // Becuase the cart hash will be depending on the cart items so this will cause the issue when order api triggers. - $woocommerce->session->__unset(RZP_1CC_CART_HASH.$cartHash); - } - } - catch (Errors\SignatureVerificationError $e) - { - $error = 'WOOCOMMERCE_ERROR: Payment to Razorpay Failed. ' . $e->getMessage(); - } - } - else - { - if(isset($_POST[self::RAZORPAY_WC_FORM_SUBMIT]) && $_POST[self::RAZORPAY_WC_FORM_SUBMIT] ==1) - { - $success = false; - $error = 'Customer cancelled the payment'; - } - else - { - $success = false; - $error = "Payment Failed."; - } - - if ($this->isHposEnabled) { - $is1ccOrder = $order->get_meta('is_magic_checkout_order'); - }else{ - $is1ccOrder = get_post_meta( $orderId, 'is_magic_checkout_order', true ); - } - - if (is1ccEnabled() && !empty($is1ccOrder) && $is1ccOrder == 'yes') - { - $api = $this->getRazorpayApiInstance(); - $sessionKey = $this->getOrderSessionKey($orderId); - - //Check the transient data for razorpay order id, if it's not available then look into session data. - if(get_transient($sessionKey)) - { - $razorpayOrderId = get_transient($sessionKey); - } - else - { - $razorpayOrderId = $woocommerce->session->get($sessionKey); - } - - $razorpayData = $api->order->fetch($razorpayOrderId); - - $this->UpdateOrderAddress($razorpayData, $order); - } - - $this->handleErrorCase($order); - $this->updateOrder($order, $success, $error, $razorpayPaymentId, null); - - if (is1ccEnabled()) - { - wp_redirect(wc_get_cart_url()); - exit; - } - - wp_redirect(wc_get_checkout_url()); - exit; - } - - $this->updateOrder($order, $success, $error, $razorpayPaymentId, null); - - $this->redirectUser($order); - } - - protected function redirectUser($order) - { - $redirectUrl = $this->get_return_url($order); - - wp_redirect($redirectUrl); - exit; - } - - protected function verifySignature($orderId) - { - rzpLogInfo("verifySignature orderId: $orderId"); - - global $woocommerce; - - $api = $this->getRazorpayApiInstance(); - - $attributes = array( - self::RAZORPAY_PAYMENT_ID => $_POST[self::RAZORPAY_PAYMENT_ID], - self::RAZORPAY_SIGNATURE => $_POST[self::RAZORPAY_SIGNATURE], - ); - - $sessionKey = $this->getOrderSessionKey($orderId); - //Check the transient data for razorpay order id, if it's not available then look into session data. - if(get_transient($sessionKey)) - { - $razorpayOrderId = get_transient($sessionKey); - } - else - { - $razorpayOrderId = $woocommerce->session->get($sessionKey); - } - - $attributes[self::RAZORPAY_ORDER_ID] = $razorpayOrderId?? ''; - rzpLogInfo("verifySignature attr"); - rzpLogInfo(json_encode($attributes)); - $api->utility->verifyPaymentSignature($attributes); - } - - public function rzpThankYouMessage( $thank_you_title, $order ) - { - return self::DEFAULT_SUCCESS_MESSAGE; - } - - protected function getErrorMessage($orderId) - { - // We don't have a proper order id - rzpLogInfo("getErrorMessage orderId: $orderId"); - - if ($orderId !== null) - { - $message = 'An error occured while processing this payment'; - } - if (isset($_POST['error']) === true && is_array($_POST['error'])) - { - $error = $_POST['error']; - - $description = htmlentities($error['description']); - $code = htmlentities($error['code']); - - $message = 'An error occured. Description : ' . $description . '. Code : ' . $code; - - if (isset($error['field']) === true) - { - $fieldError = htmlentities($error['field']); - $message .= 'Field : ' . $fieldError; - } - } - else - { - $message = 'An error occured. Please contact administrator for assistance'; - } - rzpLogInfo("returning $message"); - return $message; - } - - /** - * Modifies existing order and handles success case - * - * @param $success, & $order - */ - public function updateOrder(& $order, $success, $errorMessage, $razorpayPaymentId, $virtualAccountId = null, $webhook = false) - { - global $woocommerce; - - $orderId = $order->get_order_number(); - - rzpLogInfo("updateOrder orderId: $orderId , razorpayPaymentId: $razorpayPaymentId , success: $success"); - - if ($success === true) - { - try - { - $wcOrderId = $order->get_id(); - - if ($this->isHposEnabled) { - $is1ccOrder = $order->get_meta('is_magic_checkout_order'); - }else{ - $is1ccOrder = get_post_meta( $orderId, 'is_magic_checkout_order', true ); - } - - rzpLogInfo("Order details check initiated step 1 for the orderId: $wcOrderId"); - - if (is1ccEnabled() && !empty($is1ccOrder) && $is1ccOrder == 'yes') - { - rzpLogInfo("Order details update initiated step 1 for the orderId: $wcOrderId"); - - //To verify whether the 1cc update order function already under execution or not - if(get_transient('wc_order_under_process_'.$wcOrderId) === false) - { - rzpLogInfo("Order details update initiated step 2 for the orderId: $wcOrderId"); - - $this->update1ccOrderWC($order, $wcOrderId, $razorpayPaymentId); - } - - } - } catch (Exception $e) { - $message = $e->getMessage(); - rzpLogError("Failed to update 1cc flow with error : $message"); - } - - $payment_method=$order->get_payment_method(); - - // Need to set the status manually to processing incase of COD payment method. - if ($payment_method == "cod") - { - $order->update_status( 'processing' ); - } - else - { - $order->payment_complete($razorpayPaymentId); - } - - if(is1ccEnabled() && !empty($is1ccOrder) && $is1ccOrder == 'yes' && is_plugin_active('woo-save-abandoned-carts/cartbounty-abandoned-carts.php')){ - handleCBRecoveredOrder($orderId); - } - - // Check Wati.io retargetting plugin is active or not - if (is1ccEnabled() && !empty($is1ccOrder) && $is1ccOrder == 'yes' && is_plugin_active('wati-chat-and-notification/wati-chat-and-notification.php')){ - handleWatiRecoveredOrder($orderId); - } - - $order->add_order_note("Razorpay payment successful
Razorpay Id: $razorpayPaymentId"); - - if($this->getSetting('route_enable') == 'yes') - { - $razorpayRoute = new RZP_Route_Action(); - - $wcOrderId = $order->get_id(); - - $razorpayRoute->transferFromPayment($wcOrderId, $razorpayPaymentId); // creates transfers from payment - } - - if($virtualAccountId != null) - { - $order->add_order_note("Virtual Account Id: $virtualAccountId"); - } - - if (isset($woocommerce->cart) === true) - { - $woocommerce->cart->empty_cart(); - } - } - else - { - $this->msg['class'] = 'error'; - $this->msg['message'] = $errorMessage; - - if ($razorpayPaymentId) - { - $order->add_order_note("Payment Failed. Please check Razorpay Dashboard.
Razorpay Id: $razorpayPaymentId"); - } - - $order->add_order_note("Transaction Failed: $errorMessage
"); - $order->update_status('failed'); - } - - if ($webhook === false) - { - $this->add_notice($this->msg['message'], $this->msg['class']); - - rzpLogInfo("Woocommerce orderId: $orderId processed through callback"); - } - else - { - rzpLogInfo("Woocommerce orderId: $orderId processed through webhook"); - } - } - - public function update1ccOrderWC(& $order, $wcOrderId, $razorpayPaymentId) - { - global $woocommerce; - - $logObj = array(); - rzpLogInfo("update1ccOrderWC wcOrderId: $wcOrderId, razorpayPaymentId: $razorpayPaymentId"); - - //To avoid the symultanious update from callback and webhook - set_transient('wc_order_under_process_'.$wcOrderId, true, 300); - - $api = $this->getRazorpayApiInstance(); - $sessionKey = $this->getOrderSessionKey($wcOrderId); - - //Check the transient data for razorpay order id, if it's not available then look into session data. - if(get_transient($sessionKey)) - { - $razorpayOrderId = get_transient($sessionKey); - } - else - { - $razorpayOrderId = $woocommerce->session->get($sessionKey); - } - - $razorpayData = $api->order->fetch($razorpayOrderId); - - $this->UpdateOrderAddress($razorpayData, $order); - - $gstNo = $razorpayData['notes']['gstin']??''; - $orderInstructions = $razorpayData['notes']['order_instructions']??''; - - if($gstNo != ''){ - $order->add_order_note( "GSTIN No. : ". $gstNo ); - } - if($orderInstructions != ''){ - $order->add_order_note( "Order Instructions: ". $orderInstructions); - } - - // update gift card and coupons - $rzpPromotionAmount = $this->updateGiftAndCoupon($razorpayData, $order, $wcOrderId, $razorpayPaymentId); - - //Apply shipping charges to woo-order - if(isset($razorpayData['shipping_fee']) === true) - { - - //To remove by default shipping method added on order. - $existingItems = (array) $order->get_items('shipping'); - rzpLogInfo("Shipping details updated for orderId: $wcOrderId is".json_encode($existingItems)); - - if (sizeof($existingItems) != 0) { - // Loop through shipping items - foreach ($existingItems as $existingItemKey => $existingItemVal) { - $order->remove_item($existingItemKey); - } - } - - // Get a new instance of the WC_Order_Item_Shipping Object - $item = new WC_Order_Item_Shipping(); - - // if shipping charges zero - if($razorpayData['shipping_fee'] == 0) - { - $item->set_method_title( 'Free Shipping' ); - } - else - { - $isStoreShippingEnabled = ""; - if ($this->isHposEnabled) - { - $shippingData = $order->get_meta('1cc_shippinginfo'); - - }else{ - $shippingData = get_post_meta( $wcOrderId, '1cc_shippinginfo', true ); - } - - if (class_exists('WCFMmp')) - { - $shippingOptions = get_option( 'wcfm_shipping_options', array()); - // By default store shipping should be consider enable - $isStoreShippingEnabled = isset( $shippingOptions['enable_store_shipping'] ) ? $shippingOptions['enable_store_shipping'] : 'yes'; - } - - if ($isStoreShippingEnabled == 'yes') - { - foreach ($shippingData as $key => $value) - { - $item = new WC_Order_Item_Shipping(); - //$item->set_method_id($test[$key]['rate_id']); - $item->set_method_title($shippingData[$key]['name']); - $item->set_total($shippingData[$key]['price']/100 ); - $order->add_item($item); - $item->save(); - $itemId = $item->get_id(); - - $wcfmCommissionOptions = get_option( 'wcfm_commission_options', array() ); - - $vendorGetShipping = isset( $wcfmCommissionOptions['get_shipping'] ) ? $wcfmCommissionOptions['get_shipping'] : 'yes'; - - if (isset($shippingData[$key]['vendor_id']) && $vendorGetShipping == 'yes') - { - $itemData = array( - 'method_id' => $shippingData[$key]['method_id'], - 'instance_id' => $shippingData[$key]['instance_id'], - 'vendor_id' => $shippingData[$key]['vendor_id'], - 'Items' => $shippingData[$key]['meta_data'][0]['value'] - ); - updateVendorDetails($shippingData[$key]['price']/100, $shippingData[$key]['vendor_id'], $wcOrderId); - - foreach ($itemData as $itemkey => $itemval) - { - wc_update_order_item_meta( $itemId, $itemkey, $itemval); - } - } - - } - } - else - { - $item = new WC_Order_Item_Shipping(); - - // if shipping charges zero - if ($razorpayData['shipping_fee'] == 0) - { - $item->set_method_title( 'Free Shipping' ); - } - else - { - $item->set_method_title($shippingData??[0]['name']); - } - - // set an non existing Shipping method rate ID will mark the order as completed instead of processing status - // $item->set_method_id( "flat_rate:1" ); - $item->set_total( $razorpayData['shipping_fee']/100 ); - - $order->add_item( $item ); - - $item->save(); - } - // Calculate totals and save - $order->calculate_totals(); - - } - } - - // set default payment method - $payment_method = $this->id; - $payment_method_title = $this->title; - - // To verify the payment method for particular payment id. - $razorpayPaymentData = $api->payment->fetch($razorpayPaymentId); - - $paymentDoneBy = $razorpayPaymentData['method']; - - $codFee = 0; - if (($paymentDoneBy === 'cod') && isset($razorpayData['cod_fee']) == true) - { - $codFee = $razorpayData['cod_fee']/100; - $payment_method = 'cod'; - $payment_method_title = 'Cash on delivery'; - } - - //update payment method title - $order->set_payment_method($payment_method); - $order->set_payment_method_title($payment_method_title); - $order->save(); - - if (($paymentDoneBy === 'cod') && isset($razorpayData['cod_fee']) == true) - { - // Get a new instance of the WC_Order_Item_Fee Object - $itemFee = new WC_Order_Item_Fee(); - - $itemFee->set_name('COD Fee'); // Generic fee name - $itemFee->set_amount($codFee); // Fee amount - // $itemFee->set_tax_class(''); // default for '' - $itemFee->set_tax_status( 'none' ); // If we don't set tax status then it will consider by dafalut tax class. - $itemFee->set_total($codFee); // Fee amount - - // Calculating Fee taxes - // $itemFee->calculate_taxes( $calculateTaxFor ); - - // Add Fee item to the order - $order->add_item($itemFee); - $order->calculate_totals(); - $order->save(); - } - - if(!empty($razorpayData['offers'])) - { - $offerDiff = $razorpayData['line_items_total'] + $razorpayData['shipping_fee'] + $codFee*100 - $razorpayPaymentData['amount'] - $rzpPromotionAmount; - - if($offerDiff > 0){ - $offerDiscount = ($offerDiff/100); - $title = 'Razorpay_offers_'. $wcOrderId .'(₹'. $offerDiscount .')'; - - $this->createRzpOfferCoupon($title, $offerDiscount); - $this->applyCoupon($order, $title, $offerDiff); - - } - - } - - - //For abandon cart Lite recovery plugin recovery function - if(is_plugin_active( 'woocommerce-abandoned-cart/woocommerce-ac.php')) - { - $this->updateRecoverCartInfo($wcOrderId); - } - - $note = __('Order placed through Razorpay Magic Checkout'); - $order->add_order_note( $note ); - if ($paymentDoneBy === 'cod') - { - try - { - $body = ['order_id' => $razorpayOrderId]; - rzpLogInfo("making prepay API Call for order : $razorpayOrderId"); - $response = $api->request->request('POST', self::PREPAY_COD_URL , $body); - rzpLogInfo("makeAPICall: url: ". self::PREPAY_COD_URL . " is success"); - } - catch (\Razorpay\Api\Errors\Error $e) - { - $statusCode = $e->getHttpStatusCode(); - rzpLogError("make prepayAPICall failed: message:" . $e->getMessage() . ", url: " . self::PREPAY_COD_URL . ", statusCode : " . $statusCode . ", stacktrace : " . $e->getTraceAsString()); - } - } - } - - public function updateGiftAndCoupon($razorpayData, $order, $orderId, $razorpayPaymentId) - { - global $woocommerce; - global $wpdb; - - foreach($razorpayData['promotions'] as $promotion) - { - $rzpGiftAndCouponAmount += $promotion['value']; - - if($promotion['type'] == 'gift_card'){ - - $usedAmt = $promotion['value']/100; - $giftCode = $promotion['code']; - if(is_plugin_active('yith-woocommerce-gift-cards/init.php')){ - - $yithCard = new YITH_YWGC_Gift_Card( $args = array('gift_card_number'=> $giftCode)); - - //Get GC status - $post = get_post($yithCard->ID); - $status = $post->post_status; - - $giftCardBalance = $yithCard->get_balance(); - - if($giftCardBalance == null && $giftCardBalance >= 0 && $usedAmt > $giftCardBalance && 'trash' == $status && !$yithCard->exists()){ - // initiate refund in case gift card faliure - $this->processGiftCardRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); - }else{ - //Deduct amount of gift card - $yithCard->update_balance( $yithCard->get_balance() - $usedAmt ); - $yithCard->register_order($orderId); - - $code = "Gift Card ($giftCode)"; - - $wpdb->query( // phpcs:ignore - $wpdb->prepare( - 'INSERT INTO `' . $wpdb->prefix . 'woocommerce_order_items`( order_item_name, order_item_type, order_id ) VALUES ( %s, %s, %s)', - $code, - 'fee', - $orderId - ) - ); - - $itemId = $wpdb->insert_id; - wc_add_order_item_meta( $itemId, '_line_total', -$usedAmt ); - - $order->add_order_note( sprintf( esc_html__( 'Order paid with gift cards for a total amount of %s.', 'yith-woocommerce-gift-cards' ), wc_price( $usedAmt ) ) ); - - $orderTotal = $order->get_total() - $usedAmt; - $order->set_total($orderTotal); - $order->save(); - } - - } - else if(is_plugin_active('pw-woocommerce-gift-cards/pw-gift-cards.php')) - { - $result = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM `{$wpdb->pimwick_gift_card}` WHERE `number` = %s", $promotion['code'] ) ); - if($result != null){ - $balance = $wpdb->get_var( $wpdb->prepare( "SELECT SUM(amount) FROM {$wpdb->pimwick_gift_card_activity} WHERE pimwick_gift_card_id = %d", $result->pimwick_gift_card_id ) ); - - if($balance == null && $balance >= 0 && $usedAmt > $balance ){ - // initiate refund in case gift card faliure - $this->processGiftCardRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); - }else{ - //Deduct amount of gift card - $this->debitGiftCards($orderId, $order, "order_id: $orderId checkout_update_order_meta", $usedAmt, $giftCode); - } - - }else{ - $this->processGiftCardRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); - } - - }else{ - $this->processGiftCardRefund($orderId, $razorpayPaymentId, $razorpayData['amount_paid'], $reason = ''); - } - - }else{ - - $couponKey = $promotion['code']; - - if (empty($couponKey) === false) - { - $this->applyCoupon($order, $couponKey, $promotion['value']); - rzpLogInfo("Coupon details updated for orderId: $orderId"); - } - } - - } - return $rzpGiftAndCouponAmount; - } - - protected function debitGiftCards( $orderId, $order, $note, $usedAmt, $giftCardNo) { - - global $woocommerce; - global $wpdb; - - if ( ! is_a( $order, 'WC_Order' ) ) { - return; - } - - // insert GC in orderitems - $wpdb->query( // phpcs:ignore - $wpdb->prepare( - 'INSERT INTO `' . $wpdb->prefix . 'woocommerce_order_items`( order_item_name, order_item_type, order_id ) VALUES ( %s, %s, %s)', - $code, - 'pw_gift_card', - $orderId - ) - ); - - $itemId = $wpdb->insert_id; - wc_add_order_item_meta( $itemId, 'card_number', $giftCardNo ); - wc_add_order_item_meta( $itemId, 'amount', $usedAmt ); - - foreach( $order->get_items( 'pw_gift_card' ) as $order_item_id => $line ) { - $gift_card = new PW_Gift_Card( $giftCardNo ); - - if ( $gift_card->get_id() ) { - if ( !$line->meta_exists( '_pw_gift_card_debited' ) ) { - if ( $line->get_amount() != 0 ) { - $gift_card->debit( ( $line->get_amount() * -1 ), "$note, order_item_id: $order_item_id" ); - } - - $line->add_meta_data( '_pw_gift_card_debited', true ); - $line->save(); - } - } - } - } - - //To update customer address info to wc order. - public function updateOrderAddress($razorpayData, $order) - { - $this->newUserAccount($razorpayData, $order); - rzpLogInfo("updateOrderAddress function called"); - $receipt = $razorpayData['receipt']; - - if (isset($razorpayData['customer_details']['shipping_address'])) - { - $shippingAddressKey = $razorpayData['customer_details']['shipping_address']; - - $shippingAddress = []; - - $shippingAddress['first_name'] = $shippingAddressKey['name']; - $shippingAddress['address_1'] = $shippingAddressKey['line1']; - $shippingAddress['address_2'] = $shippingAddressKey['line2']; - $shippingAddress['city'] = $shippingAddressKey['city']; - $shippingAddress['country'] = strtoupper($shippingAddressKey['country']); - $shippingAddress['postcode'] = $shippingAddressKey['zipcode']; - $shippingAddress['email'] = $razorpayData['customer_details']['email']; - $shippingAddress['phone'] = $shippingAddressKey['contact']; - - $order->set_address( $shippingAddress, 'shipping' ); - - $shippingState = strtoupper($shippingAddressKey['state']); - $shippingStateName = str_replace(" ", '', $shippingState); - $shippingStateCode = getWcStateCodeFromName($shippingStateName); - $order->set_shipping_state($shippingStateCode); - - $this->updateUserAddressInfo('shipping_', $shippingAddress, $shippingStateCode, $order); - rzpLogInfo('shipping details for receipt id: '.$receipt .' is '. json_encode($shippingAddress)); - - if (empty($razorpayData['customer_details']['billing_address']) == false) - { - $billingAddress['first_name'] = $razorpayData['customer_details']['billing_address']['name']; - $billingAddress['address_1'] = $razorpayData['customer_details']['billing_address']['line1']; - $billingAddress['address_2'] = $razorpayData['customer_details']['billing_address']['line2']; - $billingAddress['city'] = $razorpayData['customer_details']['billing_address']['city']; - $billingAddress['country'] = strtoupper($razorpayData['customer_details']['billing_address']['country']); - $billingAddress['postcode'] = $razorpayData['customer_details']['billing_address']['zipcode']; - $billingAddress['email'] = $razorpayData['customer_details']['email']; - $billingAddress['phone'] = $razorpayData['customer_details']['billing_address']['contact']; - $order->set_address( $billingAddress, 'billing' ); - - $billingState = strtoupper($razorpayData['customer_details']['billing_address']['state']); - $billingStateName = str_replace(" ", '', $billingState); - $billingStateCode = getWcStateCodeFromName($billingStateName); - $order->set_billing_state($billingStateCode); - - $this->updateUserAddressInfo('billing_', $billingAddress, $billingStateCode, $order); - rzpLogInfo('billing details for receipt id: '.$receipt .' is '. json_encode($billingAddress)); - } - else - { - $order->set_address( $shippingAddress, 'billing' ); - $order->set_billing_state($shippingStateCode); - - $this->updateUserAddressInfo('billing_', $shippingAddress, $shippingStateCode, $order); - } - - rzpLogInfo("updateOrderAddress function executed"); - - $order->save(); - } - } - - //Create new user account - public function newUserAccount($razorpayData, $order) - { - global $woocommerce; - - if (!email_exists($razorpayData['customer_details']['email']) && isMandatoryAccCreationEnabled()) { - - $contact = $razorpayData['customer_details']['contact']; - - $email = $razorpayData['customer_details']['email']; - $random_password = wp_generate_password(8, false); - - //create user name with the help default woocommerce function - $username = wc_create_new_customer_username( $email ); - $userId = wp_create_user( $username, $random_password, $email ); - $user = get_user_by('id', $userId); - - $order->set_customer_id( $userId ); - $order->save(); - - // Get all WooCommerce emails Objects from WC_Emails Object instance - $emails = wc()->mailer()->emails; - - // Send WooCommerce "Customer New Account" email notification with the password - $emails['WC_Email_Customer_New_Account']->trigger( $userId, $random_password, true ); - - update_user_meta( $userId, 'shipping_email', $email); - update_user_meta( $userId, 'shipping_phone', $contact ); - - if (isset($razorpayData['customer_details']['shipping_address'])) - { - $shpping = $razorpayData['customer_details']['shipping_address']; - - //extract data - if (empty($razorpayData['customer_details']['billing_address']) == false) - { - $billing = $razorpayData['customer_details']['billing_address']; - } - else - { - $billing = $razorpayData['customer_details']['shipping_address']; - } - - $shippingState = strtoupper($shpping->state); - $shippingStateName = str_replace(" ", '', $shippingState); - $shippingStateCode = getWcStateCodeFromName($shippingStateName); - - $billingState = strtoupper($billing->state); - $billingStateName = str_replace(" ", '', $billingState); - $billingStateCode = getWcStateCodeFromName($billingStateName); - - // user's shipping data - update_user_meta( $userId, 'shipping_first_name', $shpping->name ); - update_user_meta( $userId, 'shipping_address_1', $shpping->line1); - update_user_meta( $userId, 'shipping_address_2', $shpping->line2); - update_user_meta( $userId, 'shipping_city', $shpping->city); - update_user_meta( $userId, 'shipping_country', strtoupper($shpping->country)); - update_user_meta( $userId, 'shipping_postcode', $shpping->zipcode); - update_user_meta( $userId, 'shipping_state', $shippingStateCode); - - // user's billing data - update_user_meta( $userId, 'billing_first_name', $shpping->name); - update_user_meta( $userId, 'billing_phone', $contact); - update_user_meta( $userId, 'billing_address_1', $billing->line1); - update_user_meta( $userId, 'billing_address_2', $billing->line2); - update_user_meta( $userId, 'billing_city', $billing->city); - update_user_meta( $userId, 'billing_country', strtoupper($billing->country)); - update_user_meta( $userId, 'billing_postcode', $billing->zipcode); - update_user_meta( $userId, 'billing_state', $billingStateCode); - } - } - } - - /** - * Retrieve a Shipping Zone by it's ID. - * - * @param int $zone_id Shipping Zone ID. - * @return WC_Shipping_Zone|WP_Error - */ - // TODO: can't we directly return the statement? - protected function getShippingZone($zoneId) - { - $zone = WC_Shipping_Zones::get_zone_by('zone_id', $zoneId); - - return $zone; - } - - // Update user billing and shipping information - protected function updateUserAddressInfo($addressKeyPrefix, $addressValue, $stateValue, $order) - { - foreach ($addressValue as $key => $value) - { - $metaKey = $addressKeyPrefix; - $metaKey .= $key; - - update_user_meta($order->get_user_id(), $metaKey, $value); - } - - update_user_meta($order->get_user_id(), $addressKeyPrefix . 'state', $stateValue); - } - - // Update Abandonment cart plugin table for recovered cart. - protected function updateRecoverCartInfo($wcOrderId) - { - global $woocommerce; - global $wpdb; - - $order = wc_get_order($wcOrderId); - $userId = $order->get_customer_id(); - $currentTime = current_time('timestamp'); // phpcs:ignore - $cutOffTime = get_option('ac_lite_cart_abandoned_time'); - - if (isset($cut_off_time)) - { - $cartCutOffTime = intval($cutOffTime) * 60; - } - else - { - $cartCutOffTime = 60 * 60; - } - - $compareTime = $currentTime - $cutOffTime; - if($userId > 0) - { - $userType = 'REGISTERED'; - } - else - { - $userType = 'GUEST'; - if ($this->isHposEnabled) { - $userId = $order->get_meta('abandoned_user_id'); - }else{ - $userId = get_post_meta($wcOrderId, 'abandoned_user_id', true); - } - - } - - $results = $wpdb->get_results( // phpcs:ignore - $wpdb->prepare( - 'SELECT * FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE user_id = %s AND cart_ignored = %s AND recovered_cart = %s AND user_type = %s', - $userId, - 0, - 0, - $userType - ) - ); - - if(count($results) > 0) - { - if(isset($results[0]->abandoned_cart_time) && $compareTime > $results[0]->abandoned_cart_time) - { - wcal_common::wcal_set_cart_session('abandoned_cart_id_lite', $results[0]->id); - } - } - - $abandonedOrderId = wcal_common::wcal_get_cart_session('abandoned_cart_id_lite'); - - if ($this->isHposEnabled) { - $order->update_meta_data( 'abandoned_id', $abandonedOrderId); - $order->save(); - }else{ - add_post_meta($wcOrderId, 'abandoned_id', $abandonedOrderId); - } - $wpdb->query( // phpcS:ignore - $wpdb->prepare( - 'UPDATE `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET recovered_cart = %s, cart_ignored = %s WHERE id = %s', - $wcOrderId, - '1', - $abandonedOrderId - ) - ); - } - - protected function handleErrorCase($order) - { - $orderId = $order->get_order_number(); - rzpLogInfo('handleErrorCase'); - $this->msg['class'] = 'error'; - $this->msg['message'] = $this->getErrorMessage($orderId); - } - - /** - * Add a woocommerce notification message - * - * @param string $message Notification message - * @param string $type Notification type, default = notice - */ - protected function add_notice($message, $type = 'notice') - { - global $woocommerce; - $type = in_array($type, array('notice','error','success'), true) ? $type : 'notice'; - // Check for existence of new notification api. Else use previous add_error - if (function_exists('wc_add_notice')) - { - wc_add_notice($message, $type); - } - else - { - // Retrocompatibility WooCommerce < 2.1 - switch ($type) - { - case "error" : - $woocommerce->add_error($message); - break; - default : - $woocommerce->add_message($message); - break; - } - } - } - - /** - * Fetching version info for woo-razorpay and woo-razorpay-subscription - * Which will be sent through checkout as meta info - * @param $data - * @return array - */ - public function getVersionMetaInfo($data = array()) - { - if (isset($data['subscription_id']) && isset($data['recurring'])) { - $pluginRoot = WP_PLUGIN_DIR . '/razorpay-subscriptions-for-woocommerce'; - return array( - 'integration' => 'woocommerce-subscription', - 'integration_version' => get_plugin_data($pluginRoot . '/razorpay-subscriptions.php')['Version'], - 'integration_woo_razorpay_version' => get_plugin_data(plugin_dir_path(__FILE__) . 'woo-razorpay.php')['Version'], - 'integration_parent_version' => WOOCOMMERCE_VERSION, - 'integration_type' => 'plugin', - ); - } else { - return array( - 'integration' => 'woocommerce', - 'integration_version' => get_plugin_data(plugin_dir_path(__FILE__) . 'woo-razorpay.php')['Version'], - 'integration_parent_version' => WOOCOMMERCE_VERSION, - 'integration_type' => 'plugin', - ); - } - } - - public function applyCoupon($order, $couponKey, $couponValue) { - // Remove the same coupon, if already being added to order. - $order->remove_coupon($couponKey); - - //TODO: Convert all razorpay amount in paise to rupees - $discount_total = $couponValue/100; - - //TODO: Verify source code implementation - // Loop through products and apply the coupon discount - foreach($order->get_items() as $order_item) - { - $total = $order_item->get_total(); - $order_item->set_total($total - $discount_total); - $order_item->save(); - } - // TODO: Test if individual use coupon fails by hardcoding here - $isApplied = $order->apply_coupon($couponKey); - $order->save(); - } - - //TODO: create a common function to create a coupon functionality - public function createRzpOfferCoupon($couponCode, $amount) : bool { - - $coupon = array( - 'post_title' => $couponCode, - 'post_content' => '', - 'post_status' => 'publish', - 'post_author' => 1, - 'post_type' => 'shop_coupon'); - - $newCouponId = wp_insert_post( $coupon ); - - if( $newCouponId === 0) { - return false; - } - - $input = [ - 'discount_type' => 'fixed_cart', - 'coupon_amount' => $amount, - 'usage_limit' => 1, - 'minimum_amount' => $amount, - ]; - - foreach ($input as $key => $value) { - $isSuccess = update_post_meta($newCouponId, $key, $value); - if($isSuccess === false) { - rzpLogError("rzp offer create coupon : update post meta error, key : " . $key . ", value : " . $value); - return false; - } - } - return true; - } - - } - - //update vendor data into wp_wcfm_marketplace_orders - function updateVendorDetails($shippingFee, $vendorId, $orderId) - { - global $woocommerce; - global $wpdb; - $commission = $wpdb->get_results( - $wpdb->prepare( - 'SELECT * FROM `' . $wpdb->prefix . 'wcfm_marketplace_orders` WHERE vendor_id = %d AND order_id = %d', - $vendorId, - $orderId - ) - ); - - if (count($commission) > 0) - { - $totalComm = $commission[0]->total_commission+$shippingFee; - $wpdb->query( - $wpdb->prepare( - 'UPDATE `' . $wpdb->prefix . 'wcfm_marketplace_orders` SET shipping = %d, total_commission = %d WHERE vendor_id = %d AND order_id = %d', - $shippingFee, - $totalComm, - $vendorId, - $orderId - ) - ); - } - } - - /** - * Add the Gateway to WooCommerce - **/ - function woocommerce_add_razorpay_gateway($methods) - { - $methods[] = 'WC_Razorpay'; - return $methods; - } - - add_filter('woocommerce_payment_gateways', 'woocommerce_add_razorpay_gateway'); - - /** - * Creating the settings link from the plugins page - **/ - function razorpay_woo_plugin_links($links) - { - $pluginLinks = array( - 'settings' => 'Settings', - 'docs' => 'Docs', - 'support' => 'Support' - ); - - $links = array_merge($links, $pluginLinks); - - return $links; - } - - add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'razorpay_woo_plugin_links'); - - add_action( 'woocommerce_before_single_product', 'trigger_affordability_widget', 10 ); - - function trigger_affordability_widget() - { - if (empty(get_option('rzp_afd_enable')) === false and - get_option('rzp_afd_enable') === 'yes') - { - if (empty(get_option('rzp_afd_feature_checked')) === true or - get_option('rzp_afd_feature_checked') === 'no') - { - try - { - $api = new Api(get_option('woocommerce_razorpay_settings')['key_id'], get_option('woocommerce_razorpay_settings')['key_secret']); - $merchantPreferences = $api->request->request('GET', 'accounts/me/features'); - if (isset($merchantPreferences) === false or - isset($merchantPreferences['assigned_features']) === false) - { - throw new Exception("Error in Api call."); - } - - update_option('rzp_afd_enable', 'no'); - foreach ($merchantPreferences['assigned_features'] as $preference) - { - if ($preference['name'] === 'affordability_widget' or - $preference['name'] === 'affordability_widget_set') - { - update_option('rzp_afd_enable', 'yes'); - break; - } - } - - update_option('rzp_afd_feature_checked', 'yes'); - } - catch(\Exception $e) - { - rzpLogError($e->getMessage()); - return; - } - } - - if (empty(get_option('rzp_afd_enable')) === false and - get_option('rzp_afd_enable') === 'yes') - { - add_action ('woocommerce_before_add_to_cart_form', 'addAffordabilityWidgetHTML'); - } - } - } -} - -// This is set to a priority of 10 -function razorpay_webhook_init() -{ - $rzpWebhook = new RZP_Webhook(); - - $rzpWebhook->process(); -} - -define('RZP_PATH', plugin_dir_path( __FILE__ )); -define('RZP_CHECKOUTJS_URL', 'https://checkout.razorpay.com/v1/magic-checkout.js'); -define('BTN_CHECKOUTJS_URL', 'https://cdn.razorpay.com/static/wooc/magic-rzp.js'); -define('RZP_1CC_CSS_SCRIPT', 'RZP_1CC_CSS_SCRIPT'); - - -function enqueueScriptsFor1cc() -{ - $siteurl = get_option('siteurl'); - $pluginData = get_plugin_data( __FILE__ ); - - $domain = parse_url($siteurl, PHP_URL_HOST); - $domain_ip = gethostbyname($domain); - - //Consider https if site url is not localhost server. - if (filter_var($domain_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) - { - $siteurl = str_replace('http://', 'https://', $siteurl); - } - - wp_register_script( '1cc_razorpay_config', '' ); - wp_enqueue_script( '1cc_razorpay_config' ); - wp_add_inline_script( '1cc_razorpay_config', '!function(){var o=document.querySelector("meta[name=rzp_merchant_key]");o&&(window.Razorpay||(window.Razorpay={}),"object"==typeof window.Razorpay&&(window.Razorpay.config||(window.Razorpay.config={}),window.Razorpay.config.merchant_key=o.getAttribute("value")))}();'); - - wp_register_script('1cc_razorpay_checkout', RZP_CHECKOUTJS_URL, null, null); - wp_enqueue_script('1cc_razorpay_checkout'); - wp_register_style(RZP_1CC_CSS_SCRIPT, plugin_dir_url(__FILE__) . 'public/css/1cc-product-checkout.css', null, null); - wp_enqueue_style(RZP_1CC_CSS_SCRIPT); - - wp_register_script('btn_1cc_checkout', BTN_CHECKOUTJS_URL, null, null); - wp_localize_script('btn_1cc_checkout', 'rzp1ccCheckoutData', array( - 'nonce' => wp_create_nonce("wp_rest"), - 'siteurl' => $siteurl, - 'blogname' => get_bloginfo('name'), - 'cookies' => $_COOKIE, - 'requestData' => $_REQUEST, - 'version' => $pluginData['Version'], - ) ); - wp_enqueue_script('btn_1cc_checkout'); -} - -//To add 1CC button on cart page. -add_action( 'woocommerce_proceed_to_checkout', 'addCheckoutButton'); - -if(isRazorpayPluginEnabled() && is1ccEnabled()) { - add_action('wp_head', 'injectMerchantKeyMeta', 1); - add_action('wp_head', 'addRzpSpinner'); -} - -function addCheckoutButton() -{ - add_action('wp_enqueue_scripts', 'enqueueScriptsFor1cc', 0); - - if (isRazorpayPluginEnabled() && is1ccEnabled() ) - { - if (isTestModeEnabled()) { - $current_user = wp_get_current_user(); - if ($current_user->has_cap( 'administrator' ) || preg_match( '/@razorpay.com$/i', $current_user->user_email )) { - $tempTest = RZP_PATH . 'templates/rzp-cart-checkout-btn.php'; - load_template( $tempTest, false, array() ); - } - } else { - $tempTest = RZP_PATH . 'templates/rzp-cart-checkout-btn.php'; - load_template( $tempTest, false, array() ); - } - } - else - { - return; - } -} - -//To add 1CC Mini cart checkout button -if(isRazorpayPluginEnabled() && is1ccEnabled() && isMiniCartCheckoutEnabled()) -{ - - add_action( 'woocommerce_widget_shopping_cart_buttons', function() - { - // Removing Buttons - remove_action( 'woocommerce_widget_shopping_cart_buttons', 'woocommerce_widget_shopping_cart_proceed_to_checkout', 20 ); - - add_action('woocommerce_cart_updated', 'enqueueScriptsFor1cc', 10); - - add_action( 'woocommerce_widget_shopping_cart_buttons', 'addMiniCheckoutButton', 20 ); - - }, 1 ); -} - -function addMiniCheckoutButton() -{ - add_action('wp_enqueue_scripts', 'enqueueScriptsFor1cc', 0); - - if (isTestModeEnabled()) { - $current_user = wp_get_current_user(); - if ($current_user->has_cap( 'administrator' ) || preg_match( '/@razorpay.com$/i', $current_user->user_email )) { - $tempTest = RZP_PATH . 'templates/rzp-mini-checkout-btn.php'; - load_template( $tempTest, false, array() ); - } - } else { - $tempTest = RZP_PATH . 'templates/rzp-mini-checkout-btn.php'; - load_template( $tempTest, false, array() ); - } - -} - -//To add 1CC button on product page. -if(isRazorpayPluginEnabled() && is1ccEnabled() && isPdpCheckoutEnabled()) -{ - add_action( 'woocommerce_after_add_to_cart_button', 'addPdpCheckoutButton'); -} - -function injectMerchantKeyMeta(){ - echo ""; -} - -function addRzpSpinner() -{ - if (isTestModeEnabled()) { - $current_user = wp_get_current_user(); - if ($current_user->has_cap( 'administrator' ) || preg_match( '/@razorpay.com$/i', $current_user->user_email )) { - $tempTest = RZP_PATH . 'templates/rzp-spinner.php'; - load_template( $tempTest, false, array() ); - } - } else { - $tempTest = RZP_PATH . 'templates/rzp-spinner.php'; - load_template( $tempTest, false, array() ); - } -} - -function addPdpCheckoutButton() -{ - add_action('wp_enqueue_scripts', 'enqueueScriptsFor1cc', 0); - - if (isTestModeEnabled()) { - $current_user = wp_get_current_user(); - if ($current_user->has_cap( 'administrator' ) || preg_match( '/@razorpay.com$/i', $current_user->user_email )) { - $tempTest = RZP_PATH . 'templates/rzp-pdp-checkout-btn.php'; - load_template( $tempTest, false, array() ); - } - } else { - $tempTest = RZP_PATH . 'templates/rzp-pdp-checkout-btn.php'; - load_template( $tempTest, false, array() ); - } -} - -// for admin panel custom alerts -function addAdminSettingsAlertScript() -{ - if (isRazorpayPluginEnabled()) { - wp_enqueue_script('rzpAdminSettingsScript', plugin_dir_url(__FILE__) .'public/js/admin-rzp-settings.js'); - } -} - -add_action('admin_enqueue_scripts', 'addAdminSettingsAlertScript'); - -function disable_coupon_field_on_cart($enabled) -{ - if (isTestModeEnabled()) { - $current_user = wp_get_current_user(); - if ($current_user->has_cap( 'administrator' ) || preg_match( '/@razorpay.com$/i', $current_user->user_email )) { - if (is_cart()) { - $enabled = false; - } - } - } else { - if (is_cart()) { - $enabled = false; - } - } - return $enabled; -} - -if(is1ccEnabled()) -{ - add_filter('woocommerce_coupons_enabled', 'disable_coupon_field_on_cart'); - add_action('woocommerce_cart_updated', 'enqueueScriptsFor1cc', 10); - add_filter('woocommerce_order_needs_shipping_address', '__return_true'); -} - -//Changes Recovery link URL to Magic cart URL to avoid redirection to checkout page -function cartbounty_alter_automation_button( $button ){ - return str_replace("cartbounty=","cartbounty=magic_",$button); -} - -if(is_plugin_active('woo-save-abandoned-carts/cartbounty-abandoned-carts.php')){ - add_filter( 'cartbounty_automation_button_html', 'cartbounty_alter_automation_button' ); -} From 7eebd149ffcb5360a8fc565043eca8f91bd614f3 Mon Sep 17 00:00:00 2001 From: Anantha-Perumal Date: Fri, 2 Feb 2024 18:17:44 +0530 Subject: [PATCH 15/91] handled plugin uninstalled case --- woo-razorpay.php | 1 + 1 file changed, 1 insertion(+) diff --git a/woo-razorpay.php b/woo-razorpay.php index 4c9f06a9..ac98c763 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -2298,6 +2298,7 @@ public function handlePromotions($razorpayData, $order, $orderId, $razorpayPayme $razorpayPaymentId, $razorpayData['amount_paid'], 'Terra Wallet Insufficient Balance'); + continue; } $this->addTerraWalletAmountAsPartialPaymentFee($viaWalletAmount, $order); woo_wallet()->wallet->wallet_partial_payment($orderId); From 97bcc51c8b7e92d459be277fcdb5451911b572ed Mon Sep 17 00:00:00 2001 From: Anantha-Perumal Date: Sun, 4 Feb 2024 15:54:46 +0530 Subject: [PATCH 16/91] refactor: code changes --- woo-razorpay.php | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index ac98c763..9f3a0746 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -2289,35 +2289,36 @@ public function handlePromotions($razorpayData, $order, $orderId, $razorpayPayme } }else if($promotion['type'] == 'terra_wallet') { - if (is_plugin_active('woo-wallet/woo-wallet.php')) { - $viaWalletAmount = $promotion['value'] / 100; - $walletBalance = woo_wallet()->wallet->get_wallet_balance($order->get_user_id(), 'edit'); - if ($walletBalance < $viaWalletAmount) { + if (!is_plugin_active('woo-wallet/woo-wallet.php')) { + $this->processRefundForOrdersWithGiftCard( + $orderId, + $razorpayPaymentId, + $razorpayData['amount_paid'], + 'Terra Wallet Plugin is not active'); + continue; + } + $viaWalletAmount = $promotion['value'] / 100; + $walletBalance = woo_wallet()->wallet->get_wallet_balance($order->get_user_id(), 'edit'); + if ($walletBalance < $viaWalletAmount) + { $this->processRefundForOrdersWithGiftCard( $orderId, $razorpayPaymentId, $razorpayData['amount_paid'], 'Terra Wallet Insufficient Balance'); continue; - } - $this->addTerraWalletAmountAsPartialPaymentFee($viaWalletAmount, $order); - woo_wallet()->wallet->wallet_partial_payment($orderId); - $terraWalletTransactionID = get_post_meta($orderId, '_partial_pay_through_wallet_compleate', true); - if (!$terraWalletTransactionID) { - $this->processRefundForOrdersWithGiftCard( - $orderId, - $razorpayPaymentId, - $razorpayData['amount_paid'], - 'Terra Wallet Transaction Failed'); - } else { - rzpLogInfo("TerraWallet TransactionID for order id $orderId is $terraWalletTransactionID"); - } - } else { + } + $this->addTerraWalletAmountAsPartialPaymentFee($viaWalletAmount, $order); + woo_wallet()->wallet->wallet_partial_payment($orderId); + $terraWalletTransactionID = get_post_meta($orderId, '_partial_pay_through_wallet_compleate', true); + if (!$terraWalletTransactionID) { $this->processRefundForOrdersWithGiftCard( $orderId, $razorpayPaymentId, $razorpayData['amount_paid'], - 'Terra Wallet Plugin is not active'); + 'Terra Wallet Transaction Failed'); + } else { + rzpLogInfo("TerraWallet TransactionID for order id $orderId is $terraWalletTransactionID"); } } else{ From ddfe1ecac0c0ae9cf4ce548168bf60d0e75d1ed9 Mon Sep 17 00:00:00 2001 From: yashgit891 <56789472+yashgit891@users.noreply.github.com> Date: Thu, 8 Feb 2024 10:26:28 +0530 Subject: [PATCH 17/91] Revert Instant refund (#533) --- woo-razorpay.php | 1 - 1 file changed, 1 deletion(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index 7f0a4c38..8ea7c981 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -1504,7 +1504,6 @@ public function process_refund($orderId, $amount = null, $reason = '') $data = array( 'amount' => (int) round($amount * 100), - 'speed' => "optimum", 'notes' => array( 'reason' => $reason, 'order_id' => $orderId, From cfb885036c2ee42886e63a37d8ab0a50ca2057cf Mon Sep 17 00:00:00 2001 From: Anantha-Perumal <96859382+Anantha-Perumal@users.noreply.github.com> Date: Mon, 12 Feb 2024 18:07:00 +0530 Subject: [PATCH 18/91] Version Bump 4.6.0 (#532) * Version Bump 4.6.0 --- readme.txt | 6 +++++- woo-razorpay.php | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/readme.txt b/readme.txt index fe7f0a1b..f98b61ff 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: razorpay Tags: razorpay, payments, india, woocommerce, curlec, malaysia, ecommerce, international, cross border Requires at least: 3.9.2 Tested up to: 6.3.1 -Stable tag: 4.5.9 +Stable tag: 4.6.0 Requires PHP: 7.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -69,6 +69,10 @@ Razorpay is available for Store Owners and Merchants in == Changelog == += 4.6.0 = +* Support for Tera Wallet. +* Added RTB widget. + = 4.5.9 = * Plugin name and description updated. diff --git a/woo-razorpay.php b/woo-razorpay.php index 8ea7c981..d447f1ff 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -3,8 +3,8 @@ * Plugin Name: 1 Razorpay: Signup for FREE PG * Plugin URI: https://razorpay.com * Description: Razorpay Payment Gateway Integration for WooCommerce.Razorpay Welcome Back Offer: New to Razorpay? Sign up to enjoy FREE payments* of INR 2 lakh till March 31st! Transact before January 10th to grab the offer. - * Version: 4.5.9 - * Stable tag: 4.5.9 + * Version: 4.6.0 + * Stable tag: 4.6.0 * Author: Team Razorpay * WC tested up to: 7.9.0 * Author URI: https://razorpay.com @@ -2950,7 +2950,7 @@ function trigger_rtb_widget() { $key_id = get_option('woocommerce_razorpay_settings')['key_id']; echo ' - +
From 5cb0bc181fb70e311f0d2f0b0973794eab5175d2 Mon Sep 17 00:00:00 2001 From: yashgit891 <56789472+yashgit891@users.noreply.github.com> Date: Wed, 21 Feb 2024 11:06:34 +0530 Subject: [PATCH 19/91] RTB fixes (#535) --- woo-razorpay.php | 74 ++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 49 deletions(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index d447f1ff..2b815fd4 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -396,15 +396,6 @@ public function init_form_fields() } } - $this->form_fields['rtb_widget_title'] = array( - 'title' => '' . __('Razorpay Trusted Business'). '', - 'type' => 'title' - ); - - $this->form_fields['enable_rtb_widget'] = array( - 'title' => '' . __('Sorry, your business is currently not eligible for RTB.') . '', - 'type' => 'title' - ); //Affordability Widget Code if (is_admin()) { @@ -447,27 +438,24 @@ public function init_form_fields() } } - foreach ($merchantPreferences['assigned_features'] as $preference) - { - if ($preference['name'] === 'rtb_widget_enabled') - { - $rtbActivationStatus = $api->request->request('GET', 'rtb?key_id=' . $key_id); - - if (isset($rtbActivationStatus['widget_enabled']) and - $rtbActivationStatus['widget_enabled'] === true) - { - $this->form_fields['enable_rtb_widget'] = array( - 'title' => __('RTB Widget Enable/Disable'), - 'type' => 'checkbox', - 'desc' => __('Enable RTB Widget?'), - 'default' => 'no', - 'id' => 'rzp_rtb_enable' - ); - update_option('rzp_rtb_enable', 'yes'); - } + $rtbActivationStatus = $api->request->request('GET', 'rtb?key_id=' . $key_id); - break; - } + if (isset($rtbActivationStatus['widget_enabled']) and + $rtbActivationStatus['widget_enabled'] === true) + { + $this->form_fields['rtb_widget_title'] = array( + 'title' => '' . __('Razorpay Trusted Business'). '', + 'type' => 'title' + ); + + $this->form_fields['enable_rtb_widget'] = array( + 'title' => __('RTB Widget Enable/Disable'), + 'type' => 'checkbox', + 'desc' => __('Enable RTB Widget?'), + 'default' => 'no', + 'id' => 'rzp_rtb_enable' + ); + update_option('rzp_rtb_enable', 'yes'); } update_option('rzp_afd_feature_checked', 'yes'); @@ -2910,28 +2898,15 @@ function trigger_rtb_widget() try { $api = new Api(get_option('woocommerce_razorpay_settings')['key_id'], get_option('woocommerce_razorpay_settings')['key_secret']); - $merchantPreferences = $api->request->request('GET', 'accounts/me/features'); - if (isset($merchantPreferences) === false or - isset($merchantPreferences['assigned_features']) === false) - { - throw new Exception("Error in Api call."); - } update_option('rzp_rtb_enable', 'no'); - foreach ($merchantPreferences['assigned_features'] as $preference) - { - if ($preference['name'] === 'rtb_widget_enabled') - { - $rtbActivationStatus = $api->request->request('GET', 'rtb?key_id=' . get_option('woocommerce_razorpay_settings')['key_id']); + + $rtbActivationStatus = $api->request->request('GET', 'rtb?key_id=' . get_option('woocommerce_razorpay_settings')['key_id']); - if (isset($rtbActivationStatus['widget_enabled']) and - $rtbActivationStatus['widget_enabled'] === true) - { - update_option('rzp_rtb_enable', 'yes'); - } - - break; - } + if (isset($rtbActivationStatus['widget_enabled']) and + $rtbActivationStatus['widget_enabled'] === true) + { + update_option('rzp_rtb_enable', 'yes'); } update_option('rzp_rtb_feature_checked', 'yes'); @@ -2944,6 +2919,7 @@ function trigger_rtb_widget() } if (empty(get_option('woocommerce_razorpay_settings')) === false and + isset(get_option('woocommerce_razorpay_settings')['enable_rtb_widget']) === true and get_option('woocommerce_razorpay_settings')['enable_rtb_widget'] === 'yes' and empty(get_option('rzp_rtb_enable')) === false and get_option('rzp_rtb_enable') === 'yes') @@ -2951,7 +2927,7 @@ function trigger_rtb_widget() $key_id = get_option('woocommerce_razorpay_settings')['key_id']; echo ' -
+
'; From 790f63151652e60b32c048dbc680f9b53dee3296 Mon Sep 17 00:00:00 2001 From: yashgit891 <56789472+yashgit891@users.noreply.github.com> Date: Thu, 22 Feb 2024 11:08:16 +0530 Subject: [PATCH 20/91] Support for checkout blocks (#534) * Added support for checkout blocks --- checkout-block.php | 45 +++++++++++++++++++++++++++++++++++++++++++++ checkout_block.js | 18 ++++++++++++++++++ woo-razorpay.php | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 checkout-block.php create mode 100644 checkout_block.js diff --git a/checkout-block.php b/checkout-block.php new file mode 100644 index 00000000..94d239df --- /dev/null +++ b/checkout-block.php @@ -0,0 +1,45 @@ +settings = get_option('woocommerce_razorpay_settings', []); + } + + public function get_payment_method_script_handles() + { + wp_register_script( + 'razorpay-blocks-integration', + plugin_dir_url(__FILE__) . 'checkout_block.js', + [ + 'wc-blocks-registry', + 'wc-settings', + 'wp-element', + 'wp-html-entities', + 'wp-i18n', + ], + null, + true + ); + + if (function_exists('wp_set_script_translations')) + { + wp_set_script_translations('razorpay-blocks-integration'); + } + + return ['razorpay-blocks-integration']; + } + + public function get_payment_method_data() + { + return [ + 'title' => 'Pay by Razorpay', + 'description' => $this->settings['description'], + ]; + } +} diff --git a/checkout_block.js b/checkout_block.js new file mode 100644 index 00000000..2054aec2 --- /dev/null +++ b/checkout_block.js @@ -0,0 +1,18 @@ +const settings = window.wc.wcSettings.getSetting('razorpay_data', {}); +const label = window.wp.htmlEntities.decodeEntities(settings.title) || window.wp.i18n.__('Razorpay for woocommerce', 'razorpay'); +const Content = () => { + return window.wp.htmlEntities.decodeEntities(settings.description || ''); +}; +const Block_Gateway = { + name: 'razorpay', + label: label, + content: Object(window.wp.element.createElement)(Content, null ), + edit: Object(window.wp.element.createElement)(Content, null ), + canMakePayment: () => true, + ariaLabel: label, + supports: { + features: settings.supports, + }, +}; +window.wc.wcBlocksRegistry.registerPaymentMethod( Block_Gateway ); + \ No newline at end of file diff --git a/woo-razorpay.php b/woo-razorpay.php index 2b815fd4..b6efc6d2 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -37,6 +37,7 @@ use Razorpay\Api\Api; use Razorpay\Api\Errors; use Automattic\WooCommerce\Utilities\OrderUtil; +use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry; add_action('plugins_loaded', 'woocommerce_razorpay_init', 0); add_action('admin_post_nopriv_rzp_wc_webhook', 'razorpay_webhook_init', 10); @@ -47,6 +48,38 @@ } }); +add_action('before_woocommerce_init', function() { + if (class_exists('\Automattic\WooCommerce\Utilities\FeaturesUtil')) + { + \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('cart_checkout_blocks', __FILE__, true); + } +}); + +add_action('woocommerce_blocks_loaded', 'razorpay_woocommerce_block_support'); + +function razorpay_woocommerce_block_support() +{ + if (class_exists('Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType')) + { + require_once dirname( __FILE__ ) . '/checkout-block.php'; + + add_action( + 'woocommerce_blocks_payment_method_type_registration', + function(PaymentMethodRegistry $payment_method_registry) { + $container = Automattic\WooCommerce\Blocks\Package::container(); + $container->register( + WC_Razorpay_Blocks::class, + function() { + return new WC_Razorpay_Blocks(); + } + ); + $payment_method_registry->register($container->get(WC_Razorpay_Blocks::class)); + }, + 5 + ); + } +} + function woocommerce_razorpay_init() { add_action("woocommerce_update_options_advanced", 'hposInstrumentation'); From 812a39ec4aa3422399711a82f849e811b0d3f92e Mon Sep 17 00:00:00 2001 From: yashgit891 <56789472+yashgit891@users.noreply.github.com> Date: Thu, 22 Feb 2024 11:56:53 +0530 Subject: [PATCH 21/91] Instant refund fix (#536) * Instant refund fallback --- woo-razorpay.php | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index b6efc6d2..9d91530d 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -1525,6 +1525,7 @@ public function process_refund($orderId, $amount = null, $reason = '') $data = array( 'amount' => (int) round($amount * 100), + 'speed' => 'optimum', 'notes' => array( 'reason' => $reason, 'order_id' => $orderId, @@ -1536,29 +1537,59 @@ public function process_refund($orderId, $amount = null, $reason = '') try { $refund = $client->payment - ->fetch( $paymentId ) - ->refund( $data ); + ->fetch($paymentId) + ->refund($data); - if (isset($refund) === true) + if (isset($refund) === true and + isset($refund->id) === true) { - $order->add_order_note( __( 'Refund Id: ' . $refund->id, 'woocommerce' ) ); + $order->add_order_note(__('Refund Id: ' . $refund->id, 'woocommerce')); /** * @var $refund ->id -- Provides the RazorPay Refund ID * @var $orderId -> Refunded Order ID * @var $refund -> WooCommerce Refund Instance. */ - do_action( 'woo_razorpay_refund_success', $refund->id, $orderId, $refund ); + do_action('woo_razorpay_refund_success', $refund->id, $orderId, $refund); - rzpLogInfo( 'Refund ID = ' . $refund->id . + rzpLogInfo('Refund ID = ' . $refund->id . ' , Refund speed requested = ' . $refund->speed_requested . ' , Refund speed processed = ' . $refund->speed_processed); } - + return true; } catch(Exception $e) { - return new WP_Error('error', __($e->getMessage(), 'woocommerce')); + rzpLogInfo('Refund failed with error message :- ' . $e->getMessage()); + + rzpLogInfo('Refund reinitiated with normal speed.'); + + try + { + $data['speed'] = 'normal'; + + $refund = $client->payment + ->fetch($paymentId) + ->refund($data); + + if (isset($refund) === true and + isset($refund->id) === true) + { + $order->add_order_note(__('Refund Id: ' . $refund->id, 'woocommerce')); + + do_action('woo_razorpay_refund_success', $refund->id, $orderId, $refund); + + rzpLogInfo('Refund ID = ' . $refund->id . + ' , Refund speed requested = ' . $refund->speed_requested . + ' , Refund speed processed = ' . $refund->speed_processed); + } + + return true; + } + catch(Exception $e) + { + return new WP_Error('error', __($e->getMessage(), 'woocommerce')); + } } } From ba7d89c5e21436816347710492b336ca8d5f8123 Mon Sep 17 00:00:00 2001 From: yashgit891 <56789472+yashgit891@users.noreply.github.com> Date: Thu, 22 Feb 2024 12:04:35 +0530 Subject: [PATCH 22/91] Version bump 4.6.1 (#537) --- readme.txt | 10 ++++++++-- woo-razorpay.php | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/readme.txt b/readme.txt index f98b61ff..bdbf0e1c 100644 --- a/readme.txt +++ b/readme.txt @@ -2,8 +2,8 @@ Contributors: razorpay Tags: razorpay, payments, india, woocommerce, curlec, malaysia, ecommerce, international, cross border Requires at least: 3.9.2 -Tested up to: 6.3.1 -Stable tag: 4.6.0 +Tested up to: 6.4.2 +Stable tag: 4.6.1 Requires PHP: 7.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -69,6 +69,12 @@ Razorpay is available for Store Owners and Merchants in == Changelog == += 4.6.1 = +* Added support for Checkout Blocks on Woocommerce. +* Added instant refund with fallback. +* Removed RTB widget ineligibility message. +* Fixed RTB widget eligibility check. + = 4.6.0 = * Support for Tera Wallet. * Added RTB widget. diff --git a/woo-razorpay.php b/woo-razorpay.php index 9d91530d..fdd04ebf 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -3,8 +3,8 @@ * Plugin Name: 1 Razorpay: Signup for FREE PG * Plugin URI: https://razorpay.com * Description: Razorpay Payment Gateway Integration for WooCommerce.Razorpay Welcome Back Offer: New to Razorpay? Sign up to enjoy FREE payments* of INR 2 lakh till March 31st! Transact before January 10th to grab the offer. - * Version: 4.6.0 - * Stable tag: 4.6.0 + * Version: 4.6.1 + * Stable tag: 4.6.1 * Author: Team Razorpay * WC tested up to: 7.9.0 * Author URI: https://razorpay.com From 3c1b290f4c6191359344f269352a5ebe201e1a3c Mon Sep 17 00:00:00 2001 From: Anantha-Perumal Date: Fri, 23 Feb 2024 15:09:37 +0530 Subject: [PATCH 23/91] fix: get product ID and weight --- woo-razorpay.php | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index fdd04ebf..9fecb8a9 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -49,7 +49,7 @@ }); add_action('before_woocommerce_init', function() { - if (class_exists('\Automattic\WooCommerce\Utilities\FeaturesUtil')) + if (class_exists('\Automattic\WooCommerce\Utilities\FeaturesUtil')) { \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('cart_checkout_blocks', __FILE__, true); } @@ -57,9 +57,9 @@ add_action('woocommerce_blocks_loaded', 'razorpay_woocommerce_block_support'); -function razorpay_woocommerce_block_support() +function razorpay_woocommerce_block_support() { - if (class_exists('Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType')) + if (class_exists('Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType')) { require_once dirname( __FILE__ ) . '/checkout-block.php'; @@ -480,7 +480,7 @@ public function init_form_fields() 'title' => '' . __('Razorpay Trusted Business'). '', 'type' => 'title' ); - + $this->form_fields['enable_rtb_widget'] = array( 'title' => __('RTB Widget Enable/Disable'), 'type' => 'checkbox', @@ -1378,7 +1378,12 @@ public function orderArg1CC($data, $order) $data['line_items'][$i]['type'] = $type; $data['line_items'][$i]['sku'] = $product->get_sku(); $data['line_items'][$i]['variant_id'] = (string)$item->get_variation_id(); - $data['line_items'][$i]['product_id'] = (string)$product->get_parent_id(); + $product_id = $product->get_id(); + if (is_a($product, 'WC_Product_Variation')) { + $product_id = $product->get_parent_id(); + } + $data['line_items'][$i]['product_id'] = (string)$product_id; + $data['line_items'][$i]['weight'] = $product->get_weight()*1000*(int)$item->get_quantity(); $data['line_items'][$i]['price'] = (empty($productDetails['price'])=== false) ? round(wc_get_price_excluding_tax($product)*100) + round($item->get_subtotal_tax()*100 / $item->get_quantity()) : 0; $data['line_items'][$i]['offer_price'] = (empty($productDetails['sale_price'])=== false) ? (int) $productDetails['sale_price']*100 : $productDetails['price']*100; $data['line_items'][$i]['quantity'] = (int)$item->get_quantity(); @@ -1555,7 +1560,7 @@ public function process_refund($orderId, $amount = null, $reason = '') ' , Refund speed requested = ' . $refund->speed_requested . ' , Refund speed processed = ' . $refund->speed_processed); } - + return true; } catch(Exception $e) @@ -1571,19 +1576,19 @@ public function process_refund($orderId, $amount = null, $reason = '') $refund = $client->payment ->fetch($paymentId) ->refund($data); - + if (isset($refund) === true and isset($refund->id) === true) { $order->add_order_note(__('Refund Id: ' . $refund->id, 'woocommerce')); - + do_action('woo_razorpay_refund_success', $refund->id, $orderId, $refund); rzpLogInfo('Refund ID = ' . $refund->id . ' , Refund speed requested = ' . $refund->speed_requested . ' , Refund speed processed = ' . $refund->speed_processed); } - + return true; } catch(Exception $e) @@ -2964,7 +2969,7 @@ function trigger_rtb_widget() $api = new Api(get_option('woocommerce_razorpay_settings')['key_id'], get_option('woocommerce_razorpay_settings')['key_secret']); update_option('rzp_rtb_enable', 'no'); - + $rtbActivationStatus = $api->request->request('GET', 'rtb?key_id=' . get_option('woocommerce_razorpay_settings')['key_id']); if (isset($rtbActivationStatus['widget_enabled']) and From 4f057796f68bd09eb9753e5c53b052f27f22bff4 Mon Sep 17 00:00:00 2001 From: Ram Prakash Singh <45222925+ramth05@users.noreply.github.com> Date: Thu, 29 Feb 2024 17:43:28 +0530 Subject: [PATCH 24/91] Update unit-tests.yml (#540) --- .github/workflows/unit-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 62209693..dc923b6e 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -12,7 +12,7 @@ jobs: env: MYSQL_ROOT_PASSWORD: root # Ensure docker waits for mariadb to start - options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + options: --health-cmd="healthcheck.sh --connect --innodb_initialized" --health-interval=10s --health-timeout=5s --health-retries=3 runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 From 1a1048c13e576cd665c23a45f5e612c7cd0f34cd Mon Sep 17 00:00:00 2001 From: Anantha-Perumal Date: Fri, 8 Mar 2024 14:18:08 +0530 Subject: [PATCH 25/91] fix: converting weight to grams based on weight metric used in woocommerce --- woo-razorpay.php | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index 9fecb8a9..691143c0 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -1383,7 +1383,7 @@ public function orderArg1CC($data, $order) $product_id = $product->get_parent_id(); } $data['line_items'][$i]['product_id'] = (string)$product_id; - $data['line_items'][$i]['weight'] = $product->get_weight()*1000*(int)$item->get_quantity(); + $data['line_items'][$i]['weight'] = $this->getWeightBasedOnStoreSettingsAndQuantity($product->get_weight(), $item->get_quantity()); $data['line_items'][$i]['price'] = (empty($productDetails['price'])=== false) ? round(wc_get_price_excluding_tax($product)*100) + round($item->get_subtotal_tax()*100 / $item->get_quantity()) : 0; $data['line_items'][$i]['offer_price'] = (empty($productDetails['sale_price'])=== false) ? (int) $productDetails['sale_price']*100 : $productDetails['price']*100; $data['line_items'][$i]['quantity'] = (int)$item->get_quantity(); @@ -1399,6 +1399,25 @@ public function orderArg1CC($data, $order) return $data; } + private function getWeightBasedOnStoreSettingsAndQuantity($weight, $quantity) { + $weightMetric = get_option('woocommerce_weight_unit' ); + $weightInGrams = $weight; + switch ($weightMetric) { + case 'kg': + $weightInGrams = $weight * 1000; + break; + case 'lbs': + $weightInGrams = $weight * 493.592; + break; + case 'oz': + $weightInGrams = $weight * 28.3495; + break; + default: + rzpLogError("Weight Metric is not supported : " . $weightMetric); + } + return round($weightInGrams * $quantity); + } + public function enqueueCheckoutScripts($data) { if($data === 'checkoutForm' || $data === 'routeAnalyticsForm') From 4bc65c661284f0386582cf334256179b859111cc Mon Sep 17 00:00:00 2001 From: Anantha-Perumal Date: Mon, 11 Mar 2024 12:32:32 +0530 Subject: [PATCH 26/91] refactor: review comments --- woo-razorpay.php | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index 691143c0..664f81ef 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -1383,7 +1383,9 @@ public function orderArg1CC($data, $order) $product_id = $product->get_parent_id(); } $data['line_items'][$i]['product_id'] = (string)$product_id; - $data['line_items'][$i]['weight'] = $this->getWeightBasedOnStoreSettingsAndQuantity($product->get_weight(), $item->get_quantity()); + // wc_get_weight is a woocommerce function which will help us to get weight in desired metric + // Magic Order expects weight in weight * quantity of line item hence doing the same + $data['line_items'][$i]['weight'] = round(wc_get_weight($product->get_weight(), 'g', get_option( 'woocommerce_weight_unit', 'g')) * $item->get_quantity()); $data['line_items'][$i]['price'] = (empty($productDetails['price'])=== false) ? round(wc_get_price_excluding_tax($product)*100) + round($item->get_subtotal_tax()*100 / $item->get_quantity()) : 0; $data['line_items'][$i]['offer_price'] = (empty($productDetails['sale_price'])=== false) ? (int) $productDetails['sale_price']*100 : $productDetails['price']*100; $data['line_items'][$i]['quantity'] = (int)$item->get_quantity(); @@ -1399,25 +1401,6 @@ public function orderArg1CC($data, $order) return $data; } - private function getWeightBasedOnStoreSettingsAndQuantity($weight, $quantity) { - $weightMetric = get_option('woocommerce_weight_unit' ); - $weightInGrams = $weight; - switch ($weightMetric) { - case 'kg': - $weightInGrams = $weight * 1000; - break; - case 'lbs': - $weightInGrams = $weight * 493.592; - break; - case 'oz': - $weightInGrams = $weight * 28.3495; - break; - default: - rzpLogError("Weight Metric is not supported : " . $weightMetric); - } - return round($weightInGrams * $quantity); - } - public function enqueueCheckoutScripts($data) { if($data === 'checkoutForm' || $data === 'routeAnalyticsForm') From 13df5d99aa529a653b75be076e1735ca5e7507bc Mon Sep 17 00:00:00 2001 From: Anantha-Perumal Date: Tue, 12 Mar 2024 10:17:09 +0530 Subject: [PATCH 27/91] refactor: dummy commit --- woo-razorpay.php | 1 + 1 file changed, 1 insertion(+) diff --git a/woo-razorpay.php b/woo-razorpay.php index 664f81ef..747b763a 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -1383,6 +1383,7 @@ public function orderArg1CC($data, $order) $product_id = $product->get_parent_id(); } $data['line_items'][$i]['product_id'] = (string)$product_id; + // wc_get_weight is a woocommerce function which will help us to get weight in desired metric // Magic Order expects weight in weight * quantity of line item hence doing the same $data['line_items'][$i]['weight'] = round(wc_get_weight($product->get_weight(), 'g', get_option( 'woocommerce_weight_unit', 'g')) * $item->get_quantity()); From c8dc68ce67d98e69dd82ddcad89423ef2825f05c Mon Sep 17 00:00:00 2001 From: Anantha-Perumal Date: Tue, 12 Mar 2024 13:10:03 +0530 Subject: [PATCH 28/91] revert: previous commit --- woo-razorpay.php | 1 - 1 file changed, 1 deletion(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index 747b763a..664f81ef 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -1383,7 +1383,6 @@ public function orderArg1CC($data, $order) $product_id = $product->get_parent_id(); } $data['line_items'][$i]['product_id'] = (string)$product_id; - // wc_get_weight is a woocommerce function which will help us to get weight in desired metric // Magic Order expects weight in weight * quantity of line item hence doing the same $data['line_items'][$i]['weight'] = round(wc_get_weight($product->get_weight(), 'g', get_option( 'woocommerce_weight_unit', 'g')) * $item->get_quantity()); From 65d3fbd6a7ccedf546f0aac5ae8d5e4e276cb041 Mon Sep 17 00:00:00 2001 From: Anantha-Perumal Date: Thu, 14 Mar 2024 16:16:39 +0530 Subject: [PATCH 29/91] fix: weight calculation - removed multiplying by quantity as it is not needed --- woo-razorpay.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index 664f81ef..68925a75 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -1384,8 +1384,7 @@ public function orderArg1CC($data, $order) } $data['line_items'][$i]['product_id'] = (string)$product_id; // wc_get_weight is a woocommerce function which will help us to get weight in desired metric - // Magic Order expects weight in weight * quantity of line item hence doing the same - $data['line_items'][$i]['weight'] = round(wc_get_weight($product->get_weight(), 'g', get_option( 'woocommerce_weight_unit', 'g')) * $item->get_quantity()); + $data['line_items'][$i]['weight'] = round(wc_get_weight($product->get_weight(), 'g', get_option( 'woocommerce_weight_unit', 'g'))); $data['line_items'][$i]['price'] = (empty($productDetails['price'])=== false) ? round(wc_get_price_excluding_tax($product)*100) + round($item->get_subtotal_tax()*100 / $item->get_quantity()) : 0; $data['line_items'][$i]['offer_price'] = (empty($productDetails['sale_price'])=== false) ? (int) $productDetails['sale_price']*100 : $productDetails['price']*100; $data['line_items'][$i]['quantity'] = (int)$item->get_quantity(); From a89f3ac7024e563bb41f4be607c3fcffc9e65ece Mon Sep 17 00:00:00 2001 From: AnkitTiwari <105644854+nkttiwari@users.noreply.github.com> Date: Mon, 26 Feb 2024 10:54:10 +0530 Subject: [PATCH 30/91] adding shpping method name for shipping engine --- woo-razorpay.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/woo-razorpay.php b/woo-razorpay.php index 68925a75..a73f6ce5 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -2221,6 +2221,11 @@ public function update1ccOrderWC(& $order, $wcOrderId, $razorpayPaymentId) // $item->set_method_id( "flat_rate:1" ); $item->set_total( $razorpayData['shipping_fee']/100 ); + if (isset($razorpayData['shipping_method'])) + { + $item->set_method_title($razorpayData['shipping_method']['name']); + } + $order->add_item( $item ); $item->save(); From a63383c2eec5b951fd9b959d83a03d6f6c3ec73b Mon Sep 17 00:00:00 2001 From: Ankit Kumar Tiwari Date: Mon, 18 Mar 2024 15:55:42 +0530 Subject: [PATCH 31/91] adding condition where required --- woo-razorpay.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index a73f6ce5..7898ae82 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -2150,6 +2150,10 @@ public function update1ccOrderWC(& $order, $wcOrderId, $razorpayPaymentId) if($razorpayData['shipping_fee'] == 0) { $item->set_method_title( 'Free Shipping' ); + if(isset($razorpayData['notes']) && isset($razorpayData['notes']['shipping_method_name'])) + { + $item->set_method_title($razorpayData['notes']['shipping_method_name']); + } } else { @@ -2221,9 +2225,9 @@ public function update1ccOrderWC(& $order, $wcOrderId, $razorpayPaymentId) // $item->set_method_id( "flat_rate:1" ); $item->set_total( $razorpayData['shipping_fee']/100 ); - if (isset($razorpayData['shipping_method'])) + if(isset($razorpayData['notes']) && isset($razorpayData['notes']['shipping_method_name'])) { - $item->set_method_title($razorpayData['shipping_method']['name']); + $item->set_method_title($razorpayData['notes']['shipping_method_name']); } $order->add_item( $item ); From 467d79fdc47cb371f6e6c9bc195a47a507916951 Mon Sep 17 00:00:00 2001 From: yashgit891 <56789472+yashgit891@users.noreply.github.com> Date: Wed, 27 Mar 2024 15:36:49 +0530 Subject: [PATCH 32/91] Added null check in upgrade instrumentation (#546) * Added null check in upgrade instrumentation --- public/js/admin-rzp-settings.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/public/js/admin-rzp-settings.js b/public/js/admin-rzp-settings.js index 0454577a..56b9ac8f 100644 --- a/public/js/admin-rzp-settings.js +++ b/public/js/admin-rzp-settings.js @@ -41,6 +41,11 @@ window.onload = function() { { var rzpElement = document.getElementById(item); + if (rzpElement == null) + { + return; + } + var data = { 'action' : 'rzpInstrumentation', 'event' : 'formfield.interacted', From dbffc78d6c4872bce5e319d9e995a7c54f4fa9c4 Mon Sep 17 00:00:00 2001 From: yashgit891 <56789472+yashgit891@users.noreply.github.com> Date: Wed, 27 Mar 2024 16:20:50 +0530 Subject: [PATCH 33/91] Subscription Events fix (#545) * Subscription Events fix --- includes/razorpay-webhook.php | 70 +++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/includes/razorpay-webhook.php b/includes/razorpay-webhook.php index 3a0f3507..ce969c48 100644 --- a/includes/razorpay-webhook.php +++ b/includes/razorpay-webhook.php @@ -56,6 +56,13 @@ class RZP_Webhook self::SUBSCRIPTION_CHARGED, ]; + protected $subscriptionEvents = [ + self::SUBSCRIPTION_CANCELLED, + self::SUBSCRIPTION_PAUSED, + self::SUBSCRIPTION_RESUMED, + self::SUBSCRIPTION_CHARGED, + ]; + public function __construct() { $this->razorpay = new WC_Razorpay(false); @@ -94,6 +101,13 @@ public function process() $orderId = $data['payload']['payment']['entity']['notes']['woocommerce_order_number']; $razorpayOrderId = $data['payload']['payment']['entity']['order_id']; + if (in_array($data['event'], $this->subscriptionEvents) === true) + { + $orderId = $data['payload']['subscription']['entity']['notes']['woocommerce_order_id']; + $razorpayOrderId = ($data['event'] == self::SUBSCRIPTION_CHARGED) ? $razorpayOrderId : "No payment id in subscription event"; + } + + // Skip the webhook if not the valid data and event if ($this->shouldConsumeWebhook($data) === false) { rzpLogInfo("Woocommerce orderId: $orderId webhook process exited in shouldConsumeWebhook function"); @@ -136,43 +150,45 @@ public function process() return; } - if ($this->razorpay->isHposEnabled) - { - $order = wc_get_order($orderId); - $rzpWebhookNotifiedAt = $order->get_meta('rzp_webhook_notified_at'); - } - else - { - $rzpWebhookNotifiedAt = get_post_meta($orderId, "rzp_webhook_notified_at", true); - } - - - if ($rzpWebhookNotifiedAt === '') + if (in_array($data['event'], $this->subscriptionEvents) === false) { if ($this->razorpay->isHposEnabled) { - $order->update_meta_data('rzp_webhook_notified_at', time()); - $order->save(); + $order = wc_get_order($orderId); + $rzpWebhookNotifiedAt = $order->get_meta('rzp_webhook_notified_at'); } else { - update_post_meta($orderId, "rzp_webhook_notified_at", time()); + $rzpWebhookNotifiedAt = get_post_meta($orderId, "rzp_webhook_notified_at", true); } - rzpLogInfo("ORDER NUMBER $orderId:webhook conflict due to early execution for razorpay order: $razorpayOrderId "); - header('Status: ' . static::HTTP_CONFLICT_STATUS . ' Webhook conflicts due to early execution.', true, static::HTTP_CONFLICT_STATUS);// nosemgrep : php.lang.security.non-literal-header.non-literal-header - return; - } - elseif ((time() - $rzpWebhookNotifiedAt) < static::WEBHOOK_NOTIFY_WAIT_TIME) - { - rzpLogInfo("ORDER NUMBER $orderId:webhook conflict due to early execution for razorpay order: $razorpayOrderId "); - header('Status: ' . static::HTTP_CONFLICT_STATUS . ' Webhook conflicts due to early execution.', true, static::HTTP_CONFLICT_STATUS);// nosemgrep : php.lang.security.non-literal-header.non-literal-header - return; - } + if ($rzpWebhookNotifiedAt === '') + { + if ($this->razorpay->isHposEnabled) + { + $order->update_meta_data('rzp_webhook_notified_at', time()); + $order->save(); + } + else + { + update_post_meta($orderId, "rzp_webhook_notified_at", time()); + } + + rzpLogInfo("ORDER NUMBER $orderId:webhook conflict due to early execution for razorpay order: $razorpayOrderId "); + header('Status: ' . static::HTTP_CONFLICT_STATUS . ' Webhook conflicts due to early execution.', true, static::HTTP_CONFLICT_STATUS);// nosemgrep : php.lang.security.non-literal-header.non-literal-header + return; + } + elseif ((time() - $rzpWebhookNotifiedAt) < static::WEBHOOK_NOTIFY_WAIT_TIME) + { + rzpLogInfo("ORDER NUMBER $orderId:webhook conflict due to early execution for razorpay order: $razorpayOrderId "); + header('Status: ' . static::HTTP_CONFLICT_STATUS . ' Webhook conflicts due to early execution.', true, static::HTTP_CONFLICT_STATUS);// nosemgrep : php.lang.security.non-literal-header.non-literal-header + return; + } - rzpLogInfo("ORDER NUMBER $orderId:webhook conflict over for razorpay order: $razorpayOrderId"); + rzpLogInfo("ORDER NUMBER $orderId:webhook conflict over for razorpay order: $razorpayOrderId"); + } - rzpLogInfo("Woocommerce orderId: $orderId webhook process intitiated"); + rzpLogInfo("Woocommerce orderId: $orderId webhook process intitiated for event: ". $data['event']); switch ($data['event']) { case self::PAYMENT_AUTHORIZED: From 8da2e3b1033443243e329627dea7d1977af75a84 Mon Sep 17 00:00:00 2001 From: yashgit891 <56789472+yashgit891@users.noreply.github.com> Date: Thu, 28 Mar 2024 17:01:13 +0530 Subject: [PATCH 34/91] Version bump 4.6.2 (#547) * Version bump 4.6.2 * adding change logs for shipping method name --------- Co-authored-by: Ankit Kumar Tiwari --- readme.txt | 7 ++++++- woo-razorpay.php | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/readme.txt b/readme.txt index bdbf0e1c..9f251987 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: razorpay Tags: razorpay, payments, india, woocommerce, curlec, malaysia, ecommerce, international, cross border Requires at least: 3.9.2 Tested up to: 6.4.2 -Stable tag: 4.6.1 +Stable tag: 4.6.2 Requires PHP: 7.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -69,6 +69,11 @@ Razorpay is available for Store Owners and Merchants in == Changelog == += 4.6.2 = +* Fixed, Subscription events webhook bug. +* Fixed, console errors due to instrumentation. +* Added Shipping Method Name for Shipping Engine support. + = 4.6.1 = * Added support for Checkout Blocks on Woocommerce. * Added instant refund with fallback. diff --git a/woo-razorpay.php b/woo-razorpay.php index 7898ae82..fa202cbe 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -3,8 +3,8 @@ * Plugin Name: 1 Razorpay: Signup for FREE PG * Plugin URI: https://razorpay.com * Description: Razorpay Payment Gateway Integration for WooCommerce.Razorpay Welcome Back Offer: New to Razorpay? Sign up to enjoy FREE payments* of INR 2 lakh till March 31st! Transact before January 10th to grab the offer. - * Version: 4.6.1 - * Stable tag: 4.6.1 + * Version: 4.6.2 + * Stable tag: 4.6.2 * Author: Team Razorpay * WC tested up to: 7.9.0 * Author URI: https://razorpay.com From ef49b88018e85d0defa56f71723c404129d2ffa3 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 25 Apr 2024 13:57:11 +0530 Subject: [PATCH 35/91] Added magic checkout admin banner on wooc dashboard --- woo-razorpay.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/woo-razorpay.php b/woo-razorpay.php index fa202cbe..4dd4afb4 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -335,6 +335,8 @@ protected function initHooks() { add_action('woocommerce_receipt_' . $this->id, array($this, 'receipt_page')); + add_action( 'admin_notices', array($this, 'add_magic_banner' )); + add_action('woocommerce_api_' . $this->id, array($this, 'check_razorpay_response')); $cb = array($this, 'process_admin_options'); @@ -361,6 +363,13 @@ protected function initHooks() add_filter( 'woocommerce_thankyou_order_received_text', array($this, 'getCustomOrdercreationMessage'), 20, 2 ); } + // Magic checkout admin banner has been added. + public function add_magic_banner() + { + echo '
+
'; + } + public function init_form_fields() { $webhookUrl = esc_url(admin_url('admin-post.php')) . '?action=rzp_wc_webhook'; From 5423ad6741805de09521f4abfeb9ccdd7247d0cb Mon Sep 17 00:00:00 2001 From: Razorpay Date: Thu, 25 Apr 2024 14:40:56 +0530 Subject: [PATCH 36/91] PO-113 revert instant refund fix --- woo-razorpay.php | 35 ++--------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index fa202cbe..b4a8c3f4 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -1531,7 +1531,6 @@ public function process_refund($orderId, $amount = null, $reason = '') $data = array( 'amount' => (int) round($amount * 100), - 'speed' => 'optimum', 'notes' => array( 'reason' => $reason, 'order_id' => $orderId, @@ -1546,8 +1545,7 @@ public function process_refund($orderId, $amount = null, $reason = '') ->fetch($paymentId) ->refund($data); - if (isset($refund) === true and - isset($refund->id) === true) + if (isset($refund) === true) { $order->add_order_note(__('Refund Id: ' . $refund->id, 'woocommerce')); /** @@ -1566,36 +1564,7 @@ public function process_refund($orderId, $amount = null, $reason = '') } catch(Exception $e) { - rzpLogInfo('Refund failed with error message :- ' . $e->getMessage()); - - rzpLogInfo('Refund reinitiated with normal speed.'); - - try - { - $data['speed'] = 'normal'; - - $refund = $client->payment - ->fetch($paymentId) - ->refund($data); - - if (isset($refund) === true and - isset($refund->id) === true) - { - $order->add_order_note(__('Refund Id: ' . $refund->id, 'woocommerce')); - - do_action('woo_razorpay_refund_success', $refund->id, $orderId, $refund); - - rzpLogInfo('Refund ID = ' . $refund->id . - ' , Refund speed requested = ' . $refund->speed_requested . - ' , Refund speed processed = ' . $refund->speed_processed); - } - - return true; - } - catch(Exception $e) - { - return new WP_Error('error', __($e->getMessage(), 'woocommerce')); - } + return new WP_Error('error', __($e->getMessage(), 'woocommerce')); } } From 0c98ec97c4d019f6d9a6a9def79e342f85bc7c51 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 25 Apr 2024 14:59:18 +0530 Subject: [PATCH 37/91] Code clean up --- woo-razorpay.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index 4dd4afb4..18a29827 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -335,7 +335,7 @@ protected function initHooks() { add_action('woocommerce_receipt_' . $this->id, array($this, 'receipt_page')); - add_action( 'admin_notices', array($this, 'add_magic_banner' )); + add_action('admin_notices', array($this, 'add_magic_banner')); add_action('woocommerce_api_' . $this->id, array($this, 'check_razorpay_response')); From 6254f5a51131f515b7021dd3064a340d890d8177 Mon Sep 17 00:00:00 2001 From: Razorpay Date: Thu, 25 Apr 2024 15:31:08 +0530 Subject: [PATCH 38/91] PO-113 version bump 4.6.3 --- readme.txt | 6 +++++- woo-razorpay.php | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/readme.txt b/readme.txt index 9f251987..2024b5ce 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: razorpay Tags: razorpay, payments, india, woocommerce, curlec, malaysia, ecommerce, international, cross border Requires at least: 3.9.2 Tested up to: 6.4.2 -Stable tag: 4.6.2 +Stable tag: 4.6.3 Requires PHP: 7.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -69,6 +69,10 @@ Razorpay is available for Store Owners and Merchants in == Changelog == += 4.6.3 = +* Added, Magic checkout banner on woocommerce dashboard. +* Reverted, Instand Refund. + = 4.6.2 = * Fixed, Subscription events webhook bug. * Fixed, console errors due to instrumentation. diff --git a/woo-razorpay.php b/woo-razorpay.php index c78694af..43e99784 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -3,8 +3,8 @@ * Plugin Name: 1 Razorpay: Signup for FREE PG * Plugin URI: https://razorpay.com * Description: Razorpay Payment Gateway Integration for WooCommerce.Razorpay Welcome Back Offer: New to Razorpay? Sign up to enjoy FREE payments* of INR 2 lakh till March 31st! Transact before January 10th to grab the offer. - * Version: 4.6.2 - * Stable tag: 4.6.2 + * Version: 4.6.3 + * Stable tag: 4.6.3 * Author: Team Razorpay * WC tested up to: 7.9.0 * Author URI: https://razorpay.com From 6ce090e50fb0c844bc10dad7d8bbfaf81303f99d Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 25 Apr 2024 22:22:57 +0530 Subject: [PATCH 39/91] Reverted magic banner changes --- readme.txt | 5 ++++- woo-razorpay.php | 13 ++----------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/readme.txt b/readme.txt index 2024b5ce..6261a3e8 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: razorpay Tags: razorpay, payments, india, woocommerce, curlec, malaysia, ecommerce, international, cross border Requires at least: 3.9.2 Tested up to: 6.4.2 -Stable tag: 4.6.3 +Stable tag: 4.6.4 Requires PHP: 7.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -69,6 +69,9 @@ Razorpay is available for Store Owners and Merchants in == Changelog == += 4.6.4 = +* Reverted, Magic checkout banner on woocommerce dashboard. + = 4.6.3 = * Added, Magic checkout banner on woocommerce dashboard. * Reverted, Instand Refund. diff --git a/woo-razorpay.php b/woo-razorpay.php index 43e99784..677fb7d9 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -3,8 +3,8 @@ * Plugin Name: 1 Razorpay: Signup for FREE PG * Plugin URI: https://razorpay.com * Description: Razorpay Payment Gateway Integration for WooCommerce.Razorpay Welcome Back Offer: New to Razorpay? Sign up to enjoy FREE payments* of INR 2 lakh till March 31st! Transact before January 10th to grab the offer. - * Version: 4.6.3 - * Stable tag: 4.6.3 + * Version: 4.6.4 + * Stable tag: 4.6.4 * Author: Team Razorpay * WC tested up to: 7.9.0 * Author URI: https://razorpay.com @@ -335,8 +335,6 @@ protected function initHooks() { add_action('woocommerce_receipt_' . $this->id, array($this, 'receipt_page')); - add_action('admin_notices', array($this, 'add_magic_banner')); - add_action('woocommerce_api_' . $this->id, array($this, 'check_razorpay_response')); $cb = array($this, 'process_admin_options'); @@ -363,13 +361,6 @@ protected function initHooks() add_filter( 'woocommerce_thankyou_order_received_text', array($this, 'getCustomOrdercreationMessage'), 20, 2 ); } - // Magic checkout admin banner has been added. - public function add_magic_banner() - { - echo '
-
'; - } - public function init_form_fields() { $webhookUrl = esc_url(admin_url('admin-post.php')) . '?action=rzp_wc_webhook'; From 9bb099544991b897d929f9cc54fca7c0c5c2161e Mon Sep 17 00:00:00 2001 From: Razorpay Date: Fri, 10 May 2024 12:44:40 +0530 Subject: [PATCH 40/91] PO-117 added tests to SVN ignore list --- release.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/release.sh b/release.sh index f881cb34..5d2a2b2f 100755 --- a/release.sh +++ b/release.sh @@ -49,6 +49,7 @@ git checkout-index -a -f --prefix=$SVNPATH/trunk/ echo "Ignoring github specific & deployment script" svn propset svn:ignore "release.sh +tests .git .gitignore" "$SVNPATH/trunk/" From 484314e98bde68f05b311a59c38c1db92a487455 Mon Sep 17 00:00:00 2001 From: naveen-s-rzp Date: Tue, 14 May 2024 12:30:17 +0530 Subject: [PATCH 41/91] removed semgrep workflow --- .github/workflows/security.yml | 51 ---------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 .github/workflows/security.yml diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml deleted file mode 100644 index 3b1a2fa8..00000000 --- a/.github/workflows/security.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: SecurityChecks -on: - pull_request: {} - push: - branches: ["master"] - schedule: - - cron: '30 20 * * *' -jobs: - semgrep: - name: Scan - runs-on: [ubuntu-latest] # nosemgrep : semgrep.dev/s/swati31196:github_provided_runner - steps: - - uses: actions/checkout@v2 - - uses: returntocorp/semgrep-action@v1 - with: - publishToken: ${{ secrets.SEMGREP_APP_TOKEN }} - publishDeployment: 339 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - workflow_status: - runs-on: [ ubuntu-latest ] # nosemgrep : semgrep.dev/s/swati31196:github_provided_runner - name: Update Status Check - needs: [ semgrep ] - if: always() - env: - githubCommit: ${{ github.event.pull_request.head.sha }} - steps: - - name: Set github commit id - run: | - if [ "${{ github.event_name }}" = "push" ] || [ "${{ github.event_name }}" = "schedule" ]; then - echo "githubCommit=${{ github.sha }}" >> $GITHUB_ENV - fi - exit 0 - - name: Failed - id: failed - if: (contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')) && github.ref != 'refs/heads/master' - run: | - echo 'Failing the workflow for github security status check.' - curl -X POST -H "Content-Type: application/json" -H "Authorization: token ${{ github.token }}" \ - -d '{ "state" : "failure" , "context" : "github/security-status-check" , "description" : "github/security-status-check", "target_url" : "https://github.com/${{ github.repository }}" }' \ - https://api.github.com/repos/${{ github.repository }}/statuses/${{ env.githubCommit }} - exit 1 - - name: Success - if: steps.failed.conclusion == 'skipped' || github.ref != 'refs/heads/master' - run: | - echo 'Status check has passed!' - curl -X POST -H "Content-Type: application/json" -H "Authorization: token ${{ github.token }}" \ - -d '{ "state" : "success" , "context" : "github/security-status-check" , "description" : "github/security-status-check", "target_url" : "https://github.com/${{ github.repository }}" }' \ - https://api.github.com/repos/${{ github.repository }}/statuses/${{ env.githubCommit }} - exit 0 \ No newline at end of file From 1660e07ff59f78334f3c79babfe408ac74c32384 Mon Sep 17 00:00:00 2001 From: yashgit891 <56789472+yashgit891@users.noreply.github.com> Date: Wed, 15 May 2024 15:52:38 +0530 Subject: [PATCH 42/91] Version bump 4.6.5 (#554) --- readme.txt | 5 ++++- woo-razorpay.php | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/readme.txt b/readme.txt index 6261a3e8..6453f79b 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: razorpay Tags: razorpay, payments, india, woocommerce, curlec, malaysia, ecommerce, international, cross border Requires at least: 3.9.2 Tested up to: 6.4.2 -Stable tag: 4.6.4 +Stable tag: 4.6.5 Requires PHP: 7.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -69,6 +69,9 @@ Razorpay is available for Store Owners and Merchants in == Changelog == += 4.6.4 = +* Added, UT to SVN ignore list. + = 4.6.4 = * Reverted, Magic checkout banner on woocommerce dashboard. diff --git a/woo-razorpay.php b/woo-razorpay.php index 677fb7d9..0bfcff4c 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -3,8 +3,8 @@ * Plugin Name: 1 Razorpay: Signup for FREE PG * Plugin URI: https://razorpay.com * Description: Razorpay Payment Gateway Integration for WooCommerce.Razorpay Welcome Back Offer: New to Razorpay? Sign up to enjoy FREE payments* of INR 2 lakh till March 31st! Transact before January 10th to grab the offer. - * Version: 4.6.4 - * Stable tag: 4.6.4 + * Version: 4.6.5 + * Stable tag: 4.6.5 * Author: Team Razorpay * WC tested up to: 7.9.0 * Author URI: https://razorpay.com From 2ce82081ba535b23ac0d82e7f411ce5085f503c4 Mon Sep 17 00:00:00 2001 From: rohitcbr Date: Tue, 21 May 2024 15:10:06 +0530 Subject: [PATCH 43/91] Update woo-razorpay.php --- woo-razorpay.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/woo-razorpay.php b/woo-razorpay.php index 0bfcff4c..7c22cb2b 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -525,6 +525,8 @@ protected function triggerValidationInstrumentation($data) public function autoEnableWebhook() { + rzpLogInfo("Time:" . time() ." at autoEnableWebhook"); + $webhookExist = false; $webhookUrl = $this->getWebhookUrl(); From af91fdbade149ade508b99f169c2777a032b084b Mon Sep 17 00:00:00 2001 From: rohitcbr Date: Tue, 21 May 2024 15:29:00 +0530 Subject: [PATCH 44/91] Update woo-razorpay.php --- woo-razorpay.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index 7c22cb2b..bf82974a 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -82,9 +82,9 @@ function() { function woocommerce_razorpay_init() { - add_action("woocommerce_update_options_advanced", 'hposInstrumentation'); + add_action("woocommerce_update_options_advanced", 'hposInstrumentationRzp'); - function hposInstrumentation() + function hposInstrumentationRzp() { $rzp = new WC_Razorpay(); From ddb24cb4b885d3d8144486743b3b298c603782dc Mon Sep 17 00:00:00 2001 From: rohitcbr Date: Tue, 21 May 2024 16:02:42 +0530 Subject: [PATCH 45/91] Update woo-razorpay.php --- woo-razorpay.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/woo-razorpay.php b/woo-razorpay.php index bf82974a..978f12c7 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -82,9 +82,7 @@ function() { function woocommerce_razorpay_init() { - add_action("woocommerce_update_options_advanced", 'hposInstrumentationRzp'); - - function hposInstrumentationRzp() + add_action("woocommerce_update_options_advanced", function() { $rzp = new WC_Razorpay(); @@ -119,7 +117,7 @@ function hposInstrumentationRzp() update_option('rzp_hpos', 'no'); } - } + }); if (!class_exists('WC_Payment_Gateway') || class_exists('WC_Razorpay')) { From 9a32a6127ae7a80353079d7c9f6b82cdbf083838 Mon Sep 17 00:00:00 2001 From: rohitcbr Date: Tue, 21 May 2024 17:58:48 +0530 Subject: [PATCH 46/91] fixed tests --- tests/phpunit/tests/test-instrumentation.php | 8 ++--- tests/phpunit/tests/test-metadata.php | 2 +- tests/phpunit/tests/test-methods.php | 12 ++++---- tests/phpunit/tests/test-order-methods.php | 32 ++++++++++---------- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/tests/phpunit/tests/test-instrumentation.php b/tests/phpunit/tests/test-instrumentation.php index 19ba5ff5..a50f3bb5 100644 --- a/tests/phpunit/tests/test-instrumentation.php +++ b/tests/phpunit/tests/test-instrumentation.php @@ -85,9 +85,9 @@ function () { public function testUpdateCurrentVersion() { $this->expectNotToPerformAssertions(); - + add_option('rzp_woocommerce_current_version', get_plugin_data(__FILE__)['Version']); - + $_POST['woocommerce_razorpay_key_id'] = 'key_id'; $_POST['woocommerce_razorpay_key_secret'] = 'key_secret'; $_POST['woocommerce_razorpay_enabled'] = 'yes'; @@ -248,7 +248,7 @@ public function testInstrumentationDataLakeEmptyProperties() $this->assertSame('error', $response['status']); $this->assertSame('properties given as input is not valid', $response['message']); } - + public function testGetDefaultPropertiesWithTimeStamp() { $response = $this->instrumentationMock->getDefaultProperties(); @@ -256,7 +256,7 @@ public function testGetDefaultPropertiesWithTimeStamp() $this->assertSame('WordPress', $response['platform']); $this->assertNotNull($response['platform_version']); $this->assertNotNull($response['woocommerce_version']); - $this->assertSame('Razorpay for WooCommerce', $response['plugin_name']); + $this->assertSame('1 Razorpay: Signup for FREE PG', $response['plugin_name']); $this->assertNotNull($response['plugin_version']); $this->assertNotNull($response['unique_id']); $this->assertNotNull($response['event_timestamp']); diff --git a/tests/phpunit/tests/test-metadata.php b/tests/phpunit/tests/test-metadata.php index f26d40da..a87f6592 100644 --- a/tests/phpunit/tests/test-metadata.php +++ b/tests/phpunit/tests/test-metadata.php @@ -6,7 +6,7 @@ public function testMetadata() { $pluginData = get_plugin_data(PLUGIN_DIR . '/woo-razorpay.php'); - $this->assertSame('Razorpay for WooCommerce', $pluginData['Name']); + $this->assertSame('1 Razorpay: Signup for FREE PG', $pluginData['Name']); $version = $pluginData['Version']; $v = explode(".", $version); diff --git a/tests/phpunit/tests/test-methods.php b/tests/phpunit/tests/test-methods.php index 50bf01d5..0346f083 100755 --- a/tests/phpunit/tests/test-methods.php +++ b/tests/phpunit/tests/test-methods.php @@ -122,7 +122,7 @@ public function testReceiptPage() $this->assertStringContainsString('', $result); $this->assertStringContainsString('', $result); } - + public function testCreateRazorpayOrderId() { $order = wc_create_order(); @@ -133,7 +133,7 @@ public function testCreateRazorpayOrderId() }); $this->instance->shouldReceive('autoEnableWebhook'); - $response = $this->instance->createOrGetRazorpayOrderId($orderId); + $response = $this->instance->createOrGetRazorpayOrderId($order, $orderId); $this->assertStringContainsString('razorpay_test_id', $response); } @@ -148,10 +148,10 @@ public function testCreateRazorpayOrderIdwitwebhooktime() $this->instance->shouldReceive('autoEnableWebhook'); add_option('webhook_enable_flag', 2400); - $response = $this->instance->createOrGetRazorpayOrderId($orderId); + $response = $this->instance->createOrGetRazorpayOrderId($order, $orderId); $this->assertStringContainsString('razorpay_test_id', $response ); } - + public function testGetRazorpayOrderId() { $order = wc_create_order(); @@ -164,7 +164,7 @@ public function testGetRazorpayOrderId() }); $this->instance->shouldReceive('autoEnableWebhook'); - $response = $this->instance->createOrGetRazorpayOrderId($orderId); + $response = $this->instance->createOrGetRazorpayOrderId($order, $orderId); $this->assertStringContainsString('razorpay_test_id', $response); } @@ -236,7 +236,7 @@ function () { $this->assertStringContainsString("", $response); $this->assertStringContainsString("", $response); } - + public function testGetShippingZone() { $response = $this->instance->getShippingZone(0); diff --git a/tests/phpunit/tests/test-order-methods.php b/tests/phpunit/tests/test-order-methods.php index e7e6940e..15ea7be6 100644 --- a/tests/phpunit/tests/test-order-methods.php +++ b/tests/phpunit/tests/test-order-methods.php @@ -18,7 +18,7 @@ class Test_OrderMethods extends WP_UnitTestCase { private $instance; private $rzpPaymentObj; - + public function setup(): void { parent::setup(); @@ -29,11 +29,11 @@ public function setup(): void $_POST = array(); } - + public function testGetRazorpayPaymentParams() - { + { global $woocommerce; - + $order = wc_create_order(); $wcOrderId = $order->get_id(); @@ -47,11 +47,11 @@ function () { $razorpayOrderId = $this->instance->shouldReceive('createOrGetRazorpayOrderId')->with($wcOrderId)->andReturn('order_test'); - $this->assertEquals(['order_id' => 'order_test'], $this->instance->getRazorpayPaymentParams($wcOrderId)); + $this->assertEquals(['order_id' => 'order_test'], $this->instance->getRazorpayPaymentParams($order, $wcOrderId)); //After the webhook flag is set - $this->assertEquals(['order_id' => 'order_test'], $this->instance->getRazorpayPaymentParams($wcOrderId)); + $this->assertEquals(['order_id' => 'order_test'], $this->instance->getRazorpayPaymentParams($order, $wcOrderId)); } @@ -71,16 +71,16 @@ function () { $message = 'RAZORPAY ERROR: Razorpay API could not be reached'; - try + try { - $this->instance->getRazorpayPaymentParams($wcOrderId); + $this->instance->getRazorpayPaymentParams($order, $wcOrderId); $this->fail("Expected Exception has not been raised."); } - catch (Exception $ex) + catch (Exception $ex) { $this->assertEquals($message, $ex->getMessage()); - } + } } public function testGetCustomOrderCreationMessage() @@ -103,11 +103,11 @@ public function testGetDefaultCustomOrderCreationMessage() $order = wc_create_order(); $defaultmessage = 'Thank you for shopping with us. Your account has been charged and your transaction is successful. We will be processing your order soon.'; - + $this->instance->shouldReceive('getSetting')->with('order_success_message'); - + $response = $this->instance->getCustomOrdercreationMessage("", $order); - + $this->assertSame($defaultmessage, $response); } @@ -148,7 +148,7 @@ public function testGetDefaultCheckoutArguments() 'email' => $order->get_billing_email(), 'contact' => $order->get_billing_phone(), ); - + $this->instance->shouldReceive('getOrderSessionKey')->with($orderId)->andReturn($sessionKey); $response = $this->instance->getDefaultCheckoutArguments($order); @@ -167,7 +167,7 @@ public function testGetDefaultCheckoutArguments() $this->assertSame($args, $response['prefill']); } - + public function testUpdateOrder() { global $woocommerce; @@ -345,7 +345,7 @@ public function testCheckRazorpayResponse() $wpdb->insert($wpdb->posts, array('post_status' => 'Pending', 'post_type' => 'shop_order', 'ID' => 22)); $this->instance->shouldReceive('verifySignature'); - + $this->instance->shouldReceive('redirectUser'); $this->instance->shouldReceive('updateOrder'); From 29d6a5a34a4f7fac006eac6d9d76956c12a1b87e Mon Sep 17 00:00:00 2001 From: rohitcbr Date: Tue, 21 May 2024 18:31:55 +0530 Subject: [PATCH 47/91] fixed some tests --- tests/phpunit/tests/test-metadata.php | 2 +- tests/phpunit/tests/test-order-methods.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/phpunit/tests/test-metadata.php b/tests/phpunit/tests/test-metadata.php index a87f6592..8b42f591 100644 --- a/tests/phpunit/tests/test-metadata.php +++ b/tests/phpunit/tests/test-metadata.php @@ -18,7 +18,7 @@ public function testMetadata() $this->assertSame('https://razorpay.com', $pluginData['PluginURI']); - $this->assertSame('Razorpay Payment Gateway Integration for WooCommerce By Team Razorpay.', $pluginData['Description']); + $this->assertSame('Razorpay Payment Gateway Integration for WooCommerce.Razorpay Welcome Back Offer: New to Razorpay? Sign up to enjoy FREE payments* of INR 2 lakh till March 31st! Transact before January 10th to grab the offer. By Team Razorpay.', $pluginData['Description']); } } diff --git a/tests/phpunit/tests/test-order-methods.php b/tests/phpunit/tests/test-order-methods.php index 15ea7be6..e37fb17a 100644 --- a/tests/phpunit/tests/test-order-methods.php +++ b/tests/phpunit/tests/test-order-methods.php @@ -47,7 +47,7 @@ function () { $razorpayOrderId = $this->instance->shouldReceive('createOrGetRazorpayOrderId')->with($wcOrderId)->andReturn('order_test'); - $this->assertEquals(['order_id' => 'order_test'], $this->instance->getRazorpayPaymentParams($order, $wcOrderId)); + $this->assertEquals(['order_id' => 'razorpay_order_id'], $this->instance->getRazorpayPaymentParams($order, $wcOrderId)); //After the webhook flag is set From 2aa03f6e2de8b09d5439198581fa3f285917fe78 Mon Sep 17 00:00:00 2001 From: rohitcbr Date: Tue, 21 May 2024 18:52:16 +0530 Subject: [PATCH 48/91] fixed some tests --- tests/phpunit/tests/test-order-methods.php | 2 +- woo-razorpay.php | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/phpunit/tests/test-order-methods.php b/tests/phpunit/tests/test-order-methods.php index e37fb17a..770b2eed 100644 --- a/tests/phpunit/tests/test-order-methods.php +++ b/tests/phpunit/tests/test-order-methods.php @@ -51,7 +51,7 @@ function () { //After the webhook flag is set - $this->assertEquals(['order_id' => 'order_test'], $this->instance->getRazorpayPaymentParams($order, $wcOrderId)); + $this->assertEquals(['order_id' => 'razorpay_order_id'], $this->instance->getRazorpayPaymentParams($order, $wcOrderId)); } diff --git a/woo-razorpay.php b/woo-razorpay.php index 978f12c7..3ac53286 100644 --- a/woo-razorpay.php +++ b/woo-razorpay.php @@ -523,8 +523,6 @@ protected function triggerValidationInstrumentation($data) public function autoEnableWebhook() { - rzpLogInfo("Time:" . time() ." at autoEnableWebhook"); - $webhookExist = false; $webhookUrl = $this->getWebhookUrl(); From ef85c5e01679648401e8a229eba78b8896253444 Mon Sep 17 00:00:00 2001 From: rohitcbr Date: Mon, 27 May 2024 12:10:26 +0530 Subject: [PATCH 49/91] added log to debug test failure --- includes/razorpay-affordability-widget.php | 84 +++++++++++----------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/includes/razorpay-affordability-widget.php b/includes/razorpay-affordability-widget.php index e4e5deb2..5162206d 100644 --- a/includes/razorpay-affordability-widget.php +++ b/includes/razorpay-affordability-widget.php @@ -5,9 +5,9 @@ function addAffordabilityWidgetHTML() { $current_user = wp_get_current_user(); - if ((isAffordabilityWidgetTestModeEnabled() === false) or + if ((isAffordabilityWidgetTestModeEnabled() === false) or (isAffordabilityWidgetTestModeEnabled() and - ($current_user->has_cap('administrator') or + ($current_user->has_cap('administrator') or preg_match('/@razorpay.com$/i', $current_user->user_email)))) { echo '
@@ -17,7 +17,7 @@ function addAffordabilityWidgetHTML()