Stripe is a popular payment gateway due to the number of different credit cards and currencies that it supports as well as its back office features. Theoretically, Stripe can be used to store all of your customer and order information, handle your invoicing, etc. This is a good option if you have limited resources to build what your need into your own back office. The risk of leveraging Stripe to manage all of your back office information is that the closer you tie your systems to Stripe, the more difficult it will be to switch payment providers. One of the main drawbacks of Stripe is that they don't refund the fees on returned or refunded orders. Therefore, if your refund rates are high, it might be cheaper to switch to a provider that offers full refunds for cancelled payments (as the Credit Card companies themselves do). Another drawback of using Stripe is that it does not eliminate the requirement for your website to be PCI compliant. If does reduce the threshold of the PCI measures you must take since you won't have any direct access to credit card details on your site.

By default, the GenHelm framework offers support for Stripe Payments but does not have built-in support for saving customer and order information within Stripe.

Stripe Payment Overview

Please refer to the following diagram which shows the typical flow of a Stripe payment.

Stripe Payment Flow

  1. Your site uses Stripe JavaScript to build a payment form dynamically.
  2. Before the user interacts with the form, your site sends a Payment Intent notification to Stripe including the payment amount and information about the user.
  3. The user enters their credit card details and, upon a successful payment, the user is redirected to an "acknowledgement" page on your site.
  4. In the background, Stripe calls a Webhook link on your site. This Webhook must be configured in advance using the Stripe developer portal.

Setup in Stripe

In order to use Stripe you must set up a Stripe account using the Stripe Dashboard to obtain six codes consisting of three production codes and three test codes. You will use this toggle on the Stripe portal to switch between production information and test information.

Stripe Production/Test Toggle

Main Account Keys

In each mode you will go to the API keys section to determine the keys that you will need to communicate with Stripe. Notice below that the Publishable Key is revealed by default. To see the Secret Key you must click on the Reveal button. Copy and paste these keys into a text file making sure to label which keys are for production and which are for testing.

Stripe Publishable and Secret Key

Webhook Keys

In order to obtain the webhook key you must add a webhook endpoint in the Webhooks area of the Developer's dashboard. Once again you should add separate endpoints for test and production. The test endpoint will reference a URL in your sandbox environment and the production endpoint will reference a URL on your live website. In each case, the URL will look like the following:


Let's break this down:

Here we show the Stripe form where you will add your endpoint:

 Add an endpoint in stripe

You can add as many different events as you want. Stripe will call your webhook for each event selected. If you a managing accounting data within your site or if you perform other automated processes when payment is received the only event that you must add is the payment_intent.succeeded event. If you want to record refunds within your on-site accounting system you should also register the "charge.refunded" event. 

If you are not planning to maintain any accounting data on your site, or perform any other automated processing upon order payment, you don't actually need to define a webhook at all. 

Once your webhook has been created you will need to reveal the Signing Secret key. Copy your test and production Signing Secrets to a text file.

Stripe signing secret

Configuring Stripe in GenHelm

If you are using Stripe Webhooks, we recommend following the procedure set out in the main payment help to configure debug options and log Payment Notifications. Since Stripe Webhooks call your site in the background adding this logging will give you more visibility if you discover that payments are not being processed as expected.

Additionally, Stripe required the following config settings to be defined within the stripe_config file.

Sample Stripe Config Definition

Let's review these config settings next. Notice that the last column heading begins with //. This is used to define columns within the php_array_data model that are to be designated as comments.

encrypted Column

Use the encrypted column to indicate whether the information in the production and sandbox columns is encrypted. Enter one of the following values:

To encrypt a key enter $encrypt() somewhere on the page then place your cursor on this function and enter <ctrl>g to launch the help for this function. Then enter the key supplied by Stripe and check the Server Independent option and press the Test button. The encryption needs to be server independent since you normally will be generating your production keys from within your sandbox environment. You can copy either the Generated HTML or the Rendered HTLM value.

