Why Stripe?

I’ve been a fan of Stripe ever since I looked at their API. It’s the reason they were the first tool that Integrated into PressPay. But, there’s another – more compelling – reason that I personally use Stripe for credit card processing: chargebacks.

There are a lot of credit card processors that have ridiculous fees around chargebacks. I’ve worked with one company that charged $15 when the customer charged back their purchase and they charged $15 for you to dispute the chargeback. Neither of those charges were refundable. So, even if you were the victim of fraud, you had to spend $30 to defend yourself against the chargeback. As a result, we never fought chargebacks when we were using that credit card processor. Some of our customers figured out that we were never disputing chargebacks and they started posting on reddit that you could get free stuff from us by ordering with your credit card and then just disputing the charge.

Not Stripe. Stripe deducts $15 from your account when a customer charges back a purchase. But, they don’t charge you to dispute the chargeback. And, they refund the $15 fee if the dispute is resolved in your favor. So, for the first time ever, I disputed a chargeback. And then this happened:

We have good news for you! The disputed payment from August 29 was successfully resolved in your favor by your customer’s bank or credit card company.

I won! The part that really blows me away is that I’d always assumed that you could not win this kind of dispute. But, because I was using Stripe, I fought the charge anyway. After all, it didn’t cost me anything other than a few minutes of looking through my records and sending an email stating why I thought the charge was legitimate.

The most important difference, however, is that the fraudsters are going to learn that I dispute every chargeback. They will see that I’m not a soft target and they’ll move on to someone else. I’m really looking forward to spending more time working for my customers and less time fighting against the fraudsters.

Now, while Stripe is the right choice to fight fraudulent chargebacks, there are other types of fraud that we still need to deal with. For instance, did you know that people who steal credit card numbers will use online marketplaces to test the numbers to see which ones are still active? They do this to protect their reputation for selling high quality stolen numbers. This is bad for us because it creates a liability for every online marketplace that they use. You see, those charges eventually get back to the owner of the credit card. And, that owner eventually charges back those transactions. At that point, you just have to eat the $15 chargeback fee.

What if you could identify a fraudster before you were hit with a chargeback? That’s the question that a great little company called Sift Science is answering. They’re collecting massive amounts of data and using machine learning to find patterns of fraud. This means they can tell you who’s a fraudster and who’s a customer before you get his with a chargeback.

Much like Stripe, I’m really impressed with Sift Science. That’s why I’ve decided that they will be the next technology that I integrate into PressPay. If you hate fraud as much as I do, watch this space for the next release of PressPay which will give you some great tools for fighting the fraudsters.

Posted in Uncategorized

Press Pay version 1.0 Released

Press Pay version 1.0 Released

Press Pay is the fast and easy way to turn any WordPress Blog into a Web Store. Simply sign up for an account with Stripe, enter your keys into Press Pay:

Stripe Settings

Enter your API keys in the Stripe Settings page.

Then you can add a short code to any Page or Post turning it into a Web Store:

[presspay amount="2000" product_id="1" description="Wonder Widget"]

Your customers will see a button on the page that let’s them purchase your product:

Pay With Card

Pay With Card

Clicking the payment button will bring up a dialog to gather credit card details and process the payment:

Checkout Dialog

Checkout Dialog

Email Dialog

Email Dialog

 

Shipping Address Dialog

Shipping Address Dialog

Thank You Dialog

Thank You Dialog

Your customers are emailed a copy of their receipt:

Payment Receipt

Payment Receipt

And you’re emailed a confirmation of the sale:

Sale Confirmation

Sale Confirmation

Download PressPay now or Get it from the Plugin Directory on WordPress.org.

Posted in Uncategorized

A Model, View, Controller Pattern for WordPress Plugins

The Model, View, Control (MVC) design pattern is very useful for Web development. When you follow this pattern, your applications will have 3 distinct pieces. Models will handle your program’s interactions with data storage. This is often means running a query against a database. Views present your program’s User Interface. Usually, this means rendering HTML. Finally, Controllers will act as brokers passing data between Models and Controllers. The benefit to structuring your programs this way is that it is easier to swap out User Interfaces or change databases. In this post, we’re going to look at how this pattern can be applied to WordPress Plugin development.

We’ll illustrate development with an example. Let’s build a simple Plugin to log a user in to WordPress. The goal is to give the Admin to a WordPress blog a short code that he can imbed in any page or post that will show the user a login screen if they are not logged into WordPress.

