Masjid Donation Manager

الوصف

Masjid Donation Manager is a complete donation management system built specifically for masjids, surau, and Islamic charitable organizations in Malaysia. It supports multiple campaigns, two popular Malaysian payment gateways (ChipIn Asia and Bayarcash), and ships with a frontend dashboard so the masjid committee can manage everything without ever touching wp-admin.

The plugin is bilingual-friendly — the user-facing strings are in Bahasa Malaysia by default, and all strings pass through __() so they can be translated.

Key Features

  • Multiple campaigns — create unlimited fundraising campaigns, each with its own image, description, target amount and schedule (ongoing, time-limited, or one-off).
  • Two Malaysian payment gateways out of the box — ChipIn Asia and Bayarcash, both with sandbox and live modes.
  • Frontend dashboard — a dedicated /masjid-admin/ page lets the masjid committee (administrator and the included “Bendahari Masjid” role) view donations, manage campaigns, send receipts and pull reports without learning wp-admin.
  • Donor wall — automatic recognition wall showing recent donors (with option for anonymous donations).
  • Live statistics bar — total collected and donor count update in real time.
  • Elementor widget & Gutenberg block — drop a donation button into any page with full visual configuration (toggle stats, toggle donor wall, customize colors and button text).
  • Shortcodes[masjid_donation id="1"], [masjid_donor_wall id="1"], [masjid_donation_stats id="1"], [masjid_campaigns_list].
  • Receipt emails — automatic, customizable HTML receipts on every successful payment.
  • Custom reports — daily/weekly/monthly breakdowns, gateway-by-gateway and campaign-by-campaign comparisons.
  • CSV export — export all donation data for accounting or audit.
  • Webhook hardening — signature verification, replay-window protection and optional IP allowlisting for incoming gateway callbacks.
  • PDPA / GDPR considerations — data-retention period configurable, donor anonymization tool, and external resources (Google Fonts) are opt-in only.

External services

This plugin relies on third-party services to process donations. Connection to a gateway only happens when a donor actually clicks “Pay” on the donation form — no data is sent at any other time, and no data is ever sent to the plugin author. By using this plugin you (and your donors) are accepting the terms and privacy policies of whichever gateway you enable.

ChipIn Asia (CHIP) — payment gateway

What it is: a Malaysian payment gateway by CHIP IN Sdn. Bhd. used to process FPX, e-wallet and card payments.

What is sent and when: when a donor initiates a donation through a campaign that uses ChipIn Asia, the plugin sends the donor’s name, email, phone number, donation amount, currency (MYR) and a unique reference (donation_id) to ChipIn’s API to create a payment session. The donor’s browser is then redirected to ChipIn to complete payment. After payment, ChipIn calls our webhook with the transaction status. No donor card / bank details ever touch your WordPress server.

API endpoint contacted: https://gate.chip-in.asia/api/v1/ (the same hostname is used for both sandbox and live; mode is selected per-account on ChipIn’s side).

  • Service URL: https://www.chip-in.asia/
  • Terms of service: https://chip-in.asia/terms-of-service
  • Privacy policy: https://chip-in.asia/privacy-policy

Bayarcash — payment gateway

What it is: a Malaysian Shariah-compliant payment gateway by Web Impian Sdn. Bhd. used to process FPX, DuitNow QR and DuitNow Online Banking payments.

What is sent and when: when a donor initiates a donation through a campaign that uses Bayarcash, the plugin sends the donor’s name, email, phone number, donation amount, currency (MYR), a unique reference (donation_id / order_number) and a selected payment channel to Bayarcash’s API to create a payment intent. The donor’s browser is then redirected to Bayarcash to complete payment. After payment, Bayarcash calls our webhook (and POSTs to the return URL) with the transaction status. No donor card / bank details ever touch your WordPress server.

API endpoints contacted (depending on the “Mod” selected in Tetapan Bayarcash):

  • Live mode: https://console.bayar.cash/api/v2/ and https://api.console.bayar.cash/v3/
  • Sandbox mode: https://console.bayarcash-sandbox.com/api/v2/ and https://api.console.bayarcash-sandbox.com/v3/