Encrypting Your Stripe Keys

The Stripe Key Rows

The first two rows are required. The remaining row is only needed if you are using webhooks.


These values come from API keys section of Stripe's developer portal. Use Test Mode to generate the sandbox keys. These are the Publishable key values.


These are the Secret Keys you copied from Stripe's Developer portal. It is a good idea to encrypt your production key. In the example above, since the encrypted column shows production, this means that only the production secret key has been encrypted.


These values come from the Webhooks link on Stripe's Developer Portal. Consider encrypting your production key. In the example, since the encryption column is set to 1 (true), both the production and sandbox keys have been encrypted.

To save this config file you can follow these steps:

  1. Enter the command "e php_array_data".
  2. Enter the command "example stripe_config".
  3. Update the key values to reflect information obtained from your Stripe account.
  4. Enter the command "stow invoice_admin/stripe_config".

Creating the Payment Form

When using Stripe, we will change the initiate-payment form to include the ability to accept the credit card details directly, rather than asking the user to choose their payment option. Here we show an example of this form created using the bootgrid model:

Stripe Payment Form

If you want to build such a page you can do so by launching the bootgrid model and entering the command example stripe-payment-form.

The key component of this page definition is a reference to $page(payment/stripe_payment_form). This will embed a payment form using a form defined within the system pseudo site. Here we see an example of the rendered page.

Rendered Stripe Payment Form

This form is different from the forms that you normally work with in GenHelm in that it is built dynamically by JavaScript provided by Stripe. Therefore, you won't be able to write code within your form handler to interact with the form fields. Instead, your form handler only needs a single method named initialize. Let's review the form handler next.

Stripe Form Handlers

You must supply a form handler named stripe_form_handler to interface with the form shown above. This form handler uses some framework code to interface with Stripe so that most of the logic is handled for you. Generally, your stripe_form_handler class only needs one method named initialize. This method is called for both get and post processing. Here we see an example of this method.

