2014/11/13

カラーミーAPIとエクセルを連動して在庫更新を試してみた



正直何がうれしいのか良くわからないレベルです。

ざっくり見た感じいろいろと便利になるWEBアプリ的なものを作れる。

みたいな感じでしょうか??

そしてなんといっても無料!!感謝!

結局のとこサーバーサイドがいじれんことには始まらんのかなと。

そんな雰囲気を感じながら恐る恐るカラーミーショップAPIドキュメントを見てみる。

必要なもの

カラーミーデベロッパーアカウント
登録はこちら
APIのクライアントには以下が必要です
RESTfulなHTTPリクエスト
JSONのパースやシリアライズ
認可コードの受け取り
カラーミーの認可ページからのHTTPリクエストを受けられるWebサーバ
または、スマートホンアプリのWebView

利用手順

以下の手順で、OAuth2プロトコルでの認証をします。

OAuth、、正直この辺で撃沈です。

が、とりあえず諦めずにサンプルどおりXAMPP環境にて進めてみる。

すると以外とすんなり動かすことができました。

そもそもカラーミーAPIを調べようとした経緯とか


なんかカラーミーで在庫更新するの以外とめんどくさい。と、思ったり。

各モールや店頭などで併用販売している在庫をある程度連動して管理できないかな、、

とか考えておりました。

なんかそーゆーのってAPIとかいうの使ったりすんでしょ?

みたいな気持ちでとりあえず軽く試してみる。

書いてあることは難しそうだが以外と動くじゃん!

ただサーバサイドは良くわかりませんので、とりあえずHTTPリクエストができれば

利用できそうだし、ちょっとした在庫管理によく使われているであろう

エクセルVBAからAPIを利用してみました。

以下Evernoteに殴りメモした内容。乱雑ですいません


目標としてアクセストークンを手に入れて、

在庫管理しているエクセルから連動して在庫の増減などを試みる。

なのでとりあえずローカル環境で全て事足りる感じです。

まずアプリを登録

カラーミー管理画面にログイン > アカウント設定 > カラーミーアプリ開発
新規登録 > (アプリ名) 適当な名前 > (リダイレクトURL) 適当なサイト(自分のカラーミーのサイトでいいんでないでしょうか) > 登録
もどるボタン > 先ほど作成したアプリの修正ボタン

そのページにアクセストークンを取得する際に必要となる

・client_id
・client_secret
・アプリケーション名
・redirect_uri

が表示されます。

そんで認可コードの取得

以下URLをブラウザで普通に読み込む。

https://api.shop-pro.jp/oauth/authorize?client_id= 編集ページのclient_id &response_type=code&scope=write_products&redirect_uri=http://example.shop-pro.jp

・client_id > 編集画面の数値
・response_type > code
・scope > write_products(商品編集だけの場合)
・redirect_uri > http://example.shop-pro.jp(さっきの適当なサイト)

URLバーに普通に入れてリクエストを送る

http://api.shop-pro.jp/login ここにリダイレクトされます

アプリの許可

自分のカラーミーショップのIDとPASSを入力

あなたのショップでアプリケーション
「アプリ名」
の使用を許可しますか?
(自分が作成した(作成する)アプリが、自分のショップの
商品データへの書き込みを許可しますか)

「 承認する」をクリック

http://example.shop-pro.jp(登録した適当なサイト)にリダイレクトされる

アクセストークンの取得

エラーがなければリダイレクト先のURLに?code=承認コード

パラメータが付属される。

この承認コードをアクセストークン取得で使う。

以下VBAでの例ですがこんな感じでとにかくPOSTリクエストするとresponseにJSONが返る

client_id、client_secretの値はカラーミーの画面に記載されています。

codeは先ほどの承認コードです。

以下標準モジュールにはっつけて実行

