携帯のユーザーIDを取得する

DoCoMoの場合は端末ID、SoftBankの場合はユーザID、AUの場合はサブスクライバIDを返すというもの。

CPAN漁ってみたところ、一応HTTP::MobileAgent::Plugin::ExtensionSledge::MobileGate::Mobileとか携帯のIDを取得できるヤツはあった。

だけど、HTTP::MobileAgent::Plugin::ExtensionはSoftBankのときにUAから取得できるシリアルナンバーしか取れない。あとDoCoMoのis_utnの判定がhtml_version取得できない場合に未対応になるのがどうにもいけてない。

一方Sledge::MobileGate::MobileはユーザID取れるには取れるんだけど取得できなかった場合にシリアルナンバー返すんでちょい微妙。というかどっちにしろSledgeからしか扱えないのでもっと汎用的なのが欲しかったので結局自分で実装してみた。

モジュールのネーミングは凄く迷ったんだけどHTTP::MobileUserID::Japaneseとしてみた。

まぁJapaneseの部分はなくてもいいかも。

package HTTP::MobileUserID::Japanese;

use strict;
use warnings;
use base qw/Class::Data::Accessor/;
__PACKAGE__->mk_classaccessors(qw/agent user_id/);

our $VERSION = '0.01';

sub new {
    my $proto = shift;
    my $self = bless {
        agent   => shift,
        support => 1,
        user_id => undef,
    } , ref $proto || $proto;
    $self->init(@_);
    return $self;
}

sub is_support     {  shift->{support} }
sub is_not_support { !shift->{support} }

sub is_exists     {  shift->{user_id} }
sub is_not_exists { !shift->{user_id} }

*id = \&user_id;

sub init {
    my $self = shift;
    my $agent = $self->agent;
    
    if ( $agent->is_docomo ) {
        $self->{support} = 0 if $agent->html_version && $agent->html_version <= 2.0;
        return if $self->is_not_support;
        $self->user_id($agent->serial_number);
    }
    elsif ( $agent->is_softbank ) {
        $self->{support} = 0 if $agent->is_type_c;
        return if $self->is_not_support;
        my $user_id = $agent->get_header('x-jphone-uid') || 'NULL';
        $self->user_id($user_id) if $user_id ne 'NULL';
    }
    elsif ( $agent->is_ezweb ) {
        $self->user_id($agent->get_header('x-up-subno'));
    }
    else {
        $self->{support} = 0;
    }
}

1;

使い方

  use HTTP::MobileUserID::Japanese;
  use HTTP::MobileAgent;
  
  my $agent  = HTTP::MobileAgent->new;
  my $userid = HTTP::MobildUserID::Japanese->new($agent);
  
  print $userid->id;

is_supportとかis_not_supportってのはその端末がそもそも固有のIDを取得できるかどうかを判定する。

is_not_supportが真になるのは以下のケース

  • DoCoMoのHTMLバージョンが2.0以下の端末はutn属性が使えないので端末固有のIDを取得することは不可能。
  • SoftBankのC型端末はユーザIDの取得ができない。(公式サイトなら可能、だったはず)

is_existsやis_not_existsは端末IDの取得には対応しているが何らかの理由でユーザIDが取得できないケースがあるのでそれを判定する。

is_not_existsが真になるのは以下のケース

  • DoCoMoでutn属性のリンクを経由しなかった場合
  • SoftBankでユーザIDの通知設定を行わなかった場合
  • AUサブスクライバIDの通知設定を行わなかった場合

という感じ。

んでおなじみ、これをCatalystから扱えるようにしたCatalyst::Plugin::MobileUserIDも作ってみた。

package Catalyst::Plugin::MobileUserID;

use warnings;
use strict;
use NEXT;
use Catalyst::Request;
use HTTP::MobileUserID::Japanese;

our $VERSION = '0.01';

{
    package Catalyst::Request;
    sub mobile_userid {
        my $req = shift;
        $req->{mobile_userid} ||= HTTP::MobileUserID::Japanese->new($req->mobile_agent);
    }
}

1;

Catalyst::Plugin::MobileUserIDを使う場合は当然ながらCatalyst::Plugin::MobileAgentを継承している必要があります。
ちなみに継承順に依存はしません。

というわけで今流行り?の携帯サイトのかんたんログインみたいなのを実装しようと思ったらこれを使えば楽チンになります。is_supportで対応してるかどうかを判別してis_existsで取得できてるかを判別してあとはお好きにごにょごにょやるといった感じで。

テンプレート側は

 [% IF c.req.mobile_userid.is_not_support %]
    お使いの端末には対応しておりません。
 [% ELSE %]
   [% IF c.req.mobile_userid.is_not_exists %]
     [% IF c.req.mobile_agent.is_softbank %]
       ユーザIDの通知設定を行ってください
     [% ELSIF c.req.mobile_agent.is_ezweb %]
       サブスクライバIDの通知設定を行ってください。
     [% END %]
   [% END %]
 [% END %]

こんな感じになる?

さてと。

特に問題もなければこれCPANにあげてみようかな。英語の壁が大きいけどまぁなんとかなるっしょ^^;

追記

reqが抜けてたorz

追記 2007/05/06:

勝手に添削を添削 HTTP::MobileUserID - Unknown::Programming
HTTP::MobileUserID & Catalyst::Plugin::MobileUserID Released - Unknown::Programming