商店会アプリ作成 その5

商店会アプリのその5です。
前回までの記事一覧

ポイントカード

ポイントカードの機能ですが、時間もなかったのでなるべく既存のプラグインを使いたい。
色々探してはみたのですが、いいものが見つかりませんでした。
ポイント管理システムは”myCRED”を導入しました。

myCRED

 

myCREDはシンプルなポイント管理プラグインです。

機能はアドオンで追加していく形です。

ドキュメントを読むと、拡張用のAPIや関数も色々用意されているので導入しました。

今回はQRコードをスキャン後に来店ポイントを追加、マイページでのポイントカード表示、

景品交換の仕組みが必要となります。

来店ポイント追加

その3 で作ったQRコードリーダープラグインで、Post後の動作をカスタマイズ。

functions.phpに以下のようなフックを追加しました。

function suehiro_qrr_submit_exec($result) {
  $args = array(
    'post_type' => 'shop',
    'title' => $result,
  );
  $query = new WP_Query($args);
  if ($query->have_posts()) {
    $query->the_post();
    // 念のためタイトル比較
    if ($query->post->post_title == $result) {
      $point_type = 'mycred_default';
      $mycred = mycred( $point_type );
      $user_id = get_current_user_id();
      $shop_url = get_permalink($query->post->ID);
      if ($user_id && !$mycred->exclude_user( $user_id )) {
        $log_args = array (
          'ref' => $query->post->ID,
          'user_id' => $user_id,
          'time' => 'today',
        );
        $log_query = new myCRED_Query_Log($log_args);
        if ($log_query->num_rows == 0) {
          mycred_add( $query->post->ID, $user_id, 1, $query->post->post_title);
          $shop_url .= "?add_point=1#stamp";
        }
      }
      header('Location: ' . $shop_url);
    }
    else {
      header('Location: ' . $result);
    }
  }
  else {
    header('Location: ' . $result);
  }
}
add_action( 'qrr_submit_exec', 'suehiro_qrr_submit_exec');
  • 2行目~10行目 QRコード対応店舗ページ検索
  • 11行目~22行目 来店ポイント検索(同一店舗は1日1回のみ)
  • 23行目~24行目 ポイント追加

使用したmyCREDのAPI

 

スタンプカード

プラグインではいいのが見つからなかったので、ここを参考に作りました。

cssとjsは上記のページをほぼそのまま使用。

QRコード読み込み後に飛ぶ各店舗ページのテンプレートに以下を追加しました。

$args = array (
  'ref' => get_the_ID(),
);
$query = new myCRED_Query_Log($args);
$points = $query->num_rows;
$user_points = 0;
if (get_current_user_id()) {
  $user_points = mycred_get_users_balance(get_current_user_id());
}
if (isset($_REQUEST['add_point']) && $user_points) {
  $stamp_num = $user_points % 10;
  if ($stamp_num == 0 && $user_points != 0) {
    $stamp_num = 10;
  }
  $args = array (
    'user_id' => get_current_user_id(),
    'orderby' => 'time',
    'order' => 'DESC',
    'number' => $stamp_num
  );
  $query = new myCRED_Query_Log($args);
  $stamps = array('訪','訪','訪','訪','訪','訪','訪','訪','訪','訪');
  if ($query->have_entries()) {
    $index = $stamp_num - 1;
    foreach ($query->results as $entry) {
      $pid = $entry->ref;
      $st = get_post_meta($pid, 'stamp', true);
      if ($st === '') {
        $st = mb_substr(get_the_title($pid), 0, 1);
      }
      $stamps[$index] = $st;
      $index -= 1;
    }
  }
?>
<script>
var visitCount = <?php echo $user_points - 1; ?>;
var stampCount = <?php echo $stamp_num - 1; ?>;
</script>
<link rel="stylesheet" href="<?php echo get_stylesheet_directory_uri() . '/visit-stamp.css'; ?>" />
<script src="<?php echo get_stylesheet_directory_uri() . '/visit-stamp.js'; ?>"></script>
<div id="stamp">
<div id="visit-stamp">
<table>
<thead>
<tr>
<th colspan="5">商店会のお店でスタンプを集めよう</th>
</tr>
</thead>
<tbody>
<tr>
<td><span><?php echo $stamps[0]; ?></span></td>
<td><span><?php echo $stamps[1]; ?></span></td>
<td><span><?php echo $stamps[2]; ?></span></td>
<td><span><?php echo $stamps[3]; ?></span></td>
<td><span><?php echo $stamps[4]; ?></span></td>
</tr>
<tr>
<td><span><?php echo $stamps[5]; ?></span></td>
<td><span><?php echo $stamps[6]; ?></span></td>
<td><span><?php echo $stamps[7]; ?></span></td>
<td><span><?php echo $stamps[8]; ?></span></td>
<td><span><?php echo $stamps[9]; ?></span></td>
</tr>
</tbody>
</table>
</div>
<p id="visitnum"></p>
</div>
<?php
}
  • 8行目 ポイント取得
  • 25行目~33行目 スタンプデータ作成