Sub getToken()
   
    Dim xhr As Object
    Set xhr = CreateObject("MSXML2.ServerXMLHTTP.6.0")
    Dim content As String
   
    content = "client_id=****&"
    content = content & "client_secret=****&"
    content = content & "code=****&"
    content = content & "grant_type=authorization_code&"
    content = content & "redirect_uri=http://example.shop-pro.jp"
   
    xhr.Open "POST", "https://api.shop-pro.jp/oauth/token", False
    xhr.Send (content)
    Debug.Print xhr.responseText
   
End Sub

イミディエイトウィンドウに下記のようなJSONが表示されます。

{"access_token":"アクセストークン","token_type":"bearer","scope":"write_products"}

念願のアクセストークンが手に入ります。

これであとはやりたい放題。

※認可コードからアクセストークン取得するとき変換は1度きりで、制限時間もあるらしい。

ためしに在庫の更新

Sub stockUpdate()
   
    Dim xhr As Object
    Set xhr = CreateObject("MSXML2.ServerXMLHTTP.6.0")
   
    xhr.Open "PUT", "https://api.shop-pro.jp/v1/products/" & Range("A1") & ".json", False
    xhr.setRequestHeader "Authorization", "Bearer アクセストークン"
    xhr.setRequestHeader "Content-Type", "application/json"
    xhr.Send "{ ""product"" : { ""stocks"": 0 } }"
    MsgBox IIf(InStr(xhr.responseText, "error"), "err", "ok")
End Sub

Bearer アクセストークンの部分に先ほどのJSONのアクセストークンを入れる。

Range("A1")にカラーミーの商品IDをいれてこのプロシージャを呼び出せば

その商品の在庫が0になる。

もう少しつっこんでみる

エクセルシートのChangeイベントで呼び出せば

エクセルの在庫数を変更した時ほぼ同時にカラーミーの在庫数へ反映させる的なこともできるのでは??

例えばこんな感じのエクセル簡易データベースがあったとして

1品番 品名 単価 在庫数 PID
21001 ふんわりクッキー 1000 10 77777777
31002 しっとりクッキー 1500 5 88888888
41003 ずっしりクッキー 500 8 99999999

エクセルの在庫数を書き換えたときにAPIを呼び出してカラミの在庫も書き換える

'データのあるシートモジュール
Private Sub Worksheet_Change(ByVal Target As Range)

    If Target.Column <> 4 Then Exit Sub
    Call stockUpdate(Target.Value, Target.Offset(0, 1).Value)
    
End Sub

'標準モジュール
Sub stockUpdate(stock, pid)
   
    Dim xhr As Object
    Set xhr = CreateObject("MSXML2.ServerXMLHTTP.6.0")
   
    xhr.Open "PUT", "https://api.shop-pro.jp/v1/products/" & pid & ".json", False
    xhr.setRequestHeader "Authorization", "Bearer アクセストークン"
    xhr.setRequestHeader "Content-Type", "application/json"
    xhr.Send "{ ""product"" : { ""stocks"": " & stock & " } }"
    If InStr(xhr.responseText, "error") Then MsgBox "err"
End Sub

アクセストークンを書き換える。

こんな感じでエクセルの在庫数を書き換えると、同時にカラミーの在庫数も更新。

できるのか?いろいろ問題はありそうですがとりあえずはできそうです。

その他もろもろ

ちなみにアプリの削除(トークンの無効化)は

カラーミーのアプリケーション管理から削除できるようです。

それとあくまでテストでいろいろ試してみただけす!

もしもご参考していただける方いらっしゃってもセキュリティ等自己責任でお願いします!!

次回できれば


逆バージョンというか、受注を監視してローカルの在庫、

また他のモールの監視とカラミの連動などちょっと考えてみたいと思います!

2014/11/11

超軽量画像モーダル系jQueryプラグイン

いわゆるLightboxみたいな感じで、

でもいろんな機能とか、派手なアニメーションはいらない。

あとスライドショーもいらない。

ほんっと画像をオーバーレイで表示させるだけ!

っていうか、画像ファイルとか、CSSまで読込みたくない!

そんなシンプルなプラグインを探したけどなかったので作ってみました。

単なる手抜きでもありますが良く言えば軽量!

