Changeset 3436262
- Timestamp:
- 01/09/2026 07:37:19 PM (2 months ago)
- Location:
- woo-razorpay/trunk
- Files:
-
- 1 added
- 10 edited
-
includes/api/api.php (modified) (1 diff)
-
includes/api/auth.php (modified) (2 diffs)
-
includes/api/cart.php (modified) (2 diffs)
-
includes/api/coupon-apply.php (modified) (2 diffs)
-
includes/api/coupon-get.php (modified) (1 diff)
-
includes/razorpay-webhook.php (modified) (2 diffs)
-
includes/support/smart-coupons.php (added)
-
readme.txt (modified) (2 diffs)
-
tests/phpunit/tests/test-instrumentation.php (modified) (1 diff)
-
tests/phpunit/tests/test-metadata.php (modified) (1 diff)
-
woo-razorpay.php (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
woo-razorpay/trunk/includes/api/api.php
r3002146 r3436262 37 37 'methods' => 'POST', 38 38 'callback' => 'getCouponList', 39 'permission_callback' => 'check AuthCredentials',39 'permission_callback' => 'checkHmacSignature', 40 40 ) 41 41 ); -
woo-razorpay/trunk/includes/api/auth.php
r2687215 r3436262 5 5 */ 6 6 7 require_once __DIR__ . '/../../razorpay-sdk/Razorpay.php'; 8 use Razorpay\Api\Errors; 9 7 10 function checkAuthCredentials() 8 11 { … … 10 13 } 11 14 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 */ 22 function 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 12 60 ?> -
woo-razorpay/trunk/includes/api/cart.php
r3324918 r3436262 206 206 $type = "e-commerce"; 207 207 $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 } 209 220 // check product type for gift card plugin 210 221 if(is_plugin_active('pw-woocommerce-gift-cards/pw-gift-cards.php') || is_plugin_active('yith-woocommerce-gift-cards/init.php')){ … … 226 237 227 238 $data[$i]['type'] = $type; 228 $data[$i]['sku'] = $product->get_sku();239 $data[$i]['sku'] = $sku; 229 240 $data[$i]['quantity'] = $item['quantity']; 230 241 $data[$i]['name'] = mb_substr($product->get_title(), 0, 125, "UTF-8"); 231 242 $data[$i]['description'] = mb_substr($product->get_title(), 0, 250,"UTF-8"); 232 $productImage = $product->get_image_id()?? null;233 243 $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; 235 245 $data[$i]['product_url'] = $product->get_permalink(); 236 246 $data[$i]['price'] = (empty($productDetails['price']) === false) ? (int)$productDetails['price'] * 100 / $item['quantity'] : 0; -
woo-razorpay/trunk/includes/api/coupon-apply.php
r3324918 r3436262 4 4 * for coupon related API 5 5 */ 6 require_once __DIR__.'/../support/smart-coupons.php'; 6 7 7 8 function applyCouponOnCart(WP_REST_Request $request) … … 47 48 initCustomerSessionAndCart(); 48 49 49 // Set current user for smart coupon plugin50 50 if (is_plugin_active('wt-smart-coupons-for-woocommerce/wt-smart-coupon.php')) { 51 // Set current user for smart coupon plugin 51 52 if (empty($email) === false) { 52 53 $user = get_user_by('email', $email); 53 54 wp_set_current_user($user->id); 54 55 } 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 } 55 66 } 56 67 -
woo-razorpay/trunk/includes/api/coupon-get.php
r3324918 r3436262 48 48 ]; 49 49 $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 50 60 return new WP_REST_Response($response, $statusCode); 51 61 } -
woo-razorpay/trunk/includes/razorpay-webhook.php
r3331331 r3436262 154 154 $webhookFilteredData = [ 155 155 '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'], 157 157 'razorpay_payment_id' => $data['payload']['payment']['entity']['id'], 158 158 'event' => $data['event'] … … 296 296 } 297 297 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 301 303 $orderId = $data['woocommerce_order_id']; 302 304 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; 312 312 } 313 313 -
woo-razorpay/trunk/readme.txt
r3388904 r3436262 3 3 Tags: razorpay, payments, india, woocommerce, curlec, malaysia, ecommerce, international, cross border 4 4 Requires at least: 3.9.2 5 Tested up to: 6. 86 Stable tag: 4.7. 85 Tested up to: 6.9 6 Stable tag: 4.7.9 7 7 Requires PHP: 7.0 8 8 License: GPLv2 or later … … 69 69 70 70 == Changelog == 71 72 = 4.7.9 = 73 * Security Enhancement. 71 74 72 75 = 4.7.8 = -
woo-razorpay/trunk/tests/phpunit/tests/test-instrumentation.php
r3100300 r3436262 257 257 $this->assertNotNull($response['platform_version']); 258 258 $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']); 260 260 $this->assertNotNull($response['plugin_version']); 261 261 $this->assertNotNull($response['unique_id']); -
woo-razorpay/trunk/tests/phpunit/tests/test-metadata.php
r3100300 r3436262 7 7 $pluginData = get_plugin_data(PLUGIN_DIR . '/woo-razorpay.php'); 8 8 9 $this->assertSame('1 Razorpay : Signup for FREE PG', $pluginData['Name']);9 $this->assertSame('1 Razorpay', $pluginData['Name']); 10 10 11 11 $version = $pluginData['Version']; -
woo-razorpay/trunk/woo-razorpay.php
r3388904 r3436262 1 1 <?php 2 2 /* 3 * Plugin Name: 1 Razorpay : Signup for FREE PG3 * Plugin Name: 1 Razorpay 4 4 * Plugin URI: https://razorpay.com 5 5 * 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. 87 * Stable tag: 4.7. 86 * Version: 4.7.9 7 * Stable tag: 4.7.9 8 8 * Author: Team Razorpay 9 9 * WC tested up to: 10.3.4 … … 35 35 require_once __DIR__.'/includes/cron/plugin-fetch.php'; 36 36 require_once ABSPATH . '/wp-admin/includes/upgrade.php'; 37 require_once __DIR__.'/includes/support/smart-coupons.php'; 37 38 38 39 use Razorpay\Api\Api; … … 80 81 ); 81 82 } 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 */ 89 add_action('plugins_loaded', 'rzpWcEnsure1ccSecret', 20); 90 91 function 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 } 82 157 } 83 158 … … 892 967 } 893 968 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 894 1006 // showing notice : status of 1cc active / inactive message in admin dashboard 895 1007 function addAdminCheckoutSettingsAlert() { … … 2984 3096 $order_item->save(); 2985 3097 } 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 } 2986 3110 // TODO: Test if individual use coupon fails by hardcoding here 2987 3111 $isApplied = $order->apply_coupon($couponKey);
Note: See TracChangeset
for help on using the changeset viewer.