{"id":347787,"date":"2026-08-28T06:56:48","date_gmt":"2026-08-28T06:56:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/ozupay-m-pesa-payments\/"},"modified":"2026-08-28T07:11:57","modified_gmt":"2026-08-28T07:11:57","slug":"ozupay-payment-gateway","status":"publish","type":"plugin","link":"https:\/\/os.wordpress.org\/plugins\/ozupay-payment-gateway\/","author":23519974,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"5.1.15","stable_tag":"5.1.15","tested":"7.1","requires":"6.0","requires_php":"8.0","requires_plugins":null,"header_name":"OzuPay Payment Gateway for M-Pesa","header_author":"OzuPay","header_description":"M-Pesa STK Push payments for WooCommerce. Customers pay via their phone \u2014 no card required.","assets_banners_color":"0a5a3d","last_updated":"2026-08-28 07:11:57","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/ozupay.com\/plugins\/ozupay-payment-gateway\/","header_author_uri":"https:\/\/ozupay.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":108,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"5.1.15":{"tag":"5.1.15","author":"fearofbug","date":"2026-08-28 07:11:57","revision":3669947}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3669924,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3669924,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3669924,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3669924,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["5.1.15"],"block_files":[],"assets_screenshots":[],"screenshots":[]},"plugin_section":[],"plugin_tags":[37731,3050,6593,277553,286],"plugin_category":[45],"plugin_contributors":[278009],"plugin_business_model":[],"class_list":["post-347787","plugin","type-plugin","status-publish","hentry","plugin_tags-kenya","plugin_tags-mpesa","plugin_tags-payment-gateway","plugin_tags-safaricom","plugin_tags-woocommerce","plugin_category-ecommerce","plugin_contributors-fearofbug","plugin_committers-fearofbug"],"banners":{"banner":"https:\/\/ps.w.org\/ozupay-payment-gateway\/assets\/banner-772x250.png?rev=3669924","banner_2x":"https:\/\/ps.w.org\/ozupay-payment-gateway\/assets\/banner-1544x500.png?rev=3669924","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/ozupay-payment-gateway\/assets\/icon-128x128.png?rev=3669924","icon_2x":"https:\/\/ps.w.org\/ozupay-payment-gateway\/assets\/icon-256x256.png?rev=3669924","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p>OzuPay accepts M-Pesa payments in WooCommerce. Customers enter their Safaricom number at checkout and receive a payment prompt on their phone.<\/p>\n\n<h4>What's included in the free edition<\/h4>\n\n<ul>\n<li><strong>STK Push payments<\/strong> \u2014 send a payment prompt directly to the customer's phone via the Daraja API<\/li>\n<li><strong>Payment waiting modal<\/strong> \u2014 shows payment status in real time on the confirmation page<\/li>\n<li><strong>Retry support<\/strong> \u2014 customers can resend the STK Push prompt up to 2 times if they missed it<\/li>\n<li><strong>Manual verification fallback<\/strong> \u2014 if automation fails, customers can submit their M-Pesa transaction code for admin review<\/li>\n<li><strong>Paybill fallback matching<\/strong> \u2014 matches an external Paybill payment by account reference<\/li>\n<li><strong>Transaction log<\/strong> \u2014 every Daraja API request and callback is logged for easy troubleshooting<\/li>\n<li><strong>Sandbox testing panel<\/strong> \u2014 test your Daraja credentials in the sandbox before going live<\/li>\n<li><strong>Health check<\/strong> \u2014 instant feedback on missing credentials, SSL issues, and other common misconfigurations<\/li>\n<li><strong>Privacy tools integration<\/strong> \u2014 supports WooCommerce personal-data export and erasure<\/li>\n<li><strong>HPOS compatible<\/strong> \u2014 works with WooCommerce High-Performance Order Storage<\/li>\n<li><strong>Blocks compatible<\/strong> \u2014 works with the WooCommerce Cart\/Checkout Block editor<\/li>\n<\/ul>\n\n<h4>What OzuPay Pro adds<\/h4>\n\n<ul>\n<li><strong>M-Pesa on Delivery (COD Deposit)<\/strong> \u2014 deposit + balance on delivery gateway<\/li>\n<li><strong>C2B Buy Goods (Till) Reconciliation<\/strong> \u2014 match Till payments made outside an STK prompt<\/li>\n<li><strong>B2C Automatic Refunds<\/strong> \u2014 process WooCommerce refunds via the Daraja B2C API<\/li>\n<li><strong>Analytics Dashboard<\/strong> \u2014 revenue, conversion, and payment path charts<\/li>\n<li><strong>Scheduled Email Reports<\/strong> \u2014 daily, weekly, or monthly payment summary emails<\/li>\n<li><strong>POS REST API<\/strong> \u2014 REST endpoints for the OzuPay Android cashier application<\/li>\n<li><strong>Webhook Enrichment<\/strong> \u2014 add M-Pesa receipt data to WooCommerce webhook payloads<\/li>\n<\/ul>\n\n<p>Upgrade at <a href=\"https:\/\/ozupay.com\/#pricing\">ozupay.com<\/a><\/p>\n\n<h4>Requirements<\/h4>\n\n<ul>\n<li><strong>WooCommerce is required<\/strong> \u2014 OzuPay is a WooCommerce payment gateway and does not run without it<\/li>\n<li>A Safaricom Daraja developer account (free at <a href=\"https:\/\/developer.safaricom.co.ke\">developer.safaricom.co.ke<\/a>)<\/li>\n<li>Store currency must be set to <strong>KES (Kenyan Shilling)<\/strong><\/li>\n<li>A public HTTPS URL for Daraja callbacks (required for production; not needed for sandbox testing)<\/li>\n<\/ul>\n\n<h3>External services<\/h3>\n\n<p>This plugin relies on the following external services. Nothing else is contacted.<\/p>\n\n<p><strong>1. Safaricom Daraja API (required)<\/strong><\/p>\n\n<p>The plugin connects to Daraja to send STK Push prompts and receive payment results. This core service is required.<\/p>\n\n<p>Endpoints: <code>https:\/\/api.safaricom.co.ke<\/code> (production) and <code>https:\/\/sandbox.safaricom.co.ke<\/code> (sandbox, used only when you select Sandbox mode in settings).<\/p>\n\n<p>What is sent, and when:<\/p>\n\n<ul>\n<li>When a customer places an order with the M-Pesa gateway: the customer's Safaricom phone number, the order amount, your store's Paybill\/Till shortcode, the order number as the payment reference, and your site's callback URL.<\/li>\n<li>When the plugin needs an API token (before each request batch): your Daraja Consumer Key and Consumer Secret.<\/li>\n<li>While a customer is on the payment-waiting page and their payment hasn't confirmed after 15 seconds: your store's Paybill\/Till shortcode and the CheckoutRequestID for that specific payment, to proactively check whether Daraja already has an outcome (rate-limited to once every 30 seconds per order).<\/li>\n<li>Safaricom sends results back to your site's callback URL; nothing is sent by the plugin in that direction.<\/li>\n<\/ul>\n\n<p>You supply your own Daraja credentials, so your store's relationship is directly with Safaricom.<\/p>\n\n<p>Safaricom Daraja API terms and conditions: https:\/\/developer.safaricom.co.ke\/terms\nSafaricom data privacy statement: https:\/\/www.safaricom.co.ke\/dataprivacystatement\/<\/p>\n\n<p><strong>2. OzuPay diagnostics (optional, disabled by default)<\/strong><\/p>\n\n<p>If you enable \"Share optional diagnostic telemetry\" in OzuPay \u2192 Settings \u2192 Advanced, the plugin sends a daily report to <code>https:\/\/ozupay.com\/wp-json\/ozls\/v1\/telemetry<\/code>. It also sends once immediately after opt-in. Fresh installs default to off.<\/p>\n\n<p>What is sent, and when: once per day (and once immediately after you enable it) \u2014 your site's hostname, the plugin\/PHP\/WordPress\/WooCommerce version numbers, store locale and country, whether the site is a WordPress multisite install, whether the site is in sandbox or production mode, whether HPOS and block checkout are in use, whether your M-Pesa shortcode is a Paybill or Till, boolean configuration-health flags (for example \"credentials configured: yes\/no\", \"callback URL reachable: yes\/no\"), install and last-active dates, daily aggregate payment counts (initiated, confirmed, failed, retried), and error type slugs with their frequency.<\/p>\n\n<p>What is never sent: customer names, phone numbers, emails, addresses, order IDs, order contents, payment amounts, M-Pesa receipt numbers, or your Daraja API credentials.<\/p>\n\n<p>OzuPay terms of service: https:\/\/ozupay.com\/terms\nOzuPay privacy policy: https:\/\/ozupay.com\/privacy<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>ozupay-payment-gateway<\/code> folder to the <code>\/wp-content\/plugins\/<\/code> directory, or install directly through the WordPress plugins screen.<\/li>\n<li>Activate the plugin through the <strong>Plugins<\/strong> screen in WordPress.<\/li>\n<li>Go to <strong>OzuPay \u2192 Settings<\/strong> and enter your Daraja credentials.<\/li>\n<li>Go to <strong>WooCommerce \u2192 Payments<\/strong> and enable the <strong>M-Pesa<\/strong> gateway.<\/li>\n<li>Configure the gateway title and description under <strong>WooCommerce \u2192 Payments \u2192 M-Pesa \u2192 Manage<\/strong>.<\/li>\n<li>Test with the Sandbox Testing panel before going live.<\/li>\n<\/ol>\n\n<h4>Getting your Daraja credentials<\/h4>\n\n<ol>\n<li>Create a free developer account at <a href=\"https:\/\/developer.safaricom.co.ke\">developer.safaricom.co.ke<\/a><\/li>\n<li>Create an app under <strong>My Apps<\/strong> and add the <strong>Lipa Na M-Pesa<\/strong> product<\/li>\n<li>Copy the <strong>Consumer Key<\/strong> and <strong>Consumer Secret<\/strong> from the Keys tab<\/li>\n<li>Copy the <strong>STK Passkey<\/strong> from the sandbox credentials section<\/li>\n<li>Use shortcode <strong>174379<\/strong> and passkey from the test credentials page for sandbox testing<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"what%20is%20the%20test%20phone%20number%20for%20sandbox%20stk%20push%3F\"><h3>What is the test phone number for sandbox STK Push?<\/h3><\/dt>\n<dd><p>Safaricom's official sandbox test phone is <strong>254708374149<\/strong>. Any STK Push to this number in sandbox mode will succeed. You can change this in the Sandbox Testing panel.<\/p><\/dd>\n<dt id=\"what%20are%20the%20sandbox%20credentials%3F\"><h3>What are the sandbox credentials?<\/h3><\/dt>\n<dd><p>Shortcode: 174379\nPasskey: bfb279f9aa9bdbcf158e97dd71a467cd2e0c893059b10f78e6b72ada1ed2c919<\/p>\n\n<p>These are public Safaricom test credentials. The plugin's Sandbox Testing panel can pre-fill these automatically.<\/p><\/dd>\n<dt id=\"why%20is%20the%20gateway%20not%20showing%20at%20checkout%3F\"><h3>Why is the gateway not showing at checkout?<\/h3><\/dt>\n<dd><p>The most common reasons:\n1. The store currency is not set to KES \u2014 go to WooCommerce \u2192 Settings \u2192 General\n2. The gateway is not enabled \u2014 go to WooCommerce \u2192 Payments and enable M-Pesa\n3. Consumer Key, Consumer Secret, Shortcode, or Passkey is missing \u2014 go to OzuPay \u2192 Settings\n4. The Health Check panel (OzuPay \u2192 Settings \u2192 Health Check) will tell you exactly what is missing<\/p><\/dd>\n<dt id=\"why%20is%20%22invalid%20transactiontype%22%20returned%20by%20daraja%3F\"><h3>Why is \"Invalid TransactionType\" returned by Daraja?<\/h3><\/dt>\n<dd><p>Your Shortcode Type setting does not match the type registered in Daraja. Paybill numbers use <strong>CustomerPayBillOnline<\/strong> and Till numbers use <strong>CustomerBuyGoodsOnline<\/strong>. The sandbox shortcode 174379 is a Paybill \u2014 set the type to Paybill.<\/p><\/dd>\n<dt id=\"do%20callbacks%20work%20on%20localhost%2C%20and%20is%20https%20required%3F\"><h3>Do callbacks work on localhost, and is HTTPS required?<\/h3><\/dt>\n<dd><p>Daraja requires a publicly accessible HTTPS callback URL. For local testing, use a secure tunnel such as <a href=\"https:\/\/ngrok.com\">ngrok<\/a>, then confirm delivery with the Sandbox Testing panel.<\/p><\/dd>\n<dt id=\"can%20i%20upgrade%20to%20pro%20later%20without%20losing%20data%3F\"><h3>Can I upgrade to Pro later without losing data?<\/h3><\/dt>\n<dd><p>Yes. The free and Pro editions use the same database tables and option names (<code>ozupay_mpesa_settings<\/code>, <code>wp_ozupay_mpesa_transactions<\/code>). Upgrading to Pro or switching back to free never deletes your data.<\/p><\/dd>\n<dt id=\"where%20are%20api%20credentials%20stored%3F\"><h3>Where are API credentials stored?<\/h3><\/dt>\n<dd><p>Consumer Key, Consumer Secret, and STK Passkey are stored AES-256-GCM encrypted in the WordPress options table. The encryption key is derived from your site's <code>AUTH_KEY<\/code> and <code>SECURE_AUTH_KEY<\/code> constants. They are never stored in plain text.<\/p><\/dd>\n<dt id=\"does%20this%20plugin%20phone%20home%20or%20send%20usage%20data%3F\"><h3>Does this plugin phone home or send usage data?<\/h3><\/dt>\n<dd><p>Payment processing uses Daraja. Optional OzuPay diagnostics are <strong>off by default<\/strong> and run only after you opt in. The report includes your hostname and is not anonymous. Details follow.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>5.1.15<\/h4>\n\n<ul>\n<li>fix: Reopening the payment status modal from the \"Got it, thank you!\" sticky bar's View button (after a manual M-Pesa code had already been submitted) no longer auto-closes and reloads the page a couple of seconds later.<\/li>\n<\/ul>\n\n<h4>5.1.14<\/h4>\n\n<ul>\n<li>security: Removed unused Pro-only deposit\/refund setter methods (set_deposit_data, confirm_deposit, mark_balance_collected, set_refund_data, confirm_refund) that had no caller anywhere in Free \u2014 a fully-implemented, callable, state-changing method with no caller is still shipping the feature, even if nothing reaches it at runtime.<\/li>\n<\/ul>\n\n<h4>5.1.13<\/h4>\n\n<ul>\n<li>security: A legacy M-Pesa on Delivery order left over from a Pro-to-Free downgrade could have Free automatically run Pro's deposit\/balance confirmation logic on a real incoming payment \u2014 including setting an order status Free doesn't even register. Free now records the payment (nothing is ever lost) and flags it for manual review instead of pretending to run business logic it doesn't have.<\/li>\n<\/ul>\n\n<p>For the full version history, see changelog.txt in the plugin package.<\/p>","raw_excerpt":"Accept M-Pesa STK Push payments in your WooCommerce store. Customers pay via their phone \u2014 no card required.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/347787","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=347787"}],"author":[{"embeddable":true,"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/fearofbug"}],"wp:attachment":[{"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=347787"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=347787"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=347787"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=347787"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=347787"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=347787"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}