(function($) {
 $.fn.imgModal = function() {
  $(this).click(function(e) {
   if(navigator.userAgent.match(/msie [6.|7.|8.]/i)) return;
   e.preventDefault();
   var that = this;
   var $loading = $('<div>').text('Loading...').attr('style', 'font-family: Helvetica,Arial; font-size: 17px; color: #eee; text-align: center; position: relative; top: 50%;');
   var $div = $('<div>').attr('style', 'z-index: 100; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,.4); display: none;')
    .on('click', function() { $(this).fadeOut('fast', function(){ $(this).remove() } )})
    .append($loading)
    .appendTo($('body'))
    .fadeIn('fast', function() {
     $('<img>').on('load', function() {
      $(this).fadeIn('slow', function() { $loading.remove() });
     })
     .attr('style', 'max-width : ' + (window.innerWidth - 50) + 'px; max-height: ' + (window.innerHeight - 50) + 'px; width: auto; height: auto; display: none; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; border-radius: 5px;')
     .attr('src', that.href)
     .appendTo($div)
    });
  });
 };
})(jQuery);

IE8以下は切りました。手抜きです。

画像が大きい場合ウィンドウサイズによって縮小されるので

ブラウザによって少々画像が荒くなります、、

それとイベントの設定にonを使用しているのでjQuery1.7未満ですと動きません!



そんで以下で実行。引数はありません。

単純明快、シンプルに。

$(function() {
 $('a[rel="imgModal"]').imgModal();
});

アンカーのrel属性にimgModalを入れればOK。

<a rel="imgModal" href="http://www.example.com/test.jpg">img</a>

よかったらご利用ください。



DEMO



turunto

2014/10/10

カラーミーショップのカートにマウスオーバーでカゴの中身を表してみる

ここ最近ほとんど(プライベートで)PCをいじる事がなく、

ブログ書くような記事もなく、、、。

なもんで、仕事で少し使っておりますカラーミーの小ネタを少しずつ書いていこうと思います。

カラーミキットのカスタマイズ


たいしたカスタマイズではないのですが、

先日カラーミーキットを少しカスタマイズしてみました。

その際、カートの中身が(詳細)が表示されない。

商品確認するのに1ページ遷移するのも、、と思い

マウスオーバー&ツールチップで表示させてみよう。

備忘録もかねて。

使わせていただいたツールチップはこちら

jQuery PowerTip

うれしいMITライセンスで公開されているようです(要確認!!)

使い方に関しましては

coliss様のサイトが大変参考になりました。

そんで共通HTML内に大体こんな感じのコードを入れる!

<{if $incart != ""}>//カートに商品があれば実行
  var data = [];
  data.push('<div style="width: 300px;">');
  <{section name=num loop=$incart}>
    data.push('<p><a style="color: #fff; text-overflow: ellipsis; display: block; overflow: hidden;" href="<{$incart[num].link_url}>"><{$incart[num].name}></a></p>');
    data.push('<p class="txt_r"><{$incart[num].price}>円</p>');
  <{/section}>
  data.push('<p class="bor_t_1 mar_t_5 pad_t_5"><b>商品合計&nbsp;<{$incart_total_price}>円</b></p>');
  data.push('</div>');
  $('#cart-tool-tip').data('powertipjq', $(data.join('\n'))).powerTip({placement: 'sw', mouseOnToPopup: true, closeDelay: 200, intentPollInterval: 0});
<{/if}>

とりあえずは設置してみたものの、

かごの中身の表示方法はどんな感じがベストなんでしょうか、、。

もっと色々調べてみようと思います。

一応DEMO







2014/09/06

ブログとかのアーカイブの表示方法について考えてみた

長くなってきたブログのアーカイブをどう表示するか?

とりあえず「もっとみる」的なスクリプトを考えてみました。

こんな感じのhtmlで。

<aside id="archives">
 <h3 class="widget-title">Archives</h3>
 <ul>
  <li>2013/12</li>
  <li>2014/1</li>
  <li>2014/2</li>
  <li>2014/3</li>
  <li>2014/4</li>
  <li>2014/5</li>
  <li>2014/6</li>
  <li>2014/7</li>
  <li>2014/8</li>
  <li>2014/9</li>
 </ul>