function initialize() {
// Initiate the stripe support class
require_once CLASS_PATH.'paymentgateway/stripe_payment.php';
$stripe = new \system\stripe_payment($this->site);
$name = empty($_SESSION['company_name']) ? '' : $_SESSION['company_name'].' - ';
$name .= $_SESSION['first_name'].' '.$_SESSION['last_name'];
// Set the page to be redirect to upon a successful payment  

// Define the customer and payment information  
$stripe->set_metadata(array('invoice' => $_SESSION['invoice_number'], 'name' => $name));
$stripe->set_statement_descriptor_suffix('Inv. '.$_SESSION['invoice_number']);

// The 2 fields below can only be set if you fully integrate with Stripe to have it 
// manage your customers and invoices
//$stripe->set_customer($name); This can only be set if customer defined in skype
$script = $stripe->get_client_script();
if ($script === false) {
	return false;
$this->form->add_script('stripe_submit',array('javascript'=>$script,'placement' => 'bottom'));
// Insert a webform debug link in the sandbox
if ($stripe->get_environment() === 'sandbox') {
	$debug_link = $stripe->get_debug_link();

Let's review a few aspects of this code.

Acknowledging Payments

If the user completes their payment, the payment page will redirect to the page you designated as your confirmation page. Often this page will thank the customer for completing their purchase and release any resources that are no longer required in the user's session. It is important to note that it is very easy for hackers to navigate to this "payment completed" page without actually making a payment. Therefore, you should never perform any processing or business logic within this page that assumes that a payment has been made. Instead, follow the process of defining callback classes via webhooks defined below.

To obtain a sample payment acknowledgement page edit the tags model and enter the command example payment-acknowledged.

Sending a Receipt to the Customer

Stripe is able to send an email receipt to the customer upon a successful payment. To activate this feature call the set_email_receipt method as shown above.

Passing Data to Your Callback Routine

The set_metatags method is used to assign a keyed array of values that will be passed to your callback class.

Testing Your Webhook Functionality

It is a good idea to test and debug your Webhook processing locally (within a browser session) before triggering an actual Webhook callback (from Stripe). If you look at the last few lines of the sample code above you can see that this is used to generate a debug link within your sandbox environment. This link will appear just below the Submit button as shown here:

Stripe form with Test Webhook link

Clicking this link will simulate a call to the default Webhook to allow you to test this functionality without processing an actual payment to trigger a callback from Stripe. Of course you should also test the actual Stripe Webhook callback however it is easier to debug your code in isolation of Stripe first by using this simulated webhook test, then, once you feel this is working as expected you can trigger actual Stripe Webhook callbacks by completing payments in the sandbox.

Webhook Interaction

Please review the following diagram that shows how your site interacts with Stripe Webhooks:

Stripe webhook interaction

Note the following:

  1. Stripe issues an https request to your site for each event that has been registered to process webhooks using the Stripe portal.
  2. Normally all events are filtered through a common page named payment/stripe_handler which is defined within GenHelm's system framework. In the unlikely event that the system page does not meet your needs, you could code a site-specific payment/stripe_webhook page and this would take precedence over the framework page.
  3. If your invoice_admin/payment_config file has enabled the update_text_based_account flag, the default payment/stripe_webhook will automatically update your site's account records when processing payment_intent.succeeded and charge.refunded events.
  4. If your invoice_admin/payment_config has designated a payment_callback_class, this will be called for all successful payments. This can handle site-specific automated payment actions such as emailing your shipping department for new orders.
  5. If you have coded a class within the classes/stripe folder whose name exactly matches the name of the webhook event triggered by Stripe, this class will be called. If no such class exists but your site does contain a class named classes/stripe/webhook, this class will be called to perform additional webhook processing. These custom classes can code for events beyond the payment and refund events that are handled by default.

Do You Need Custom Callback Classes?

If you are using the text-based accounting files, these can be automatically updated by the supplied payment/stripe_webhook page. If you don't need to perform any other automated processing you may not need any callback classes.

If you need to perform certain automated processing whenever a payment is made you will likely want to integrate a callback class into the generic webhook handler by specifying the class to be called within the invoice_admin/payment_config definition. This class could also be used to update database oriented accounting records if your have implemented this.

Handling Other Events

If you have configured your webhook in Stripe to call back to your site for many different events you can create a custom class that will be called to handle these events. Your handler will perform processing to supplement or replace the default handling described above. When writing your own handler you have two different options:

  1. Write event-specific handlers named stripe/[event-name]
  2. Write a single handler named stripe/webhook

You can actually combine these options by having specific handlers for some events and a generic handler for other events. For example, if you define a class named stripe/payment_intent, this class will be called when processing webhooks pertaining to payment_intents. On the other hand, if you have subscribed to charge events and you have not written a class named stripe/charge (and you want to code for this event), you must define a class named stripe/webhook to be used as the alternate class name.

Here is an example of a custom webhook handler:

function process_request($event,$event_obj) {
  switch ($event[0]) {
    case 'payment_intent':
      if ($event[1] === 'succeeded') {
        // Custom handling for a successful payment
        if (some_error_condition) {
          $this->message = 'Message to be written to the log file';
          return false;
        else {
          return true; // Success
    case 'charge':
      if ($event[1] === 'refunded') {
        // Custom handling for a refund
        return true

Note the following regarding this sample code:

  1. The first parameter to the process_request method is an array which identifies the event. Stripe events are named [object_name].[result], for example, payment_intent.succeeded. $event[0] will contain  the object_name of the event and $event[1] will contain the result portion of the event. 
  2. process_request should return true upon success and false if there is a problem processing the event. When returning false, the method should also set a message.
  3. The class should expose a get_message method so that the framework can obtain the message set when returning false. This message will be written to the background payment log.

You can load a sample webhook handler by using the command "e php_class" followed by "example stripe_webhook".