We’ll call our plugin ‘Lightbox Login’ and set up our files accordingly. We need to name our folder ‘lightbox-login/’ and our main plugin file ‘lightbox-login/lightbox-login.php’. We’ll also create an `app` folder with the sub-folders `model`, `view`, and `controller`. Our MVC class files will live here. Finally, we have a `lib` folder with a `Mixer` class in it. We’ll explain how `Mixer` is used in a bit.

lightbox-login/
              |-lightbox-login.php
              |-lightbox-login.css
              |-lightbox-login.js
              |-app/
                   |-model/
                          |-debug.model.php
                   |-view/
                         |-login.view.php
                   |-controller/
                               |-login.controller.php
              |-lib/
                   |-Mixer.php  

Let’s take a look at `lightbox-login/lightbox-login.php` first:

<?php
/*
 * Plugin Name: Lightbox Login
 * Plugin URI: http://atomicbroadcast.net/lightbox-login/
 * Description: A simple shortcode that will require a user to login to view a
 *              page.
 * Author: Andrew Dixon
 * Author URI: http://atomicbroadcast.net
 * Version: 0.1
 */
/*****************************************************************************
 * constants and globals                                                     *
 *****************************************************************************/
if (!defined( 'LIGHTBOX_URL' )) {
  define( 'LIGHTBOX_URL', plugin_dir_url( __FILE__ ) );
}
if (!defined( 'LIGHTBOX_DIR' )) {
  define( 'LIGHTBOX_DIR', dirname( __FILE__ ) );
}
/*****************************************************************************
 * include files                                                             *
 *****************************************************************************/
require_once( LIGHTBOX_DIR . '/lib/Mixer.php' );
require_once( LIGHTBOX_DIR . '/app/controller/login.controller.php' );
/*****************************************************************************
 * instantiate loginController                                               *
 *****************************************************************************/
$loginController = new LoginController();
?>

All that we’re doing here is defining a few constants, including a few files and instantiating our LoginController. So, let’s move on and take a look at the controller:

<?php
require_once( LIGHTBOX_DIR . '/app/model/debug.model.php' );
include_once( LIGHTBOX_DIR . '/app/view/login.view.php' );
/*****************************************************************************
 * class LoginController                                                     *
 *****************************************************************************/
class LoginController extends Mixer
{
  /***************************************************************************
   * __construct()                                                           *
   ***************************************************************************/
  public function __construct()
  {
    $this->addMixin( new DebugModel() );
    $this->addMixin( new LoginView() );
    add_action( 'template_redirect',
     array( $this, 'check_login' ) );
    add_shortcode( 'lightbox_login',
      array( $this, 'lightbox_login_shortcode' ) );
    add_action( 'wp_enqueue_scripts',
      array( $this, 'load_scripts' ) );
  }
 /***************************************************************************
  * check_login()                                                           *
  ***************************************************************************/
  public function check_login()
  {
     if (isset( $_POST['username'] ) && (isset( $_POST['password'] ))){
       $credentials = array(
         'user_login' => $_POST['username'],
         'user_password' => $_POST['password']
       );
       wp_signon( $credentials );
     }
  }
  /***************************************************************************
   * lightbox_login_shortcode( $atts, $content = null )                      *
   ***************************************************************************/
  public function lightbox_login_shortcode( $atts, $content = null )
  {
    $this->debug( 'lightbox_login_shortcode()' );
    if (!is_user_logged_in()){
      $this->debug( 'show login lightbox' );
      $this->render_login( $this );
    } else {
      $this->debug( 'do nothing because user is logged in' );
    }
  }
 /****************************************************************************
  * load_scripts()                                                           *
  ****************************************************************************/
  public function load_scripts()
  {
    $this->debug( 'load_scripts()' );
    wp_enqueue_script( 'jquery' );
    wp_enqueue_script( 'jquery-ui' );
    wp_enqueue_script( 'jquery-ui-dialog' );
    wp_enqueue_script( 'lightbox-login', LIGHTBOX_URL . 'lightbox-login.js' );
    wp_register_style( 'lightbox-login', LIGHTBOX_URL . 'lightbox-login.css' );
    wp_enqueue_style( 'lightbox-login' );
  }
}
?>

OK. So, there’s a lot more going on here. The first thing you’ll notice is that LoginController extends the Mixer Class (code below). Mixer is an implementation of the Mixin patter. It is used to “mix in” the function from on Class into another. It’s a good solution for our purposes because it doesn’t require us to use a newer version of php (most WordPress installs use older versions) and it gives us most of the functionality of Multiple Inheritance.