</aside>

こんな感じのスクリプトを入れる(jQuery使用)

$(function() {
 var $target = $('#archives');
 var count = 1;
 var num = 5;//表示する数
 var l = $target.find('li').length;
 var style = 'display: block; margin: 0 auto; width: 25px; height: 25px; box-shadow: none; cursor: pointer';
 if(num < l) {
  $('#archives li:gt(' + (num - 1) + ')').css('display', 'none');
  $('').attr({ 'src': 'http://example.com/images/arrow.png', 'style': style })
   .appendTo($target)
   .bind('click', function() {
    $('#archives li:lt(' + (num * ++count) + ')').fadeIn(350);
    if(l <= num * count) $(this).remove();
   });
 }
});

もっと見る的なjavascriptがUX的にいけてないとの記事発見。

ページ遷移して、戻ったときに「もっと見る」で開いた部分が元に戻ってる。

確かに。読んで納得。

そんで少し訂正。タブを閉じるまで開いた分をキープ。

var num = 5;//表示する数
var isStorage = false;
try {
 if(typeof sessionStorage['moreCnt'] === 'undefined') sessionStorage['moreCnt'] = 1;
 isStorage = true;
 moreBtn(sessionStorage['moreCnt']);
} catch(e) {
 moreBtn();
}

function moreBtn(count) {
 count = count || 1;
 var $target = $('#archives');
 var l = $target.find('li').length;
 var style = 'display: block; margin: 0 auto; width: 25px; height: 25px; box-shadow: none; cursor: pointer';
 if(num * count < l) {
  $('#archives li:gt(' + (num * count - 1) + ')').css('display', 'none');
  $('').attr({ 'src': 'http://example.com/images/arrow.png', 'style': style })
   .appendTo($target)
   .bind('click', function() {
    $('#archives li:lt(' + (num * ++count) + ')').fadeIn(350);
    if(isStorage) sessionStorage['moreCnt'] = count;
    if(l <= num * count) $(this).remove();
   });
 }
};

なんかコードがすっきりしませんが、、、

一応DEMO



今後は小ネタを遠慮なく書いていこうと思います。

2014/05/22

カラーミーキットを使ってみた!



仕事でカラーミーさんを利用させてもらってまして、

以前は「プレーン」というテンプレートを少しカスタマイズして使用していたのですが、

時代も変わってきたというこで、ここはモデルチェンジでもしてみっか!ってことで重い腰を上げてみました。

カラーミーキット(2カラム)


まずはテンプレート選び。

久々にひらくとなんとも素敵なテンプレートが増えてるではないですか、、、

Panoramaとかワンプレートホワイトとか、

と、思ったらどーやらこれらは有料版。素敵だけど少し金額に怖気づく、残念。

改めて無料版を拝見。

すると目立つ部分にどんっ



なんでしょう、これ。

いったんスルーして下のテンプレに目を向けるとBitこれとかも

ぜんぜん素敵じゃないですか!さっきの有料版とどんだけ違うの??

とか思いながら、先ほどのカラーミーキットをクリック。

すると素敵なテンプレたちはどーやらこのテンプレを元に作られているらしい。

詳細→テンプレートフレームワーク カラーミーキット

そして無料。

これは気になるってことでとりあえず軽く調べてみました。

Bootstrap?見たいな感じ??


ドキュメントを見てみるとどーやら

流行??のBootstrap風のClassでぐりぐりカラムを分けるような仕組みのようです。

って、Bootsrapいじったことはありませんが、、、。

これもいい機会だし流行(ってますよね?)のレスポンシブとやらを経験してみようと、

カスタムテンプレのカラーミーキット(2カラム)をポチる。

いざカスタム。

col-lg-(n) col-sm-(n)


ほんと、これの意味すら良くわからなくて、、、

良くカスタムできたと自分でも思います。はい。

