Plugin Directory

Changeset 3436262


Ignore:
Timestamp:
01/09/2026 07:37:19 PM (2 months ago)
Author:
razorpay
Message:

Update: 4.7.9

Location:
woo-razorpay/trunk
Files:
1 added
10 edited

Legend:

Unmodified
Added
Removed
  • woo-razorpay/trunk/includes/api/api.php

    r3002146 r3436262  
    3737            'methods'             => 'POST',
    3838            'callback'            => 'getCouponList',
    39             'permission_callback' => 'checkAuthCredentials',
     39            'permission_callback' => 'checkHmacSignature',
    4040        )
    4141    );
  • woo-razorpay/trunk/includes/api/auth.php

    r2687215 r3436262  
    55 */
    66
     7require_once __DIR__ . '/../../razorpay-sdk/Razorpay.php';
     8use Razorpay\Api\Errors;
     9
    710function checkAuthCredentials()
    811{
     
    1013}
    1114
     15/**
     16 * Validate HMAC signature using Razorpay Webhook Secret.
     17 * Expects header 'X-Razorpay-Signature' computed over raw request body with HMAC-SHA256.
     18 *
     19 * @param WP_REST_Request $request
     20 * @return bool|WP_Error
     21 */
     22function checkHmacSignature($request)
     23{
     24    $signature = '';
     25    if (isset($_SERVER['HTTP_X_RAZORPAY_SIGNATURE']))
     26    {
     27        $signature = sanitize_text_field($_SERVER['HTTP_X_RAZORPAY_SIGNATURE']);
     28    }
     29
     30    if (empty($signature))
     31    {
     32        return new WP_Error('rest_forbidden', __('Signature missing'), array('status' => 403));
     33    }
     34
     35    $payload = file_get_contents('php://input');
     36
     37    // Retrieve 1CC signing HMAC secret saved at plugin load time
     38    $secret = get_option('rzp1cc_hmac_secret');
     39
     40    if (empty($secret))
     41    {
     42        return new WP_Error('rest_forbidden', __('Secret not configured'), array('status' => 403));
     43    }
     44
     45    // Verify using Razorpay SDK (same as webhook)
     46    try
     47    {
     48        $rzp = new WC_Razorpay(false);
     49        $api = $rzp->getRazorpayApiInstance();
     50        $api->utility->verifySignature($payload, $signature, $secret);
     51    }
     52    catch (Errors\SignatureVerificationError $e)
     53    {
     54        return new WP_Error('rest_forbidden', __('Invalid signature'), array('status' => 403));
     55    }
     56
     57    return true;
     58}
     59
    1260?>
  • woo-razorpay/trunk/includes/api/cart.php

    r3324918 r3436262  
    206206        $type = "e-commerce";
    207207        $productDetails = $product->get_data();
    208 
     208        $sku          = $product->get_sku();
     209        $productImage = $product->get_image_id()?? null;
     210
     211        // If variation exists, use its image and SKU instead of parent product
     212        if (!empty($item['variation_id'])) {
     213            $variation_id = (int) $item['variation_id'];
     214            $variation = wc_get_product( $variation_id );
     215            if ( $variation && $variation->is_type( 'variation' ) ) {
     216                $productImage = $variation->get_image_id();
     217                $sku          = $variation->get_sku() ?: $sku;
     218            }
     219        }
    209220       // check product type for gift card plugin
    210221       if(is_plugin_active('pw-woocommerce-gift-cards/pw-gift-cards.php') || is_plugin_active('yith-woocommerce-gift-cards/init.php')){
     
    226237
    227238       $data[$i]['type'] = $type;
    228        $data[$i]['sku'] = $product->get_sku();
     239       $data[$i]['sku']  = $sku;
    229240       $data[$i]['quantity'] = $item['quantity'];
    230241       $data[$i]['name'] = mb_substr($product->get_title(), 0, 125, "UTF-8");
    231242       $data[$i]['description'] = mb_substr($product->get_title(), 0, 250,"UTF-8");
    232        $productImage = $product->get_image_id()?? null;
    233243       $data[$i]['product_id'] = $item['product_id'];
    234        $data[$i]['image_url'] = $productImage? wp_get_attachment_url( $productImage ) : null;
     244       $data[$i]['image_url']  = $productImage? wp_get_attachment_url( $productImage ) : null;
    235245       $data[$i]['product_url'] = $product->get_permalink();
    236246       $data[$i]['price'] = (empty($productDetails['price']) === false) ? (int)$productDetails['price'] * 100 / $item['quantity'] : 0;
  • woo-razorpay/trunk/includes/api/coupon-apply.php

    r3324918 r3436262  
    44 * for coupon related API
    55 */
     6require_once __DIR__.'/../support/smart-coupons.php';
    67
    78function applyCouponOnCart(WP_REST_Request $request)
     
    4748        initCustomerSessionAndCart();
    4849
    49         // Set current user for smart coupon plugin
    5050        if (is_plugin_active('wt-smart-coupons-for-woocommerce/wt-smart-coupon.php')) {
     51            // Set current user for smart coupon plugin
    5152            if (empty($email) === false) {
    5253                $user = get_user_by('email', $email);
    5354                wp_set_current_user($user->id);
    5455            }
     56
     57            // Apply Smart Coupon if allowed for selected payment method (e.g., Razorpay)
     58            try
     59            {
     60                smartCouponPaymentRestriction($couponCode);
     61            }
     62            catch ( Throwable $e )
     63            {
     64                rzpLogError('Smart Coupon restricted by payment method  : ' . $e->getMessage());
     65            }
    5566        }
    5667
  • woo-razorpay/trunk/includes/api/coupon-get.php

    r3324918 r3436262  
    4848            ];
    4949            $trackObject->rzpTrackDataLake('razorpay.1cc.get.coupons.validation.error', $properties);
     50            return new WP_REST_Response($response, $statusCode);
     51        }
     52
     53        // Allow listing coupons only if order still requires payment
     54        if ($order->needs_payment() === false)
     55        {
     56            $response['failure_reason'] = 'Order not eligible for coupons';
     57            $response['failure_code']   = 'INVALID_STATE';
     58            $statusCode                 = 403;
     59
    5060            return new WP_REST_Response($response, $statusCode);
    5161        }
  • woo-razorpay/trunk/includes/razorpay-webhook.php

    r3331331 r3436262  
    154154                        $webhookFilteredData = [
    155155                            'invoice_id'                => $data['payload']['payment']['entity']['invoice_id'],
    156                             'woocommerce_order_id'  => $data['payload']['payment']['entity']['notes']['woocommerce_order_id'],
     156                            'woocommerce_order_id'      => $data['payload']['payment']['entity']['notes']['woocommerce_order_id'],
    157157                            'razorpay_payment_id'       => $data['payload']['payment']['entity']['id'],
    158158                            'event'                     => $data['event']
     
    296296        }
    297297
    298         //
    299         // Order entity should be sent as part of the webhook payload
    300         //
     298        if (empty($data['woocommerce_order_id'])) {
     299            rzpLogInfo("woocommerce_order_id not found in data:" . json_encode($data));
     300            return;
     301        }
     302
    301303        $orderId = $data['woocommerce_order_id'];
    302304
    303         rzpLogInfo("Woocommerce orderId: $orderId, webhook process intitiated for payment authorized event by cron");
    304 
    305         if (!empty($orderId)) {
    306             $order = $this->checkIsObject($orderId);
    307 
    308             if ($order === false)
    309             {
    310                 return;
    311             }
     305        rzpLogInfo("Woocommerce orderId: $orderId, webhook process initiated for payment authorized event by cron");
     306
     307
     308        $order = $this->checkIsObject($orderId);
     309        if ($order === false)
     310        {
     311            return;
    312312        }
    313313
  • woo-razorpay/trunk/readme.txt

    r3388904 r3436262  
    33Tags: razorpay, payments, india, woocommerce, curlec, malaysia, ecommerce, international, cross border
    44Requires at least: 3.9.2
    5 Tested up to: 6.8
    6 Stable tag: 4.7.8
     5Tested up to: 6.9
     6Stable tag: 4.7.9
    77Requires PHP: 7.0
    88License: GPLv2 or later
     
    6969
    7070== Changelog ==
     71
     72= 4.7.9 =
     73* Security Enhancement.
    7174
    7275= 4.7.8 =
  • woo-razorpay/trunk/tests/phpunit/tests/test-instrumentation.php

    r3100300 r3436262  
    257257        $this->assertNotNull($response['platform_version']);
    258258        $this->assertNotNull($response['woocommerce_version']);
    259         $this->assertSame('1 Razorpay: Signup for FREE PG', $response['plugin_name']);
     259        $this->assertSame('1 Razorpay', $response['plugin_name']);
    260260        $this->assertNotNull($response['plugin_version']);
    261261        $this->assertNotNull($response['unique_id']);
  • woo-razorpay/trunk/tests/phpunit/tests/test-metadata.php

    r3100300 r3436262  
    77        $pluginData = get_plugin_data(PLUGIN_DIR . '/woo-razorpay.php');
    88
    9         $this->assertSame('1 Razorpay: Signup for FREE PG', $pluginData['Name']);
     9        $this->assertSame('1 Razorpay', $pluginData['Name']);
    1010
    1111        $version = $pluginData['Version'];
  • woo-razorpay/trunk/woo-razorpay.php

    r3388904 r3436262  
    11<?php
    22/*
    3  * Plugin Name: 1 Razorpay: Signup for FREE PG
     3 * Plugin Name: 1 Razorpay
    44 * Plugin URI: https://razorpay.com
    55 * 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.
    6  * Version: 4.7.8
    7  * Stable tag: 4.7.8
     6 * Version: 4.7.9
     7 * Stable tag: 4.7.9
    88 * Author: Team Razorpay
    99 * WC tested up to: 10.3.4
     
    3535require_once __DIR__.'/includes/cron/plugin-fetch.php';
    3636require_once ABSPATH . '/wp-admin/includes/upgrade.php';
     37require_once __DIR__.'/includes/support/smart-coupons.php';
    3738
    3839use Razorpay\Api\Api;
     
    8081        );
    8182    }
     83}
     84
     85/**
     86 * Ensure 1CC signing secret is present and in sync with current keys.
     87 * - If rzp1cc_hmac_secret is missing or key_id changed, generate and register it via internal API.
     88 */
     89add_action('plugins_loaded', 'rzpWcEnsure1ccSecret', 20);
     90
     91function rzpWcEnsure1ccSecret()
     92{
     93    // Only act when Magic Checkout is enabled
     94    if (!(function_exists('is1ccEnabled') && is1ccEnabled()))
     95    {
     96        return;
     97    }
     98
     99    // Refresh secret if key_id changed since last run OR if secret is missing
     100    $settings     = get_option('woocommerce_razorpay_settings');
     101    $settings     = (is_array($settings)) ? $settings : array();
     102    $currentKeyId = isset($settings['key_id']) ? $settings['key_id'] : '';
     103    $lastKeyId    = get_option('rzp_wc_last_key_id');
     104    $existingSecret = get_option('rzp1cc_hmac_secret');
     105
     106    $hasKeyChanged   = (!empty($currentKeyId) && $currentKeyId !== $lastKeyId);
     107    $isSecretMissing = empty($existingSecret);
     108
     109    if ($hasKeyChanged || $isSecretMissing)
     110    {
     111        // Short-lived lock to avoid concurrent duplicate registrations across rapid requests
     112        $lockKey = 'rzp_wc_ensure_1cc_secret_lock';
     113        if (get_transient($lockKey))
     114        {
     115            return;
     116        }
     117        // hold for 30s to coalesce bursts; will be deleted on completion
     118        set_transient($lockKey, 1, 30);
     119
     120        $secretUpdated = false;
     121        try
     122        {
     123            // Validate credentials once to avoid internal re-fetches
     124            $currentKeySec = isset($settings['key_secret']) ? $settings['key_secret'] : '';
     125            if (empty($currentKeyId) || empty($currentKeySec))
     126            {
     127                // Release the lock before exiting early
     128                delete_transient($lockKey);
     129                return;
     130            }
     131           
     132            $rzp = new WC_Razorpay(false);
     133            $newSecret = $rzp->registerRzp1ccSigningSecret($currentKeyId, $currentKeySec);
     134            if ($newSecret)
     135            {
     136                update_option('rzp1cc_hmac_secret', $newSecret, false);
     137                $secretUpdated = true;
     138                rzpLogInfo("1cc hmac secret is Added/Updated");
     139            }
     140        }
     141        catch (\Exception $e)
     142        {
     143            rzpLogError("Refresh 1cc hmac secret on key change failed: ". $e->getMessage());
     144            // Release the lock on failure as well
     145            delete_transient($lockKey);
     146            return;
     147        }
     148
     149        if ($hasKeyChanged && $secretUpdated === true)
     150        {
     151            // Persist the observed key to detect future changes (add or update; do not autoload)
     152            update_option('rzp_wc_last_key_id', $currentKeyId, 'no');
     153        }
     154        // Release the lock
     155        delete_transient($lockKey);
     156    }
    82157}
    83158
     
    892967        }
    893968
     969        /**
     970         * Register 1CC signing secret with Razorpay internal API using private auth.
     971         * Caller MUST pass credentials; this method will not fetch from settings.
     972         *
     973         * @param string $keyId
     974         * @param string $keySec
     975         * @return string|false The registered secret on success, false otherwise
     976         */
     977        public function registerRzp1ccSigningSecret($keyId, $keySec)
     978        {
     979            // Always generate a new secret for registration
     980            $secret = $this->generateSecret();
     981
     982            $payload = array(
     983                'key_id'   => $keyId,
     984                'platform' => 'woocommerce',
     985                'secret'   => $secret,
     986            );
     987
     988            try
     989            {
     990                $api      = $this->getRazorpayApiInstance($keyId, $keySec);
     991                $response = $api->request->request('POST', 'magic/merchant/auth/secret', $payload);
     992
     993                if (is_array($response) && isset($response['success']) && $response['success'] === true)
     994                {
     995                    return $secret;
     996                }
     997                return false;
     998            }
     999            catch (\Exception $e)
     1000            {
     1001                rzpLogError("Register 1cc signing secret failed: " . $e->getMessage());
     1002                return false;
     1003            }
     1004        }
     1005
    8941006        // showing notice : status of 1cc active / inactive message in admin dashboard
    8951007        function addAdminCheckoutSettingsAlert() {
     
    29843096                $order_item->save();
    29853097            }
     3098
     3099            // Apply Smart Coupon if allowed for selected payment method (e.g., Razorpay)
     3100            if (is_plugin_active('wt-smart-coupons-for-woocommerce/wt-smart-coupon.php')) {
     3101                try
     3102                {
     3103                    smartCouponPaymentRestriction($couponKey);
     3104                }
     3105                catch ( Throwable $e )
     3106                {
     3107                    rzpLogError('Smart Coupon restricted by payment method  : ' . $e->getMessage());
     3108                }
     3109            }
    29863110            // TODO: Test if individual use coupon fails by hardcoding here
    29873111            $isApplied = $order->apply_coupon($couponKey);
Note: See TracChangeset for help on using the changeset viewer.