| 开发者 | sulemanshahjahan |
|---|---|
| 更新时间 | 2026年5月18日 06:04 |
| PHP版本: | 8.2 及以上 |
| WordPress版本: | 6.9 |
| 版权: | GPL-2.0-or-later |
| 版权网址: | 版权信息 |
RateService::quote() entry point feeds Classic Checkout, Blocks Checkout, and the WP-CLI wp precision-rates test-rate command — so cart, checkout, and your terminal all return byte-identical rates within the cache TTL.
The diagnostic surface is built for real-world support load. The Rate Test admin screen captures every quote attempt's full request and response from ShipEngine into a 1-hour transient and surfaces it inline (collapsible, color-coded by HTTP status) so when a customer reports "no shipping options," you can see exactly which carrier returned what. The Services screen auto-discovers every carrier:service_code flowing through the rate filter and lets you uncheck the ones you don't want shown. The Plugin Status panel on the Overview tab reports the running version, saved API key state, active carriers, cache TTL, and current markup at a glance — so verifying "is the new code actually live with my settings" is a glance, not an SSH dive.
Privacy and compliance are first-class. The plugin transmits only postal codes, country codes, and parcel dimensions to ShipEngine — never customer name, email, IP, billing address, or order ID. Suggested privacy-policy boilerplate auto-registers with WP's Settings → Privacy editor on activation. Personal-data exporter and eraser hooks are wired so the WP Tools → Export/Erase Personal Data flows recognize the plugin as compliant. EU/UK merchants can flip on a Settings → Privacy toggle to render a "Shipping rates calculated using ShipEngine — Privacy policy" line under the cart and checkout shipping options.
Highlights
/v1/rates endpoint — UPS, USPS, FedEx, DHL Express, Stamps.com all behind a single API key. Or connect UPS / USPS directly with your own developer credentials.dvdoug/boxpacker library. Define your box catalog under WooCommerce → Box catalog and items pack into the smallest viable box, ships-alone items respected.sodium_crypto_secretbox, derived per-install from wp_salt('auth') . AUTH_KEY. The plugin refuses to encrypt anything when AUTH_KEY is missing or matches the WP install placeholder./wp-content/plugins/precision-live-rates/, or install via the WordPress Plugins screen. Activate.AUTH_KEY defined in wp-config.php (rotate via https://api.wordpress.org/secret-key/1.1/salt/ if you've never customized it)Sign up at https://dashboard.shipengine.com/ — the free sandbox tier returns synthetic rates that work end-to-end for testing. Once you're ready for production, the same dashboard issues LIVE_… keys; connect at least one carrier (USPS via Stamps.com Connect is free and the easiest start) under ShipStation/ShipEngine → Settings → Shipping → Carriers, then paste the key into Precision Live Rates → Settings → ShipEngine. The Test Connection button below the key field pings /v1/carriers and lists everything connected — use it to confirm the key authenticates before going live.
ShipEngine returns each carrier's account/negotiated rate. For UPS specifically, that's typically 30-50% below ups.com retail (UPS heavily discounts via aggregators to compete with USPS). To display retail-equivalent prices to customers, set the UPS markup % under Precision Live Rates → Settings → Markup. 65-75% bridges the gap for most accounts; check a few real shipments via the Rate Test tab to calibrate. USPS rates from ShipEngine already match retail — leave the USPS markup at 0.
Yes. Under Settings → UPS direct or USPS direct, paste your client ID + client secret. The plugin uses OAuth 2.0 client-credentials flows for both carriers. Sandbox and production toggle with a single checkbox. You can run UPS direct + USPS direct + ShipEngine simultaneously — rates from all three sources merge into a single deduped list at checkout.
Trigger at least one rate quote (open the cart with a shippable address). Then visit Precision Live Rates → Services. Every carrier:service_code the plugin has seen is listed as a checkbox. Uncheck what you don't want, save. The change applies to the very next cart view — the plugin auto-flushes WC's shipping cache on save. If a service still shows up after saving, the cause is almost always a downstream cache (Varnish, Breeze, browser, CDN) serving a stale checkout page; the diagnostic count at the top of the Services screen tells you whether the save itself persisted.
Default on. When no box catalog is configured, the plugin can either ship each cart line as its own parcel (carriers bill each one — 4 mugs = 4 UPS labels = 4× the cost), or aggregate the cart into one representative parcel by stacking items along their smallest dimension. The default "combine" behavior is what most small shops want; toggle off under Settings → Packing if you genuinely need strict per-item billing. Once you configure a box catalog under Precision Live Rates → Boxes, items pack into real boxes regardless of this setting.
A few possibilities. (1) The plugin's own rate cache. Default TTL is 60 seconds; click "Clear cached rates now" on Overview → Quick actions to bust it immediately. (2) WC's shipping transient. Auto-flushed on every settings save, but if you saved via raw update_option() the auto-flush didn't fire — clear from Overview. (3) Editing a product's weight/dimensions/shipping class auto-invalidates the rate cache, so 0.2.2+ shouldn't have this issue from product edits. (4) Downstream cache (Cloudways Varnish, Breeze, browser, CDN) serving stale checkout HTML. The Services tab's diagnostic count distinguishes "save didn't persist" from "downstream cache is stale."
It returns whatever the carrier returns for international destinations. The plugin's address-fallback logic currently optimizes for US ZIPs (auto-derives state from ZIP when the customer leaves it blank); other countries pass through. There is no separate customs declaration workflow yet — declared values and dimensions pass through to the carrier; carriers handle customs ingestion. Canadian and UK postal-code → province/region inference is on the roadmap (BACKLOG E4).
GitHub issues: https://github.com/sulemanshahjahan/precision-live-rates-for-wooCommerce/issues. Please include WordPress version, WooCommerce version, PHP version, plugin version, and (for rate-related issues) the relevant <details> block from Precision Live Rates → Rate test → Raw ShipEngine I/O. The Logs tab also captures debug output when "Verbose debug logging" is enabled in Settings → Cache & diagnostics — the most recent entries are usually the most relevant.
OnboardingWizard::renderField() refactored to take typed bool $required and ?int $maxLength parameters instead of an opaque $extraAttrs HTML-fragment string. Every dynamic value is now individually esc_attr()-escaped at the echo site, eliminating the WordPress.Security.EscapeOutput.OutputNotEscaped warning without resorting to a phpcs:ignore. Fixed two more 404 URLs in the External services + Privacy sections: ShipEngine terms now points to https://www.shipengine.com/terms-of-service/ and the privacy policy to https://auctane.com/privacy-policy/ (ShipEngine's parent company).strpos($hookSuffix, ...) check was matching against the text domain string instead of the admin menu slug, so the precision-live-rates-admin stylesheet never enqueued on a fresh install. Pinned the check to AdminScreen::PAGE_SLUG so it stays in sync with the menu slug regardless of what the text domain is renamed to.precision-live-rates to precision-live-rates-for-woocommerce across every __(), _e(), esc_html__(), etc. call (251 sites), the plugin header, the Plugin::TEXT_DOMAIN constant, the privacy exporter/eraser slug, the WC Blocks integration name, the phpcs.xml configured text domain, and the language file names. Existing translations on translate.wordpress.org will now resolve correctly once the plugin is published. The admin menu slug (?page=precision-live-rates), CSS class prefixes, option/transient keys, and hook prefixes are unchanged.dvdoug/boxpacker upgraded from 3.12.1 to 4.1.1 (InfalliblePacker → Packer::throwOnUnpackableItem(false), getKeepFlat() → getAllowedRotation()). Minimum PHP bumped 8.1 → 8.2 to match the new boxpacker requirement. Vendor dev artifacts (*.feature, *.py, *.ps1, vendor/dvdoug/boxpacker/docs/, vendor/dvdoug/boxpacker/features/) now stripped from the submission zip via the build script's extension + path excludes. BoxCatalogScreen::carriersField() now runs each POSTed allowed_carriers entry through sanitize_key() before the value reaches update_option(). Fixed two USPS URLs in the External services section that returned 404.registerLicensing() method, no premium-tier mentions in the readme) so the plugin is fully GPL-compliant per Guideline 5. Renamed the PHP namespace from the generic Acme\PrecisionRates to a project-specific PrecisionLiveRates per the prefix-uniqueness guideline. Tightened nonce handling in the SettingsPage and BoxCatalogScreen guard methods — $_POST['_wpnonce'] now flows through sanitize_text_field() before wp_verify_nonce(). Removed the comparative-marketing paragraph from the description per directory-content rules. Added a Requires Plugins: woocommerce header. Replaced broken GitHub URLs in the plugin header. Expanded the External services section with explicit data-flow, ToS, and privacy-policy links for ShipEngine, UPS, and USPS.wc-precision-rates to precision-live-rates to clear the trademarked_term reviewer warning (wc is reserved for WooCommerce trademark protection). Bulk rename touches text domain, hook prefixes (precision_live_rates_*), constants (PRECISION_LIVE_RATES_FILE / _DIR), CSS asset handles, form-field prefixes (plr_*), and the plugin entry filename (precision-live-rates.php). The three remaining AuditLog SQL warnings (WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber, UnfinishedPrepare, and the $wpdb->insert() DirectQuery warning) are now suppressed with the correct phpcs rule names — the previous phpcs:disable bands had WordPress.DB.PreparedSQL.NotPrepared listed, which is a different sniff than the PreparedSQLPlaceholders.* family that Plugin Check actually flags. Result: zero Plugin Check errors, zero warnings.pre_set_site_transient_update_plugins token no longer appears in any shipped file. Excluded WP-ORG-SUBMISSION.md and any root *.md from the submission build. Removed the redundant load_plugin_textdomain() call (WP 4.6+'s just-in-time loader handles this). Migrated the AuditLog INSERT to $wpdb->insert() to clear UnescapedDBParameter warnings.Tested up to: bumped 6.6 → 6.9; readme tags trimmed 12 → 5; short description trimmed to 121 chars; .gitkeep files excluded from the build script; composer.json now ships alongside vendor/; $_SERVER['REMOTE_ADDR'] now flows through wp_unslash + sanitize_text_field; AuditLog SQL strings inlined into $wpdb->prepare() to clear false-positive UnescapedDBParameter warnings; TransientStorage prefix-DELETE warnings annotated.WooCommerce\CustomerPolish class with 14-test coverage.Audit\AuditLog class + custom DB table records every state-changing admin action: settings saves, box CRUD, service-filter changes, cache clears, ShipEngine connection tests. New "Audit log" tab on the AdminScreen renders the most recent 100 entries with filter-by-event-type + paginated history; CSV export available. 30-day retention via daily cron (precision_live_rates_audit_prune); the cron event + retention window are filterable. Schema bootstraps idempotently via dbDelta() on admin_init so first-time installs see the table appear without an explicit activation hook. 10-test AuditLogTest + new InMemoryWpdb test double covering insert / SELECT / count / pagination / prune / CSV / event-slug stability.Support\AddressInference free function class extracted from the ShipEngine mapper: stateFromPostalCode($postal, $country) dispatches by ISO country code to US (50 states + DC + PR), Canada (10 provinces + 3 territories via the leading postal-code letter), or GB / UK (ENG / SCT / WLS / NIR via the postcode area prefix). Other countries pass through with empty state — ShipEngine doesn't strictly require it for non-US/CA shipments. ShipEngineRateMapper::buildAddress() now uses the new helper for any country with no user-supplied state, so a Toronto M5V address with state blank produces state_province: ON in the ShipEngine payload, an Edinburgh EH1 address produces SCT, etc. 49-test parametric AddressInferenceTest covers ~20 Canadian postal-code prefixes, 16 UK postcode areas, and the dispatch-by-country surface.sulemanshahjahan; Description string in the plugin header updated to reflect the actual ShipEngine/UPS/USPS/FedEx/DHL surface; Tested up to bumped to 6.6. Static pre-flight scan against plugin-check expectations: zero hits for eval/exec/system/shell_exec/passthru/proc_open, zero sslverify=>false, zero unserialize of HTTP bodies, zero translation calls without text domain, all __()/_e()/etc. calls use the static precision-live-rates text domain. New composer ci script bundles lint + stan + test + probe-mo for one-command pre-submission verification.Admin\PrivacyNotice class wires three things: (1) a suggested privacy-policy boilerplate auto-registered into WP Settings → Privacy → Policy guide editor, naming ShipEngine explicitly and enumerating exactly what is and isn't transmitted; (2) WordPress personal-data exporter + eraser hooks that report the plugin as compliant (the cache is keyed on parcel dimensions, not customer identity, so there's nothing to export or erase); (3) a merchant-controlled toggle (Settings → Privacy) that, when enabled, renders a small "Shipping rates calculated using ShipEngine — Privacy policy" line under the cart and checkout shipping options. Default off; EU/UK merchants should turn it on. New PRIVACY.md documents the full data flow, retention windows, and compliance posture against GDPR / CCPA / Quebec Law 25.load_plugin_textdomain wired on plugins_loaded, .pot regenerated against the live source (192 strings), and Spanish (es_ES) and French (fr_FR) translations bundled. Set the WordPress site language to Español (España) or Français (France) to see the AdminScreen tabs, onboarding wizard, settings, and Rate Test screen render in the chosen locale. New CONTRIBUTING.md documents the translation contribution flow.usStateFromZip() mislabelled MA ZIPs (010xx-027xx) as Puerto Rico and didn't recognise RI (028xx-029xx); and the cache-clear admin-post handler was crashing because the $tabUrl closure variable wasn't imported.
For the full per-release history including 0.1.0 through 0.2.20, see CHANGELOG.md in the repo.