The sandbox URLs are only contacted when the merchant explicitly selects sandbox mode for testing; live installations never reach the sandbox hosts.

  • Service URL: https://bayarcash.com/
  • Terms of service: https://bayarcash.com/terms-conditions/
  • Privacy policy: https://bayarcash.com/privacy-policy/

Google Fonts (optional, opt-in)

What it is: the Poppins font family hosted by Google Fonts, used for the donation button UI and the frontend dashboard.

What is sent and when: this connection is disabled by default. If — and only if — the masjid administrator enables “Muat Google Fonts” in Tetapan Keselamatan Privasi & Sumber Luar, the visitor’s browser will fetch the Poppins font family from fonts.googleapis.com on any page that displays the donation button, dashboard, or thank-you template. When disabled (the default), the plugin falls back to system fonts and no requests are ever made to Google.

  • Service URL: https://fonts.google.com/
  • Terms of service: https://policies.google.com/terms
  • Privacy policy: https://policies.google.com/privacy

All donation records remain in your own WordPress database. No data is ever transmitted to the plugin author.

Privacy Policy

This plugin processes the following personal data of donors:

  • Full name
  • Email address
  • Phone number (optional)
  • Donation amount and currency
  • IP address (for webhook security only — not stored against the donor record)
  • Anonymous flag (if the donor opts to donate anonymously)

This data is:

  • Stored in your WordPress database (tables wp_masjid_donations and wp_masjid_donation_logs).
  • Transmitted to the payment gateway (ChipIn Asia or Bayarcash) only at the moment a donor proceeds to checkout, so the gateway can process the payment. See the External services section above for exactly what is sent to each gateway.
  • Retained for a period configurable in the plugin’s data-retention setting. After this period, donor identifying fields are anonymized.

Donors may request anonymization or deletion of their record at any time. The frontend dashboard includes a one-click anonymization tool for the masjid administrator.

This plugin does not send any data to the plugin author or to any third party other than the payment gateway the donor actually transacts with.

لقطات الشاشة

المكوّنات

تقدّم هذه الإضافة مكوّن واحد (1).

  • Masjid Donation

التنصيب

Automatic installation

  1. From your WordPress dashboard, go to Plugins Add New.
  2. Search for “Masjid Donation Manager”.
  3. Click Install Now, then Activate.
  4. Follow the setup wizard that appears on first activation.

Manual installation

  1. Download the plugin .zip file.
  2. In your WordPress dashboard, go to Plugins Add New Upload Plugin.
  3. Choose the .zip file and click Install Now.
  4. Activate the plugin.
  5. Follow the setup wizard.

After activation

  1. The setup wizard will walk you through entering your masjid name, logo, and payment gateway credentials.
  2. A frontend dashboard page is automatically created at yoursite.com/masjid-admin/.
  3. Create your first campaign from the dashboard (or via Kempen Derma in wp-admin).
  4. Place a donation button on any page using:
    • Elementor — drag the “Masjid Donation” widget onto your page.
    • Gutenberg — search for “Masjid Donation” in the block inserter.
    • Shortcode — use [masjid_donation id="X"] where X is your campaign ID.

System requirements

  • WordPress 6.4 or higher.
  • PHP 8.0 or higher.
  • HTTPS recommended (required by both payment gateways in live mode).
  • Active ChipIn Asia and/or Bayarcash merchant account.

الأسئلة المتكررّة

Do I need to pay anything to use this plugin?

The plugin itself is free and GPL-licensed. However, the payment gateways (ChipIn Asia, Bayarcash) charge their own transaction fees according to their pricing — please see their respective websites for current rates.

Which payment gateway should I choose?

Both work well. ChipIn Asia is generally easier to onboard for smaller organizations and supports FPX, e-wallets and cards. Bayarcash is widely used by Malaysian masjids and supports FPX and DuitNow QR. You can also enable both and pick per campaign.

Can I run the plugin without a payment gateway, for cash donations?

The current version requires at least one payment gateway to be configured because donations flow through online checkout. A pure offline / cash-receipting mode is on the roadmap.

My Elementor “Papar Statistik” / “Papar Dinding Penderma” toggles don’t seem to do anything.

This was a bug in versions prior to 1.1.13 — please update. Both toggles are now respected as widget-level overrides regardless of the campaign-level setting.

Where is the donation data stored?

