# Payments and billing schema

**URL:** <https://community.open-emr.org/t/payments-and-billing-schema/26422>\
**Category:** OpenEMR Development\
**Created:** [December 22, 2025, 6:11pm UTC](https://community.open-emr.org/t/payments-and-billing-schema/26422 "2025-12-22T18:11:29Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Firehed](https://community.open-emr.org/user_avatar/community.open-emr.org/firehed/32/22653_2.png) [@Firehed](https://community.open-emr.org/u/Firehed)\
**Post date:** [December 22, 2025, 6:11pm UTC](https://community.open-emr.org/t/payments-and-billing-schema/26422/1 "2025-12-22T18:11:29Z")

</div>

Hi all,

I’m wondering if there’s any good reference material on the database schema around billing and payments, or if someone with experience in this area might be able to provide some info.

For context, I’m looking into adding another payment provider and integrating it into the portals. I’ve managed to get most of the UI pieces working (up through capturing the payment on the gateway’s end - money can move) but none of that ends up getting reflected in the OpenEMR UIs. I’ve found a few tables in the database that look relevant, and can _probably_ reverse-engineer it given enough time, but when it comes to payments, I don’t want to guess. I also did a before-and-after diff of the database contents when using a stripe test key for reference when using the patient portal and that didn’t look quite right, but it seemed to put the payment in some sort of “pending admin approval” state.

For now, I’m trying to concretely know where payments that occurred get recorded in the db, and how that should make it back into the UIs. In particular, the “patient paid” column and the “locked payment pending” that can show up in the patient portal (how do I get past that? when I tried to accept it in the admin side, I’d run into blank screens or permissions errors)

If anyone can point me in a useful direction here, I’d super appreciate it! Thank you and happy holidays!

---

<div class="post-metadata">

**Author:** ![stephenwaite](https://community.open-emr.org/user_avatar/community.open-emr.org/stephenwaite/32/15754_2.png) [@stephenwaite](https://community.open-emr.org/u/stephenwaite)\
**Post date:** [December 22, 2025, 6:34pm UTC](https://community.open-emr.org/t/payments-and-billing-schema/26422/2 "2025-12-22T18:34:55Z")

</div>

hi @Firehed, not sure if you have seen the [ehi export docs](https://seven.openemr.io/openemr/Documentation/EHI_Export/docs/tables/ar_activity.html), a good place to start for sure. There’s also the [ar\_session table](https://seven.openemr.io/openemr/Documentation/EHI_Export/docs/tables/ar_session.html) and [payments table](https://seven.openemr.io/openemr/Documentation/EHI_Export/docs/tables/payments.html).

---

<div class="post-metadata">

**Author:** ![Firehed](https://community.open-emr.org/user_avatar/community.open-emr.org/firehed/32/22653_2.png) [@Firehed](https://community.open-emr.org/u/Firehed)\
**Post date:** [December 22, 2025, 8:28pm UTC](https://community.open-emr.org/t/payments-and-billing-schema/26422/3 "2025-12-22T20:28:21Z")

</div>

Hi @stephenwaite - thanks for that! I did come across those, and also saw data being written into `onsite_portal_activity` that seems to exist for some sort of pending payment state (this was the only non-log table that saw writes when I made a test payment through the patient portal). I see after the payment form, data is posted to `portal/lib/paylib.php`(or the fairly-similar `interface/patient_file/front_payment_cc.php`) but I was having trouble following where it would actually write that a payment happened. The `ar_activity` table looks like the “more” canonical record of payments happening as far as the UI data is concerned, but I also see it loading data from `payments`… so I wasn’t really sure what data needs to end up where by the end of processing.

---

<div class="post-metadata">

**Author:** ![stephenwaite](https://community.open-emr.org/user_avatar/community.open-emr.org/stephenwaite/32/15754_2.png) [@stephenwaite](https://community.open-emr.org/u/stephenwaite)\
**Post date:** [December 22, 2025, 8:33pm UTC](https://community.open-emr.org/t/payments-and-billing-schema/26422/4 "2025-12-22T20:33:12Z")

</div>

Okay great. Yes, sounds like there should be something in the portal audit process that moves the payments through to be stored in the tables referenced.

---

<div class="post-metadata">

**Author:** ![sjpadgett](https://community.open-emr.org/user_avatar/community.open-emr.org/sjpadgett/32/21623_2.png) [@sjpadgett](https://community.open-emr.org/u/sjpadgett)\
**Post date:** [December 22, 2025, 9:04pm UTC](https://community.open-emr.org/t/payments-and-billing-schema/26422/5 "2025-12-22T21:04:22Z")

</div>

I developed stripe several years ago so I don’t recall the nitty gritty.

I can say the In House is the only method that will put payment in

> [@Firehed](#):
>
> “pending admin approval”

for audit. In audit user verifies credit card, payment and then post the payment. At that point, patient is notified in portal ledger.

Here’s audit

 ![image](https://discourse-uploads-openemr.s3.dualstack.us-east-1.amazonaws.com/original/3X/f/0/f04247779dad9bbd232c5adab4105e85c09b15aa.png)

I forget what an electronic payment looks like in audit and if you can post from there, I believe so.

It’d make sense I’d also make available for posting in Post Payments.

Also note, Front Payment also takes credit payments and again i’m unsure but believe if integrated in portal the payment type will appear here as well.

My last integration was for a stripe terminal and Brady did Sphere(better terminal).

---

<div class="post-metadata">

**Author:** ![Firehed](https://community.open-emr.org/user_avatar/community.open-emr.org/firehed/32/22653_2.png) [@Firehed](https://community.open-emr.org/u/Firehed)\
**Post date:** [December 22, 2025, 9:26pm UTC](https://community.open-emr.org/t/payments-and-billing-schema/26422/6 "2025-12-22T21:26:39Z")

</div>

Thanks for the background! When I tried to open that portal payments page from your screenshot I immediately got bounced out with an auth error (using a clean install with the default admin account). When I commented out a bunch of checks to bypass that for testing purposes, I still wasn’t able to get to a page that would allow me to accept the payment.

Here’s what I got on the patient side when making a payment via stripe (in test mode, which I’d assume shouldn’t matter):

 ![Screenshot 2025-12-22 at 1.15.54 PM](https://discourse-uploads-openemr.s3.dualstack.us-east-1.amazonaws.com/original/3X/5/9/59bbdb073c627cf4729e80305cdd454deff6fe54.png)

And on the admin side (again, new install using the default admin account) when clicking the portal payments button circled above:

```auto
Oh Snap!

Unauthorized

You may want to try returning to the the previous page and verifying that all fields have been filled out correctly.

If you continue to experience this error please contact support.

Stack Trace:

#0 /var/www/localhost/htdocs/openemr/portal/patient/fwk/libs/verysimple/Phreeze/Dispatcher.php(91): GenericRouter->GetRoute()
#1 /var/www/localhost/htdocs/openemr/portal/patient/index.php(54): Dispatcher::Dispatch()
#2 {main}

```

I’ll try again shortly with “in house” to see if I get a different result, but I’m assuming this isn’t the expected behavior. Could it be related to needing a webhook to process? I didn’t see anything that referenced that, but it sort of matches what I’d expect in terms of behavior.

---

<div class="post-metadata">

**Author:** ![sjpadgett](https://community.open-emr.org/user_avatar/community.open-emr.org/sjpadgett/32/21623_2.png) [@sjpadgett](https://community.open-emr.org/u/sjpadgett)\
**Post date:** [December 22, 2025, 9:35pm UTC](https://community.open-emr.org/t/payments-and-billing-schema/26422/7 "2025-12-22T21:35:13Z")

</div>

Try from main audit page to see if payment is there for audit. Miscellaneous → Portal Dashboard

 ![image](https://discourse-uploads-openemr.s3.dualstack.us-east-1.amazonaws.com/original/3X/1/5/15e561a0fe312d207abfb9566d1de16480fa878e.png)

---

<div class="post-metadata">

**Author:** ![Firehed](https://community.open-emr.org/user_avatar/community.open-emr.org/firehed/32/22653_2.png) [@Firehed](https://community.open-emr.org/u/Firehed)\
**Post date:** [December 22, 2025, 9:38pm UTC](https://community.open-emr.org/t/payments-and-billing-schema/26422/8 "2025-12-22T21:38:56Z")

</div>

When navigating directly there per your screenshot, I just get an empty page. The home button takes me back to the previous page. Nothing actionable that I can find, despite that top-right menu having the (2) indicator on it.

 ![Screenshot 2025-12-22 at 1.38.39 PM](https://discourse-uploads-openemr.s3.dualstack.us-east-1.amazonaws.com/original/3X/c/0/c0dcb88d7c891d1819d593eed6c84a316b708db9.png)

---

<div class="post-metadata">

**Author:** ![sjpadgett](https://community.open-emr.org/user_avatar/community.open-emr.org/sjpadgett/32/21623_2.png) [@sjpadgett](https://community.open-emr.org/u/sjpadgett)\
**Post date:** [December 22, 2025, 9:42pm UTC](https://community.open-emr.org/t/payments-and-billing-schema/26422/9 "2025-12-22T21:42:02Z")

</div>

Are the payments in the onsite\_activity\_table?

re turn on debug in Config

---

<div class="post-metadata">

**Author:** ![Firehed](https://community.open-emr.org/user_avatar/community.open-emr.org/firehed/32/22653_2.png) [@Firehed](https://community.open-emr.org/u/Firehed)\
**Post date:** [December 22, 2025, 9:44pm UTC](https://community.open-emr.org/t/payments-and-billing-schema/26422/10 "2025-12-22T21:44:47Z")

</div>

Yes, I have a single record that appeared in there after making the payment on the stripe gateway through the patient portal.

---

<div class="post-metadata">

**Author:** ![sjpadgett](https://community.open-emr.org/user_avatar/community.open-emr.org/sjpadgett/32/21623_2.png) [@sjpadgett](https://community.open-emr.org/u/sjpadgett)\
**Post date:** [December 22, 2025, 9:51pm UTC](https://community.open-emr.org/t/payments-and-billing-schema/26422/11 "2025-12-22T21:51:39Z")

</div>

Does audit work for a document Clinical Documents card i.e. do a Privacy doc and submit.

---

<div class="post-metadata">

**Author:** ![sjpadgett](https://community.open-emr.org/user_avatar/community.open-emr.org/sjpadgett/32/21623_2.png) [@sjpadgett](https://community.open-emr.org/u/sjpadgett)\
**Post date:** [December 22, 2025, 10:00pm UTC](https://community.open-emr.org/t/payments-and-billing-schema/26422/12 "2025-12-22T22:00:47Z")

</div>

yep There’s a bug. I’ll look into prob a simple fix

```auto
[22-Dec-2025 16:58:29 America/New_York] PHP Fatal error: Uncaught TypeError: property_exists(): Argument #1 ($object_or_class) must be of type object|string, array given in C:\xampp\htdocs\openemr\portal\patient\fwk\libs\verysimple\Phreeze\Reporter.php:179
Stack trace:
#0 C:\xampp\htdocs\openemr\portal\patient\fwk\libs\verysimple\Phreeze\Reporter.php(179): property_exists(Array, 'OnsiteActivityV...')
#1 C:\xampp\htdocs\openemr\portal\patient\fwk\libs\verysimple\Phreeze\Reporter.php(219): Reporter->GetPublicProperties()
#2 C:\xampp\htdocs\openemr\portal\patient\fwk\libs\verysimple\Phreeze\DataPage.php(101): Reporter->ToObject(Array)
#3 C:\xampp\htdocs\openemr\portal\patient\libs\Controller\OnsiteActivityViewController.php(106): DataPage->ToObjectArray(true, Array)
#4 C:\xampp\htdocs\openemr\portal\patient\fwk\libs\verysimple\Phreeze\Dispatcher.php(172): OnsiteActivityViewController->Query()
#5 C:\xampp\htdocs\openemr\portal\patient\index.php(54): Dispatcher::Dispatch(Object(Phreezer), Object(SavantRenderEngine), '', NULL, Object(GenericRouter))
#6 {main}
  thrown in C:\xampp\htdocs\openemr\portal\patient\fwk\libs\verysimple\Phreeze\Reporter.php on line 179

```

---

<div class="post-metadata">

**Author:** ![sjpadgett](https://community.open-emr.org/user_avatar/community.open-emr.org/sjpadgett/32/21623_2.png) [@sjpadgett](https://community.open-emr.org/u/sjpadgett)\
**Post date:** [December 22, 2025, 10:30pm UTC](https://community.open-emr.org/t/payments-and-billing-schema/26422/13 "2025-12-22T22:30:16Z")

</div>

@Firehed Here is a fix so you can continue. Looks like the UI has issues also with styling.

portal/patient/fwk/libs/verysimple/Phreeze/Reporter.php

[Reporter.php](https://community.open-emr.org/uploads/short-url/3Q5TLn3syabm7nZV9cEd3yD57n4.php) (9.3 KB)

---

<div class="post-metadata">

**Author:** ![sjpadgett](https://community.open-emr.org/user_avatar/community.open-emr.org/sjpadgett/32/21623_2.png) [@sjpadgett](https://community.open-emr.org/u/sjpadgett)\
**Post date:** [December 22, 2025, 10:32pm UTC](https://community.open-emr.org/t/payments-and-billing-schema/26422/14 "2025-12-22T22:32:29Z")

</div>

btw: Here is what you’re after. Can edit and post from audit

 ![image](https://discourse-uploads-openemr.s3.dualstack.us-east-1.amazonaws.com/original/3X/c/2/c2bdad97bb217d4330aedcc1a4613365ba2d86e3.png)

---

<div class="post-metadata">

**Author:** ![Stanisierra](https://community.open-emr.org/letter_avatar_proxy/v4/letter/s/91b2a8/32.png) [@Stanisierra](https://community.open-emr.org/u/Stanisierra)\
**Post date:** [October 22, 2026, 6:38am UTC](https://community.open-emr.org/t/payments-and-billing-schema/26422/15 "2026-10-22T06:38:05Z")

</div>

This post was flagged by the community and is temporarily hidden.
