Booking paid-for events: How? First off, I appreciate this is open ended and SE isn't the best place for it. For a lack of a better place to ask though, here we are:

I've just built a system for a client where users could sign up an book places on events. None of the bookings on this system require payment, so it's just a case of submitting a form which creates an entry in a channel called "bookings" using:

action=saveEntry


I now have a client who needs to take bookings for events which require payment, and to list those bookings in a front end page. I'm trying to use Charge for payments (only because it seems easy to use, and my client doesn't want to pay monthly for something), which requires the form action:

action=charge/charge


The issue I have is that I want to submit a single form which takes a payment and creates a booking (action=saveEntry) without writing a plugin. I'm not a backend developer, I don't know how to write plugins (despite trying). None of the eCommerce addons available for Craft are out of beta yet.

Is there any way to take a payment and create a booking using template code?
We did something similar with Charge when we were accepting payments for a Craft Virtual Training course. It does involve writing a plugin, but thankfully all of the heavy lifting for saving entries and charging credit cards is handled by the services provided by Craft and Charge, so the only thing the plugin has to worry about is collecting post data and passing it to some APIs.

Start off by creating a primary plugin class (see Setting Things Up in the Craft plugin docs), and then giving your plugin a controller with the following code:

&lt;?php
namespace Craft;

class FooController extends BaseController
{
    public $allowAnonymous = array('actionCreateBooking');

    public function actionCreateBooking()
    {
        // Require this to be a POST request
        $this-&gt;requirePostRequest();

        // Require that the user is logged in
        craft()-&gt;userSession-&gt;requireLogin();

        // Get the user
        $user = craft()-&gt;userSession-&gt;getUser();

        // Do any custom validation here
        // ...

        // Charge the card
        $charge = new ChargeModel();

        $charge-&gt;cardToken     = craft()-&gt;request-&gt;getRequiredPost('cardToken');
        $charge-&gt;cardLast4     = craft()-&gt;request-&gt;getPost('cardLast4');
        $charge-&gt;cardType      = craft()-&gt;request-&gt;getPost('cardType');
        $charge-&gt;cardName      = craft()-&gt;request-&gt;getPost('cardName');
        $charge-&gt;cardExpMonth  = craft()-&gt;request-&gt;getPost('cardExpMonth');
        $charge-&gt;cardExpYear   = craft()-&gt;request-&gt;getPost('cardExpYear');

        $charge-&gt;customerName  = craft()-&gt;request-&gt;getPost('customerName');
        $charge-&gt;customerEmail = craft()-&gt;request-&gt;getPost('customerEmail');

        $charge-&gt;planAmount    = 10000; // In cents

        if ($charge-&gt;validate() &amp;&amp; craft()-&gt;charge-&gt;handlePayment($charge))
        {
            // Save the booking entry
            $entry = new EntryModel();
            $entry-&gt;sectionId = craft()-&gt;request-&gt;getPost('sectionId');
            $entry-&gt;typeId    = craft()-&gt;request-&gt;getPost('typeId'); // Not necessary if there's only one entry type
            $entry-&gt;authorId  = $user-&gt;id;
            $entry-&gt;enabled   = true;

            $entry-&gt;getContent()-&gt;title = 'New Booking: '.$user-&gt;username;
            $entry-&gt;getContent()-&gt;chargeId = $charge-&gt;id; // Custom number field
            $entry-&gt;getContent()-&gt;someOtherCustomField = 'xyz';

            craft()-&gt;entries-&gt;saveEntry($entry);

            // Redirect the request based on the 'redirect' param
            craft()-&gt;userSession-&gt;setNotice('Booking saved.');
            $this-&gt;redirectToPostedUrl();
        }
        else
        {
            craft()-&gt;userSession-&gt;setError('Couldn’t charge the card.');

            // Send the charge model to the template
            craft()-&gt;urlManager-&gt;setRouteVariables(array(
                'charge' =&gt; $charge
            ));
        }
    }
}


You might want to hard-code the sectionId and typeId rather than leaving it up to the POST data, and there might be other slight changes you want to make, but that’s the gist.

With the plugin in place, you would just need to create a form that captures all of the info the controller is looking for, and posts it to the foo/createBooking action:

&lt;form method="post" accept-charset="UTF-8"&gt;
    {{ getCsrfInput() }}
    &lt;input type="hidden" name="action" value="foo/createBooking"&gt;

    &lt;!-- ... --&gt;
&lt;/form&gt;