(12 / n) カラムって感じでしょうか。

ちょっとドキュメントが素人にはもの足りない感じですが

ただ、なんでもそうですがいじってるうちに以外と慣れるもんで、、、。

しかしマージンとかパディングとかこーゆー指定の仕方が今主流なんでしょうか?

わかり易いような、面倒くさいような。

つまづいたところ


あくまでBootstrap、レスポンシブ未経験の体験談なので、

そのコードが指し示す真意を理解できていない気がしますが、

結構悩んでしまったところをいくつか。

■icon-b, icon-w, icon-lg-b, icon-lg-w

<i class="icon-b icon-twitter"></i>

的な感じでiconが用意されていて、サイズも大、小あるのですが、

なぜか768px以下のデバイスは小アイコンを選んでも大アイコンにCSSが設定されています。

768以下でアイコンがズレます。

共通CSSに入っているんですが、この真意をいろいろ考えたのですが解明できず。

■viewportを書き出すところ

最初ある程度カスタムしてから、スマホで確認してみたんですが、

ページを遷移する度にチラつくんです。

困った困った。原因を考えたところ、

スマホ用のmeta viewportをスクリプトで書き出しているんですが、

これが共通HTMLのfooter下のDOM readyイベント内に書かれています。

なのでスマホでアクセスするとbodyが一瞬PC用にレンダリングされた後スマホ用のCSS

が読み込まれるようで画面がちらつきます。

サイドにカラムなどなければ気にならない程度かもしれませんが、、。

とりあえず共通HTMLのスクリプトをbody直下へ移動。

そんでviewport書き出しはDOM readyから出しました。

とりあえず問題なさそうだし、自分的にはちらつきがなくなったのでなにより。

■btnクラスのinline-block

がinlineにアスタリスクがついてるんでIE用のハックだと思うんですが

zoom:1;がはいった方がしっくりくるような。

ま、正直この辺良くわかりませんが!

結論


これは慣れれば量産できそうな予感。

今度Bootstrapもいじってみたいな。

2014/04/25

websocketを使ってみて感動した件


なぜにwebsocket


ふと、サーバー側からクライアントへどーにかデータ送信ってできないか??

と思うことがり、そんなような内容をググってみたところ。

ポーリングということばに出会いました。

そこが今回の始まりです。

知りませんでしたぽーりんぐという言葉。

そんでちゃちゃっと自分で調べた感じ、

javascriptにおけるポーリングとはF5又はXHR連打。

ロングポーリングとはXHRでデータ送信、

サーバ側でぐるぐる待つ。

変更があればクライアントに戻す。

かなり斜め読みのざっくり把握です。

コメットなる言葉も出てきましたがロングポーリングと

似たようなもの、ということみたい。

CometとAjaxを利用したチャットサーバの実装

こちらのサイトがわかりやすかったです。

まぁ結局のところ当たり前かも知れませんが、

クライアントからサーバへ問い合わせないと始まらんよ、と。

しかし、まぁ見てのとおりサーバーの負担が気になるところです。

よくチャット禁止とか書かれているレンタルサーバーはこういうことっだのでしょうか?

そしてwebsocketなる技術はそんなサーバーの負担を和らげてくれる技術らしい。

まぁ難しいんでしょうね~と、思いながらもちょっとググってみる。

websocketはnode.jsというもので実装されている方が多いようでした。

聞いたことはあるがイマイチなぞなnode.js。

唯一かろうじて雰囲気はわかるPHPでどーにかできないもんか。

ありました、完璧に教えてくださるサイト様が。

PHPでWebSocket

同時にお絵かき。魅力的です。

早速試してみることに。

簡単!


といってもPHPでWebSocketこちらのブログのおかげですが、、、

今回とりあえず動かす!!という目標なのでXAMPP環境でチャレンジです。

サーバサイドはphp-websocketこちらのライブラリを

ダウンロードしてまんま使わせいただきました。

ドメイン部分だけ書き換えをしたらあっさりとdemo起動。

PC、iPhoneで問題なくつながりました!