各店舗ごとにスタンプを変えています。スタンプカードっぽくて気に入ってます。

使用したmyCREDのAPI

景品交換

仕様

  • ポイント数に応じて景品を交換する
  • 同じ景品は一人1つに制限
  • 3ポイントでエコバッグ、10ポイントで福引券
  • 交換時に繰り返し並んで取得できないような仕組みが必要

今回はmyCREDのクーポン機能を使いました。

クーポンは本来は特定のクーポンコード(文字列)を入力すると、一定のポイントが付与される機能です。最大取得回数が指定できるので、1人1つにしました。あと、使用期限が指定できるので、福引を実施する翌日を制限日に指定しました。

クーポン設定

  • 入力値:1(景品交換時に付与されるポイント数)
  • 有効期限(イベントの翌日)
  • 全体の最大回数:300(景品の数)
  • ユーザーの最大回数:1(一人1個に限定)
  • クーポンの要件:最低限の残りポイント: 3(景品交換に必要なポイント数)

本当は、交換時にポイントをマイナスすることを考えていましたが、クーポンは加算しかできない仕組みだったので断念。

景品ごとにページを作って以下のコードを追加し、QRコードで景品ページのURLを読み込めば、クーポンが交換される仕組みにしました。

$user_id = get_current_user_id();
$code = "{name}";
$coupon_post = mycred_get_coupon_post( $code );
if ( isset( $coupon_post->ID ) ) {
  $results = mycred_use_coupon( $coupon_post->ID, $user_id );
  if ( mycred_coupon_was_successfully_used( $results ) ) {
  ?>
    {content}
<?php
  }
  else {
    $coupon = mycred_get_coupon( $coupon_post->ID );
    $msg = mycred_get_coupon_error_message($results, $coupon);
    echo "交換できませんでした。" . $msg;
  }
}
else {
  echo "クーポン名が違います";
}

使用したmyCREDのAPI

  • クーポンページ取得: mycred_get_coupon_post
  • クーポンを使う:mycred_use_coupon
  • クーポンオブジェクトを取得:mycred_get_coupon
  • エラーメッセージを取得:mycred_get_coupon_error_message

クーポンのアドオンにバグがあって、クーポンコードではmycred_use_couponの中で使用しているmycred_get_couponがエラーになります。
プラグインを直接修正するのはアップデート時に面倒なので、クーポンのIDを取得するようにしています。

ちなみに、不具合はこの部分。

  • mycred-coupon-object.php 82行目~
function __construct( $coupon_id = NULL ) {

  parent::__construct();

  $coupon_code = '';

  // If we provide the coupon code
  if ( ! is_numeric( $coupon_id ) ) {

    $coupon_id = 0;
    $coupon = mycred_get_coupon_post( $coupon_id );
    if ( $coupon !== NULL && $coupon->post_type == MYCRED_COUPON_KEY ) {
      $coupon_id = $coupon->ID;
      $coupon_code = $coupon->post_title;
    }

  }

  // If we provide the post ID
  else {

    $coupon_id = absint( $coupon_id );
    if ( mycred_get_post_type( $coupon_id ) != MYCRED_COUPON_KEY )
    $coupon_id = 0;

  }

  if ( $coupon_id === 0 ) return false;

  $this->populate( $coupon_id, $coupon_code );

}
91行目でcoupon_id = 0にしちゃうので、次の行のmycred_get_coupon_postがエラーになります。
修正するなら91行目を削除して、97行目あたりにelse文を挿入して、coupon_id = 0 にするかな?

お気軽にコメントしてください(管理者の承認後に表示されます)

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です


The maximum upload file size: 8 MB.
You can upload: image, audio, video, document, spreadsheet, interactive, archive, other.
Links to YouTube, Facebook, Twitter and other services inserted in the comment text will be automatically embedded.

Translate »