Changeset 3768791
- Timestamp:
- 10/27/2026 02:27:24 PM (4 days ago)
- Location:
- mintage-pay
- Files:
-
- 4 added
- 12 edited
- 1 copied
-
tags/1.18.0 (copied) (copied from mintage-pay/trunk )
-
tags/1.18.0/assets/img/mintage-pay.svg (added)
-
tags/1.18.0/includes/class-mintagepay-admin.php (modified) (1 diff)
-
tags/1.18.0/includes/class-mintagepay-blocks.php (modified) (2 diffs)
-
tags/1.18.0/includes/class-mintagepay-connect.php (added)
-
tags/1.18.0/includes/class-mintagepay-two-rail.php (modified) (6 diffs)
-
tags/1.18.0/includes/class-wc-gateway-mintagepay.php (modified) (8 diffs)
-
tags/1.18.0/mintage-pay.php (modified) (5 diffs)
-
tags/1.18.0/readme.txt (modified) (8 diffs)
-
trunk/assets/img/mintage-pay.svg (added)
-
trunk/includes/class-mintagepay-admin.php (modified) (1 diff)
-
trunk/includes/class-mintagepay-blocks.php (modified) (2 diffs)
-
trunk/includes/class-mintagepay-connect.php (added)
-
trunk/includes/class-mintagepay-two-rail.php (modified) (6 diffs)
-
trunk/includes/class-wc-gateway-mintagepay.php (modified) (8 diffs)
-
trunk/mintage-pay.php (modified) (5 diffs)
-
trunk/readme.txt (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
mintage-pay/tags/1.18.0/includes/class-mintagepay-admin.php
r3768248 r3768791 166 166 * Webhook connection 167 167 * ------------------------------------------------------------------ */ 168 169 /** 170 * After the API key was saved (the settings form, or "Connect to Mintage Pay", 1.18.0): check the new key with 171 * GET /v1/me, remember it as verified, and connect the webhook (deleting the old key's endpoint). The same steps for 172 * both, so a connected store is set up exactly like one where the key was pasted. 173 * 174 * @param string $old_key The key saved before. 175 * @param string $old_base The API base the old key used (Mintage_Pay::api_base_for()). 176 * @param string $new_key The key saved now ('' = removed). 177 * @param string $base_setting The saved "API base URL" setting ('' = automatic). 178 * @return string 'removed', 'unchanged', 'verified' (the webhook was already connected), 'connected', or 'failed'. 179 */ 180 public static function activate_key( $old_key, $old_base, $new_key, $base_setting ) { 181 $old_key = (string) $old_key; 182 $new_key = (string) $new_key; 183 $new_base = Mintage_Pay::api_base_for( $new_key, (string) $base_setting ); 184 delete_transient( Mintage_Pay::RAILS_TRANSIENT ); 185 $old_api = '' !== $old_key ? Mintage_Pay::api( $old_key, $old_base ) : null; 186 187 if ( '' === $new_key ) { 188 // Key removed: disable the old endpoint and forget the secret. 189 $hook = Mintage_Pay::get_webhook(); 190 if ( $hook && $old_api && isset( $hook['fingerprint'] ) && Mintage_Pay::fingerprint( $old_base, $old_key ) === $hook['fingerprint'] ) { 191 $old_api->delete_webhook( $hook['id'] ); 192 } 193 Mintage_Pay::clear_webhook(); 194 Mintage_Pay::clear_key_verified(); 195 return 'removed'; 196 } 197 198 $credentials_changed = ( $new_key !== $old_key || $new_base !== $old_base ); 199 $hook = Mintage_Pay::get_webhook(); 200 $fingerprint = Mintage_Pay::fingerprint( $new_base, $new_key ); 201 $hook_ok = $hook && ! empty( $hook['secret'] ) && isset( $hook['fingerprint'] ) && $hook['fingerprint'] === $fingerprint; 202 203 if ( ! $credentials_changed && $hook_ok && Mintage_Pay::is_key_verified() ) { 204 return 'unchanged'; 205 } 206 207 $api = Mintage_Pay::api( $new_key, $new_base ); 208 $me = $api->get_me(); 209 if ( is_wp_error( $me ) ) { 210 // A new key is unverified by definition (the stored flag holds another key's fingerprint). 211 self::handle_me_error( $me ); 212 Mintage_Pay::add_notice( 213 'error', 214 sprintf( 215 /* translators: %s: error message */ 216 __( 'Mintage Pay: the API key could not be verified (%s). The payment method stays hidden at checkout until the key is verified. Check the key and save again.', 'mintage-pay' ), 217 self::me_error_text( $me, $new_key, (string) $base_setting ) 218 ) 219 ); 220 return 'failed'; 221 } 222 223 $merchant_id = self::merchant_id( $me ); 224 $name = self::merchant_name( $me ); 225 Mintage_Pay::mark_key_verified( $api->fingerprint(), $merchant_id, $name ); 226 Mintage_Pay::cache_rails( $me ); 227 228 if ( $hook_ok ) { 229 Mintage_Pay::add_notice( 'success', self::connected_message( $name, $new_key ) ); 230 return 'verified'; 231 } 232 233 $previous_api = null; 234 if ( $hook && isset( $hook['fingerprint'] ) ) { 235 if ( $old_api && Mintage_Pay::fingerprint( $old_base, $old_key ) === $hook['fingerprint'] ) { 236 $previous_api = $old_api; 237 } elseif ( $hook['fingerprint'] === $fingerprint ) { 238 $previous_api = $api; 239 } 240 } 241 242 $result = self::connect_webhook( $api, $previous_api, $merchant_id ); 243 if ( true === $result ) { 244 Mintage_Pay::add_notice( 'success', self::connected_message( $name, $new_key ) . ' ' . __( 'Webhook connected.', 'mintage-pay' ) ); 245 return 'connected'; 246 } 247 return 'failed'; 248 } 249 250 /** 251 * "Mintage Pay: API key verified for X (live)." 252 * 253 * @param string $name Merchant name. 254 * @param string $api_key The key (test or live). 255 * @return string 256 */ 257 public static function connected_message( $name, $api_key ) { 258 $mode = Mintage_Pay::is_test_key( (string) $api_key ) 259 ? __( 'TEST MODE: sandbox, test money only', 'mintage-pay' ) 260 : __( 'live', 'mintage-pay' ); 261 return '' !== $name 262 /* translators: 1: merchant business name, 2: "live" or "TEST MODE: ..." */ 263 ? sprintf( __( 'Mintage Pay: API key verified for %1$s (%2$s).', 'mintage-pay' ), $name, $mode ) 264 /* translators: %s: "live" or "TEST MODE: ..." */ 265 : sprintf( __( 'Mintage Pay: API key verified (%s).', 'mintage-pay' ), $mode ); 266 } 168 267 169 268 /** -
mintage-pay/tags/1.18.0/includes/class-mintagepay-blocks.php
r3768248 r3768791 105 105 106 106 /** 107 * The apps' marks for this method's own row (WC_Gateway_MintagePay::get_icon() for the classic checkout) : Cash App,108 * plus Apple Pay / Google Pay where Mintage Pay offers the card route for the cart's total. None while the two109 * choices are inside the method (the marks are on the choices then) or when it is the only rail.107 * The apps' marks for this method's own row (WC_Gateway_MintagePay::get_icon() for the classic checkout), by the one 108 * rule in Mintage_Pay_Two_Rail::row_marks(): only what Pay by app offers this store for the cart's total, none while 109 * the two choices are inside the method (the marks are on the choices then). 110 110 * 111 111 * @return array[] … … 117 117 $currency = function_exists( 'get_woocommerce_currency' ) ? (string) get_woocommerce_currency() : 'USD'; 118 118 $total = $this->cart_total(); 119 $apps = Mintage_Pay::split_on() 120 || ( Mintage_Pay::crypto_on() && ! ( $total > 0 && Mintage_Pay_Two_Rail::offered( $total, $currency ) ) ); 121 if ( ! $apps ) { 122 return array(); 123 } 124 $wallets = $total > 0 ? Mintage_Pay_Two_Rail::card_status( $total, $currency )['available'] : true; 125 return Mintage_Pay_Two_Rail::mark_images( 'app', $wallets ); 119 // The same rule as the classic checkout (Mintage_Pay_Two_Rail::row_marks()); no cart (the editor): $total is 0. 120 return Mintage_Pay_Two_Rail::row_mark_images( $total, $currency, $total <= 0 ); 126 121 } 127 122 -
mintage-pay/tags/1.18.0/includes/class-mintagepay-two-rail.php
r3768248 r3768791 223 223 */ 224 224 public static function card_status( $total, $currency ) { 225 $none = self::card_from_options( null ); 225 return self::status( $total, $currency )['card']; 226 } 227 228 /** 229 * Read `options.cash_app` and `options.wallet` of a GET /v1/payment-options response (1.18.0): whether Pay by app 230 * offers Cash App, and crypto, for this store and total. Pure. A server that does not send them offers neither. 231 * 232 * @param mixed $options Response. 233 * @return array { cash_app: bool, wallet: bool } 234 */ 235 public static function apps_from_options( $options ) { 236 $o = is_array( $options ) && isset( $options['options'] ) && is_array( $options['options'] ) ? $options['options'] : array(); 237 return array( 238 'cash_app' => isset( $o['cash_app'] ) && true === $o['cash_app'], 239 'wallet' => isset( $o['wallet'] ) && true === $o['wallet'], 240 ); 241 } 242 243 /** 244 * The card route and the apps for an amount, from one GET /v1/payment-options (card_status() caching: 10 minutes per 245 * amount, 2 after a failure). Unknown (no verified key, the API failed): no card, no apps. 246 * 247 * @param float|string $total Order total in the store currency. 248 * @param string $currency ISO 4217. 249 * @return array { card: card_from_options(), apps: apps_from_options() } 250 */ 251 public static function status( $total, $currency ) { 252 $none = array( 253 'card' => self::card_from_options( null ), 254 'apps' => self::apps_from_options( null ), 255 ); 226 256 $currency = strtoupper( (string) $currency ); 227 257 if ( ! class_exists( 'Mintage_Pay_Webhook' ) || ! Mintage_Pay_Webhook::currency_supported( $currency ) || ! Mintage_Pay::is_key_verified() ) { … … 238 268 $key = self::TRANSIENT . md5( $api->fingerprint() . '|' . $currency . '|' . $minor ); 239 269 $cached = get_transient( $key ); 240 if ( is_array( $cached ) && isset( $cached['available'] ) ) { 241 return self::card_from_options( array( 'card' => $cached ) ); 270 // A value cached by 1.17.0 has no 'apps': asked again. 271 if ( is_array( $cached ) && isset( $cached['available'] ) && isset( $cached['apps'] ) && is_array( $cached['apps'] ) ) { 272 return array( 273 'card' => self::card_from_options( array( 'card' => $cached ) ), 274 'apps' => self::apps_from_options( array( 'options' => $cached['apps'] ) ), 275 ); 242 276 } 243 277 $options = $api->payment_options( Mintage_Pay_Webhook::format_minor( $minor, $currency ), $currency, 5 ); 244 278 $card = self::card_from_options( is_wp_error( $options ) ? null : $options ); 245 set_transient( $key, $card, is_wp_error( $options ) ? 2 * MINUTE_IN_SECONDS : 10 * MINUTE_IN_SECONDS ); 279 $apps = self::apps_from_options( is_wp_error( $options ) ? null : $options ); 280 set_transient( $key, $card + array( 'apps' => $apps ), is_wp_error( $options ) ? 2 * MINUTE_IN_SECONDS : 10 * MINUTE_IN_SECONDS ); 246 281 if ( is_wp_error( $options ) ) { 247 282 Mintage_Pay::log( 'payment options could not be read (the card choice stays hidden for now): ' . $options->get_error_message(), 'warning' ); 248 283 } 249 return $card; 284 return array( 285 'card' => $card, 286 'apps' => $apps, 287 ); 288 } 289 290 /** 291 * The marks on the main method's own row at checkout (classic get_icon() and the block checkout's data use this 292 * one rule, 1.18.0). Pure. 293 * - The two choices are inside the method: none (the marks are on the choices). 294 * - No cart (admin, the block editor): the apps' marks where the method is the apps (split, or crypto its own 295 * method), none otherwise, as before 1.18.0. 296 * - Otherwise only where Pay by app offers Cash App for this store (options.cash_app): Cash App, then Apple Pay and 297 * Google Pay where the card route is offered, then USDC and USDT where crypto is inside Pay by app (crypto not its 298 * own method) and offered (options.wallet). A store without Cash App, or a failed read, shows none. 299 * 300 * @param bool $split "Pay by card" is its own method (Mintage_Pay::split_on()). 301 * @param bool $crypto "Pay with crypto" is its own method (Mintage_Pay::crypto_on()). 302 * @param bool $offered The two choices are offered inside the method for this total. 303 * @param array|null $status status() for the cart's total, or null when there is no cart. 304 * @return array[] marks() entries. 305 */ 306 public static function row_marks( $split, $crypto, $offered, $status ) { 307 if ( ! $split && $offered ) { 308 return array(); 309 } 310 if ( null === $status ) { 311 return ( $split || $crypto ) ? self::marks( 'app', true ) : array(); 312 } 313 if ( empty( $status['apps']['cash_app'] ) ) { 314 return array(); 315 } 316 return self::marks( 'app', ! empty( $status['card']['available'] ), ! $crypto && ! empty( $status['apps']['wallet'] ) ); 317 } 318 319 /** 320 * row_marks() for this store and cart, as image addresses. 321 * 322 * @param float|string $total Cart or order total. 323 * @param string $currency ISO 4217. 324 * @param bool $no_cart There is no cart (admin, the block editor). 325 * @return array[] 326 */ 327 public static function row_mark_images( $total, $currency, $no_cart ) { 328 $status = $no_cart ? null : self::status( $total, $currency ); 329 $offered = ! $no_cart && self::offered( $total, $currency ); 330 return self::images( self::row_marks( Mintage_Pay::split_on(), Mintage_Pay::crypto_on(), $offered, $status ) ); 250 331 } 251 332 … … 329 410 * @param string $choice 'card', 'app' or 'crypto'. 330 411 * @param bool $wallets Apple Pay and Google Pay are offered on Pay by app. 412 * @param bool $coins USDC and USDT after the apps (Pay by app with crypto inside it, row_marks()). 331 413 * @return array[] 332 414 */ 333 public static function marks( $choice, $wallets = true ) {415 public static function marks( $choice, $wallets = true, $coins = false ) { 334 416 if ( 'card' === $choice ) { 335 417 return array( … … 350 432 $out[] = array( 'google-pay', 'Google Pay', 45 ); 351 433 } 434 if ( $coins ) { 435 $out[] = array( 'usdc', 'USDC', 38 ); 436 $out[] = array( 'usdt', 'USDT', 38 ); 437 } 352 438 return $out; 353 439 } … … 361 447 */ 362 448 public static function mark_images( $choice, $wallets = true ) { 449 return self::images( self::marks( $choice, $wallets ) ); 450 } 451 452 /** 453 * marks() entries as addresses: file, label, width. 454 * 455 * @param array[] $marks marks() entries. 456 * @return array[] 457 */ 458 public static function images( array $marks ) { 363 459 $base = plugins_url( 'assets/img/marks/', MINTAGE_PAY_FILE ); 364 460 $out = array(); 365 foreach ( self::marks( $choice, $wallets )as $m ) {461 foreach ( $marks as $m ) { 366 462 $out[] = array( 367 463 'src' => $base . $m[0] . '.svg?ver=' . MINTAGE_PAY_VERSION, … … 382 478 */ 383 479 public static function marks_html( $choice, $wallets = true ) { 480 return self::images_html( self::mark_images( $choice, $wallets ) ); 481 } 482 483 /** 484 * Image addresses (images()) as the payment method row's HTML. 485 * 486 * @param array[] $images images() entries. 487 * @return string 488 */ 489 public static function images_html( array $images ) { 384 490 $html = ''; 385 foreach ( self::mark_images( $choice, $wallets )as $m ) {491 foreach ( $images as $m ) { 386 492 $html .= '<img class="mintagepay-method-mark" src="' . esc_url( $m['src'] ) . '" alt="' . esc_attr( $m['alt'] ) . '" title="' . esc_attr( $m['alt'] ) . '" width="' . (int) $m['width'] . '" height="24" decoding="async" />'; 387 493 } -
mintage-pay/tags/1.18.0/includes/class-wc-gateway-mintagepay.php
r3768248 r3768791 27 27 // claiming a refund was sent (WooCommerce would otherwise only offer "Refund manually"). 28 28 $this->supports = array_merge( Mintage_Pay_Subscriptions::supports(), array( 'refunds' ) ); 29 // The square Mintage Pay mark for WooCommerce's Payments page (it reads this property, over REST too). The 30 // checkout row never shows it: get_icon() below does not call parent::get_icon(). 31 $this->icon = plugins_url( 'assets/img/mintage-pay.svg', MINTAGE_PAY_FILE ); 29 32 30 33 $this->init_form_fields(); … … 80 83 public function get_icon() { 81 84 $rail = $this->method_rail(); 82 // With "Pay with crypto" as its own method (1.17.0) this method is the apps, unless it shows the two choices83 // inside itself (their marks are on the choices then).84 if ( '' === $rail && Mintage_Pay::crypto_on() && ! $this->two_rail_offered() ) {85 $rail = 'app';86 }87 if ( '' === $rail ) {88 return parent::get_icon();89 }90 return apply_filters( 'woocommerce_gateway_icon', Mintage_Pay_Two_Rail:: marks_html( $rail, $this->wallets_offered()), $this->id );85 if ( 'card' === $rail || 'crypto' === $rail ) { 86 return apply_filters( 'woocommerce_gateway_icon', Mintage_Pay_Two_Rail::marks_html( $rail, $this->wallets_offered() ), $this->id ); 87 } 88 // This method (Pay by app): one rule with the block checkout (Mintage_Pay_Two_Rail::row_marks(), 1.18.0). Never 89 // parent::get_icon(): $this->icon is set for the WooCommerce Payments page only, not for the checkout row. 90 $no_cart = is_admin() && ! wp_doing_ajax(); 91 $currency = function_exists( 'get_woocommerce_currency' ) ? (string) get_woocommerce_currency() : 'USD'; 92 $images = Mintage_Pay_Two_Rail::row_mark_images( $no_cart ? 0 : $this->get_order_total(), $currency, $no_cart ); 93 return apply_filters( 'woocommerce_gateway_icon', Mintage_Pay_Two_Rail::images_html( $images ), $this->id ); 91 94 } 92 95 … … 306 309 'title' => __( 'API key', 'mintage-pay' ), 307 310 'type' => 'password', 308 'description' => __( ' Create one in the Mintage Pay dashboard under Developers > API keys. Saving a new key checks it and connects the webhook automatically.', 'mintage-pay' ),311 'description' => __( 'Easiest: click "Connect to Mintage Pay" at the top of this page and the key is filled in for you. Or create one in the Mintage Pay dashboard under Developers > API keys and paste it here. Saving a new key checks it and connects the webhook automatically.', 'mintage-pay' ), 309 312 'default' => '', 310 313 ), … … 366 369 'type' => 'mintagepay_webhook', 367 370 ), 371 'auto_update' => array( 372 'title' => __( 'Plugin updates', 'mintage-pay' ), 373 'type' => 'mintagepay_auto_update', 374 ), 368 375 'debug' => array( 369 376 'title' => __( 'Debug log', 'mintage-pay' ), … … 399 406 <td class="forminp"> 400 407 <?php if ( '' === (string) $this->get_option( 'api_key' ) ) : ?> 401 <p><?php esc_html_e( 'Not connected. Save an API key first.', 'mintage-pay' ); ?></p> 408 <p><?php esc_html_e( 'Not connected yet.', 'mintage-pay' ); ?></p> 409 <p><?php $this->connect_buttons(); ?></p> 402 410 <?php else : ?> 403 411 <?php if ( $hook && ! empty( $hook['secret'] ) && isset( $hook['fingerprint'] ) && $hook['fingerprint'] === $fingerprint ) : ?> … … 446 454 447 455 /** 456 * The two Connect buttons (live account, sandbox test account). 457 */ 458 protected function connect_buttons() { 459 ?> 460 <a class="button button-primary" href="<?php echo esc_url( Mintage_Pay_Connect::start_url( 'live' ) ); ?>"><?php esc_html_e( 'Connect to Mintage Pay', 'mintage-pay' ); ?></a> 461 <a class="button" href="<?php echo esc_url( Mintage_Pay_Connect::start_url( 'test' ) ); ?>"><?php esc_html_e( 'Connect a test (sandbox) account', 'mintage-pay' ); ?></a> 462 <?php 463 } 464 465 /** 466 * Settings page: the "Get started" panel (no key yet) or the "Replace the key?" box (a Connect came back while a 467 * working key is saved), then the settings. Only on this method's own page, not the card or crypto method's. 468 */ 469 public function admin_options() { 470 if ( Mintage_Pay::GATEWAY_ID === $this->id ) { 471 $pending = Mintage_Pay_Connect::pending(); 472 if ( $pending ) { 473 $this->confirm_box( $pending ); 474 } elseif ( '' === (string) $this->get_option( 'api_key' ) ) { 475 $this->get_started_panel(); 476 } 477 } 478 parent::admin_options(); 479 } 480 481 /** 482 * "Get started": connect, try the sandbox, apply, read the guide. 483 */ 484 private function get_started_panel() { 485 ?> 486 <div class="notice notice-info inline" style="padding:12px 16px;margin:16px 0;"> 487 <h3 style="margin-top:0;"><?php esc_html_e( 'Get started with Mintage Pay', 'mintage-pay' ); ?></h3> 488 <ol style="margin-left:1.5em;"> 489 <li><?php esc_html_e( 'Have a Mintage Pay account? Click "Connect to Mintage Pay", sign in and approve this store. The API key and the webhook are set up for you and the payment method is switched on.', 'mintage-pay' ); ?></li> 490 <li> 491 <?php 492 printf( 493 /* translators: %s: link to the Mintage Pay application form */ 494 esc_html__( 'No account yet? %s (a few minutes).', 'mintage-pay' ), 495 '<a href="https://mintagepay.com/#apply" target="_blank" rel="noopener noreferrer">' . esc_html__( 'Apply for a Mintage Pay account', 'mintage-pay' ) . '</a>' 496 ); 497 ?> 498 </li> 499 <li> 500 <?php 501 printf( 502 /* translators: %s: link to the sandbox */ 503 esc_html__( 'Want to try it first? Make a free test account on the %s, then click "Connect a test (sandbox) account". Test orders use test money only.', 'mintage-pay' ), 504 '<a href="https://sandbox.mintagepay.com/" target="_blank" rel="noopener noreferrer">' . esc_html__( 'Mintage Pay sandbox', 'mintage-pay' ) . '</a>' 505 ); 506 ?> 507 </li> 508 </ol> 509 <p><?php $this->connect_buttons(); ?></p> 510 <p class="description"> 511 <?php 512 printf( 513 /* translators: %s: link to the setup guide */ 514 esc_html__( 'Step by step: %s.', 'mintage-pay' ), 515 '<a href="https://mintagepay.com/docs/integrations/#woocommerce" target="_blank" rel="noopener noreferrer">' . esc_html__( 'the WooCommerce setup guide', 'mintage-pay' ) . '</a>' 516 ); 517 ?> 518 </p> 519 </div> 520 <?php 521 } 522 523 /** 524 * A Connect came back while a working key is saved: replace it, or keep it. 525 * 526 * @param array $pending The waiting connect (code, verifier, base). 527 */ 528 private function confirm_box( array $pending ) { 529 $current_name = Mintage_Pay::verified_merchant_name(); 530 $current_mode = Mintage_Pay::is_test_key( (string) $this->get_option( 'api_key' ) ) ? __( 'test mode (sandbox)', 'mintage-pay' ) : __( 'live', 'mintage-pay' ); 531 $new_mode = Mintage_Pay::SANDBOX_API_BASE === $pending['base'] ? __( 'test mode (sandbox)', 'mintage-pay' ) : __( 'live', 'mintage-pay' ); 532 ?> 533 <div class="notice notice-warning inline" style="padding:12px 16px;margin:16px 0;"> 534 <h3 style="margin-top:0;"><?php esc_html_e( 'Replace the Mintage Pay key?', 'mintage-pay' ); ?></h3> 535 <p> 536 <?php 537 if ( '' !== $current_name ) { 538 /* translators: 1: Mintage Pay business name, 2: "live" or "test mode (sandbox)" */ 539 echo esc_html( sprintf( __( 'This store takes payments for %1$s (%2$s) now.', 'mintage-pay' ), $current_name, $current_mode ) ); 540 } else { 541 /* translators: %s: "live" or "test mode (sandbox)" */ 542 echo esc_html( sprintf( __( 'This store has a working Mintage Pay key now (%s).', 'mintage-pay' ), $current_mode ) ); 543 } 544 echo ' '; 545 /* translators: %s: "live" or "test mode (sandbox)" */ 546 echo esc_html( sprintf( __( 'You just approved a new connection (%s). Replacing the key sends new payments to the account you approved.', 'mintage-pay' ), $new_mode ) ); 547 ?> 548 </p> 549 <?php if ( Mintage_Pay::SANDBOX_API_BASE === $pending['base'] && ! Mintage_Pay::is_test_key( (string) $this->get_option( 'api_key' ) ) ) : ?> 550 <p><strong style="color:#b32d2e;"><?php esc_html_e( 'The new key is a test key: customers would pay with test money and no real payment would reach you.', 'mintage-pay' ); ?></strong></p> 551 <?php endif; ?> 552 <p> 553 <a class="button button-primary" href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin-post.php?action=' . Mintage_Pay_Connect::CONFIRM_ACTION ), Mintage_Pay_Connect::CONFIRM_ACTION ) ); ?>"><?php esc_html_e( 'Replace the key', 'mintage-pay' ); ?></a> 554 <a class="button" href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin-post.php?action=' . Mintage_Pay_Connect::CANCEL_ACTION ), Mintage_Pay_Connect::CANCEL_ACTION ) ); ?>"><?php esc_html_e( 'Keep the current key', 'mintage-pay' ); ?></a> 555 </p> 556 </div> 557 <?php 558 } 559 560 /** 561 * The "Plugin updates" row: WordPress's own auto-update choice for this plugin (the Plugins page's "Enable 562 * auto-updates" link), shown as a checkbox. 563 * 564 * @param string $key Field key. 565 * @param array $data Field data. 566 * @return string 567 */ 568 public function generate_mintagepay_auto_update_html( $key, $data ) { 569 $state = Mintage_Pay_Connect::auto_update_state(); 570 $field_key = $this->get_field_key( $key ); 571 ob_start(); 572 ?> 573 <tr valign="top"> 574 <th scope="row" class="titledesc"><label for="<?php echo esc_attr( $field_key ); ?>"><?php echo esc_html( $data['title'] ); ?></label></th> 575 <td class="forminp"> 576 <fieldset> 577 <label for="<?php echo esc_attr( $field_key ); ?>"> 578 <input type="checkbox" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" value="1" <?php checked( $state['on'] ); ?> <?php disabled( ! $state['allowed'] ); ?> /> 579 <?php esc_html_e( 'Update Mintage Pay automatically when a new version is out', 'mintage-pay' ); ?> 580 </label> 581 <p class="description"> 582 <?php 583 if ( $state['allowed'] ) { 584 esc_html_e( 'The same as "Enable auto-updates" for Mintage Pay on the Plugins page. Recommended: fixes and new payment options reach your checkout without you doing anything. If your host or a tool such as MainWP manages your updates, that may already cover this site.', 'mintage-pay' ); 585 } else { 586 esc_html_e( 'Your host or your site settings manage plugin updates here, or your user cannot update plugins, so this cannot be changed from this page.', 'mintage-pay' ); 587 } 588 ?> 589 </p> 590 </fieldset> 591 </td> 592 </tr> 593 <?php 594 return (string) ob_get_clean(); 595 } 596 597 /** 598 * The auto-update checkbox: 'yes' or 'no' (WordPress's own setting is the one that counts, see process_admin_options()). 599 * 600 * @param string $key Key. 601 * @param mixed $value Value. 602 * @return string 603 */ 604 public function validate_mintagepay_auto_update_field( $key, $value ) { 605 return ! empty( $value ) ? 'yes' : 'no'; 606 } 607 608 /* ------------------------------------------------------------------ * 609 * WooCommerce's Payments page (WooCommerce 9.6+ calls these; older versions never do). The card and crypto methods 610 * share the main method's key, so "set up", "connected" and "test mode" are the same for all three. 611 * ------------------------------------------------------------------ */ 612 613 /** 614 * Needs setup until a key has been checked with Mintage Pay. Not "is usable": that also needs the method switched 615 * on, and WooCommerce will not switch on a method that says it needs setup. 616 * 617 * @return bool 618 */ 619 public function needs_setup() { 620 return ! Mintage_Pay::is_key_verified(); 621 } 622 623 /** 624 * Connected: a key is saved and Mintage Pay accepted it. 625 * 626 * @return bool 627 */ 628 public function is_account_connected() { 629 return Mintage_Pay::is_key_verified(); 630 } 631 632 /** 633 * Test mode: the saved key is a sandbox key. 634 * 635 * @return bool 636 */ 637 public function is_test_mode() { 638 return Mintage_Pay::is_test_key( (string) Mintage_Pay::setting( 'api_key', '' ) ); 639 } 640 641 /** 642 * This method's own settings page. 643 * 644 * @return string 645 */ 646 public function get_settings_url() { 647 return admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=' . $this->id ); 648 } 649 650 /** 651 * Where "Complete setup" goes: the main method's settings, with the Connect buttons. 652 * 653 * @param string $return_url Where WooCommerce would like to come back to (not used: the settings page is the end). 654 * @return string 655 */ 656 public function get_connection_url( $return_url = '' ) { 657 return Mintage_Pay::settings_url(); 658 } 659 660 /** 661 * Links on the Payments page's menu for this method. 662 * 663 * @param string $country_code Store country (not used: the same links everywhere). 664 * @return array[] 665 */ 666 public function get_provider_links( $country_code = '' ) { 667 return self::provider_links(); 668 } 669 670 /** 671 * The Payments page links (pure, tested in tests/payments-page-test.php). 672 * 673 * @return array[] 674 */ 675 public static function provider_links() { 676 return array( 677 array( 678 '_type' => 'about', 679 'url' => 'https://mintagepay.com/', 680 ), 681 array( 682 '_type' => 'documentation', 683 'url' => 'https://mintagepay.com/docs/integrations/#woocommerce', 684 ), 685 array( 686 '_type' => 'support', 687 'url' => 'https://mintagepay.com/docs/', 688 ), 689 array( 690 '_type' => 'pricing', 691 'url' => 'https://mintagepay.com/#pricing', 692 ), 693 array( 694 '_type' => 'terms', 695 'url' => 'https://mintagepay.com/terms.html', 696 ), 697 ); 698 } 699 700 /** 448 701 * The webhook row stores nothing. 449 702 * … … 521 774 522 775 /** 523 * Save settings, then validate a new key with GET /v1/me and register the webhook. 776 * Save settings, then validate a new key with GET /v1/me and register the webhook (Mintage_Pay_Admin::activate_key(), 777 * the same steps "Connect to Mintage Pay" runs), and apply the auto-update choice. 524 778 * 525 779 * @return bool … … 536 790 $this->enabled = $this->get_option( 'enabled' ); 537 791 538 $new_key = (string) $this->get_option( 'api_key' ); 539 $new_base = Mintage_Pay::api_base_for( $new_key, (string) $this->get_option( 'api_base_url' ) ); 540 delete_transient( Mintage_Pay::RAILS_TRANSIENT ); 541 $old_api = '' !== $old_key ? Mintage_Pay::api( $old_key, $old_base ) : null; 542 543 if ( '' === $new_key ) { 544 // Key removed: disable the old endpoint and forget the secret. 545 $hook = Mintage_Pay::get_webhook(); 546 if ( $hook && $old_api && isset( $hook['fingerprint'] ) && Mintage_Pay::fingerprint( $old_base, $old_key ) === $hook['fingerprint'] ) { 547 $old_api->delete_webhook( $hook['id'] ); 548 } 549 Mintage_Pay::clear_webhook(); 550 Mintage_Pay::clear_key_verified(); 551 return $saved; 552 } 553 554 $credentials_changed = ( $new_key !== $old_key || $new_base !== $old_base ); 555 $hook = Mintage_Pay::get_webhook(); 556 $fingerprint = Mintage_Pay::fingerprint( $new_base, $new_key ); 557 $hook_ok = $hook && ! empty( $hook['secret'] ) && isset( $hook['fingerprint'] ) && $hook['fingerprint'] === $fingerprint; 558 559 if ( ! $credentials_changed && $hook_ok && Mintage_Pay::is_key_verified() ) { 560 return $saved; 561 } 562 563 $api = Mintage_Pay::api( $new_key, $new_base ); 564 $me = $api->get_me(); 565 if ( is_wp_error( $me ) ) { 566 // A new key is unverified by definition (the stored flag holds another key's fingerprint). 567 Mintage_Pay_Admin::handle_me_error( $me ); 568 Mintage_Pay::add_notice( 569 'error', 570 sprintf( 571 /* translators: %s: error message */ 572 __( 'Mintage Pay: the API key could not be verified (%s). The payment method stays hidden at checkout until the key is verified. Check the key and save again.', 'mintage-pay' ), 573 Mintage_Pay_Admin::me_error_text( $me, $new_key, (string) $this->get_option( 'api_base_url' ) ) 574 ) 575 ); 576 return $saved; 577 } 578 579 $merchant_id = Mintage_Pay_Admin::merchant_id( $me ); 580 $name = isset( $me['merchant']['name'] ) && is_string( $me['merchant']['name'] ) ? $me['merchant']['name'] : ''; 581 Mintage_Pay::mark_key_verified( $api->fingerprint(), $merchant_id, $name ); 582 Mintage_Pay::cache_rails( $me ); 583 584 if ( $hook_ok ) { 585 Mintage_Pay::add_notice( 'success', $this->connected_message( $name ) ); 586 return $saved; 587 } 588 589 $previous_api = null; 590 if ( $hook && isset( $hook['fingerprint'] ) ) { 591 if ( $old_api && Mintage_Pay::fingerprint( $old_base, $old_key ) === $hook['fingerprint'] ) { 592 $previous_api = $old_api; 593 } elseif ( $hook['fingerprint'] === $fingerprint ) { 594 $previous_api = $api; 595 } 596 } 597 598 $result = Mintage_Pay_Admin::connect_webhook( $api, $previous_api, $merchant_id ); 599 if ( true === $result ) { 600 Mintage_Pay::add_notice( 'success', $this->connected_message( $name ) . ' ' . __( 'Webhook connected.', 'mintage-pay' ) ); 601 } 792 Mintage_Pay_Admin::activate_key( $old_key, $old_base, (string) $this->get_option( 'api_key' ), (string) $this->get_option( 'api_base_url' ) ); 793 Mintage_Pay_Connect::save_auto_update( 'yes' === $this->get_option( 'auto_update' ) ); 602 794 return $saved; 603 }604 605 /**606 * "Connected to Mintage Pay as X."607 *608 * @param string $name Merchant name.609 * @return string610 */611 private function connected_message( $name ) {612 $mode = Mintage_Pay::is_test_key( (string) $this->get_option( 'api_key' ) )613 ? __( 'TEST MODE: sandbox, test money only', 'mintage-pay' )614 : __( 'live', 'mintage-pay' );615 return '' !== $name616 /* translators: 1: merchant business name, 2: "live" or "TEST MODE: ..." */617 ? sprintf( __( 'Mintage Pay: API key verified for %1$s (%2$s).', 'mintage-pay' ), $name, $mode )618 /* translators: %s: "live" or "TEST MODE: ..." */619 : sprintf( __( 'Mintage Pay: API key verified (%s).', 'mintage-pay' ), $mode );620 795 } 621 796 -
mintage-pay/tags/1.18.0/mintage-pay.php
r3768248 r3768791 4 4 * Plugin URI: https://mintagepay.com/docs/integrations/#woocommerce 5 5 * Description: Accept USDC and USDT stablecoin payments through the Mintage Pay hosted checkout, with prices in USD, EUR, GBP and more. 6 * Version: 1.1 7.06 * Version: 1.18.0 7 7 * Requires at least: 6.4 8 8 * Requires PHP: 7.4 … … 14 14 * Text Domain: mintage-pay 15 15 * WC requires at least: 8.0 16 * WC tested up to: 11. 116 * WC tested up to: 11.2 17 17 * 18 18 * @package MintagePay … … 21 21 defined( 'ABSPATH' ) || exit; 22 22 23 define( 'MINTAGE_PAY_VERSION', '1.1 7.0' );23 define( 'MINTAGE_PAY_VERSION', '1.18.0' ); 24 24 define( 'MINTAGE_PAY_FILE', __FILE__ ); 25 25 define( 'MINTAGE_PAY_PATH', plugin_dir_path( __FILE__ ) ); … … 153 153 require_once MINTAGE_PAY_PATH . 'includes/class-mintagepay-reminder.php'; 154 154 require_once MINTAGE_PAY_PATH . 'includes/class-mintagepay-two-rail.php'; 155 require_once MINTAGE_PAY_PATH . 'includes/class-mintagepay-connect.php'; 155 156 156 157 add_filter( 'woocommerce_payment_gateways', array( __CLASS__, 'add_gateway' ) ); … … 176 177 Mintage_Pay_Discount::init(); 177 178 Mintage_Pay_Reminder::init(); 179 Mintage_Pay_Connect::init(); 178 180 } 179 181 -
mintage-pay/tags/1.18.0/readme.txt
r3768368 r3768791 7 7 WC requires at least: 8.0 8 8 WC tested up to: 11.2 9 Stable tag: 1.1 7.09 Stable tag: 1.18.0 10 10 License: GPLv2 or later 11 11 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 21 21 * **Pay by app**: Cash App in one tap, plus Apple Pay and Google Pay where Mintage Pay offers them for the total. 22 22 23 **Get started in minutes:** install, try it with test money in the sandbox, then apply for a live account. See Installation below, or the full guide at https://mintagepay.com/docs/integrations/#woocommerce23 **Get started in minutes:** install, click "Connect to Mintage Pay" and approve your store. No key to copy. Try it with test money in the sandbox first if you like, then apply for a live account. See Installation below, or the full guide at https://mintagepay.com/docs/integrations/#woocommerce 24 24 25 25 Mintage Pay sends your customer to a secure hosted checkout where they pay in stablecoins (USDC or USDT) from a wallet or an exchange, on the networks you turn on in your Mintage Pay dashboard (for example Base, Polygon, Solana or TRON). A network appears at checkout only when you have set a payout address for it. … … 53 53 What is sent, and when: 54 54 55 * When you click "Connect to Mintage Pay" (or "Connect a test (sandbox) account"): your browser opens app.mintagepay.com (or sandbox.mintagepay.com) with this site's address, its name, the plugin version, a random value and a code challenge (PKCE). You sign in there and approve this store. Your browser then comes back to this site with a one-time code, and the plugin sends that code and its secret to Mintage Pay to receive this store's API key. Nothing is sent before you click. 55 56 * When you save the settings, reconnect the webhook, or activate, deactivate or delete the plugin: your API key (in the Authorization header), this store's webhook URL and the store name, to check the key and to add or remove the webhook endpoint. 56 57 * When a customer chooses Mintage Pay at checkout: the order total and currency, the order number, a description ("Order #1042 from Your Store"), the thank-you and cancel page addresses, the WooCommerce order id and order key, the invoice expiry, and the customer's billing email address. Mintage Pay emails the customer a receipt only if you turn off "Let WooCommerce send the order emails"; otherwise it writes to them only when they ask for a refund on Mintage Pay's refund page. For an order paid by card, the email is also kept as part of the record of that card payment, in case the customer disputes the charge. … … 74 75 **3. Go live.** Apply at https://mintagepay.com/#apply. Once your account is approved, sign in at https://app.mintagepay.com, set a payout address for each network you want to be paid on, and create a live key (mp_live_...). 75 76 76 **4. Connect your store.** Go to WooCommerce > Settings > Payments > Mintage Pay , paste the key,tick Enable and save. Saving checks the key and registers this store's webhook automatically. The settings page shows "Connected to (your business name) (live)" when it is done, or "(TEST MODE: sandbox, test money only)" for a sandbox key.77 78 To try it first, use a sandbox key (mp_test_...) from https://sandbox.mintagepay.com. Leave "API base URL" empty: the key decides whether the plugin talks to the sandbox or the live service. Replace it with a live key (mp_live_...) before you take real orders.77 **4. Connect your store.** Go to WooCommerce > Settings > Payments > Mintage Pay and click "Connect to Mintage Pay" (or "Connect a test (sandbox) account"). Sign in to Mintage Pay, check that the store address shown is yours, and click Approve. You come back to WordPress with the key saved, the webhook registered and the payment method switched on. You can also paste a key from Developers > API keys instead: tick Enable and save. Saving checks the key and registers this store's webhook automatically. The settings page shows "Connected to (your business name) (live)" when it is done, or "(TEST MODE: sandbox, test money only)" for a sandbox key. 78 79 To try it first, connect a sandbox account, or paste a sandbox key (mp_test_...) from https://sandbox.mintagepay.com. Click "Connect to Mintage Pay" again later to switch to your live account: the plugin asks before it replaces a working key. Leave "API base URL" empty: the key decides whether the plugin talks to the sandbox or the live service. Replace it with a live key (mp_live_...) before you take real orders. 79 80 80 81 If you move the store to a new address or the webhook shows "Not connected", click "Reconnect webhook" on the settings page. … … 82 83 **5. Choose your methods.** Under WooCommerce > Settings > Payments, switch on "Mintage Pay: Pay by card" and "Mintage Pay: Pay with crypto" if you want them as their own methods, and drag the methods into the order you want. 83 84 84 **6. Stay up to date automatically.** On the Plugins screen, click "Enable auto-updates" next to Mintage Pay. Fixes and new payment options then install on their own.85 **6. Stay up to date automatically.** Tick "Update Mintage Pay automatically" on the settings page, or click "Enable auto-updates" next to Mintage Pay on the Plugins screen (it is the same setting). Fixes and new payment options then install on their own. 85 86 86 87 = Documentation = … … 100 101 Yes. A sandbox account for testing is free and instant at https://sandbox.mintagepay.com. A live account is by application at https://mintagepay.com/#apply. 101 102 103 = What does "Connect to Mintage Pay" do? = 104 105 It makes an API key for this store in your Mintage Pay account and saves it here, so you never copy a key by hand. You approve it on Mintage Pay's own site, signed in to your account, and the page shows the store address that asked. Only approve if you just clicked Connect in your own WordPress. The key appears under Developers > API keys as "WooCommerce (your store address)" and the account owner gets an email. If you connect the same store again, the key from the earlier Connect is revoked as soon as the new one is used. Keys you made by hand are never touched. 106 102 107 = Why don't I see Pay by card or Pay by app? = 103 108 … … 151 156 152 157 == Changelog == 158 159 = 1.18.0 = 160 * New: "Connect to Mintage Pay". Click it on the settings page, sign in to Mintage Pay and approve your store: the API key is saved, the webhook is registered and the payment method is switched on. No key to copy. "Connect a test (sandbox) account" does the same with test money. If a working key is already saved, the plugin asks before replacing it. 161 * New: a "Get started" box on the settings page while no key is saved, with Connect, the sandbox, the application form and the setup guide. 162 * New: "Update Mintage Pay automatically" on the settings page (WordPress's own auto-update setting for this plugin). 163 * WooCommerce's Payments page now shows the Mintage Pay icon, says the method needs setup until a key is verified and shows test mode for a sandbox key, and links to the guide, pricing and terms. Each Mintage Pay method opens its own settings. 164 * Fix: with only the main method on, its row showed the Cash App, Apple Pay and Google Pay icons even where Mintage Pay does not offer those apps for the store. The icons now follow what Mintage Pay offers, on the classic and the block checkout. 165 * Tested with WooCommerce 11.2. 153 166 154 167 = 1.17.0 = … … 269 282 = 1.0.0 = 270 283 * First release. 284 285 == Upgrade Notice == 286 287 = 1.18.0 = 288 One-click "Connect to Mintage Pay" (no key to copy), a Get started box, an "Update Mintage Pay automatically" setting, and a fix for app icons shown where the apps are not offered. -
mintage-pay/trunk/includes/class-mintagepay-admin.php
r3768248 r3768791 166 166 * Webhook connection 167 167 * ------------------------------------------------------------------ */ 168 169 /** 170 * After the API key was saved (the settings form, or "Connect to Mintage Pay", 1.18.0): check the new key with 171 * GET /v1/me, remember it as verified, and connect the webhook (deleting the old key's endpoint). The same steps for 172 * both, so a connected store is set up exactly like one where the key was pasted. 173 * 174 * @param string $old_key The key saved before. 175 * @param string $old_base The API base the old key used (Mintage_Pay::api_base_for()). 176 * @param string $new_key The key saved now ('' = removed). 177 * @param string $base_setting The saved "API base URL" setting ('' = automatic). 178 * @return string 'removed', 'unchanged', 'verified' (the webhook was already connected), 'connected', or 'failed'. 179 */ 180 public static function activate_key( $old_key, $old_base, $new_key, $base_setting ) { 181 $old_key = (string) $old_key; 182 $new_key = (string) $new_key; 183 $new_base = Mintage_Pay::api_base_for( $new_key, (string) $base_setting ); 184 delete_transient( Mintage_Pay::RAILS_TRANSIENT ); 185 $old_api = '' !== $old_key ? Mintage_Pay::api( $old_key, $old_base ) : null; 186 187 if ( '' === $new_key ) { 188 // Key removed: disable the old endpoint and forget the secret. 189 $hook = Mintage_Pay::get_webhook(); 190 if ( $hook && $old_api && isset( $hook['fingerprint'] ) && Mintage_Pay::fingerprint( $old_base, $old_key ) === $hook['fingerprint'] ) { 191 $old_api->delete_webhook( $hook['id'] ); 192 } 193 Mintage_Pay::clear_webhook(); 194 Mintage_Pay::clear_key_verified(); 195 return 'removed'; 196 } 197 198 $credentials_changed = ( $new_key !== $old_key || $new_base !== $old_base ); 199 $hook = Mintage_Pay::get_webhook(); 200 $fingerprint = Mintage_Pay::fingerprint( $new_base, $new_key ); 201 $hook_ok = $hook && ! empty( $hook['secret'] ) && isset( $hook['fingerprint'] ) && $hook['fingerprint'] === $fingerprint; 202 203 if ( ! $credentials_changed && $hook_ok && Mintage_Pay::is_key_verified() ) { 204 return 'unchanged'; 205 } 206 207 $api = Mintage_Pay::api( $new_key, $new_base ); 208 $me = $api->get_me(); 209 if ( is_wp_error( $me ) ) { 210 // A new key is unverified by definition (the stored flag holds another key's fingerprint). 211 self::handle_me_error( $me ); 212 Mintage_Pay::add_notice( 213 'error', 214 sprintf( 215 /* translators: %s: error message */ 216 __( 'Mintage Pay: the API key could not be verified (%s). The payment method stays hidden at checkout until the key is verified. Check the key and save again.', 'mintage-pay' ), 217 self::me_error_text( $me, $new_key, (string) $base_setting ) 218 ) 219 ); 220 return 'failed'; 221 } 222 223 $merchant_id = self::merchant_id( $me ); 224 $name = self::merchant_name( $me ); 225 Mintage_Pay::mark_key_verified( $api->fingerprint(), $merchant_id, $name ); 226 Mintage_Pay::cache_rails( $me ); 227 228 if ( $hook_ok ) { 229 Mintage_Pay::add_notice( 'success', self::connected_message( $name, $new_key ) ); 230 return 'verified'; 231 } 232 233 $previous_api = null; 234 if ( $hook && isset( $hook['fingerprint'] ) ) { 235 if ( $old_api && Mintage_Pay::fingerprint( $old_base, $old_key ) === $hook['fingerprint'] ) { 236 $previous_api = $old_api; 237 } elseif ( $hook['fingerprint'] === $fingerprint ) { 238 $previous_api = $api; 239 } 240 } 241 242 $result = self::connect_webhook( $api, $previous_api, $merchant_id ); 243 if ( true === $result ) { 244 Mintage_Pay::add_notice( 'success', self::connected_message( $name, $new_key ) . ' ' . __( 'Webhook connected.', 'mintage-pay' ) ); 245 return 'connected'; 246 } 247 return 'failed'; 248 } 249 250 /** 251 * "Mintage Pay: API key verified for X (live)." 252 * 253 * @param string $name Merchant name. 254 * @param string $api_key The key (test or live). 255 * @return string 256 */ 257 public static function connected_message( $name, $api_key ) { 258 $mode = Mintage_Pay::is_test_key( (string) $api_key ) 259 ? __( 'TEST MODE: sandbox, test money only', 'mintage-pay' ) 260 : __( 'live', 'mintage-pay' ); 261 return '' !== $name 262 /* translators: 1: merchant business name, 2: "live" or "TEST MODE: ..." */ 263 ? sprintf( __( 'Mintage Pay: API key verified for %1$s (%2$s).', 'mintage-pay' ), $name, $mode ) 264 /* translators: %s: "live" or "TEST MODE: ..." */ 265 : sprintf( __( 'Mintage Pay: API key verified (%s).', 'mintage-pay' ), $mode ); 266 } 168 267 169 268 /** -
mintage-pay/trunk/includes/class-mintagepay-blocks.php
r3768248 r3768791 105 105 106 106 /** 107 * The apps' marks for this method's own row (WC_Gateway_MintagePay::get_icon() for the classic checkout) : Cash App,108 * plus Apple Pay / Google Pay where Mintage Pay offers the card route for the cart's total. None while the two109 * choices are inside the method (the marks are on the choices then) or when it is the only rail.107 * The apps' marks for this method's own row (WC_Gateway_MintagePay::get_icon() for the classic checkout), by the one 108 * rule in Mintage_Pay_Two_Rail::row_marks(): only what Pay by app offers this store for the cart's total, none while 109 * the two choices are inside the method (the marks are on the choices then). 110 110 * 111 111 * @return array[] … … 117 117 $currency = function_exists( 'get_woocommerce_currency' ) ? (string) get_woocommerce_currency() : 'USD'; 118 118 $total = $this->cart_total(); 119 $apps = Mintage_Pay::split_on() 120 || ( Mintage_Pay::crypto_on() && ! ( $total > 0 && Mintage_Pay_Two_Rail::offered( $total, $currency ) ) ); 121 if ( ! $apps ) { 122 return array(); 123 } 124 $wallets = $total > 0 ? Mintage_Pay_Two_Rail::card_status( $total, $currency )['available'] : true; 125 return Mintage_Pay_Two_Rail::mark_images( 'app', $wallets ); 119 // The same rule as the classic checkout (Mintage_Pay_Two_Rail::row_marks()); no cart (the editor): $total is 0. 120 return Mintage_Pay_Two_Rail::row_mark_images( $total, $currency, $total <= 0 ); 126 121 } 127 122 -
mintage-pay/trunk/includes/class-mintagepay-two-rail.php
r3768248 r3768791 223 223 */ 224 224 public static function card_status( $total, $currency ) { 225 $none = self::card_from_options( null ); 225 return self::status( $total, $currency )['card']; 226 } 227 228 /** 229 * Read `options.cash_app` and `options.wallet` of a GET /v1/payment-options response (1.18.0): whether Pay by app 230 * offers Cash App, and crypto, for this store and total. Pure. A server that does not send them offers neither. 231 * 232 * @param mixed $options Response. 233 * @return array { cash_app: bool, wallet: bool } 234 */ 235 public static function apps_from_options( $options ) { 236 $o = is_array( $options ) && isset( $options['options'] ) && is_array( $options['options'] ) ? $options['options'] : array(); 237 return array( 238 'cash_app' => isset( $o['cash_app'] ) && true === $o['cash_app'], 239 'wallet' => isset( $o['wallet'] ) && true === $o['wallet'], 240 ); 241 } 242 243 /** 244 * The card route and the apps for an amount, from one GET /v1/payment-options (card_status() caching: 10 minutes per 245 * amount, 2 after a failure). Unknown (no verified key, the API failed): no card, no apps. 246 * 247 * @param float|string $total Order total in the store currency. 248 * @param string $currency ISO 4217. 249 * @return array { card: card_from_options(), apps: apps_from_options() } 250 */ 251 public static function status( $total, $currency ) { 252 $none = array( 253 'card' => self::card_from_options( null ), 254 'apps' => self::apps_from_options( null ), 255 ); 226 256 $currency = strtoupper( (string) $currency ); 227 257 if ( ! class_exists( 'Mintage_Pay_Webhook' ) || ! Mintage_Pay_Webhook::currency_supported( $currency ) || ! Mintage_Pay::is_key_verified() ) { … … 238 268 $key = self::TRANSIENT . md5( $api->fingerprint() . '|' . $currency . '|' . $minor ); 239 269 $cached = get_transient( $key ); 240 if ( is_array( $cached ) && isset( $cached['available'] ) ) { 241 return self::card_from_options( array( 'card' => $cached ) ); 270 // A value cached by 1.17.0 has no 'apps': asked again. 271 if ( is_array( $cached ) && isset( $cached['available'] ) && isset( $cached['apps'] ) && is_array( $cached['apps'] ) ) { 272 return array( 273 'card' => self::card_from_options( array( 'card' => $cached ) ), 274 'apps' => self::apps_from_options( array( 'options' => $cached['apps'] ) ), 275 ); 242 276 } 243 277 $options = $api->payment_options( Mintage_Pay_Webhook::format_minor( $minor, $currency ), $currency, 5 ); 244 278 $card = self::card_from_options( is_wp_error( $options ) ? null : $options ); 245 set_transient( $key, $card, is_wp_error( $options ) ? 2 * MINUTE_IN_SECONDS : 10 * MINUTE_IN_SECONDS ); 279 $apps = self::apps_from_options( is_wp_error( $options ) ? null : $options ); 280 set_transient( $key, $card + array( 'apps' => $apps ), is_wp_error( $options ) ? 2 * MINUTE_IN_SECONDS : 10 * MINUTE_IN_SECONDS ); 246 281 if ( is_wp_error( $options ) ) { 247 282 Mintage_Pay::log( 'payment options could not be read (the card choice stays hidden for now): ' . $options->get_error_message(), 'warning' ); 248 283 } 249 return $card; 284 return array( 285 'card' => $card, 286 'apps' => $apps, 287 ); 288 } 289 290 /** 291 * The marks on the main method's own row at checkout (classic get_icon() and the block checkout's data use this 292 * one rule, 1.18.0). Pure. 293 * - The two choices are inside the method: none (the marks are on the choices). 294 * - No cart (admin, the block editor): the apps' marks where the method is the apps (split, or crypto its own 295 * method), none otherwise, as before 1.18.0. 296 * - Otherwise only where Pay by app offers Cash App for this store (options.cash_app): Cash App, then Apple Pay and 297 * Google Pay where the card route is offered, then USDC and USDT where crypto is inside Pay by app (crypto not its 298 * own method) and offered (options.wallet). A store without Cash App, or a failed read, shows none. 299 * 300 * @param bool $split "Pay by card" is its own method (Mintage_Pay::split_on()). 301 * @param bool $crypto "Pay with crypto" is its own method (Mintage_Pay::crypto_on()). 302 * @param bool $offered The two choices are offered inside the method for this total. 303 * @param array|null $status status() for the cart's total, or null when there is no cart. 304 * @return array[] marks() entries. 305 */ 306 public static function row_marks( $split, $crypto, $offered, $status ) { 307 if ( ! $split && $offered ) { 308 return array(); 309 } 310 if ( null === $status ) { 311 return ( $split || $crypto ) ? self::marks( 'app', true ) : array(); 312 } 313 if ( empty( $status['apps']['cash_app'] ) ) { 314 return array(); 315 } 316 return self::marks( 'app', ! empty( $status['card']['available'] ), ! $crypto && ! empty( $status['apps']['wallet'] ) ); 317 } 318 319 /** 320 * row_marks() for this store and cart, as image addresses. 321 * 322 * @param float|string $total Cart or order total. 323 * @param string $currency ISO 4217. 324 * @param bool $no_cart There is no cart (admin, the block editor). 325 * @return array[] 326 */ 327 public static function row_mark_images( $total, $currency, $no_cart ) { 328 $status = $no_cart ? null : self::status( $total, $currency ); 329 $offered = ! $no_cart && self::offered( $total, $currency ); 330 return self::images( self::row_marks( Mintage_Pay::split_on(), Mintage_Pay::crypto_on(), $offered, $status ) ); 250 331 } 251 332 … … 329 410 * @param string $choice 'card', 'app' or 'crypto'. 330 411 * @param bool $wallets Apple Pay and Google Pay are offered on Pay by app. 412 * @param bool $coins USDC and USDT after the apps (Pay by app with crypto inside it, row_marks()). 331 413 * @return array[] 332 414 */ 333 public static function marks( $choice, $wallets = true ) {415 public static function marks( $choice, $wallets = true, $coins = false ) { 334 416 if ( 'card' === $choice ) { 335 417 return array( … … 350 432 $out[] = array( 'google-pay', 'Google Pay', 45 ); 351 433 } 434 if ( $coins ) { 435 $out[] = array( 'usdc', 'USDC', 38 ); 436 $out[] = array( 'usdt', 'USDT', 38 ); 437 } 352 438 return $out; 353 439 } … … 361 447 */ 362 448 public static function mark_images( $choice, $wallets = true ) { 449 return self::images( self::marks( $choice, $wallets ) ); 450 } 451 452 /** 453 * marks() entries as addresses: file, label, width. 454 * 455 * @param array[] $marks marks() entries. 456 * @return array[] 457 */ 458 public static function images( array $marks ) { 363 459 $base = plugins_url( 'assets/img/marks/', MINTAGE_PAY_FILE ); 364 460 $out = array(); 365 foreach ( self::marks( $choice, $wallets )as $m ) {461 foreach ( $marks as $m ) { 366 462 $out[] = array( 367 463 'src' => $base . $m[0] . '.svg?ver=' . MINTAGE_PAY_VERSION, … … 382 478 */ 383 479 public static function marks_html( $choice, $wallets = true ) { 480 return self::images_html( self::mark_images( $choice, $wallets ) ); 481 } 482 483 /** 484 * Image addresses (images()) as the payment method row's HTML. 485 * 486 * @param array[] $images images() entries. 487 * @return string 488 */ 489 public static function images_html( array $images ) { 384 490 $html = ''; 385 foreach ( self::mark_images( $choice, $wallets )as $m ) {491 foreach ( $images as $m ) { 386 492 $html .= '<img class="mintagepay-method-mark" src="' . esc_url( $m['src'] ) . '" alt="' . esc_attr( $m['alt'] ) . '" title="' . esc_attr( $m['alt'] ) . '" width="' . (int) $m['width'] . '" height="24" decoding="async" />'; 387 493 } -
mintage-pay/trunk/includes/class-wc-gateway-mintagepay.php
r3768248 r3768791 27 27 // claiming a refund was sent (WooCommerce would otherwise only offer "Refund manually"). 28 28 $this->supports = array_merge( Mintage_Pay_Subscriptions::supports(), array( 'refunds' ) ); 29 // The square Mintage Pay mark for WooCommerce's Payments page (it reads this property, over REST too). The 30 // checkout row never shows it: get_icon() below does not call parent::get_icon(). 31 $this->icon = plugins_url( 'assets/img/mintage-pay.svg', MINTAGE_PAY_FILE ); 29 32 30 33 $this->init_form_fields(); … … 80 83 public function get_icon() { 81 84 $rail = $this->method_rail(); 82 // With "Pay with crypto" as its own method (1.17.0) this method is the apps, unless it shows the two choices83 // inside itself (their marks are on the choices then).84 if ( '' === $rail && Mintage_Pay::crypto_on() && ! $this->two_rail_offered() ) {85 $rail = 'app';86 }87 if ( '' === $rail ) {88 return parent::get_icon();89 }90 return apply_filters( 'woocommerce_gateway_icon', Mintage_Pay_Two_Rail:: marks_html( $rail, $this->wallets_offered()), $this->id );85 if ( 'card' === $rail || 'crypto' === $rail ) { 86 return apply_filters( 'woocommerce_gateway_icon', Mintage_Pay_Two_Rail::marks_html( $rail, $this->wallets_offered() ), $this->id ); 87 } 88 // This method (Pay by app): one rule with the block checkout (Mintage_Pay_Two_Rail::row_marks(), 1.18.0). Never 89 // parent::get_icon(): $this->icon is set for the WooCommerce Payments page only, not for the checkout row. 90 $no_cart = is_admin() && ! wp_doing_ajax(); 91 $currency = function_exists( 'get_woocommerce_currency' ) ? (string) get_woocommerce_currency() : 'USD'; 92 $images = Mintage_Pay_Two_Rail::row_mark_images( $no_cart ? 0 : $this->get_order_total(), $currency, $no_cart ); 93 return apply_filters( 'woocommerce_gateway_icon', Mintage_Pay_Two_Rail::images_html( $images ), $this->id ); 91 94 } 92 95 … … 306 309 'title' => __( 'API key', 'mintage-pay' ), 307 310 'type' => 'password', 308 'description' => __( ' Create one in the Mintage Pay dashboard under Developers > API keys. Saving a new key checks it and connects the webhook automatically.', 'mintage-pay' ),311 'description' => __( 'Easiest: click "Connect to Mintage Pay" at the top of this page and the key is filled in for you. Or create one in the Mintage Pay dashboard under Developers > API keys and paste it here. Saving a new key checks it and connects the webhook automatically.', 'mintage-pay' ), 309 312 'default' => '', 310 313 ), … … 366 369 'type' => 'mintagepay_webhook', 367 370 ), 371 'auto_update' => array( 372 'title' => __( 'Plugin updates', 'mintage-pay' ), 373 'type' => 'mintagepay_auto_update', 374 ), 368 375 'debug' => array( 369 376 'title' => __( 'Debug log', 'mintage-pay' ), … … 399 406 <td class="forminp"> 400 407 <?php if ( '' === (string) $this->get_option( 'api_key' ) ) : ?> 401 <p><?php esc_html_e( 'Not connected. Save an API key first.', 'mintage-pay' ); ?></p> 408 <p><?php esc_html_e( 'Not connected yet.', 'mintage-pay' ); ?></p> 409 <p><?php $this->connect_buttons(); ?></p> 402 410 <?php else : ?> 403 411 <?php if ( $hook && ! empty( $hook['secret'] ) && isset( $hook['fingerprint'] ) && $hook['fingerprint'] === $fingerprint ) : ?> … … 446 454 447 455 /** 456 * The two Connect buttons (live account, sandbox test account). 457 */ 458 protected function connect_buttons() { 459 ?> 460 <a class="button button-primary" href="<?php echo esc_url( Mintage_Pay_Connect::start_url( 'live' ) ); ?>"><?php esc_html_e( 'Connect to Mintage Pay', 'mintage-pay' ); ?></a> 461 <a class="button" href="<?php echo esc_url( Mintage_Pay_Connect::start_url( 'test' ) ); ?>"><?php esc_html_e( 'Connect a test (sandbox) account', 'mintage-pay' ); ?></a> 462 <?php 463 } 464 465 /** 466 * Settings page: the "Get started" panel (no key yet) or the "Replace the key?" box (a Connect came back while a 467 * working key is saved), then the settings. Only on this method's own page, not the card or crypto method's. 468 */ 469 public function admin_options() { 470 if ( Mintage_Pay::GATEWAY_ID === $this->id ) { 471 $pending = Mintage_Pay_Connect::pending(); 472 if ( $pending ) { 473 $this->confirm_box( $pending ); 474 } elseif ( '' === (string) $this->get_option( 'api_key' ) ) { 475 $this->get_started_panel(); 476 } 477 } 478 parent::admin_options(); 479 } 480 481 /** 482 * "Get started": connect, try the sandbox, apply, read the guide. 483 */ 484 private function get_started_panel() { 485 ?> 486 <div class="notice notice-info inline" style="padding:12px 16px;margin:16px 0;"> 487 <h3 style="margin-top:0;"><?php esc_html_e( 'Get started with Mintage Pay', 'mintage-pay' ); ?></h3> 488 <ol style="margin-left:1.5em;"> 489 <li><?php esc_html_e( 'Have a Mintage Pay account? Click "Connect to Mintage Pay", sign in and approve this store. The API key and the webhook are set up for you and the payment method is switched on.', 'mintage-pay' ); ?></li> 490 <li> 491 <?php 492 printf( 493 /* translators: %s: link to the Mintage Pay application form */ 494 esc_html__( 'No account yet? %s (a few minutes).', 'mintage-pay' ), 495 '<a href="https://mintagepay.com/#apply" target="_blank" rel="noopener noreferrer">' . esc_html__( 'Apply for a Mintage Pay account', 'mintage-pay' ) . '</a>' 496 ); 497 ?> 498 </li> 499 <li> 500 <?php 501 printf( 502 /* translators: %s: link to the sandbox */ 503 esc_html__( 'Want to try it first? Make a free test account on the %s, then click "Connect a test (sandbox) account". Test orders use test money only.', 'mintage-pay' ), 504 '<a href="https://sandbox.mintagepay.com/" target="_blank" rel="noopener noreferrer">' . esc_html__( 'Mintage Pay sandbox', 'mintage-pay' ) . '</a>' 505 ); 506 ?> 507 </li> 508 </ol> 509 <p><?php $this->connect_buttons(); ?></p> 510 <p class="description"> 511 <?php 512 printf( 513 /* translators: %s: link to the setup guide */ 514 esc_html__( 'Step by step: %s.', 'mintage-pay' ), 515 '<a href="https://mintagepay.com/docs/integrations/#woocommerce" target="_blank" rel="noopener noreferrer">' . esc_html__( 'the WooCommerce setup guide', 'mintage-pay' ) . '</a>' 516 ); 517 ?> 518 </p> 519 </div> 520 <?php 521 } 522 523 /** 524 * A Connect came back while a working key is saved: replace it, or keep it. 525 * 526 * @param array $pending The waiting connect (code, verifier, base). 527 */ 528 private function confirm_box( array $pending ) { 529 $current_name = Mintage_Pay::verified_merchant_name(); 530 $current_mode = Mintage_Pay::is_test_key( (string) $this->get_option( 'api_key' ) ) ? __( 'test mode (sandbox)', 'mintage-pay' ) : __( 'live', 'mintage-pay' ); 531 $new_mode = Mintage_Pay::SANDBOX_API_BASE === $pending['base'] ? __( 'test mode (sandbox)', 'mintage-pay' ) : __( 'live', 'mintage-pay' ); 532 ?> 533 <div class="notice notice-warning inline" style="padding:12px 16px;margin:16px 0;"> 534 <h3 style="margin-top:0;"><?php esc_html_e( 'Replace the Mintage Pay key?', 'mintage-pay' ); ?></h3> 535 <p> 536 <?php 537 if ( '' !== $current_name ) { 538 /* translators: 1: Mintage Pay business name, 2: "live" or "test mode (sandbox)" */ 539 echo esc_html( sprintf( __( 'This store takes payments for %1$s (%2$s) now.', 'mintage-pay' ), $current_name, $current_mode ) ); 540 } else { 541 /* translators: %s: "live" or "test mode (sandbox)" */ 542 echo esc_html( sprintf( __( 'This store has a working Mintage Pay key now (%s).', 'mintage-pay' ), $current_mode ) ); 543 } 544 echo ' '; 545 /* translators: %s: "live" or "test mode (sandbox)" */ 546 echo esc_html( sprintf( __( 'You just approved a new connection (%s). Replacing the key sends new payments to the account you approved.', 'mintage-pay' ), $new_mode ) ); 547 ?> 548 </p> 549 <?php if ( Mintage_Pay::SANDBOX_API_BASE === $pending['base'] && ! Mintage_Pay::is_test_key( (string) $this->get_option( 'api_key' ) ) ) : ?> 550 <p><strong style="color:#b32d2e;"><?php esc_html_e( 'The new key is a test key: customers would pay with test money and no real payment would reach you.', 'mintage-pay' ); ?></strong></p> 551 <?php endif; ?> 552 <p> 553 <a class="button button-primary" href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin-post.php?action=' . Mintage_Pay_Connect::CONFIRM_ACTION ), Mintage_Pay_Connect::CONFIRM_ACTION ) ); ?>"><?php esc_html_e( 'Replace the key', 'mintage-pay' ); ?></a> 554 <a class="button" href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin-post.php?action=' . Mintage_Pay_Connect::CANCEL_ACTION ), Mintage_Pay_Connect::CANCEL_ACTION ) ); ?>"><?php esc_html_e( 'Keep the current key', 'mintage-pay' ); ?></a> 555 </p> 556 </div> 557 <?php 558 } 559 560 /** 561 * The "Plugin updates" row: WordPress's own auto-update choice for this plugin (the Plugins page's "Enable 562 * auto-updates" link), shown as a checkbox. 563 * 564 * @param string $key Field key. 565 * @param array $data Field data. 566 * @return string 567 */ 568 public function generate_mintagepay_auto_update_html( $key, $data ) { 569 $state = Mintage_Pay_Connect::auto_update_state(); 570 $field_key = $this->get_field_key( $key ); 571 ob_start(); 572 ?> 573 <tr valign="top"> 574 <th scope="row" class="titledesc"><label for="<?php echo esc_attr( $field_key ); ?>"><?php echo esc_html( $data['title'] ); ?></label></th> 575 <td class="forminp"> 576 <fieldset> 577 <label for="<?php echo esc_attr( $field_key ); ?>"> 578 <input type="checkbox" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" value="1" <?php checked( $state['on'] ); ?> <?php disabled( ! $state['allowed'] ); ?> /> 579 <?php esc_html_e( 'Update Mintage Pay automatically when a new version is out', 'mintage-pay' ); ?> 580 </label> 581 <p class="description"> 582 <?php 583 if ( $state['allowed'] ) { 584 esc_html_e( 'The same as "Enable auto-updates" for Mintage Pay on the Plugins page. Recommended: fixes and new payment options reach your checkout without you doing anything. If your host or a tool such as MainWP manages your updates, that may already cover this site.', 'mintage-pay' ); 585 } else { 586 esc_html_e( 'Your host or your site settings manage plugin updates here, or your user cannot update plugins, so this cannot be changed from this page.', 'mintage-pay' ); 587 } 588 ?> 589 </p> 590 </fieldset> 591 </td> 592 </tr> 593 <?php 594 return (string) ob_get_clean(); 595 } 596 597 /** 598 * The auto-update checkbox: 'yes' or 'no' (WordPress's own setting is the one that counts, see process_admin_options()). 599 * 600 * @param string $key Key. 601 * @param mixed $value Value. 602 * @return string 603 */ 604 public function validate_mintagepay_auto_update_field( $key, $value ) { 605 return ! empty( $value ) ? 'yes' : 'no'; 606 } 607 608 /* ------------------------------------------------------------------ * 609 * WooCommerce's Payments page (WooCommerce 9.6+ calls these; older versions never do). The card and crypto methods 610 * share the main method's key, so "set up", "connected" and "test mode" are the same for all three. 611 * ------------------------------------------------------------------ */ 612 613 /** 614 * Needs setup until a key has been checked with Mintage Pay. Not "is usable": that also needs the method switched 615 * on, and WooCommerce will not switch on a method that says it needs setup. 616 * 617 * @return bool 618 */ 619 public function needs_setup() { 620 return ! Mintage_Pay::is_key_verified(); 621 } 622 623 /** 624 * Connected: a key is saved and Mintage Pay accepted it. 625 * 626 * @return bool 627 */ 628 public function is_account_connected() { 629 return Mintage_Pay::is_key_verified(); 630 } 631 632 /** 633 * Test mode: the saved key is a sandbox key. 634 * 635 * @return bool 636 */ 637 public function is_test_mode() { 638 return Mintage_Pay::is_test_key( (string) Mintage_Pay::setting( 'api_key', '' ) ); 639 } 640 641 /** 642 * This method's own settings page. 643 * 644 * @return string 645 */ 646 public function get_settings_url() { 647 return admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=' . $this->id ); 648 } 649 650 /** 651 * Where "Complete setup" goes: the main method's settings, with the Connect buttons. 652 * 653 * @param string $return_url Where WooCommerce would like to come back to (not used: the settings page is the end). 654 * @return string 655 */ 656 public function get_connection_url( $return_url = '' ) { 657 return Mintage_Pay::settings_url(); 658 } 659 660 /** 661 * Links on the Payments page's menu for this method. 662 * 663 * @param string $country_code Store country (not used: the same links everywhere). 664 * @return array[] 665 */ 666 public function get_provider_links( $country_code = '' ) { 667 return self::provider_links(); 668 } 669 670 /** 671 * The Payments page links (pure, tested in tests/payments-page-test.php). 672 * 673 * @return array[] 674 */ 675 public static function provider_links() { 676 return array( 677 array( 678 '_type' => 'about', 679 'url' => 'https://mintagepay.com/', 680 ), 681 array( 682 '_type' => 'documentation', 683 'url' => 'https://mintagepay.com/docs/integrations/#woocommerce', 684 ), 685 array( 686 '_type' => 'support', 687 'url' => 'https://mintagepay.com/docs/', 688 ), 689 array( 690 '_type' => 'pricing', 691 'url' => 'https://mintagepay.com/#pricing', 692 ), 693 array( 694 '_type' => 'terms', 695 'url' => 'https://mintagepay.com/terms.html', 696 ), 697 ); 698 } 699 700 /** 448 701 * The webhook row stores nothing. 449 702 * … … 521 774 522 775 /** 523 * Save settings, then validate a new key with GET /v1/me and register the webhook. 776 * Save settings, then validate a new key with GET /v1/me and register the webhook (Mintage_Pay_Admin::activate_key(), 777 * the same steps "Connect to Mintage Pay" runs), and apply the auto-update choice. 524 778 * 525 779 * @return bool … … 536 790 $this->enabled = $this->get_option( 'enabled' ); 537 791 538 $new_key = (string) $this->get_option( 'api_key' ); 539 $new_base = Mintage_Pay::api_base_for( $new_key, (string) $this->get_option( 'api_base_url' ) ); 540 delete_transient( Mintage_Pay::RAILS_TRANSIENT ); 541 $old_api = '' !== $old_key ? Mintage_Pay::api( $old_key, $old_base ) : null; 542 543 if ( '' === $new_key ) { 544 // Key removed: disable the old endpoint and forget the secret. 545 $hook = Mintage_Pay::get_webhook(); 546 if ( $hook && $old_api && isset( $hook['fingerprint'] ) && Mintage_Pay::fingerprint( $old_base, $old_key ) === $hook['fingerprint'] ) { 547 $old_api->delete_webhook( $hook['id'] ); 548 } 549 Mintage_Pay::clear_webhook(); 550 Mintage_Pay::clear_key_verified(); 551 return $saved; 552 } 553 554 $credentials_changed = ( $new_key !== $old_key || $new_base !== $old_base ); 555 $hook = Mintage_Pay::get_webhook(); 556 $fingerprint = Mintage_Pay::fingerprint( $new_base, $new_key ); 557 $hook_ok = $hook && ! empty( $hook['secret'] ) && isset( $hook['fingerprint'] ) && $hook['fingerprint'] === $fingerprint; 558 559 if ( ! $credentials_changed && $hook_ok && Mintage_Pay::is_key_verified() ) { 560 return $saved; 561 } 562 563 $api = Mintage_Pay::api( $new_key, $new_base ); 564 $me = $api->get_me(); 565 if ( is_wp_error( $me ) ) { 566 // A new key is unverified by definition (the stored flag holds another key's fingerprint). 567 Mintage_Pay_Admin::handle_me_error( $me ); 568 Mintage_Pay::add_notice( 569 'error', 570 sprintf( 571 /* translators: %s: error message */ 572 __( 'Mintage Pay: the API key could not be verified (%s). The payment method stays hidden at checkout until the key is verified. Check the key and save again.', 'mintage-pay' ), 573 Mintage_Pay_Admin::me_error_text( $me, $new_key, (string) $this->get_option( 'api_base_url' ) ) 574 ) 575 ); 576 return $saved; 577 } 578 579 $merchant_id = Mintage_Pay_Admin::merchant_id( $me ); 580 $name = isset( $me['merchant']['name'] ) && is_string( $me['merchant']['name'] ) ? $me['merchant']['name'] : ''; 581 Mintage_Pay::mark_key_verified( $api->fingerprint(), $merchant_id, $name ); 582 Mintage_Pay::cache_rails( $me ); 583 584 if ( $hook_ok ) { 585 Mintage_Pay::add_notice( 'success', $this->connected_message( $name ) ); 586 return $saved; 587 } 588 589 $previous_api = null; 590 if ( $hook && isset( $hook['fingerprint'] ) ) { 591 if ( $old_api && Mintage_Pay::fingerprint( $old_base, $old_key ) === $hook['fingerprint'] ) { 592 $previous_api = $old_api; 593 } elseif ( $hook['fingerprint'] === $fingerprint ) { 594 $previous_api = $api; 595 } 596 } 597 598 $result = Mintage_Pay_Admin::connect_webhook( $api, $previous_api, $merchant_id ); 599 if ( true === $result ) { 600 Mintage_Pay::add_notice( 'success', $this->connected_message( $name ) . ' ' . __( 'Webhook connected.', 'mintage-pay' ) ); 601 } 792 Mintage_Pay_Admin::activate_key( $old_key, $old_base, (string) $this->get_option( 'api_key' ), (string) $this->get_option( 'api_base_url' ) ); 793 Mintage_Pay_Connect::save_auto_update( 'yes' === $this->get_option( 'auto_update' ) ); 602 794 return $saved; 603 }604 605 /**606 * "Connected to Mintage Pay as X."607 *608 * @param string $name Merchant name.609 * @return string610 */611 private function connected_message( $name ) {612 $mode = Mintage_Pay::is_test_key( (string) $this->get_option( 'api_key' ) )613 ? __( 'TEST MODE: sandbox, test money only', 'mintage-pay' )614 : __( 'live', 'mintage-pay' );615 return '' !== $name616 /* translators: 1: merchant business name, 2: "live" or "TEST MODE: ..." */617 ? sprintf( __( 'Mintage Pay: API key verified for %1$s (%2$s).', 'mintage-pay' ), $name, $mode )618 /* translators: %s: "live" or "TEST MODE: ..." */619 : sprintf( __( 'Mintage Pay: API key verified (%s).', 'mintage-pay' ), $mode );620 795 } 621 796 -
mintage-pay/trunk/mintage-pay.php
r3768248 r3768791 4 4 * Plugin URI: https://mintagepay.com/docs/integrations/#woocommerce 5 5 * Description: Accept USDC and USDT stablecoin payments through the Mintage Pay hosted checkout, with prices in USD, EUR, GBP and more. 6 * Version: 1.1 7.06 * Version: 1.18.0 7 7 * Requires at least: 6.4 8 8 * Requires PHP: 7.4 … … 14 14 * Text Domain: mintage-pay 15 15 * WC requires at least: 8.0 16 * WC tested up to: 11. 116 * WC tested up to: 11.2 17 17 * 18 18 * @package MintagePay … … 21 21 defined( 'ABSPATH' ) || exit; 22 22 23 define( 'MINTAGE_PAY_VERSION', '1.1 7.0' );23 define( 'MINTAGE_PAY_VERSION', '1.18.0' ); 24 24 define( 'MINTAGE_PAY_FILE', __FILE__ ); 25 25 define( 'MINTAGE_PAY_PATH', plugin_dir_path( __FILE__ ) ); … … 153 153 require_once MINTAGE_PAY_PATH . 'includes/class-mintagepay-reminder.php'; 154 154 require_once MINTAGE_PAY_PATH . 'includes/class-mintagepay-two-rail.php'; 155 require_once MINTAGE_PAY_PATH . 'includes/class-mintagepay-connect.php'; 155 156 156 157 add_filter( 'woocommerce_payment_gateways', array( __CLASS__, 'add_gateway' ) ); … … 176 177 Mintage_Pay_Discount::init(); 177 178 Mintage_Pay_Reminder::init(); 179 Mintage_Pay_Connect::init(); 178 180 } 179 181 -
mintage-pay/trunk/readme.txt
r3768368 r3768791 7 7 WC requires at least: 8.0 8 8 WC tested up to: 11.2 9 Stable tag: 1.1 7.09 Stable tag: 1.18.0 10 10 License: GPLv2 or later 11 11 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 21 21 * **Pay by app**: Cash App in one tap, plus Apple Pay and Google Pay where Mintage Pay offers them for the total. 22 22 23 **Get started in minutes:** install, try it with test money in the sandbox, then apply for a live account. See Installation below, or the full guide at https://mintagepay.com/docs/integrations/#woocommerce23 **Get started in minutes:** install, click "Connect to Mintage Pay" and approve your store. No key to copy. Try it with test money in the sandbox first if you like, then apply for a live account. See Installation below, or the full guide at https://mintagepay.com/docs/integrations/#woocommerce 24 24 25 25 Mintage Pay sends your customer to a secure hosted checkout where they pay in stablecoins (USDC or USDT) from a wallet or an exchange, on the networks you turn on in your Mintage Pay dashboard (for example Base, Polygon, Solana or TRON). A network appears at checkout only when you have set a payout address for it. … … 53 53 What is sent, and when: 54 54 55 * When you click "Connect to Mintage Pay" (or "Connect a test (sandbox) account"): your browser opens app.mintagepay.com (or sandbox.mintagepay.com) with this site's address, its name, the plugin version, a random value and a code challenge (PKCE). You sign in there and approve this store. Your browser then comes back to this site with a one-time code, and the plugin sends that code and its secret to Mintage Pay to receive this store's API key. Nothing is sent before you click. 55 56 * When you save the settings, reconnect the webhook, or activate, deactivate or delete the plugin: your API key (in the Authorization header), this store's webhook URL and the store name, to check the key and to add or remove the webhook endpoint. 56 57 * When a customer chooses Mintage Pay at checkout: the order total and currency, the order number, a description ("Order #1042 from Your Store"), the thank-you and cancel page addresses, the WooCommerce order id and order key, the invoice expiry, and the customer's billing email address. Mintage Pay emails the customer a receipt only if you turn off "Let WooCommerce send the order emails"; otherwise it writes to them only when they ask for a refund on Mintage Pay's refund page. For an order paid by card, the email is also kept as part of the record of that card payment, in case the customer disputes the charge. … … 74 75 **3. Go live.** Apply at https://mintagepay.com/#apply. Once your account is approved, sign in at https://app.mintagepay.com, set a payout address for each network you want to be paid on, and create a live key (mp_live_...). 75 76 76 **4. Connect your store.** Go to WooCommerce > Settings > Payments > Mintage Pay , paste the key,tick Enable and save. Saving checks the key and registers this store's webhook automatically. The settings page shows "Connected to (your business name) (live)" when it is done, or "(TEST MODE: sandbox, test money only)" for a sandbox key.77 78 To try it first, use a sandbox key (mp_test_...) from https://sandbox.mintagepay.com. Leave "API base URL" empty: the key decides whether the plugin talks to the sandbox or the live service. Replace it with a live key (mp_live_...) before you take real orders.77 **4. Connect your store.** Go to WooCommerce > Settings > Payments > Mintage Pay and click "Connect to Mintage Pay" (or "Connect a test (sandbox) account"). Sign in to Mintage Pay, check that the store address shown is yours, and click Approve. You come back to WordPress with the key saved, the webhook registered and the payment method switched on. You can also paste a key from Developers > API keys instead: tick Enable and save. Saving checks the key and registers this store's webhook automatically. The settings page shows "Connected to (your business name) (live)" when it is done, or "(TEST MODE: sandbox, test money only)" for a sandbox key. 78 79 To try it first, connect a sandbox account, or paste a sandbox key (mp_test_...) from https://sandbox.mintagepay.com. Click "Connect to Mintage Pay" again later to switch to your live account: the plugin asks before it replaces a working key. Leave "API base URL" empty: the key decides whether the plugin talks to the sandbox or the live service. Replace it with a live key (mp_live_...) before you take real orders. 79 80 80 81 If you move the store to a new address or the webhook shows "Not connected", click "Reconnect webhook" on the settings page. … … 82 83 **5. Choose your methods.** Under WooCommerce > Settings > Payments, switch on "Mintage Pay: Pay by card" and "Mintage Pay: Pay with crypto" if you want them as their own methods, and drag the methods into the order you want. 83 84 84 **6. Stay up to date automatically.** On the Plugins screen, click "Enable auto-updates" next to Mintage Pay. Fixes and new payment options then install on their own.85 **6. Stay up to date automatically.** Tick "Update Mintage Pay automatically" on the settings page, or click "Enable auto-updates" next to Mintage Pay on the Plugins screen (it is the same setting). Fixes and new payment options then install on their own. 85 86 86 87 = Documentation = … … 100 101 Yes. A sandbox account for testing is free and instant at https://sandbox.mintagepay.com. A live account is by application at https://mintagepay.com/#apply. 101 102 103 = What does "Connect to Mintage Pay" do? = 104 105 It makes an API key for this store in your Mintage Pay account and saves it here, so you never copy a key by hand. You approve it on Mintage Pay's own site, signed in to your account, and the page shows the store address that asked. Only approve if you just clicked Connect in your own WordPress. The key appears under Developers > API keys as "WooCommerce (your store address)" and the account owner gets an email. If you connect the same store again, the key from the earlier Connect is revoked as soon as the new one is used. Keys you made by hand are never touched. 106 102 107 = Why don't I see Pay by card or Pay by app? = 103 108 … … 151 156 152 157 == Changelog == 158 159 = 1.18.0 = 160 * New: "Connect to Mintage Pay". Click it on the settings page, sign in to Mintage Pay and approve your store: the API key is saved, the webhook is registered and the payment method is switched on. No key to copy. "Connect a test (sandbox) account" does the same with test money. If a working key is already saved, the plugin asks before replacing it. 161 * New: a "Get started" box on the settings page while no key is saved, with Connect, the sandbox, the application form and the setup guide. 162 * New: "Update Mintage Pay automatically" on the settings page (WordPress's own auto-update setting for this plugin). 163 * WooCommerce's Payments page now shows the Mintage Pay icon, says the method needs setup until a key is verified and shows test mode for a sandbox key, and links to the guide, pricing and terms. Each Mintage Pay method opens its own settings. 164 * Fix: with only the main method on, its row showed the Cash App, Apple Pay and Google Pay icons even where Mintage Pay does not offer those apps for the store. The icons now follow what Mintage Pay offers, on the classic and the block checkout. 165 * Tested with WooCommerce 11.2. 153 166 154 167 = 1.17.0 = … … 269 282 = 1.0.0 = 270 283 * First release. 284 285 == Upgrade Notice == 286 287 = 1.18.0 = 288 One-click "Connect to Mintage Pay" (no key to copy), a Get started box, an "Update Mintage Pay automatically" setting, and a fix for app icons shown where the apps are not offered.
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)