そしてこのながながとひっぱていながら全くアクセスのない

お絵かきアプリPaint!をカスタムです。

大抵この手の未知なことをはじめるとどつぼにはまるのですが、

以外にもスムーズに。

クライアント側


は、とりあえずpaintとというオブジェクトを作成して、そのオブジェクトに

カラー情報やらタッチの位置やら様々な描く情報を入れているのですが、

今回はタッチ系のイベントごとにこのpaintオブジェクトのプロパティの一部をJSONして

データを送信するという感じにしました。

そんでこのオブジェクトを通常のタッチによるcanvasへの書込み用と

websocketから来るプロパティをコピーして同じくcanvasに書き込むようの

2つのオブジェクトを作成して使用してみました。

マルチタッチとかになるとさすがに重いのかなぁとか思ったんですが意外にも

軽快に動いてこれまた感動。

そんで参加時に任意の文字で参加グループを選べるように設定。

ただ新たに端末が加わった際は同じグループ内の任意の端末からcanvasデータをbase64して送信、

その他の端末はそれを読み込み、ということをしたんですが、

写真だと重くて結構な遅延が生じてしまいました。

試してませんがbase64でやりとりよりWebSocket の導入: ウェブにソケットを実装する

みたいにバイナリデータの方が早そう気が、、、わかりませんが。

そんで今回iPhone5c2台とHTCAndroidで通信してみました↓



予想以上な軽快な動きです。感動です。

ここでひとつ思ったなのですが、Androidは今までcanvasの性能が(iPhoneに比べて)イマイチなんかなぁ

と思ってたんですが、意外と位置情報から書き込むと結構スムーズな気がしました。

なんでこのはがゆさはタッチの反応の問題?

いつかサーバサイドの理解が深まったらこんな技術も入れてみたいもんです。

少しでもきになった方、よかったらこの

ウェブアプリをホーム画面への追加よろしくお願いします。

Paint!

サーバーが不安定気味でチョイチョイアクセス出来ないことがありますが、

それとwebsocketは試せませんが、、、

ちなみにあんまり関係ないのですが、new Image()した要素を入れたプロパティを

一生懸命JSON.stringifyしようとして

TypeError: Converting circular structure to JSON

と怒られまくってしまいました。循環参照???って思ったんですが、

確かにDOMをそのままJSONっておかしいよなと原因わかって納得。

まとめ


すごい技術があるもんだ。

2014/02/12

動的に追加される要素にイベントを登録する



なぜこんな記事を書いたのか。

前回のhandleEventってなんかよさそうこの記事書いてて

思い出したついでです。

<html>
<head>
<body>
<button id="add">追加</button>
<ul id="listUL">
<li>list1<button class="remove">削除</button></li>
</ul>
このリストは動的に追加され、削除ボタンでそのリストを削除したい場合。

add.addEventListener('click', function() {
  var listLength = document.getElementsByClassName('remove').length;
  var list = '
  • list' + (listLength + 1) + '
  • '; listUL.innerHTML += list; }); listUL.addEventListener('click', function(e) { //親がイベントを監視し、伝播するイベントをキャッチし発生元の親listを削除する //親が上の要素にいけば行くほど(広く監視するほど)無駄なイベント捕捉が増える??と思われる if(e.target.className === 'remove') { this.removeChild(e.target.parentNode); //ここのthisはリスナが登録されたlistULを指す //thisは e.currentTarget、e.targetはクリックされた要素 } });
    ちなみに動的な要素もそうだけど、大量のリストにイベント設定するときとかもforで回すして

    全ての要素に登録するより、親に1つ登録してe.targetを監視した方がよいのかしら??

    以前、ふとどーやってあとから追加された要素にイベント登録するんだろーって思って、

    ググったところjQueryのliveとかonとか出てくるんですよね。

    まぁみなさんその情報を求めているんでしょう。

    がしかしここ最近なぜかjQueryをあまり使わなくって。

    そんで調べてなるほど!

    うーん、

    参考

    jQueryのliveやdelegateは実際何をやってるのか