PluginProbe ʕ •ᴥ•ʔ
Razorpay for WooCommerce / trunk
Razorpay for WooCommerce vtrunk
4.8.6 4.8.5 4.8.4 trunk 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.5.0 1.5.1 1.5.2 1.5.3 1.6.0 1.6.0-beta 1.6.1 1.6.2 1.6.3 1.6.5 2.0.0 2.0.1 2.1.0 2.2.0 2.3.0 2.3.1 2.3.2 2.4.0 2.4.1 2.4.2 2.4.3 2.5.0 2.6.0 2.7.0 2.7.1 2.7.2 2.8.0 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 3.0.0 3.0.1 3.1.0 3.1.1 3.2.0 3.2.1 3.2.2 3.3.0 3.4.0 3.4.1 3.5.0 3.5.1 3.6.0 3.7.0 3.7.1 3.7.2 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.0.1 4.1.0 4.2.0 4.3.0 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.4.0 4.4.1 4.4.2 4.4.3 4.5.0 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.5.6 4.5.7 4.5.8 4.5.9 4.6.0 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.6.6 4.6.7 4.6.8 4.6.9 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.7.5 4.7.6 4.7.7 4.7.8 4.7.9 4.8.0 4.8.1 4.8.2 4.8.3
woo-razorpay / includes / api / order.php
woo-razorpay / includes / api Last commit date
api.php 2 months ago auth.php 5 months ago cart.php 5 months ago coupon-apply.php 5 months ago coupon-get.php 5 months ago giftcard-apply.php 11 months ago order.php 7 months ago prepay-cod.php 2 months ago save-abandonment-data.php 11 months ago shipping-info.php 11 months ago
order.php
378 lines
1 <?php
2
3 /**
4 * create order with status pending
5 * user, adddress, coupon and shipping are left blank
6 */
7 use Automattic\WooCommerce\Utilities\OrderUtil;
8
9 function createWcOrder(WP_REST_Request $request)
10 {
11 try
12 {
13 rzpLogInfo("createWcOrder");
14 global $woocommerce;
15 $params = $request->get_params();
16 $logObj = array();
17 $logObj['api'] = 'createWcOrder';
18 $logObj['params'] = $params;
19
20 // fetching wp_woocommerce_session_ from cookies
21 $sessionVal = array_filter($params['cookies'], function($key) {
22 return strpos($key, 'wp_woocommerce_session_') === 0;
23 }, ARRAY_FILTER_USE_KEY);
24
25 foreach($sessionVal as $key => $value){
26 $expKey = explode('wp_woocommerce_session_', $key);
27 $sessionResult = $expKey[1];
28 }
29
30 //Abandoment cart plugin decode the coupon code from token
31 $couponCode = null;
32 if (isset($params['token'])) {
33 $token = sanitize_text_field($params['token']);
34 parse_str(base64_decode(urldecode($token)), $token);
35 if (is_array($token) && array_key_exists('wcf_session_id', $token) && isset($token['wcf_coupon_code'])) {
36 $couponCode = $token['wcf_coupon_code'];
37 }
38 }
39
40 $nonce = $request->get_header('X-WP-Nonce');
41 $verifyReq = wp_verify_nonce($nonce, 'wp_rest');
42
43 if ($verifyReq === false) {
44 $response['status'] = false;
45 $response['message'] = 'Authentication failed';
46
47 $statusCode = 401;
48 $logObj['status_code'] = $statusCode;
49 $logObj['response'] = $response;
50 rzpLogError(json_encode($logObj));
51
52 return new WP_REST_Response($response, $statusCode);
53 }
54
55 initCartCommon();
56
57 // check if cart is empty
58 checkCartEmpty($logObj);
59
60 $cartHash = WC()->cart->get_cart_hash();
61 $hash = $sessionResult."_".$cartHash;
62 //Setting the $orderIdFromHash to null, to create a fresh RZP order for each checkout initialisation.
63 //In future if we need to revert back to earlier flow then consider it from transient as mentioned below.
64 // $orderIdFromHash = get_transient(RZP_1CC_CART_HASH . $hash);
65 $orderIdFromHash = null;
66
67 if (isHposEnabled()) {
68 $updateOrderStatus = 'checkout-draft';
69 } else {
70 // Check if WooCommerce supports the "checkout-draft" status (added in newer versions).
71 $postStatus = get_post_status_object('wc-checkout-draft');
72 if ($postStatus) {
73 $updateOrderStatus = 'checkout-draft';
74 } else {
75 $updateOrderStatus = 'draft'; // Older WooCommerce versions fallback
76 }
77 }
78
79 if ($orderIdFromHash == null) {
80 $checkout = WC()->checkout();
81 $orderId = $checkout->create_order(array());
82
83 if (is_wp_error($orderId) || empty($orderId)) {
84 $checkout_error = is_wp_error($orderId) ? $orderId->get_error_message() : "Invalid order ID returned";
85 rzpLogError("WooCommerce Order Creation Failed: " . $checkout_error);
86
87 $response = [
88 'status' => false,
89 'message' => "Unable to create WooCommerce order: " . $checkout_error,
90 'code' => 'ORDER_CREATION_FAILED',
91 ];
92 $status = 500;
93
94 return new WP_REST_Response($response, $status);
95 }
96 //Keep order in draft status untill customer info available
97 updateOrderStatus($orderId, $updateOrderStatus);
98 } else {
99 $existingOrder = wc_get_order($orderIdFromHash);
100 $orderStatus = $existingOrder->get_status();
101 $existingOrder->calculate_totals();
102 if ($orderStatus != $updateOrderStatus && $existingOrder->needs_payment() == false) {
103 $woocommerce->session->__unset(RZP_1CC_CART_HASH . $cartHash);
104 $checkout = WC()->checkout();
105 $orderId = $checkout->create_order(array());
106
107 if (is_wp_error($orderId) || empty($orderId)) {
108 $checkout_error = is_wp_error($orderId) ? $orderId->get_error_message() : "Invalid order ID returned";
109 rzpLogError("WooCommerce Order Creation Failed: " . $checkout_error);
110
111 $response = [
112 'status' => false,
113 'message' => "Unable to create WooCommerce order: " . $checkout_error,
114 'code' => 'ORDER_CREATION_FAILED',
115 ];
116 $status = 500;
117
118 return new WP_REST_Response($response, $status);
119 }
120 //Keep order in draft status untill customer info available
121 updateOrderStatus($orderId, $updateOrderStatus);
122 } else {
123 $orderId = $orderIdFromHash;
124 //To get the applied coupon details from cart object.
125 $coupons = WC()->cart->get_coupons();
126 $couponCode = !empty($coupons) ? array_key_first($coupons) : null;
127 }
128 }
129
130 $order = wc_get_order($orderId);
131
132 if($order){
133
134 $disableCouponFlag = false;
135
136 // Woo dynamic discount price plugin
137 if(is_plugin_active('yith-woocommerce-dynamic-pricing-and-discounts-premium/init.php')) {
138 foreach ($order->get_items() as $itemId => $item) {
139 $dynamicRules = $item->get_meta('_ywdpd_discounts');
140
141 if(empty($dynamicRules) == false){
142
143 foreach ($dynamicRules['applied_discounts'] as $appliedDiscount) {
144 if (isset( $appliedDiscount['set_id'])){
145 $ruleId = $appliedDiscount['set_id'];
146 $rule = ywdpd_get_rule($ruleId);
147 } else {
148 $rule = $appliedDiscount['by'];
149 }
150 // check coupon is disable with discount price
151 if($rule->is_disabled_with_other_coupon() == 1){
152 $disableCouponFlag = true;
153 }
154 }
155 }
156 }
157 }
158
159 // Pixel your site PRO UTM data
160 if (is_plugin_active('pixelyoursite-pro/pixelyoursite-pro.php')) {
161
162 $pysData = get_option('pys_core');
163
164 // Store UTM data only if config enabled.
165 if ($pysData['woo_enabled_save_data_to_orders'] == true) {
166 wooSaveCheckoutUTMFields($order, $params);
167 }
168 }
169
170 // To remove coupon added on order.
171 $coupons = $order->get_coupon_codes();
172 if (!empty($coupons)) {
173 foreach ($coupons as $coupon) {
174 $order->remove_coupon($coupon);
175 }
176 $couponCode = $coupons[0];
177 }
178
179 //To remove by default shipping method added on order.
180 $items = (array) $order->get_items('shipping');
181
182 if (sizeof($items) > 0) {
183 // Loop through shipping items
184 foreach ($items as $item_id => $item) {
185 $order->remove_item($item_id);
186 }
187 }
188
189 $order->calculate_totals();
190
191 if (isHposEnabled()) {
192 $order->update_meta_data( 'is_magic_checkout_order', 'yes' );
193 $order->save();
194 }else{
195 update_post_meta($orderId, 'is_magic_checkout_order', 'yes');
196 }
197
198 $minCartAmount1cc = !empty(get_option('woocommerce_razorpay_settings')['1cc_min_cart_amount']) ? get_option('woocommerce_razorpay_settings')['1cc_min_cart_amount'] : 0;
199
200 // Response sent to the user when order creation fails
201 if ($order->get_total() < $minCartAmount1cc) {
202 $response['status'] = false;
203 $response['message'] = 'Your current order total is ₹' . $order->get_total() . ' — you must have an order with a minimum of ₹' . $minCartAmount1cc . ' to place your order';
204 $response['code'] = 'MIN_CART_AMOUNT_CHECK_FAILED';
205
206 $status = 400;
207 $logObj['response'] = $response;
208 $logObj['rzp_order_id'] = $rzp_order_id;
209 $logObj['rzp_response'] = $rzp_response;
210 rzpLogError(json_encode($logObj));
211
212 return new WP_REST_Response($response, $status);
213 }
214
215 $razorpay = new WC_Razorpay(false);
216
217 $rzp_order_id = $razorpay->createOrGetRazorpayOrderId($order, $orderId, 'yes');
218 $rzp_response = $razorpay->getDefaultCheckoutArguments($order);
219
220 // Response sent to the user when order creation fails
221 if (empty($rzp_response['order_id'])) {
222 $response['status'] = false;
223 $response['message'] = 'Unable to create order';
224 $response['code'] = 'ORDER_CREATION_FAILED';
225
226 $status = 400;
227 $logObj['response'] = $response;
228 $logObj['rzp_order_id'] = $rzp_order_id;
229 $logObj['rzp_response'] = $rzp_response;
230 rzpLogError(json_encode($logObj));
231
232 $trackObject = $razorpay->newTrackPluginInstrumentation();
233 $properties = [
234 'error' => 'Unable to create order',
235 'log' => $logObj
236 ];
237 $trackObject->rzpTrackDataLake('razorpay.1cc.create.order.failed', $properties);
238
239 return new WP_REST_Response($response, $status);
240 }
241
242 // TODO: getDefaultCheckoutArguments() is already being called in L65 above
243 $response = $razorpay->getDefaultCheckoutArguments($order);
244
245 $fbAnalytics = get_option('woocommerce_razorpay_settings')['enable_1cc_fb_analytics'] === 'yes' ? true : false;
246
247
248 if($disableCouponFlag == true){
249 $response['show_coupons'] = false;
250 }
251
252 if ($fbAnalytics === true) {
253 //Customer cart related data for FB analytics.
254 $customer_cart['value'] = (string) WC()->cart->subtotal;
255 $customer_cart['content_type'] = 'product';
256 $customer_cart['currency'] = 'INR';
257
258 $x = 0;
259 // Loop over $cart items
260 foreach (WC()->cart->get_cart() as $cart_item) {
261
262 $customer_cart['contents'][$x]['id'] = (string) $cart_item['product_id'];
263 $customer_cart['contents'][$x]['name'] = $cart_item['data']->get_title();
264 $customer_cart['contents'][$x]['quantity'] = (string) $cart_item['quantity'];
265 $customer_cart['contents'][$x]['value'] = (string) ($cart_item['line_subtotal'] + $cart_item['line_subtotal_tax']) / $cart_item['quantity'];
266 $customer_cart['contents'][$x]['variant_id'] = (string) $cart_item['variation_id'];
267
268 $x++;
269 }
270
271 $response['customer_cart'] = $customer_cart ?? '';
272 }
273
274 $hash = $sessionResult."_".$cartHash;
275 $woocommerce->session->set(RZP_1CC_CART_HASH . $hash, $orderId);
276 set_transient(RZP_1CC_CART_HASH . $orderId, $hash, 14400);
277 set_transient(RZP_1CC_CART_HASH . $hash, $orderId, 14400);
278 set_transient($razorpay::SESSION_KEY, $orderId, 14400);
279
280 $logObj['response'] = $response;
281 rzpLogInfo(json_encode($logObj));
282
283 return new WP_REST_Response($response, 200);
284 } else {
285 $response['status'] = false;
286 $response['message'] = $checkout_error;
287 $response['code'] = 'WOOCOMMERCE_ORDER_CREATION_FAILED';
288
289 $logObj['response'] = $response;
290 $logObj['status_code'] = 400;
291 rzpLogError(json_encode($logObj));
292
293 $rzp = new WC_Razorpay();
294 $trackObject = $rzp->newTrackPluginInstrumentation();
295 $properties = [
296 'error' => $checkout_error,
297 'log' => $logObj
298 ];
299 $trackObject->rzpTrackDataLake('razorpay.1cc.create.woocommerce.order.failed', $properties);
300
301 return new WP_REST_Response($response, 400);
302 }
303 }
304 catch (Throwable $e)
305 {
306 $rzp = new WC_Razorpay();
307 $trackObject = $rzp->newTrackPluginInstrumentation();
308 $properties = [
309 'error' => $e->getMessage(),
310 'code' => $e->getCode(),
311 'file' => $e->getFile(),
312 'line' => $e->getLine()
313 ];
314 $trackObject->rzpTrackDataLake('razorpay.1cc.create.order.processing.failed', $properties);
315 rzpLogError(json_encode($properties));
316
317 return new WP_REST_Response(['message' => "woocommerce server error : " . $e->getMessage()], 500);
318 }
319 }
320
321 //Update order status according to the steps.
322 function updateOrderStatus($orderId, $orderStatus)
323 {
324 $order = wc_get_order( $orderId );
325
326 if (is_object($order) === false) {
327 return;
328 }
329
330 if (isHposEnabled()) {
331 $order->update_status($orderStatus);
332 $order->save();
333 }else{
334 // Handling order status update for WooCommerce versions that do not support HPOS.
335 // We are unsure if older versions use `wp_update_post()`, while newer versions may use `$order->update_status()`.
336 // To maintain compatibility across different WooCommerce versions, we add an additional if-else condition.
337 if (!isHposEnabled()) { // Explicitly checking if HPOS is NOT enabled
338 $order->update_status($orderStatus);
339 $order->save(); // Save changes
340 } else {
341 wp_update_post([
342 'ID' => $orderId,
343 'post_status' => $orderStatus,
344 ]);
345 }
346 }
347
348 }
349
350 function wooSaveCheckoutUTMFields($order, $params)
351 {
352 $pysData = [];
353 $cookieData = $params['cookies'];
354 $getQuery = $params['requestData'];
355 $browserTime = $params['dateTime'];
356 $pysData['pys_landing'] = isset($cookieData['pys_landing_page']) ? ($cookieData['pys_landing_page']) : "";
357 $pysData['pys_source'] = isset($cookieData['pysTrafficSource']) ? ($cookieData['pysTrafficSource']) : "direct";
358 if ($pysData['pys_source'] == 'direct') {
359 $pysData['pys_source'] = $params['referrerDomain'] != '' ? $params['referrerDomain'] : "direct";
360 }
361 $pysUTMSource = $cookieData['pys_utm_source'] ?? $getQuery['utm_source'];
362 $pysUTMMedium = $cookieData['pys_utm_medium'] ?? $getQuery['utm_medium'];
363 $pysUTMCampaign = $cookieData['pys_utm_campaign'] ?? $getQuery['utm_medium'];
364 $pysUTMTerm = $cookieData['pys_utm_term'] ?? $getQuery['utm_term'];
365 $pysUTMContent = $cookieData['pys_utm_content'] ?? $getQuery['utm_content'];
366
367 $pysData['pys_utm'] = "utm_source:" . $pysUTMSource . "|utm_medium:" . $pysUTMMedium . "|utm_campaign:" . $pysUTMCampaign . "|utm_term:" . $pysUTMTerm . "|utm_content:" . $pysUTMContent;
368 $pysData['pys_browser_time'] = $browserTime[0] . "|" . $browserTime[1] . "|" . $browserTime[2];
369
370 if (isHposEnabled()) {
371 $order->update_meta_data( 'pys_enrich_data', $pysData );
372 $order->save();
373 }else{
374 update_post_meta($order->get_id(), "pys_enrich_data", $pysData);
375 }
376
377 }
378