In two custom tables in your WordPress database — wp_masjid_donations (or your prefix) and wp_masjid_donation_logs. No data ever leaves your server except what is transmitted to your chosen payment gateway at the moment a donor checks out.

Is the plugin GDPR / PDPA compliant?

The plugin gives you the tools you need: donor anonymization, configurable data-retention period, and external resources (Google Fonts) are opt-in only. You are still responsible for your own privacy notice and for telling visitors what you collect and why.

How do I uninstall completely?

Deactivate the plugin, then click Delete. The uninstall routine will drop the custom tables, remove the dashboard page, delete plugin options, remove custom roles and capabilities, and remove all campaign posts. This is irreversible — back up your donation data first.

Can I translate the plugin?

Yes. All user-facing strings use the masjid-donation text domain. Drop a .mo file into wp-content/languages/plugins/ named masjid-donation-{locale}.mo.

Does this plugin support recurring / subscription donations?

Not yet. The current scope is one-off donations only. Recurring is on the roadmap pending gateway support.

المراجعات

لا توجد مراجعات لهذه الإضافة.

المساهمون والمطوّرون

“Masjid Donation Manager” هو برنامج مفتوح المصدر. وقد ساهم هؤلاء الأشخاص بالأسفل في هذه الإضافة.

المساهمون

ترجمة ”Masjid Donation Manager“ إلى لغتك.

مُهتم بالتطوير؟

تصفّح الشفرة، تحقق من مستودع SVN، أو الاشتراك في سجل التطوير بواسطة RSS.

سجل التغييرات

1.1.30

Released: 28 May 2026

  • New: Added a “Donate to author” link to the plugin’s row on the Plugins screen (Plugins Installed Plugins), letting supporters contribute towards continued development. The link is informational only and does not send any data from your site.

1.1.29

Released: 23 May 2026

  • Code quality (Plugin Check): Removed the explicit suppress_filters => true argument from the campaign lookup in the prefix-rename migration (it is prohibited by the performance sniff and was redundant — get_posts() already defaults it internally).
  • Code quality (Plugin Check): Added targeted phpcs:ignore annotations with justifications to the dashboard-page meta lookup in Page_Provisioner::find_existing_page(). The meta_key / meta_value query runs only during activation / page-provisioning / self-heal (never on a front-end request) and returns a single row, so the SlowDBQuery warning does not apply.

1.1.28

Released: 23 May 2026

  • Code quality (Plugin Check): The prefix-rename migration in the activator no longer issues direct $wpdb queries. Per-campaign meta is now copied through get_posts() / get_post_meta() / update_post_meta() and donor phone numbers through get_users() / get_user_meta(), clearing the WordPress.DB.DirectDatabaseQuery (DirectQuery / NoCaching) warnings.
  • Code quality (Plugin Check): The branded login handler’s $_POST reads now carry their phpcs:ignore annotations on the exact access lines, resolving the reported ValidatedSanitizedInput.InputNotSanitized (the password is intentionally passed raw to wp_signon()) and NonceVerification.Missing (the login POST is nonce-verified before the field is read) warnings.
  • Compatibility: Tested up to bumped to WordPress 7.0. Trimmed the 1.1.22 upgrade notice under the 300-character limit.

1.1.27

Released: 23 May 2026

  • Compatibility: The plugin prefix was lengthened from the 3-character mdm (constants MDM_, options/meta/hooks/capabilities mdm_, the localized script objects mdmData / mdmDash / mdmBlockData) to the 8-character masjiddm prefix, satisfying the WordPress.org guideline requiring a distinct prefix of at least four characters. A one-time, non-destructive migration runs on upgrade and copies every existing setting, per-campaign meta, donor phone number and role capability from the old mdm_ keys to the new masjiddm_ keys, so existing installations keep all of their data and treasurer permissions. Legacy scheduled cron events are cleared and re-registered under the new names.
  • Code quality: The white-labeled login / reset-password pages no longer emit an inline <style> block, inline <script>, or a Google Fonts <link> tag. Their CSS now lives in assets/css/auth.css and the password show/hide behaviour in assets/js/auth.js; both are registered and enqueued with wp_register_style() / wp_enqueue_style() / wp_register_script() / wp_enqueue_script() and flushed into the self-contained document with wp_print_styles() / wp_print_scripts(). The optional Poppins font is enqueued (still opt-in) instead of hard-coded as a <link>.

