Plugin Directory

Changeset 3374361


Ignore:
Timestamp:
10/07/2025 12:17:51 PM (6 months ago)
Author:
easypayment
Message:

tags/1.0.7

Location:
payment-gateway-for-phonepe-and-for-woocommerce
Files:
36 added
7 edited

Legend:

Unmodified
Added
Removed
  • payment-gateway-for-phonepe-and-for-woocommerce/trunk/includes/class-pgppw-api.php

    r3325549 r3374361  
    3737        $transient_key = 'pgppw_oauth_token_' . $env;
    3838
    39         // Try from cache
     39        // 1) Try from cache
    4040        $cached_token = get_transient($transient_key);
    41         if ($cached_token && !empty($cached_token['access_token'])) {
     41        if ($cached_token && is_array($cached_token) && !empty($cached_token['access_token'])) {
    4242            return $cached_token;
    4343        }
    4444
    45         // Token not found or expired — request a new one
    46         $url = $this->authUrl . '/v1/oauth/token';
     45        // 2) Request a new token
     46        $url = trailingslashit($this->authUrl) . 'v1/oauth/token';
    4747        $body = array(
    4848            'client_id' => $this->client_id,
     
    5656                'Content-Type' => 'application/x-www-form-urlencoded',
    5757            ),
    58             'body' => http_build_query($body),
     58            'body' => http_build_query($body, '', '&'),
    5959            'timeout' => 15,
    60                 ));
     60        ));
    6161
    6262        if (is_wp_error($response)) {
    63             return new WP_Error('pgppw_api_error', 'Failed to connect to PhonePe', [
    64                 'error' => $response->get_error_message()
    65             ]);
     63            return new WP_Error('pgppw_api_error', 'Failed to connect to PhonePe', array(
     64                'error' => $response->get_error_message(),
     65            ));
     66        }
     67
     68        $code = wp_remote_retrieve_response_code($response);
     69        $body_raw = wp_remote_retrieve_body($response);
     70        $decoded = json_decode($body_raw, true);
     71
     72        // 3) Non-2xx HTTP response: surface provider details if JSON, else raw body
     73        if ($code < 200 || $code >= 300) {
     74            $provider_code = (is_array($decoded) && isset($decoded['code'])) ? $decoded['code'] : null;
     75            $provider_err = (is_array($decoded) && isset($decoded['errorCode'])) ? $decoded['errorCode'] : null;
     76            $provider_msg = (is_array($decoded) && isset($decoded['message'])) ? $decoded['message'] : 'Invalid response from PhonePe';
     77
     78            return new WP_Error(
     79                    'pgppw_api_error',
     80                    $provider_msg,
     81                    array(
     82                'response_code' => $code,
     83                'provider_code' => $provider_code,
     84                'error_code' => $provider_err,
     85                'response_body' => $body_raw,
     86                    )
     87            );
     88        }
     89
     90        // 4) Must be valid JSON object/array at this point
     91        if (!is_array($decoded)) {
     92            return new WP_Error('pgppw_api_error', 'Invalid or malformed JSON from PhonePe', array(
     93                'response_code' => $code,
     94                'response_body' => $body_raw,
     95                'json_error' => function_exists('json_last_error_msg') ? json_last_error_msg() : 'JSON decode error',
     96            ));
     97        }
     98
     99        // 5) Validate required fields
     100        if (!isset($decoded['access_token']) || !isset($decoded['expires_in'])) {
     101            return new WP_Error('pgppw_api_error', 'Invalid token response from PhonePe', array(
     102                'response_code' => $code,
     103                'response_body' => $body_raw,
     104            ));
     105        }
     106
     107        // 6) Cache with buffered expiry (min 300s)
     108        $expires_in = (int) $decoded['expires_in'];
     109        $ttl = max($expires_in - 600, 300); // buffer 10 min
     110
     111        set_transient($transient_key, $decoded, $ttl);
     112
     113        if (!empty($this->debug)) {
     114            wc_get_logger()->info(
     115                    '[PhonePe Token] New token generated and cached for ' . $ttl . ' seconds.',
     116                    array('source' => 'pgppw_phonepe')
     117            );
     118        }
     119
     120        return $decoded;
     121    }
     122
     123    public function sendRequest($endpoint, $payload = [], $method = 'POST') {
     124        $url = ( stripos($endpoint, 'webhooks') !== false ) ? rtrim($this->webhookUrl, '/') . $endpoint : rtrim($this->baseUrl, '/') . $endpoint;
     125
     126        // --- OAuth token ---
     127        $token_data = $this->get_pgppw_oauth_token();
     128        if (is_wp_error($token_data)) {
     129            $this->log('OAuth Token Error', ['code' => $token_data->get_error_code(), 'msg' => $token_data->get_error_message()]);
     130            return $token_data; // WP_Error
     131        }
     132        if (!is_array($token_data) || empty($token_data['access_token'])) {
     133            $this->log('OAuth Token Missing', ['raw' => $token_data]);
     134            return new WP_Error('pgppw_token_missing', 'OAuth token missing or malformed.');
     135        }
     136
     137        $headers = [
     138            'Content-Type' => 'application/json',
     139            // If your provider uses standard Bearer, change to 'Bearer '.
     140            'Authorization' => 'O-Bearer ' . $token_data['access_token'],
     141        ];
     142
     143        $args = [
     144            'method' => strtoupper($method),
     145            'headers' => $headers,
     146            'timeout' => 30,
     147        ];
     148
     149        if ('POST' === $args['method']) {
     150            $json = wp_json_encode($payload);
     151            if (false === $json) {
     152                $this->log('JSON Encode Failed', ['payload' => $payload]);
     153                return new WP_Error('pgppw_json_encode_failed', 'Failed to encode request payload to JSON.');
     154            }
     155            $args['body'] = $json;
     156        }
     157
     158        $this->log('API Request Sent', [
     159            'url' => $url,
     160            'method' => $args['method'],
     161            'headers' => ['Content-Type' => $headers['Content-Type'], 'Authorization' => '***redacted***'],
     162            'payload' => ( 'POST' === $args['method'] ) ? $payload : 'N/A',
     163        ]);
     164
     165        $response = ( 'POST' === $args['method'] ) ? wp_remote_post($url, $args) : wp_remote_get($url, $args);
     166
     167        if (is_wp_error($response)) {
     168            $this->log('API Request Failed', ['error' => $response->get_error_message()]);
     169            return $response; // WP_Error
    66170        }
    67171
     
    69173        $body = wp_remote_retrieve_body($response);
    70174
    71         if ($code !== 200) {
    72             return new WP_Error('pgppw_api_error', 'Invalid response from PhonePe', [
    73                 'response_code' => $code,
    74                 'response_body' => $body,
    75             ]);
    76         }
    77 
    78         $data = json_decode($body, true);
    79         if (!isset($data['access_token']) || !isset($data['expires_in'])) {
    80             return new WP_Error('pgppw_api_error', 'Invalid token response from PhonePe', ['response' => $body]);
    81         }
    82 
    83         // ✅ Buffer expiry by 10 minutes (600 seconds)
    84         $expires_in = max((int) $data['expires_in'] - 600, 300);
    85         set_transient($transient_key, $data, $expires_in);
    86 
    87         if ($this->debug) {
    88             wc_get_logger()->info('[PhonePe Token] New token generated and cached for ' . $expires_in . ' seconds.', ['source' => 'pgppw_phonepe']);
    89         }
    90 
    91         return $data;
    92     }
    93 
    94     public function sendRequest($endpoint, $payload = [], $method = 'POST') {
    95         if (stripos($endpoint, 'webhooks') !== false) {
    96             $url = $this->webhookUrl . $endpoint;
    97         } else {
    98             $url = $this->baseUrl . $endpoint;
    99         }
    100         $token_data = $this->get_pgppw_oauth_token();
    101         if (is_wp_error($token_data)) {
    102             return $token_data;
    103         }
    104         $auth_token = $token_data['access_token'];
    105         $headers = [
    106             'Content-Type' => 'application/json',
    107             'Authorization' => 'O-Bearer ' . $auth_token,
    108         ];
    109         $args = [
    110             'method' => $method,
    111             'headers' => $headers,
    112             'timeout' => 30,
    113         ];
    114         if ($method === 'POST') {
    115             $args['body'] = json_encode($payload);
    116         } else {
    117             $args['sslverify'] = false;
    118         }
    119         $this->log("API Request Sent", [
    120             'url' => $url,
    121             'method' => $method,
    122             'headers' => $headers,
    123             'payload' => ($method === 'POST') ? $payload : 'N/A',
     175        $decoded = json_decode($body, true);
     176        $this->log('API Response Received', [
     177            'status_code' => $code,
     178            'parsed_json' => $decoded ?? 'Non-JSON response',
    124179        ]);
    125         $response = ($method === 'POST') ? wp_remote_post($url, $args) : wp_remote_get($url, $args);
    126         if (is_wp_error($response)) {
    127             $error = $response->get_error_message();
    128             $this->log("API Request Failed", ['error' => $error]);
    129             return ['error' => $error];
    130         }
    131         $response_code = wp_remote_retrieve_response_code($response);
    132         $response_body = wp_remote_retrieve_body($response);
    133         $response_parsed = json_decode($response_body, true);
    134         $this->log("API Response Received", [
    135             'status_code' => $response_code,
    136             'parsed_json' => $response_parsed ?? 'Non-JSON response',
    137         ]);
    138         if ($this->debug && !$response_parsed) {
    139             $this->log("API Raw Body", [
    140                 'raw_body' => $response_body
    141             ]);
    142         }
    143         return $response_parsed;
     180
     181        if (null === $decoded && JSON_ERROR_NONE !== json_last_error()) {
     182            if (!empty($this->debug)) {
     183                $this->log('API Raw Body', ['raw_body' => $body]);
     184            }
     185            return new WP_Error('pgppw_bad_json', 'Invalid JSON in gateway response.', ['body' => $body, 'status_code' => $code]);
     186        }
     187
     188        // Treat non-2xx as errors; include provider's message if present
     189        if ($code < 200 || $code >= 300) {
     190            $msg = isset($decoded['message']) ? $decoded['message'] : 'HTTP error from gateway.';
     191            return new WP_Error('pgppw_http_' . $code, (string) $msg, ['status_code' => $code, 'response' => $decoded]);
     192        }
     193
     194        return $decoded; // success
    144195    }
    145196
    146197    public function createPaymentRequest($amount, $orderId, $merchantUserId, $redirectUrl, $callbackUrl) {
    147         $this->log("Creating Payment Request", ['order_id' => $orderId]);
     198        $this->log('Creating Payment Request', ['order_id' => $orderId]);
     199
     200        // Convert to minor units safely
     201        $amount_minor = (int) round((float) wc_format_decimal($amount, 2) * 100);
     202
    148203        $payload = [
    149204            'merchantOrderId' => (string) $orderId,
    150             'merchantUserId' => $merchantUserId,
    151             'amount' => intval($amount * 100),
     205            'merchantUserId' => (string) $merchantUserId,
     206            'amount' => $amount_minor,
    152207            'paymentFlow' => [
    153208                'type' => 'PG_CHECKOUT',
     
    155210                'merchantUrls' => [
    156211                    'redirectUrl' => $redirectUrl,
    157                 ]
    158             ]
    159         ];
     212                    // Include callback if your provider expects it here; rename key if needed (e.g., notifyUrl)
     213                    'callbackUrl' => $callbackUrl,
     214                ],
     215            ],
     216        ];
     217
     218        // Bubble up WP_Error directly; success returns decoded array/object
    160219        return $this->sendRequest('/checkout/v2/pay', $payload, 'POST');
    161220    }
  • payment-gateway-for-phonepe-and-for-woocommerce/trunk/includes/class-pgppw-gateway.php

    r3362173 r3374361  
    8383        );
    8484        echo '</p>';
    85         echo '<table class="form-table">' . $this->generate_settings_html($this->get_form_fields(), false) . '</table>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output is safe from WooCommerce Settings API.
     85        echo '<table class="form-table" style="display:none;">' . $this->generate_settings_html($this->get_form_fields(), false) . '</table>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output is safe from WooCommerce Settings API.
    8686    }
    8787
    8888    public function process_admin_options() {
    8989        parent::process_admin_options();
     90        delete_transient('pgppw_oauth_token_live');
     91        delete_transient('pgppw_oauth_token_sandbox');
    9092        $this->init_properties();
    9193        if ($this->is_credentials_set()) {
     
    9395                include_once PGPPW_PLUGIN_DIR . '/includes/class-pgppw-api.php';
    9496            }
    95             $this->api = new PGPPW_API($this->client_id, $this->client_secret, $this->client_version, $this->environment, $this->log_enabled);
    96             /* if (!class_exists('PGPPW_Webhook')) {
    97               include_once PGPPW_PLUGIN_DIR . '/includes/class-pgppw-webhook.php';
    98               } */
    99             //$this->enabled = 'yes';
    100             /* $this->webhook = new PGPPW_Webhook([
    101               'debug' => $this->log_enabled,
    102               'api' => $this->api,
    103               ]);
    104               $this->pgppw_phonepe_create_webhook(); */
     97            $this->api = new PGPPW_API(
     98                    $this->client_id,
     99                    $this->client_secret,
     100                    $this->client_version,
     101                    $this->environment,
     102                    $this->log_enabled
     103            );
    105104        }
    106105    }
     
    124123        $this->form_fields = [
    125124            'section_one' => [
    126                 'title' => __('Step 1: Registration', 'payment-gateway-for-authorize-net-for-woocommerce'),
     125                'title' => __('Step 1: Registration', 'payment-gateway-for-phonepe-and-for-woocommerce'),
    127126                'type' => 'title',
    128127                'class' => 'pgppw-phonepe-collapsible-section'
     
    132131            ),
    133132            'section_two' => [
    134                 'title' => __('Step 2: PhonePe Gateway Settings', 'payment-gateway-for-authorize-net-for-woocommerce'),
     133                'title' => __('Step 2: PhonePe Gateway Settings', 'payment-gateway-for-phonepe-and-for-woocommerce'),
    135134                'type' => 'title',
    136135                'class' => 'pgppw-phonepe-collapsible-section'
     
    174173            'sandbox_client_version' => ['title' => __('Sandbox Client Version', 'payment-gateway-for-phonepe-and-for-woocommerce'), 'type' => 'text'],
    175174            'section_three' => [
    176                 'title' => __('Step 3: Additional Settings', 'payment-gateway-for-authorize-net-for-woocommerce'),
     175                'title' => __('Step 3: Additional Settings', 'payment-gateway-for-phonepe-and-for-woocommerce'),
    177176                'type' => 'title',
    178177                'class' => 'pgppw-phonepe-collapsible-section'
     
    208207
    209208    public function generate_phonepe_signup_banner_html($field_key, $data) {
    210     if (isset($data['type']) && $data['type'] === 'phonepe_signup_banner') {
    211         $field_key = $this->get_field_key($field_key);
    212         ob_start();
    213         ?>
    214         <tr valign="top">
    215             <th scope="row" class="titledesc">
    216                 <label for="<?php echo esc_attr($field_key); ?>">
     209        if (isset($data['type']) && $data['type'] === 'phonepe_signup_banner') {
     210            $field_key = $this->get_field_key($field_key);
     211            ob_start();
     212            ?>
     213            <tr valign="top">
     214                <th scope="row" class="titledesc">
     215                    <label for="<?php echo esc_attr($field_key); ?>">
     216                        <?php
     217                        // Friendlier default title, still clear for fintech users.
     218                        echo esc_html($data['title'] ?? __('Business Registration (Merchant Sign Up)', 'payment-gateway-for-phonepe-and-for-woocommerce'));
     219                        ?>
     220                    </label>
     221                </th>
     222                <td class="forminp" id="<?php echo esc_attr($field_key); ?>">
    217223                    <?php
    218                     // Friendlier default title, still clear for fintech users.
    219                     echo esc_html($data['title'] ?? __('Business Registration (Merchant Sign Up)', 'payment-gateway-for-phonepe-and-for-woocommerce'));
     224                    // Links
     225                    $tracking_url = 'https://easypaymentplugins.com/phonepe-signup'; // Redirect with tracking
     226                    $direct_url = 'https://business.phonepe.com/register?referral-code=RF2502041417463473449057'; // Direct PhonePe
    220227                    ?>
    221                 </label>
    222             </th>
    223             <td class="forminp" id="<?php echo esc_attr($field_key); ?>">
    224                 <?php
    225                 // Links
    226                 $tracking_url = 'https://easypaymentplugins.com/phonepe-signup'; // Redirect with tracking
    227                 $direct_url   = 'https://business.phonepe.com/register?referral-code=RF2502041417463473449057'; // Direct PhonePe
    228                 ?>
    229 
    230                 <div class="pgppw-phonepe-signup-box" role="region" aria-labelledby="<?php echo esc_attr($field_key); ?>-heading">
    231                     <!-- For Business Owners -->
    232                     <h4 id="<?php echo esc_attr($field_key); ?>-heading">
    233                         <span class="dashicons dashicons-businessperson" aria-hidden="true"></span>
    234                         <?php esc_html_e('For Business Owners', 'payment-gateway-for-phonepe-and-for-woocommerce'); ?>
    235                     </h4>
    236                     <p class="description">
    237                         <?php esc_html_e('Sign up your business to start accepting payments with PhonePe.', 'payment-gateway-for-phonepe-and-for-woocommerce'); ?>
    238                     </p>
    239                     <p>
    240                         <button type="button"
    241                                 class="button button-primary pgppw-register-btn"
    242                                 data-url="<?php echo esc_url($tracking_url); ?>"
    243                                 aria-label="<?php esc_attr_e('Sign up with PhonePe', 'payment-gateway-for-phonepe-and-for-woocommerce'); ?>">
    244                             <?php esc_html_e('Sign Up with PhonePe', 'payment-gateway-for-phonepe-and-for-woocommerce'); ?>
    245                         </button>
    246                     </p>
    247 
    248                     <hr />
    249 
    250                     <!-- For Developers -->
    251                     <h4>
    252                         <span class="dashicons dashicons-admin-links" aria-hidden="true"></span>
    253                         <?php esc_html_e('For Developers', 'payment-gateway-for-phonepe-and-for-woocommerce'); ?>
    254                     </h4>
    255                     <p class="description">
    256                         <?php esc_html_e('Share this referral link with your client for easy sign-up.', 'payment-gateway-for-phonepe-and-for-woocommerce'); ?>
    257                     </p>
    258 
    259                     <div class="pgppw-copy-wrap">
    260                        
    261                         <input type="text"
    262                                id="<?php echo esc_attr($field_key); ?>-ref-link"
    263                                class="pgppw-copy-input"
    264                                value="<?php echo esc_attr($direct_url); ?>"
    265                                readonly />
    266                         <button type="button"
    267                                 class="button pgppw-copy-link"
    268                                 data-link="<?php echo esc_attr($direct_url); ?>">
    269                             <?php esc_html_e('Copy Link', 'payment-gateway-for-phonepe-and-for-woocommerce'); ?>
    270                         </button>
     228
     229                    <div class="pgppw-phonepe-signup-box" role="region" aria-labelledby="<?php echo esc_attr($field_key); ?>-heading">
     230                        <!-- For Business Owners -->
     231                        <h4 id="<?php echo esc_attr($field_key); ?>-heading">
     232                            <span class="dashicons dashicons-businessperson" aria-hidden="true"></span>
     233                            <?php esc_html_e('For Business Owners', 'payment-gateway-for-phonepe-and-for-woocommerce'); ?>
     234                        </h4>
     235                        <p class="description">
     236                            <?php esc_html_e('Sign up your business to start accepting payments with PhonePe.', 'payment-gateway-for-phonepe-and-for-woocommerce'); ?>
     237                        </p>
     238                        <p>
     239                            <button type="button"
     240                                    class="button button-primary pgppw-register-btn"
     241                                    data-url="<?php echo esc_url($tracking_url); ?>"
     242                                    aria-label="<?php esc_attr_e('Sign up with PhonePe', 'payment-gateway-for-phonepe-and-for-woocommerce'); ?>">
     243                                        <?php esc_html_e('Sign Up with PhonePe', 'payment-gateway-for-phonepe-and-for-woocommerce'); ?>
     244                            </button>
     245                        </p>
     246
     247                        <hr />
     248
     249                        <!-- For Developers -->
     250                        <h4>
     251                            <span class="dashicons dashicons-admin-links" aria-hidden="true"></span>
     252                            <?php esc_html_e('For Developers', 'payment-gateway-for-phonepe-and-for-woocommerce'); ?>
     253                        </h4>
     254                        <p class="description">
     255                            <?php esc_html_e('Share this referral link with your client for easy sign-up.', 'payment-gateway-for-phonepe-and-for-woocommerce'); ?>
     256                        </p>
     257
     258                        <div class="pgppw-copy-wrap">
     259
     260                            <input type="text"
     261                                   id="<?php echo esc_attr($field_key); ?>-ref-link"
     262                                   class="pgppw-copy-input"
     263                                   value="<?php echo esc_attr($direct_url); ?>"
     264                                   readonly />
     265                            <button type="button"
     266                                    class="button pgppw-copy-link"
     267                                    data-link="<?php echo esc_attr($direct_url); ?>">
     268                                        <?php esc_html_e('Copy Link', 'payment-gateway-for-phonepe-and-for-woocommerce'); ?>
     269                            </button>
     270                        </div>
     271
     272                        <p class="description">
     273                            <?php esc_html_e('This referral link ensures your client’s PhonePe account is automatically linked to this plugin.', 'payment-gateway-for-phonepe-and-for-woocommerce'); ?>
     274                        </p>
    271275                    </div>
    272 
    273                     <p class="description">
    274                         <?php esc_html_e('This referral link ensures your client’s PhonePe account is automatically linked to this plugin.', 'payment-gateway-for-phonepe-and-for-woocommerce'); ?>
    275                     </p>
    276                 </div>
    277             </td>
    278         </tr>
    279         <?php
    280         return ob_get_clean();
    281     }
    282 }
    283 
     276                </td>
     277            </tr>
     278            <?php
     279            return ob_get_clean();
     280        }
     281    }
    284282
    285283    public function process_payment($order_id) {
    286         $order = wc_get_order($order_id);
    287         $amount = $order->get_total();
    288         $merchant_user_id = $order->get_user_id();
    289         $merchantTransactionId = "MT" . time();
    290         $callback_url = add_query_arg(array('pgppw_phonepe_action' => 'payment_callback', 'order_id' => $order_id, 'transactionId' => $merchantTransactionId), WC()->api_request_url('PGPPW_Gateway'));
    291         $redirect_url = add_query_arg(array('pgppw_phonepe_action' => 'process_payment', 'order_id' => $order_id, 'transactionId' => $merchantTransactionId), WC()->api_request_url('PGPPW_Gateway'));
    292         if (!$this->api) {
    293             wc_add_notice(__('Payment gateway error. Please try again later.', 'payment-gateway-for-phonepe-and-for-woocommerce'), 'error');
    294             return;
    295         }
    296         $response = $this->api->createPaymentRequest($amount, $order_id, $merchant_user_id, $redirect_url, $callback_url);
    297         if (!empty($response['redirectUrl']) && isset($response['redirectUrl'])) {
    298             return [
    299                 'result' => 'success',
    300                 'redirect' => esc_url($response['redirectUrl']),
    301             ];
    302         }
    303         wc_add_notice(__('Payment failed: ', 'payment-gateway-for-phonepe-and-for-woocommerce') . esc_html($response['message'] ?? 'Unknown error'), 'error');
    304         return;
     284        try {
     285            $order = wc_get_order($order_id);
     286            if (!$order instanceof WC_Order) {
     287                wc_add_notice(__('Invalid order.', 'payment-gateway-for-phonepe-and-for-woocommerce'), 'error');
     288                return array('result' => 'failure');
     289            }
     290
     291            $amount = (float) $order->get_total();
     292            $merchant_user_id = (int) $order->get_user_id();
     293            $merchantTransactionId = 'MT' . time() . substr($order_id, -2) . wp_rand(100, 999);
     294
     295            $callback_url = add_query_arg(
     296                    array(
     297                        'pgppw_phonepe_action' => 'payment_callback',
     298                        'order_id' => $order_id,
     299                        'transactionId' => $merchantTransactionId,
     300                    ),
     301                    WC()->api_request_url('PGPPW_Gateway')
     302            );
     303
     304            $redirect_url = add_query_arg(
     305                    array(
     306                        'pgppw_phonepe_action' => 'process_payment',
     307                        'order_id' => $order_id,
     308                        'transactionId' => $merchantTransactionId,
     309                    ),
     310                    WC()->api_request_url('PGPPW_Gateway')
     311            );
     312
     313            if (empty($this->api)) {
     314                wc_add_notice(__('Payment gateway error. Please try again later.', 'payment-gateway-for-phonepe-and-for-woocommerce'), 'error');
     315                $order->add_order_note('PGPPW: API client not initialized.');
     316                return array('result' => 'failure');
     317            }
     318
     319            $response = $this->api->createPaymentRequest($amount, $order_id, $merchant_user_id, $redirect_url, $callback_url);
     320
     321            // Handle transport/protocol errors first
     322            if (is_wp_error($response)) {
     323                $msg = $response->get_error_message();
     324                $code = $response->get_error_code();
     325                wc_add_notice(sprintf(__('Payment failed: %s', 'payment-gateway-for-phonepe-and-for-woocommerce'), esc_html($msg)), 'error');
     326                $order->update_status('failed', sprintf('PGPPW WP_Error (%s): %s', $code, $msg));
     327                return array('result' => 'failure');
     328            }
     329
     330            // Normalize (array|object) and read redirect URL/message
     331            $redirect = null;
     332            $message = 'Unknown error';
     333
     334            if (is_array($response)) {
     335                $redirect = $response['redirectUrl'] ?? ( $response['redirect'] ?? null );
     336                $message = $response['message'] ?? $message;
     337            } elseif (is_object($response)) {
     338                $redirect = $response->redirectUrl ?? ( $response->redirect ?? null );
     339                $message = $response->message ?? $message;
     340            }
     341
     342            if (!empty($redirect)) {
     343                // Save txn id for callbacks/reconciliation
     344                $order->update_meta_data('_pgppw_txn_id', $merchantTransactionId);
     345                $order->save();
     346
     347                return array(
     348                    'result' => 'success',
     349                    'redirect' => esc_url_raw($redirect),
     350                );
     351            }
     352
     353            wc_add_notice(
     354                    sprintf(
     355                            __('Payment failed: %s', 'payment-gateway-for-phonepe-and-for-woocommerce'),
     356                            esc_html((string) $message)
     357                    ),
     358                    'error'
     359            );
     360            $order->update_status('failed', 'PGPPW createPaymentRequest returned no redirect URL. Message: ' . (string) $message);
     361            return array('result' => 'failure');
     362        } catch (Throwable $e) {
     363            if (isset($order) && $order instanceof WC_Order) {
     364                $order->update_status('failed', 'PGPPW exception: ' . $e->getMessage());
     365            }
     366            wc_add_notice(__('Unexpected error while processing payment. Please try again.', 'payment-gateway-for-phonepe-and-for-woocommerce'), 'error');
     367            return array('result' => 'failure');
     368        }
    305369    }
    306370
  • payment-gateway-for-phonepe-and-for-woocommerce/trunk/includes/class-pgppw.php

    r3362173 r3374361  
    1111            $this->version = PGPPW_VERSION;
    1212        } else {
    13             $this->version = '1.0.6';
     13            $this->version = '1.0.7';
    1414        }
    1515        $this->plugin_name = 'payment-gateway-for-phonepe-and-for-woocommerce';
  • payment-gateway-for-phonepe-and-for-woocommerce/trunk/payment-gateway-for-phonepe-and-for-woocommerce.php

    r3362173 r3374361  
    66 * Plugin URI:        https://wordpress.org/plugins/payment-gateway-for-phonepe-and-for-woocommerce/
    77 * Description:       Accept payments through UPI, Cards, and Net Banking — developed by an official PhonePe Partner.
    8  * Version:           1.0.6
     8 * Version:           1.0.7
    99 * Author:            Easy Payment
    1010 * Author URI:        https://profiles.wordpress.org/easypayment/
     
    1515 * Requires PHP: 7.4
    1616 * Requires Plugins: woocommerce
    17  * Tested up to: 6.8.2
     17 * Tested up to: 6.8.3
    1818 * WC requires at least: 3.4
    19  * WC tested up to: 10.1.2
     19 * WC tested up to: 10.2.2
    2020 */
    2121// If this file is called directly, abort.
     
    3535}
    3636if (!defined('PGPPW_PLUGIN_VERSION')) {
    37     define('PGPPW_PLUGIN_VERSION', '1.0.6');
     37    define('PGPPW_PLUGIN_VERSION', '1.0.7');
    3838}
    3939
  • payment-gateway-for-phonepe-and-for-woocommerce/trunk/public/css/pgppw.css

    r3354708 r3374361  
    11.wc_pgppw_container {
    2   display: flex;
    3   flex-wrap: wrap;
    4   justify-content: center;
    5   padding: 5px;
     2    display: flex;
     3    flex-wrap: wrap;
     4    justify-content: center;
     5    padding: 5px;
    66}
    77.wc_pgppw_container p {
    8   flex: 1 1 100%;
    9   margin-top: 10px;
    10   text-align: center;
    11   margin-bottom: 10px;
     8    flex: 1 1 100%;
     9    margin-top: 10px !important;
     10    text-align: center;
     11    margin-bottom: 10px !important;
    1212}
    1313.wc_pgppw_container img {
    14   height: 56px;
    15   max-height: 77px;
    16   max-width: 150px;
    17   width: 110px;
     14    height: 56px;
     15    max-height: 77px !important;
     16    max-width: 150px;
     17    width: 110px;
    1818}
    1919#payment .payment_methods li label[for="payment_method_pgppw_phonepe"] img {
    20   margin-left: 8px;
    21   height: 25px;
     20    margin-left: 8px;
     21    height: 25px;
    2222}
    2323.phonepe_checkout_notice {
  • payment-gateway-for-phonepe-and-for-woocommerce/trunk/public/js/pgppw.js

    r3336961 r3374361  
    33        const selectedPaymentMethod = $('input[name="payment_method"]:checked').val();
    44        const currency = pgppw_js.currency_code;
    5         if (selectedPaymentMethod === 'pgppw_phonepe' && currency !== 'INR') {
     5        if ((selectedPaymentMethod === 'pgppw_phonepe' || selectedPaymentMethod === 'easy_razorpay') && currency !== 'INR') {
    66            $('#place_order').hide();
    77        } else {
  • payment-gateway-for-phonepe-and-for-woocommerce/trunk/readme.txt

    r3362173 r3374361  
    44Tags: phonepe, woocommerce, upi, payments 
    55Requires at least: 5.0 
    6 Tested up to: 6.8.2 
     6Tested up to: 6.8.3 
    77Requires PHP: 7.4 
    8 Stable tag: 1.0.6 
     8Stable tag: 1.0.7 
    99License: GPLv2 or later 
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html 
     
    6060
    6161== Changelog == 
     62
     63= 1.0.7 =
     64* Improved: Enhanced logic for better error handling and clearer user messages.
    6265
    6366= 1.0.6 =
Note: See TracChangeset for help on using the changeset viewer.