Let’s take a look at LoginController’s `__construct()` function. Notice the first line:

$this->addMixin( new DebugModel() );

Here, we’re telling the interpreter that, when it instantiates LoginController, it should look for the DebugModel class and pull all functions from DebugModel into the new instance of LoginController. Let’s take a look at DebugModel to see what new functionality we’ll have access to:

<?php
// Don't redeclare the Class if it already exists.
if (!class_exists( 'DebugModel' ))
{
  /***************************************************************************
   * class DebugModel                                                        *
   ***************************************************************************/
  class DebugModel{
   /**************************************************************************
    * debug( $message )                                                      *
    **************************************************************************/
    public function debug( $message ){
      if (WP_DEBUG_LOG === true) {
        if (is_array($message) || is_object($message)) {
          error_log( print_r( $message, true ) );
        } else {
          error_log( $message );
        }
      }
    }
  }
}
?>

So, we get a nice little function to write a debug message to the log file if WP_DEBUG_LOG is true. Notice that the debug() function actually writes to disk. Because it accesses permanent storage, it belongs in a Model according to the MVC pattern. The benefit here is that we’ve separated the debug() function from the logic in our controller. If, in the future, we decide that writing to disk isn’t good enough and we also want to email the debug message to an administrator, we only need to update the DebugModel and the rest of our plugin remains unchanged.

The rest of the __construct() function “mixes in” the LoginView and then hooks the newly created LoginController object into the WordPress core. The add_shortcode() function tells WordPress to “listen” for a [lightbox-login] shortcode. When it sees this code, the lightbox_login_shortcode() function will be executed.

Inside lightbox_login_shortcode() we’ll check to see if the user is NOT logged in.

if (!is_user_logged_in()){

if not, we want to render our login page:

      $this->debug( 'show login lightbox' );
      $this->render_login( $this );

If the user is logged in, we don’t do anything and just let them see the page:

    } else {
      $this->debug( 'do nothing because user is logged in' );
    }

Remember that we only want to display anything to the user in a View. So, the render_login() function needs to live in the LoginView Class:

<?php
/*****************************************************************************
 * class LoginView                                                           *
 *****************************************************************************/
class LoginView
{
 /****************************************************************************
  * render_login( $controller )                                              *
  ****************************************************************************/
  public function render_login( $controller )
  {
    $controller->debug( 'render_login( $controller )' );
    ob_start();
    ?>
      <div class='dialog app'
           title='<h1>Login</h1><h2>Please log in</h2>'>
        <div class='panel'>
          <form name='lightbox-login-form'
                id='lightbox-login-form'
                method='POST'>
            <article>
              <div class='username'>
                <label for='username'>User Name:</label>
                <input id='username'
                       name='username'
                       type='text'
                       value=''
                       placeholder='User Name'>
                <label for='password'>Password:</label>
                <input id='password'
                       name='password'
                       type='password'
                       value=''
                       placeholder='Password'>
              </div>
            </article>
            <footer>
              <button id='lightbox-login-submit'
                      class='blue submit'>
                <span>Login</span>
              </button>
            </footer>
          </form>
        </div>
      </div>
    <?php
    echo ob_get_clean();
  }
}
?>

Now, with a little javascript magic, and the jquery-ui-dialog plugin, we’re going to tell the browser to render a “dialog” class as a lightbox. WordPress comes with jquery, jquery-ui, and jquery-ui-dialog but we do have to load them in the LoginController. Once that is done, we can include a customer javascript to configure jquery-ui-dialog:

jQuery(document).ready(function() {
  var dialogOpts = {
    autoOpen: true,
    minHeight: 'auto',
    modal: true
  }
  jQuery('.dialog').dialog(dialogOpts);
  jQuery('#lightbox-login-form').submit(function(event) {
    jQuery('.dialog').dialog('close');
  });
});

And we have a login form that pops up in a lightbox if the user is not logged in. The last thing to do is log the user in when the form is submitted. For this we use the wp_signon() function. This presents one last problem as we can’t use this function in the lightbox_login_shortcode() function because wp_signon() needs to be run before we output any headers. The solution is to add a “template_redirect” to the WordPress core that checks to see if our POST vars are set (i.e. it checks to see if our login form was submitted).

  public function check_login()
  {
     if (isset( $_POST['username'] ) && (isset( $_POST['password'] ))){
       $credentials = array(
         'user_login' => $_POST['username'],
         'user_password' => $_POST['password']
       );
       wp_signon( $credentials );
     }
  }