1.1.26

Released: 22 May 2026

  • Change: After clicking “Log Keluar”, the user is now redirected back to the dashboard page (/masjid-admin/) instead of the site homepage. Since they’re logged out at that point, they land on the branded login page — keeping the whole experience self-contained and white-labeled.

1.1.25

Released: 22 May 2026

  • Fix: The real cause of the hidden logout button — the fixed mobile bottom navigation bar (Utama/Kempen/Derma/Laporan) shares the same stacking level as the sidebar and was painting on top of the sidebar footer, covering the “Log Keluar” button. The bottom nav is now hidden while the slide-out menu is open, and the sidebar’s stacking order was raised above it. The logout button is now fully visible when the menu is open.

1.1.24

Released: 22 May 2026

  • Fix: The logout button in the mobile slide-out menu could still be hidden behind the phone’s browser/navigation bar. The sidebar drawer now sizes itself to the actual visible viewport (using fixed top/bottom insets instead of vh/dvh units, which include the area behind the browser toolbar), and the footer adds safe-area bottom padding. The “Log Keluar” button is now fully visible above the browser bar on phones. (Note: a website cannot hide the browser’s own toolbar — this fix makes the menu respect it instead.)

1.1.23

Released: 22 May 2026

  • New — clear logout button: The dashboard sidebar now has a prominent full-width “Log Keluar” button (with a logout icon) below the user pill, replacing the small text link that was easy to miss — especially in the mobile slide-out menu. The user’s role (Pentadbir/Bendahari) is also shown under their name.
  • Fix: On mobile, the sidebar footer (and therefore the logout button) could sit below the visible area behind the browser/navigation bars. The sidebar now uses dynamic viewport height (100dvh) with safe-area insets and a non-shrinking footer, so the logout button is always reachable.

1.1.22

Released: 22 May 2026

  • New — branded password recovery: The WordPress “forgot password” and “reset password” screens (wp-login.php?action=lostpassword / rp) are now intercepted and rendered with the same branded card as the login page, so the whole recovery flow stays white-labeled. WordPress’s own secure routines (retrieve_password(), check_password_reset_key(), reset_password()) still run underneath — only the presentation is replaced. The forgot-password response is deliberately generic to avoid revealing whether an account exists.
  • New — Poppins on auth pages: The login and password-recovery pages now load the Poppins font (matching the dashboard) when the existing “Muat Google Fonts (Poppins)” setting is enabled. When the setting is off they fall back to the system font stack, keeping the WordPress.org “no remote resources without consent” compliance intact.
  • Refactor: Shared login/recovery chrome and styling extracted into a single Auth_Page_Renderer so all three screens stay visually identical.

1.1.21

Released: 22 May 2026

  • New — branded login page: Logged-out visitors to the frontend dashboard (/masjid-admin/) now see a custom “Selamat kembali” login card styled to match the dashboard, instead of being redirected to the WordPress wp-login.php screen. Includes an email/username field, show-password toggle, “keep me signed in for 30 days” option, a “forgot password” link, and inline error messages. Authentication is handled securely in-place via wp_signon() with nonce protection. Combined with the 1.1.20 white-labeling, treasurers never see WordPress branding.

1.1.20

Released: 20 May 2026

  • New — white-label for Bendahari: Users with the Bendahari (treasurer) role no longer see the WordPress admin bar on the frontend, and are redirected to the frontend dashboard if they try to open /wp-admin/. This keeps the donation system looking like a standalone app rather than a WordPress site. Administrators are unaffected and keep the normal admin bar and backend. AJAX requests are still allowed so the frontend dashboard keeps working.

1.1.19

Released: 20 May 2026

  • PluginCheck pass: Six WordPress.Security.NonceVerification.Missing warnings in Dashboard_Ajax::export_report(), assign_treasurer() and revoke_treasurer() now carry inline phpcs:ignore comments. The file-level suppression added in 1.1.18 is honoured for most handlers, but the sniff doesn’t trace nonce verification through $this->check_nonce() and re-flags the three handlers where $_POST reads happen on the line immediately after the helper call. Nonce IS verified on every public handler — see the file-header note.
  • PluginCheck pass: uninstall.php — the // phpcs:enable after the schema-change block was previously unscoped, which also re-enabled the file-wide NonPrefixedVariableFound suppression and re-flagged $mdm_page_id, $mdm_admin_role, $mdm_cap, $mdm_campaigns, $mdm_campaign_id. The enable directive is now scoped to only the DirectDatabaseQuery.* / PreparedSQL.InterpolatedNotPrepared sniffs.

