Changeset 3445633
- Timestamp:
- 01/23/2026 02:06:19 PM (4 weeks ago)
- Location:
- knit-pay/trunk
- Files:
-
- 2 added
- 9 edited
-
gateways/razorpay/src/Config.php (modified) (1 diff)
-
gateways/razorpay/src/Gateway.php (modified) (3 diffs)
-
gateways/razorpay/src/Integration.php (modified) (3 diffs)
-
gateways/sab-paisa/src/API.php (modified) (4 diffs)
-
gateways/upi-qr/src/Gateway.php (modified) (8 diffs)
-
gateways/upi-qr/src/Integration.php (modified) (9 diffs)
-
images/upi-collect (added)
-
images/upi-collect/icon.svg (added)
-
includes/Utils.php (modified) (3 diffs)
-
knit-pay.php (modified) (1 diff)
-
readme.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
knit-pay/trunk/gateways/razorpay/src/Config.php
r3220363 r3445633 38 38 public $refresh_token; 39 39 40 public $country; 41 40 42 public $company_name; 41 43 -
knit-pay/trunk/gateways/razorpay/src/Gateway.php
r3441509 r3445633 250 250 ]; 251 251 252 if ('sg' === $this->config->country){ 253 $shipping_address = $payment->get_shipping_address(); 254 255 $razorpay_customer = $this->call_api( 'customer', 'create', array( 256 'name' => KnitPayUtils::substr_after_trim( $customer->get_name(), 0, 45 ), 257 'email' => $customer->get_email(), 258 'contact'=>$payment->get_billing_address()->get_phone(), 259 'fail_existing' => false, 260 )); 261 262 $payment->set_meta( 'razorpay_customer_id', $razorpay_customer->id ); 263 $razorpay_order_data['customer_id'] = $razorpay_customer->id; 264 265 $razorpay_order_data['customer_details'] = [ 266 'name' => KnitPayUtils::substr_after_trim( $customer->get_name(), 0, 45 ), 267 'contact' => $payment->get_billing_address()->get_phone(), 268 'email' => $customer->get_email(), 269 'shipping_address' => [ 270 "line1"=> $shipping_address->get_line_1(), 271 "line2"=> $shipping_address->get_line_2(), 272 "city"=> $shipping_address->get_city(), 273 "country"=> 'IN' === $shipping_address->get_country()->get_code()?"IND":"", 274 "state"=> KnitPayUtils::get_state_name($shipping_address->get_region(), $shipping_address->get_country()), 275 "zipcode"=> (string)$shipping_address->get_postal_code(), 276 ] 277 ]; 278 } 279 252 280 $razorpay_order = $this->call_api( 'order', 'create', $razorpay_order_data ); 253 281 $razorpay_order_id = $razorpay_order['id']; … … 482 510 $razorpay_order_id = $payment->get_meta( 'razorpay_order_id' ); 483 511 $razorpay_subscription_id = $payment->get_meta( 'razorpay_subscription_id' ); 512 $razorpay_customer_id = $payment->get_meta( 'razorpay_customer_id' ); 484 513 485 514 $customer = $payment->get_customer(); … … 525 554 ]; 526 555 556 if ('sg' === $this->config->country){ 557 if (!empty($razorpay_customer_id)){ 558 $data['customer_id'] = $razorpay_customer_id; 559 } 560 561 $data['notes'] = [ 562 'invoice_number' => $payment->get_id(), 563 ]; 564 } 565 527 566 if ( ! empty( $razorpay_subscription_id ) ) { 528 567 $data['subscription_id'] = $razorpay_subscription_id; -
knit-pay/trunk/gateways/razorpay/src/Integration.php
r3436834 r3445633 210 210 // TODO: Add support for payment link. 211 211 212 // Country. 213 $fields[] = [ 214 'section' => 'general', 215 'meta_key' => '_pronamic_gateway_razorpay_country', 216 'title' => __( 'Country', 'knit-pay-lang' ), 217 'type' => 'select', 218 'options' => [ 219 'in' => 'India', 220 'sg' => 'Singapore', 221 ], 222 'default' => 'in', 223 ]; 224 212 225 // Merchant/Company Name. 213 226 $fields[] = [ … … 341 354 $config->access_token = $this->get_meta( $post_id, 'razorpay_access_token' ); 342 355 $config->refresh_token = $this->get_meta( $post_id, 'razorpay_refresh_token' ); 356 $config->country = $this->get_meta( $post_id, 'razorpay_country' ); 343 357 $config->company_name = $this->get_meta( $post_id, 'razorpay_company_name' ); 344 358 $config->checkout_image = Utils::convert_relative_path_to_url( $this->get_meta( $post_id, 'razorpay_checkout_image' ) ); … … 355 369 } 356 370 $config->checkout_mode = (int) $config->checkout_mode; 371 372 if (empty($config->country)){ 373 $config->country = 'in'; 374 } 357 375 358 376 if ( empty( $config->transaction_fees_percentage ) ) { -
knit-pay/trunk/gateways/sab-paisa/src/API.php
r3220363 r3445633 10 10 * 11 11 * @author Knit Pay 12 * @version 8. 75.3.012 * @version 8.99.4.0 13 13 * @since 8.75.3.0 14 14 */ 15 16 15 class API { 17 16 private $config; 18 17 private $mode; 19 18 20 private const OPENSSL_CIPHER_NAME = 'aes-128-cbc'; 21 private const CIPHER_KEY_LEN = 16; 19 private const CIPHER_KEY_LEN = 16; 20 21 // Constants for new encryption method (AES-256-GCM). 22 private const IV_SIZE = 12; // 96 bits for GCM. 23 private const TAG_SIZE = 16; // 128 bits = 16 bytes. 24 private const HMAC_LENGTH = 48; // SHA-384 = 48 bytes. 22 25 23 26 public function __construct( Config $config, $mode ) { … … 26 29 } 27 30 31 /** 32 * Detect if the key is in new format (base64 encoded) 33 */ 34 private function is_new_key_format( $key ) { 35 // Check if it's valid base64 and decodes to 32 bytes (256 bits). 36 $decoded = base64_decode( $key, true ); 37 if ( $decoded !== false && 32 === strlen( $decoded ) ) { 38 return true; 39 } 40 41 return false; 42 } 43 28 44 public function get_endpoint_url() { 29 45 if ( 'test' === $this->mode ) { … … 34 50 } 35 51 36 private static function fix Key( $key ) {52 private static function fix_key( $key ) { 37 53 if ( strlen( $key ) < self::CIPHER_KEY_LEN ) { 38 54 return str_pad( "$key", self::CIPHER_KEY_LEN, '0' ); 39 } 40 41 if ( strlen( $key ) > self::CIPHER_KEY_LEN ) { 55 } elseif ( strlen( $key ) > self::CIPHER_KEY_LEN ) { 42 56 return substr( $key, 0, self::CIPHER_KEY_LEN ); 43 57 } … … 87 101 } 88 102 103 /** 104 * Encrypts the data using the appropriate encryption method based on the key format. 105 * 106 * @param string $data The data to encrypt. 107 * @return string The encrypted data. 108 */ 89 109 private function encrypt( $data ) { 90 110 $key = $this->config->auth_key; 91 111 $iv = $this->config->auth_iv; 92 112 93 $encodedEncryptedData = base64_encode( openssl_encrypt( $data, self::OPENSSL_CIPHER_NAME, self::fixKey( $key ), OPENSSL_RAW_DATA, $iv ) ); 94 $encodedIV = base64_encode( $iv ); 95 $encryptedPayload = $encodedEncryptedData . ':' . $encodedIV; 96 97 return $encryptedPayload; 98 } 99 113 // Detect which encryption method to use. 114 if ( $this->is_new_key_format( $key ) ) { 115 return $this->encrypt_new( $key, $iv, $data ); 116 } else { 117 return $this->encrypt_old( $key, $iv, $data ); 118 } 119 } 120 121 // TODO - Remove this method after 1 Jan 2028. 122 /** 123 * Old encryption method (AES-128-CBC) 124 * 125 * @param string $key Encryption key. 126 * @param string $iv Initialization vector. 127 * @param string $data Data to encrypt. 128 * @return string Encrypted data. 129 */ 130 private function encrypt_old( $key, $iv, $data ) { 131 $encoded_encrypted_data = base64_encode( openssl_encrypt( $data, 'aes-128-cbc', self::fix_key( $key ), OPENSSL_RAW_DATA, $iv ) ); 132 $encoded_iv = base64_encode( $iv ); 133 $encrypted_payload = $encoded_encrypted_data . ':' . $encoded_iv; 134 135 return $encrypted_payload; 136 } 137 138 /** 139 * New encryption method (AES-256-GCM with HMAC-SHA384) 140 * 141 * @param string $aes_key_base64 Base64 encoded AES key. 142 * @param string $hmac_key_base64 Base64 encoded HMAC key. 143 * @param string $plaintext Plaintext to encrypt. 144 * @return string Encrypted data in hex format. 145 * @throws Exception If encryption fails. 146 */ 147 private function encrypt_new( $aes_key_base64, $hmac_key_base64, $plaintext ) { 148 $aes_key = base64_decode( $aes_key_base64, true ); 149 $hmac_key = base64_decode( $hmac_key_base64, true ); 150 151 $iv = random_bytes( self::IV_SIZE ); 152 $tag = ''; 153 154 $cipher_text = openssl_encrypt( 155 $plaintext, 156 'aes-256-gcm', 157 $aes_key, 158 OPENSSL_RAW_DATA, 159 $iv, 160 $tag, 161 '', 162 self::TAG_SIZE 163 ); 164 165 if ( false === $cipher_text ) { 166 throw new Exception( 'Encryption failed.' ); 167 } 168 169 $encrypted_message = $iv . $cipher_text . $tag; 170 171 // Generate HMAC. 172 $hmac = hash_hmac( 'sha384', $encrypted_message, $hmac_key, true ); 173 174 // Final message: [HMAC || IV || CipherText || Tag]. 175 $final_output = $hmac . $encrypted_message; 176 177 return strtoupper( bin2hex( $final_output ) ); 178 } 179 180 /** 181 * Decrypts the data using the appropriate decryption method based on the key format. 182 * 183 * @param string $data Encrypted data. 184 * @return string Decrypted data. 185 */ 100 186 private function decrypt( $data ) { 101 187 $key = $this->config->auth_key; 102 188 $iv = $this->config->auth_iv; 189 190 // Detect which decryption method to use. 191 if ( $this->is_new_key_format( $key ) ) { 192 return $this->decrypt_new( $key, $iv, $data ); 193 } else { 194 return $this->decrypt_old( $key, $data ); 195 } 196 } 197 198 // TODO - Remove this method after 1 Jan 2028. 199 /** 200 * Old decryption method (AES-128-CBC) 201 * 202 * @param string $key Encryption key. 203 * @param string $data Encrypted data. 204 */ 205 private function decrypt_old( $key, $data ) { 103 206 $parts = explode( ':', $data ); 104 207 $encrypted = $parts[0]; 105 // $iv = $parts[1]; 106 $decryptedData = openssl_decrypt( base64_decode( $encrypted ), self::OPENSSL_CIPHER_NAME, self::fixKey( $key ), OPENSSL_RAW_DATA ); 107 return $decryptedData; 108 } 109 208 209 $decrypted_data = openssl_decrypt( base64_decode( $encrypted ), 'aes-128-cbc', self::fix_key( $key ), OPENSSL_RAW_DATA ); 210 return $decrypted_data; 211 } 212 213 /** 214 * New decryption method (AES-256-GCM with HMAC-SHA384) 215 * 216 * @param string $aes_key_base64 Base64 encoded AES key. 217 * @param string $hmac_key_base64 Base64 encoded HMAC key. 218 * @param string $hex_cipher_text Hex encoded cipher text. 219 * @return string Decrypted data. 220 * @throws Exception If decryption fails. 221 */ 222 private function decrypt_new( $aes_key_base64, $hmac_key_base64, $hex_cipher_text ) { 223 $aes_key = base64_decode( $aes_key_base64, true ); 224 $hmac_key = base64_decode( $hmac_key_base64, true ); 225 226 $full_message = hex2bin( $hex_cipher_text ); 227 228 $hmac_received = substr( $full_message, 0, self::HMAC_LENGTH ); 229 $encrypted_data = substr( $full_message, self::HMAC_LENGTH ); 230 231 $computed_hmac = hash_hmac( 'sha384', $encrypted_data, $hmac_key, true ); 232 233 if ( ! hash_equals( $hmac_received, $computed_hmac ) ) { 234 throw new Exception( 'HMAC validation failed. Data may be tampered!' ); 235 } 236 237 $iv = substr( $encrypted_data, 0, self::IV_SIZE ); 238 $cipher_text_with_tag = substr( $encrypted_data, self::IV_SIZE ); 239 $cipher_text = substr( $cipher_text_with_tag, 0, -self::TAG_SIZE ); 240 $tag = substr( $cipher_text_with_tag, -self::TAG_SIZE ); 241 242 $plain_text = openssl_decrypt( 243 $cipher_text, 244 'aes-256-gcm', 245 $aes_key, 246 OPENSSL_RAW_DATA, 247 $iv, 248 $tag 249 ); 250 251 if ( false === $plain_text ) { 252 throw new Exception( 'Decryption failed.' ); 253 } 254 255 return $plain_text; 256 } 257 258 /** 259 * Get encrypted data array. 260 * 261 * @param array $data Data to encrypt. 262 * @param string $data_key Data key. 263 * @return array Encrypted data array. 264 */ 110 265 public function get_encrypted_data_array( $data, $data_key = 'encData' ) { 111 266 $data = $this->encrypt( build_query( $data ) ); -
knit-pay/trunk/gateways/upi-qr/src/Gateway.php
r3441509 r3445633 10 10 use KnitPay\Utils as KnitPayUtils; 11 11 use KnitPay\Gateways\PaymentMethods; 12 use Pronamic\WordPress\Http\Facades\Http; 12 13 13 14 /** … … 22 23 protected $config; 23 24 private $intent_url_parameters; 24 protected $payment_expiry_seconds = 300;25 25 protected $show_manual_confirmation = false; 26 26 protected $merchant_verified = false; … … 80 80 $mobile_error = "QR code and Payment Button can't be hidden at the same time. Kindly show at least one of them from the configuration page."; 81 81 throw new Exception( $mobile_error ); 82 }83 84 if ( PaymentMethods::UPI_COLLECT === $payment->get_payment_method() ) {85 $upi_id = $payment->get_meta( 'customer_upi_id' );86 if ( empty( $upi_id ) || ! preg_match( '/^[a-zA-Z0-9.\-_]{2,256}@[a-zA-Z]{2,64}$/', $upi_id ) ) {87 throw new Exception( 'Invalid UPI ID format.' );88 } elseif ( 2000 < $payment->get_total_amount()->get_minor_units()->format( 0, '.', '' ) ) {89 throw new Exception( 'UPI Collect payment method is only supported for payments up to ₹2000.' );90 } elseif ( '5' !== $this->config->payment_template ) {91 throw new Exception( 'UPI Collect payment method is currently only supported with Payment Template 5.' );92 }93 82 } 94 83 … … 256 245 } 257 246 258 public function knit_pay_upi_data( $payment ) {259 return [260 'knitpay_payment_id' => $payment->get_id(),261 'mode' => $payment->get_mode(),262 'gateway' => \get_post_meta( $payment->get_config_id(), '_pronamic_gateway_id', true ),263 'payment_method' => $payment->get_payment_method(),264 'source' => $payment->get_source(),265 'amount' => $payment->get_total_amount()->number_format( null, '.', '' ),266 'currency' => $payment->get_total_amount()->get_currency()->get_alphabetic_code(),267 'knitpay_version' => KNITPAY_VERSION,268 'knitpay_upi_version' => KNITPAY_UPI_VERSION,269 'php_version' => PHP_VERSION,270 'website_url' => home_url( '/' ),271 'data' => [272 'payment_template' => $this->config->payment_template,273 ],274 ];275 }276 277 247 /** 278 248 * Update status of the specified payment. … … 317 287 $payment = get_pronamic_payment_by_transaction_id( $transaction['utr'] ); 318 288 if ( null !== $payment ) { 319 continue;289 break; 320 290 } 321 291 … … 341 311 342 312 $payment->save(); 343 }344 }345 346 protected function make_amount_unique( Payment $payment ) {347 $actual_amount_minor = $payment->get_total_amount()->get_minor_units()->to_int();348 349 if ( get_transient( 'knit_pay_upi_' . $this->config->config_id . '_' . $actual_amount_minor ) ) {350 $unique_amount_minor = $this->find_unique_amount( $actual_amount_minor );351 $unique_amount = $unique_amount_minor / 100;352 $actual_amount = $actual_amount_minor / 100;353 $payment->add_note( 'Actual amount: ₹' . $actual_amount . '<br>Unique amount generated: ₹' . $unique_amount );354 355 $unique_money = new \Pronamic\WordPress\Money\Money( $unique_amount, $payment->get_total_amount()->get_currency() );356 $payment->set_total_amount( $unique_money );357 } else {358 $unique_amount_minor = $actual_amount_minor;359 }360 361 // Hold the amount for 15 minutes and can be allocated to other transaction if not paid.362 set_transient( 'knit_pay_upi_' . $this->config->config_id . '_' . $unique_amount_minor, $payment->get_id(), 15 * MINUTE_IN_SECONDS );363 }364 365 private function find_unique_amount( $actual_amount_minor, $retry = 1 ) {366 if ( $retry > 10 ) {367 throw new Exception( 'Unable to generate a unique amount. Please try again after sometime.' );368 }369 370 $range = $retry ** 2;371 $random_amount_minor = rand( -$range, $range ) + $actual_amount_minor; // phpcs:ignore WordPress.WP.AlternativeFunctions.rand_rand372 373 if ( get_transient( 'knit_pay_upi_' . $this->config->config_id . '_' . $random_amount_minor ) ) {374 return $this->find_unique_amount( $actual_amount_minor, ++$retry );375 }376 377 return $random_amount_minor;378 }379 380 public function expire_old_upi_payment( Payment $payment ) {381 // Payment can be expired only if the payment current status is Pending.382 if ( PaymentStatus::OPEN !== $payment->get_status() ) {383 return;384 }385 386 // Make payment status as expired for payment older than 5 min.387 $payment_timestamp = $payment->get_date()->getTimestamp();388 if ( $this->payment_expiry_seconds < time() - $payment_timestamp ) {389 $payment->set_status( PaymentStatus::EXPIRED );390 391 // Recheck status after 15 min if payment getting expired very soon.392 if ( time() - $payment_timestamp < 15 * MINUTE_IN_SECONDS ) {393 \as_schedule_single_action(394 time() + ( 15 * MINUTE_IN_SECONDS ),395 'knit_pay_upi_payment_status_check',396 [397 'payment_id' => $payment->get_id(),398 'gateway_id' => $this->config->gateway_id,399 ],400 'knit-pay-upi'401 );402 }403 313 } 404 314 } … … 456 366 } 457 367 458 p ublicfunction get_intent_url_parameters( $payment ) {368 protected function get_intent_url_parameters( $payment ) { 459 369 if ( isset( $this->intent_url_parameters ) ) { 460 370 return $this->intent_url_parameters; … … 469 379 } 470 380 471 p ublicfunction get_upi_qr_text( $payment ) {381 protected function get_upi_qr_text( $payment ) { 472 382 return add_query_arg( $this->get_intent_url_parameters( $payment ), 'upi://pay' ); 473 383 } -
knit-pay/trunk/gateways/upi-qr/src/Integration.php
r3441509 r3445633 20 20 */ 21 21 class Integration extends KnitPayGatewayIntegration { 22 private $gateway_name;23 24 22 const HIDE_FIELD = '0'; 25 23 const SHOW_FIELD = '1'; … … 43 41 44 42 parent::__construct( $args ); 45 46 $this->gateway_name = isset( $args['gateway_name'] ) ? $args['gateway_name'] : $this->get_name();47 48 // Add Ajax listener.49 add_action( 'wp_ajax_nopriv_knit_pay_upi_qr_payment_status_check', [ $this, 'ajax_payment_status_check' ] );50 add_action( 'wp_ajax_knit_pay_upi_qr_payment_status_check', [ $this, 'ajax_payment_status_check' ] );51 52 // Payment status check events are scheduled after payment is expired. We want to check status once more.53 add_action( 'knit_pay_upi_payment_status_check', [ $this, 'check_status' ], 10, 2 );54 43 55 44 // Show notice if Knit Pay UPI supported. … … 168 157 } 169 158 170 /**171 * Get settings fields.172 *173 * @return array174 */175 protected function get_pro_about_settings_fields( $fields ) {176 // Prerequisite.177 $fields[] = [178 'section' => 'general',179 'type' => 'custom',180 'title' => 'Prerequisite',181 'callback' => function () {182 $knit_pay_pro_setup_url = admin_url( 'admin.php?page=knit_pay_pro_setup_page' );183 $link = '<a target="_blank" href="' . $knit_pay_pro_setup_url . '">' . __( 'Knit Pay >> Knit Pay UPI Setup', 'knit-pay-lang' ) . '</a>';184 $message = sprintf( __( 'Please visit the %s page to configure "Knit Pay - UPI".', 'knit-pay-lang' ), $link );185 186 echo '<ol><li>We rely on the third-party service provider RapidAPI for the setup of Knit Pay UPI. RapidAPI will charge you based on your monthly usage.</li>187 <li>Choose a plan that suits your usage. Each plan includes a certain188 number of free transactions. If you exceed the transaction quota,189 additional charges will apply for receiving extra transactions. <br> <a190 target="_blank"191 href="https://rapidapi.com/knitpay/api/knit-pay-upi/pricing">https://rapidapi.com/knitpay/api/knit-pay-upi/pricing</a></li>192 <li>' . $message . '</li>193 </ol>';194 },195 ];196 197 // Terms and Conditions.198 $fields[] = [199 'section' => 'general',200 'type' => 'custom',201 'title' => 'Terms and Conditions',202 'callback' => function () {203 echo '<ol>204 <li>We generate QR codes on your behalf using your UPI/VPA ID so that you can accept payments with ease.</li>205 <li>Knit Pay UPI is not a payment gateway service, and we are not involved in the payment process in any way. Your Merchant Account will be used for collecting payments.</li>206 <li>We do not collect any of your payments in our account. The payment made by the user through the QR code will be received in your merchant account.</li>207 <li>We are not liable for any fraudulent activity that takes place with your merchant account.</li>208 <li>We might also suspend your RapidAPI subscription if any fraudulent activity gets detected.</li>209 <li>We are not responsible for the suspension of your merchant account due to any reason.</li>210 <li>Use of plugins/codes like these might not be allowed as per the terms of the UPI Service provider. Use this plugin at your own risk.</li>211 <li>Use this plugin at your own risk, we are not liable for any of your losses.</li>212 </ol>';213 },214 ];215 216 return $fields;217 }218 219 159 public function get_about_settings_fields( $fields ) { 220 160 $fields[] = [ … … 237 177 238 178 '<ol> 239 <li>Signup at any UPI-enabled App. If you will signup using provided signup URLs and use the referral codes, you might also get a bonus after making few payments.240 <ul>241 <li>- <a target="_blank" href="' . $this->get_url() . 'bharatpe' . $utm_parameter . '">BharatPe (' . $this->get_url() . 'bharatpe)</a> - Signup using the referral link (on the phone) to get ₹200 bonus.</li>242 <li>- <a target="_blank" href="' . $this->get_url() . 'open-money' . $utm_parameter . '">Open Money</a></li>243 <li>- <a target="_blank" href="' . $this->get_url() . 'gpay' . $utm_parameter . '">Google Pay</a> Referral Code: Z05o0</li>244 <li>- <a target="_blank" href="' . $this->get_url() . 'phonepe' . $utm_parameter . '">PhonePe</a></li>245 <li>- <a target="_blank" href="' . $this->get_url() . 'amazon-pay' . $utm_parameter . '">Amazon Pay</a> Referral Code: K1ZESF</li>246 <li>- <a target="_blank" href="https://play.google.com/store/search?q=merchant%20business%20upi&c=apps">More UPI Apps</a></li>247 </ul>248 </li>249 250 <li>Link your Bank Account and generate a UPI ID/VPA.</li>251 252 <li>Use this VPA/UPI ID on the configuration page below.253 <br><strong>Kindly use the correct VPA/UPI ID. In case of wrong settings, payments will get credited to the wrong bank account. Knit Pay will not be responsible for any of your lose.</strong></li>254 255 <li>Save the settings.</li>256 257 <li>Before going live, make a test payment of ₹1 and check that you are receiving this payment in the correct bank account.</li>258 259 </ol>';179 <li>Signup at any UPI-enabled App. If you will signup using provided signup URLs and use the referral codes, you might also get a bonus after making few payments. 180 <ul> 181 <li>- <a target="_blank" href="' . $this->get_url() . 'bharatpe' . $utm_parameter . '">BharatPe (' . $this->get_url() . 'bharatpe)</a> - Signup using the referral link (on the phone) to get ₹200 bonus.</li> 182 <li>- <a target="_blank" href="' . $this->get_url() . 'open-money' . $utm_parameter . '">Open Money</a></li> 183 <li>- <a target="_blank" href="' . $this->get_url() . 'gpay' . $utm_parameter . '">Google Pay</a> Referral Code: Z05o0</li> 184 <li>- <a target="_blank" href="' . $this->get_url() . 'phonepe' . $utm_parameter . '">PhonePe</a></li> 185 <li>- <a target="_blank" href="' . $this->get_url() . 'amazon-pay' . $utm_parameter . '">Amazon Pay</a> Referral Code: K1ZESF</li> 186 <li>- <a target="_blank" href="https://play.google.com/store/search?q=merchant%20business%20upi&c=apps">More UPI Apps</a></li> 187 </ul> 188 </li> 189 190 <li>Link your Bank Account and generate a UPI ID/VPA.</li> 191 192 <li>Use this VPA/UPI ID on the configuration page below. 193 <br><strong>Kindly use the correct VPA/UPI ID. In case of wrong settings, payments will get credited to the wrong bank account. Knit Pay will not be responsible for any of your lose.</strong></li> 194 195 <li>Save the settings.</li> 196 197 <li>Before going live, make a test payment of ₹1 and check that you are receiving this payment in the correct bank account.</li> 198 199 </ol>'; 260 200 }, 261 201 ]; … … 269 209 270 210 '<ol> 271 <li>On the payment screen, the customer scans the QR code using any UPI-enabled mobile app and makes the payment.</li>272 273 <li>The customer enters the transaction ID and submits the payment form.</li>274 275 <li>Payment remains on hold. Merchant manually checks the payment and mark it as complete on the "Knit Pay" Payments page.</li>276 277 <li>Automatic tracking is not available in the UPI QR payment method. You can signup at other supported free payment gateways to get an automatic payment tracking feature.278 <br><a target="_blank" href="https://www.knitpay.org/indian-payment-gateways-supported-in-knit-pay/">Indian Payment Gateways Supported in Knit Pay</a>279 </li>280 281 </ol>';},211 <li>On the payment screen, the customer scans the QR code using any UPI-enabled mobile app and makes the payment.</li> 212 213 <li>The customer enters the transaction ID and submits the payment form.</li> 214 215 <li>Payment remains on hold. Merchant manually checks the payment and mark it as complete on the "Knit Pay" Payments page.</li> 216 217 <li>Automatic tracking is not available in the UPI QR payment method. You can signup at other supported free payment gateways to get an automatic payment tracking feature. 218 <br><a target="_blank" href="https://www.knitpay.org/indian-payment-gateways-supported-in-knit-pay/">Indian Payment Gateways Supported in Knit Pay</a> 219 </li> 220 </ol>'; 221 }, 282 222 ]; 283 223 … … 352 292 'type' => 'text', 353 293 'classes' => [ 'regular-text', 'code' ], 294 'default' => '0000', 354 295 'tooltip' => __( 'four-digit ISO 18245 merchant category code (MCC) to classify your business.', 'knit-pay-lang' ), 355 296 'description' => 'You can refer to below links to find out your MCC.<br>' . … … 463 404 } 464 405 465 protected function get_connection_status_field( $fields ) {466 try {467 $this->is_connected();468 469 $fields[] = [470 'section' => 'general',471 'type' => 'custom',472 'title' => 'Connected',473 'callback' => function () {474 echo '<span class="dashicons dashicons-yes"></span>';475 },476 ];477 } catch ( Exception $e ) {478 $fields[] = [479 'section' => 'general',480 'type' => 'custom',481 'title' => 'Connected',482 'callback' => function () {483 echo '<span class="dashicons dashicons-no"></span>';484 },485 ];486 487 $message = '<strong>Knit Pay</strong> - The connection to ' . $this->gateway_name . ' could not be established.';488 wp_admin_notice( $message, [ 'type' => 'error' ] );489 }490 491 return $fields;492 }493 494 406 protected function get_supported_template_list() { 495 407 return [ … … 501 413 } 502 414 415 /** 416 * Get config. 417 * 418 * @param int $post_id Post ID. 419 * @return Config 420 */ 503 421 public function get_config( $post_id ) { 504 422 $config = new Config(); … … 619 537 ); 620 538 } 621 622 protected function is_connected() {623 return true;624 }625 626 /**627 * Check status of the specified payment.628 *629 * @param int $payment_id The payment ID to check.630 * @param string|null $gateway_id The gateway ID to check against.631 * @return void632 */633 public function check_status( $payment_id = null, $gateway_id = null ) {634 // Check only if this payment belongs to this gateway.635 if ( $gateway_id !== $this->get_id() ) {636 return;637 }638 639 $payment = get_pronamic_payment( $payment_id );640 641 // No payment found, unable to check status.642 if ( null === $payment ) {643 return;644 }645 646 // Add note.647 $note = sprintf(648 /* translators: %s: Knit Pay UPI */649 __( 'Payment status check at gateway by %s.', 'knit-pay-lang' ),650 __( 'Knit Pay UPI', 'knit-pay-lang' )651 );652 653 $payment->add_note( $note );654 655 // Update payment.656 Plugin::update_payment( $payment, false );657 }658 659 public function ajax_payment_status_check() {660 $payment_id = isset( $_POST['knit_pay_payment_id'] ) ? sanitize_text_field( $_POST['knit_pay_payment_id'] ) : '';661 $transaction_id = isset( $_POST['knit_pay_transaction_id'] ) ? sanitize_text_field( $_POST['knit_pay_transaction_id'] ) : '';662 $knit_pay_nonce = isset( $_POST['knit_pay_nonce'] ) ? sanitize_text_field( $_POST['knit_pay_nonce'] ) : '';663 664 $nonce_action = "knit_pay_payment_status_check|{$payment_id}|{$transaction_id}";665 666 if ( ! wp_verify_nonce( $knit_pay_nonce, $nonce_action ) ) {667 wp_send_json_error( __( 'Nonce Missmatch!', 'knit-pay-lang' ) );668 }669 670 $payment = get_pronamic_payment( $payment_id );671 672 if ( null === $payment ) {673 exit;674 }675 676 $gateway = $payment->get_gateway();677 if ( ! $gateway->supports( 'payment_status_request' ) ) {678 wp_send_json_error( __( 'Gateway does not support automatic payment status check.', 'knit-pay-lang' ) );679 }680 681 // Update status.682 try {683 $gateway->update_status( $payment );684 685 // Save New Status.686 if ( PaymentStatus::OPEN !== $payment->get_status() ) {687 $payment->save();688 }689 690 wp_send_json_success( $payment->get_status() );691 } catch ( \Exception $error ) {692 $message = $error->getMessage();693 694 // Maybe include error code in message.695 $code = $error->getCode();696 697 if ( $code > 0 ) {698 $message = \sprintf( '%s: %s', $code, $message );699 }700 701 // Add note.702 $payment->add_note( $message );703 704 wp_send_json_error( $message );705 }706 }707 539 } -
knit-pay/trunk/includes/Utils.php
r3436834 r3445633 4 4 5 5 use Pronamic\WordPress\Pay\Country; 6 use Pronamic\WordPress\Pay\Region; 6 7 use Pronamic\WordPress\Pay\ContactNameHelper; 7 8 use Exception; … … 20 21 21 22 if ( ! empty( $country->get_name() ) ) { 22 $country->get_name();23 return $country->get_name(); 23 24 } 24 25 … … 279 280 } 280 281 } 282 283 public static function get_state_name( ?Region $region, ?Country $country ) { 284 if (!function_exists('WC')){ 285 return $region->get_code(); 286 } 287 $country_code = $country->get_code(); 288 $state_code = empty($region->get_code()) ? $region->get_value() : $region->get_code(); 289 290 $countries = WC()->countries; // Get an instance of the WC_Countries Object 291 $country_states = $countries->get_states( $country_code ); // Get the states array for the specific country 292 293 if ( isset( $country_states[ $state_code ] ) ) { 294 return $country_states[ $state_code ]; // Return the full state name 295 } else { 296 return $state_code; // Return the code itself if the full name is not found (e.g., if the user typed it manually) 297 } 298 } 281 299 282 300 /* -
knit-pay/trunk/knit-pay.php
r3441509 r3445633 5 5 * Description: Seamlessly integrates 500+ payment gateways, including Cashfree, Instamojo, Razorpay, Paypal, Stripe, UPI QR, GoUrl, and SSLCommerz, with over 100 WordPress plugins. 6 6 * 7 * Version: 8.99. 3.07 * Version: 8.99.4.0 8 8 * Requires at least: 6.2 9 9 * Requires PHP: 8.1 -
knit-pay/trunk/readme.txt
r3441509 r3445633 190 190 * Sadad 191 191 * Omise 192 * Nuvei 193 * AsiaPay 194 * Paymob 192 195 * and many more... 193 196
Note: See TracChangeset
for help on using the changeset viewer.