And we hook the function check_login() into the WordPress core in the LoginController __construct() function:

add_action( 'template_redirect',
     array( $this, 'check_login' ) );

And that’s it! We’ve not got a working shortcode that will propt a user to login to any page or post that we want. Of course, this plugin isn’t very robust. The first thing to note is that we’re sending usernames and passwords in plain text over the Internet. That’s just bad. The second thing is that the user can just close the form instead of logging in. So, please, only use this plugin as an example and don’t put it on a live site :)

If you want to see this plugin in action. Check out this page.

You can log in with the username: “test” and password: “test”

And, you can download the source here.

Mixer Class magic. This post is already too long so I won’t go into how the Mixer Class works in this post but maybe I’ll write about it in a future post.

<?php
// Don't redeclare the Class if it already exists.
if (!class_exists( 'Mixer' ))
{
abstract class Mixer {

  protected $methods = array();
  protected $mixins = array();
  protected $priorities = array();

  /**
   ** @description By adding a mixin, the extending class will automatically adopt all of a mixin's methods.
   ** @param object $mixin - The instantiated object that's methods should be adopted by the extending class.
   ** @security You are expected to know if there will be a conflict in which two mixins share the same method name. If
   **      this conflict occurs, use the <a href="#setPriorities">setPriorities()</a> method to specify which method
   **      should take precedence. Mixer will not handle the conflict automatically on its own.
   **/
  public function addMixin($mixin){
    if (!is_object($mixin)){
      throw new Exception("The mixin is not valid because it is not an object.");
    }
    $name = get_class($mixin);
    $this->mixins[$name] = $mixin;
    $methods = get_class_methods($name);
    $this->methods[$name] = $methods;
  }

  /**
   ** @description Allows multiple mixins to be added at once. By adding a mixin, the extending class will
   **      automatically adopt all of a mixin's methods.
   ** @param array $mixin - An array of instantiated objects whose methods should be adopted by the extending class.
   ** @security You are expected to know if there will be a conflict in which two mixins share the same method name. If
   **      this conflict occurs, use the <a href="#setPriorities">setPriorities()</a> method to specify which method
   **      should take precedence. Mixer will not handle the conflict automatically on its own.
   **/
  public function addMixins(array $mixins){
    foreach ($mixins as $mixin){
      $this->addMixin($mixin);
    }
  }

  /**
   ** @description Gets the class's current mixins by name
   ** @return An array of mixin class names.
   **/
  public function getMixins(){
    return array_keys($this->methods);
  }

  /**
   ** @description Manages conflicts for the mixins.
   ** @param array $priorities - The method name as the key, the class name that has priority in a conflict as
   **      the value.
   ** @note Once a method has been assigned to a class, it cannot be reassigned to a different class at a later point.
   **      This is done to minimize potential bugs due to dynamic prioritization.
   **/
  public function setPriorities(array $priorities){
    $classNames = array_keys($this->methods);
    $setPriorities = array_keys($this->priorities);
    foreach ($priorities as $method=>$class){
      if (!in_array($class, $classNames)){
        throw new Exception("$class is not a valid mixin. To make $class a mixin, use the addMixin method.");
      }
      if (!in_array($method, $this->methods[$class])){
        throw new Exception("$class does not have a method named '$method'.");
      }
      if (in_array($method, $setPriorities)){
        $assigned = $this->priorities[$method];
        throw new Exception("$method has already been assigned to $assigned and cannot be reassigned.");
      }
    }
  $this->priorities = $priorities;
  }

  /**
   ** @description A magic method that calls the mixin methods automatically. This method should not be
   **      called directly.
   ** @param string $methodName - The name of the mixin method
   ** @param array $arguments - The arguments for the method
   ** @return The return value will vary depending on the function called.
   **/
  public function __call($methodName, array $arguments){
    foreach ($this->methods as $className=>$methods){
      if (in_array($methodName, $methods)){
        if (
           (in_array($methodName, array_keys($this->priorities))) &&
           ($className == $this->priorities[$methodName])
        ){
          return call_user_func_array(array($className, $methodName), $arguments);
        } else if (!in_array($methodName, array_keys($this->priorities))){
          return call_user_func_array(array($className, $methodName), $arguments);
        }
      }
    }
    $mixins = (sizeof($this->methods) > 0) ? implode(', ', array_keys($this->methods)) : 'No mixins are listed.';
    throw new Exception("$methodName is not a method. Your current mixins are: $mixins");
  }
}
}
?>
Posted in Uncategorized