1.1.18

Released: 20 May 2026

  • PluginCheck pass: Pending poller and activator migration queries now pass the table name through the %i identifier placeholder in $wpdb->prepare() instead of being interpolated into the SQL string (PluginCheck.Security.DirectDB.UnescapedDBParameter). Same treatment applied to column identifiers in the legacy migrate_to_utc_timestamps() routine.
  • PluginCheck pass: File-level phpcs:disable annotations in Dashboard_Ajax moved out of the docblock into standalone comments so static analysers honour them, and extended to cover WordPress.DB.DirectDatabaseQuery.DirectQuery / NoCaching for the reports/stats endpoints (custom-table queries with no WP API equivalent).
  • PluginCheck pass: Targeted phpcs:ignore comments added to mdm_plugin() (bootstrap function), mdm_donation_rewrite_rules_flushed (hook), and the $mdm_* globals in uninstall.php. The PluginCheck sniff cannot learn that mdm is the plugin’s chosen prefix; each ignore is paired with an inline note explaining why.
  • PluginCheck pass: fwrite() call in CSV export streamer now carries the same WordPress.WP.AlternativeFunctions.file_system_operations_fwrite ignore as the surrounding fopen() / fclose(). (The stream is php://output, which WP_Filesystem cannot abstract.)
  • readme.txt: Upgrade notice for 1.1.17 shortened to satisfy the 300-character limit.

1.1.17

Released: 20 May 2026

  • PluginCheck pass: Namespace renamed from MDM\ (3 chars) to MasjidDM\ (8 chars) across all 35 PHP files to satisfy the 4-character minimum prefix rule. Autoloader updated. No backwards-compatibility impact — nothing outside the plugin referenced the old namespace.
  • PluginCheck pass: Bootstrap function renamed from mdm() mdm_plugin(). Hook name mdm_rewrite_rules_flushed mdm_donation_rewrite_rules_flushed. Global variables in uninstall.php now carry the $mdm_ prefix.
  • Date safety: date() calls replaced with gmdate() in Donation_Manager::generate_id() and Dashboard_Ajax::dashboard_stats() so donation IDs and date filters are not subject to the WP server’s runtime timezone.
  • Redirect hardening: wp_redirect() wp_safe_redirect() in Admin::render_dashboard_redirect() and Frontend_Dashboard::maybe_render().
  • Sanitization visibility: Campaign_CPT::save_meta() now sanitizes each $_POST field through an explicit, statically-known function (sanitize_text_field / floatval / absint) instead of a dynamic $sanitizer( ... ) dispatch, so static analysers can trace input sanitization at the call site.
  • Sanitization visibility: Dashboard_Ajax::validate_ymd_date() now accepts an already-sanitized string; every call site does sanitize_text_field( wp_unslash( $_POST[...] ?? '' ) ) inline, making the input-handling chain visible.
  • Sanitization: Bayarcash return-URL params in Thank_You_Page::extract_bayarcash_return_params() now pass through sanitize_text_field() after wp_unslash() (previously unslashed but not sanitized).
  • readme.txt: Short description rewritten in English (was Bahasa Malaysia, which triggered the unofficial-language warning).
  • Maintenance: File-level PHPCS suppression notes added to Dashboard_Ajax, Thank_You_Page, Donation_Manager, Activator, and Pending_Poller explaining where each suppression applies and why (nonce verification via helper methods; custom-table queries with no WP API equivalent). Three targeted phpcs:ignore lines added to Shortcodes::donation_button() / campaigns_list() where the echoed return value is already escaped inside the method.

1.1.16

Released: 20 May 2026

  • Security: GET /wp-json/masjid-donation/v1/campaign/{id} now whitelists the fields it returns, stripping per-campaign gateway credentials (ChipIn API key / secret, Bayarcash PAT / API secret / portal key) that would otherwise have been exposed by the public endpoint. The AJAX mdm_get_campaign_data handler already whitelisted its response; the REST equivalent now does the same.
  • Security: Audit-log payload for “save campaign” no longer copies raw $_POST values into incoming_fields; each captured field is unslashed and sanitized individually before storage.
  • Hardening: Gutenberg block render now calls the donation-button shortcode handler directly with sanitized attributes instead of building a [masjid_donation ...] string and routing it through do_shortcode(). Output escaping was already correct inside the shortcode, but the new path removes the string-interpolation surface entirely.
  • Documentation: readme.txt External services section expanded to list the specific API hostnames the plugin contacts for each gateway, including sandbox endpoints (console.bayarcash-sandbox.com, api.console.bayarcash-sandbox.com) so admins know exactly which hosts are reached in test mode.
  • Cleanup: Empty-state markup in the block render no longer uses inline style="..."; styling moved to assets/css/public.css (.mdm-block-empty).

1.1.15

Released: 18 May 2026

  • Compliance (WordPress.org plugin review pass): All previously-inlined <style>, <script> and Google Fonts <link> tags are now registered through wp_enqueue_style() / wp_enqueue_script(). New asset files: assets/css/thank-you.css, assets/js/thank-you.js, assets/css/setup-wizard.css, assets/js/setup-wizard.js, assets/js/campaign-admin.js.
  • Compliance: Setup wizard inline onclick handlers replaced with data-* attributes and unobtrusive event listeners.
  • Security: Client-IP derivation from $_SERVER (HTTP_CF_CONNECTING_IP / HTTP_X_FORWARDED_FOR / REMOTE_ADDR) now sanitizes the raw header value before parsing, and the resolved value is validated through FILTER_VALIDATE_IP so spoofed or malformed proxy headers cannot land in the database.
  • Documentation: Every public REST endpoint (/campaign/{id}, /donor-wall/{id}, /return/{gateway}, /return, /webhook/{gateway}) now carries an explicit code comment explaining why its permission_callback is __return_true and where the actual trust boundary lives (checksum verification, IP allow-list, etc).
  • Library update: Chart.js bundled locally bumped from 4.4.0 4.5.1 (current stable upstream).
  • Documentation: Updated readme.txt with corrected Terms / Privacy URLs for ChipIn Asia (chip-in.asia/terms-of-service, chip-in.asia/privacy-policy) and Bayarcash (bayarcash.com/terms-conditions/, bayarcash.com/privacy-policy/). Added a dedicated == External services == section disclosing exactly what data is sent to each third party and when.

1.1.14

Released: 16 May 2026

  • Security hardening (PluginCheck pass): Date inputs for the reports endpoint are now strictly validated against Y-m-d calendar format before reaching the database layer, instead of relying on sanitize_text_field() alone.
  • SQL identifier escaping: The masjid_donations table name is now passed via the %i placeholder in $wpdb->prepare() instead of being interpolated into the SQL string, satisfying PluginCheck.Security.DirectDB.UnescapedDBParameter.
  • i18n: Created languages/ directory and shipped a masjid-donation.pot translation template so the Domain Path header points to a real folder.
  • Export format whitelist: The format parameter on the CSV export endpoint is now constrained to a known whitelist (csv) before use.

1.1.13

Released: 16 May 2026

  • Fix: Elementor widget — “Papar Statistik” and “Papar Dinding Penderma” toggles now correctly override the campaign-level setting. Previously the widget controls were ignored and the page always rendered both sections.
  • Fix: Gutenberg block — added the same “Show Stats” and “Show Donor Wall” toggles for parity with Elementor.
  • Compliance: Chart.js is now bundled locally (assets/vendor/chart.umd.min.js) instead of loaded from a CDN, per WordPress.org plugin guideline 7 (no remote-loaded scripts).
  • Privacy: Google Fonts (Poppins) loading is now opt-in via a new Tetapan Privasi setting. By default the plugin uses system fonts, which avoids leaking visitor IPs to Google.
  • Cleanup: Uninstall routine now uses $wpdb->prepare() everywhere, cleans up transients, and force-deletes campaign meta.

1.1.12

  • Internal cleanup and migration safety on plugin upgrade.

1.1.x

  • Bayarcash and ChipIn Asia gateway integration improvements, frontend dashboard, donor wall, custom reports.