DHJJ [Hatsune's Journal Japan] blog

Hatsune's Journal Japan blog

目次

Blog 利用状況

ニュース

最新ツイート

運営サイト

Hatsune's Journal Japan
DHJJ

著作など

資格など

OCP
MCP

書庫

日記カテゴリ

わんくま同盟

Microsoft Push Notification Serviceを使う

Windows Phone 7では、Push通知という手法で、トースト通知を行ったり該当アプリのライブタイルに情報を表示したりできます。

Push通知には、Microsoft Push Notification ServiceというPush通知専用のサーバーを利用します。このサーバーはマイクロソフトがWindows PhoneのPush通知用に無料で公開しているサーバーです。

Push通知を使うための大まかな流れは次のようになります。

image

この中で自作しなくてはならなのは、「Windows Phoneアプリ」と「Push通知用サービス」の2つになります。

「Push通知用サービス」は、インターネット上のWebアプリやWebサービスである必要はありません。「Pusu通知用サービス」に求められる要件は次の3つです。

  1. Windows PhoneアプリからURIを受信
  2. URIを利用者ごとに管理
  3. Push通知したい利用者のURIに対してメッセージ送信
エンドポイント作成(Windows Phoneアプリ)

Push通知サービスを利用するための最初の作業は、Microsoft.Phone.Notificationクラスを使って、Windows Phoneに内蔵されたWindows Phone Push Agent経由でMicrosoft Push Notification Serviceより専用のURIを入手する事です。

Private WithEvents PushChannel As Microsoft.Phone.Notification.HttpNotificationChannel

Private Sub Get_Button_Tap(sender As System.Object, e As System.Windows.Input.GestureEventArgs)
    PushChannel = Microsoft.Phone.Notification.HttpNotificationChannel.Find(MyApplication.ApplicationTitle)
    If PushChannel Is Nothing Then
        'チャンネル初期利用
        PushChannel = New Microsoft.Phone.Notification.HttpNotificationChannel(MyApplication.ApplicationTitle)
        PushChannel.Open()
    Else
        'チャンネル登録済
        Call SetUri(PushChannel.ChannelUri.ToString)
    End If
    If Not PushChannel.IsShellTileBound Then
        PushChannel.BindToShellTile()
    End If
    If Not PushChannel.IsShellToastBound Then
        PushChannel.BindToShellToast()
    End If
End Sub

HttpNotificationChannel.FindメソッドでWindows Phone内部に保存されている通知用URIを検索します。

もし、通知用URIが保存されていなかったならば、HttpNotificationChannelをOpenしてMicrosoft Push Notification Serviceへ専用URIの習得Requestを送信します。

Windows Phoneでの通信は非同期通信となるので、ChannelUriUpdatedイベントまたはErrorOccurredイベントを待ち合わせます。

Private Sub PushChannel_ChannelUriUpdated(sender As Object,
                                          e As Microsoft.Phone.Notification.NotificationChannelUriEventArgs) _
                                      Handles PushChannel.ChannelUriUpdated
    Dispatcher.BeginInvoke(Sub()
                               Call SetUri(e.ChannelUri.ToString)
                           End Sub)
End Sub

Private Sub PushChannel_ErrorOccurred(sender As Object,
                                      e As Microsoft.Phone.Notification.NotificationChannelErrorEventArgs) _
                                  Handles PushChannel.ErrorOccurred
    Dispatcher.BeginInvoke(Sub()
                               MessageBox.Show(e.Message, "Get Channel Uri", MessageBoxButton.OK)
                           End Sub)
End Sub

Private Sub SetUri(ByVal uri As String)
    Me.Uri_TextBox.Text = uri
    Me.Get_Button.IsEnabled = False
    Me.Set_Button.IsEnabled = True
End Sub

PushChannelのイベントが発生したらDispatcher.BeginInvokeを使ってMicrosoft Push Notification Serviceから戻ってきたURI(チャンネルURI)を取得します。このとき、Windows Phone Push Agentにも自動的にチャンネル名と紐づいてURIが自動保存されます。

URI送信(Windows Phoneアプリ)

Push通知を行うためにはMicrosoft Push Notification Serviceから返却されたチャンネルURIが必要です。

そのため実際にPush通知を行うプログラムにチャンネルURIを渡さなければなりません。

今回は、ASP.NET MVC 3で作成したWebアプリからPush通知を行う予定ですので、Windows PhoneからWebアプリにチャンネルURIを送信します。

送信方法は色々ありますが、今回は次のようなコードで送信します。

Private Sub Set_Button_Tap(sender As System.Object, e As System.Windows.Input.GestureEventArgs)
    Dim param As String = "userID=" & System.Net.HttpUtility.UrlEncode(Me.UserID_TextBox.Text.Trim) &
                         "&password=" & "zzzz" &
                         "&channelUri=" & System.Net.HttpUtility.UrlEncode(Me.Uri_TextBox.Text.Trim)
    Dim uri As String = Me.Server_TextBox.Text & "/Channel/SetChannelUri"

    WebClient = New WebClient
    WebClient.DownloadStringAsync(New Uri(uri & "?" & param))
End Sub
URI受信(Push通知用サービス)

Windows Phoneアプリからファイル送信で呼び出されるASP.NET MVC 3のコントローラーは次のようなコードになります。

Public Class ChannelController
    Inherits System.Web.Mvc.Controller

    Function SetChannelUri(ByVal userID As String,
                           ByVal password As String,
                           ByVal channelUri As String) As JsonResult
        Return Json((New ChannelModel).SetChannelUri(userID, password, channelUri), JsonRequestBehavior.AllowGet)
    End Function
End Class

このコントローラーから呼び出されるChannelModelモデルは次のようなコードになっていて、ここでSQL ServerにユーザID(と場合によっては暗号化したパスワード)とチャンネルURIを保存します。

Public Class ChannelModel
    Public Function SetChannelUri(ByVal userID As String,
                              ByVal password As String,
                              ByVal channelUri As String) _
                          As TChannelUri
        Dim returnValue As TChannelUri

        Try
            'ここにユーザ認証及びユーザごとのUri保存ロジックを記述
            Call SetRecords(userID, password, channelUri)
            returnValue = (New TChannelUri(userID,
                                            password,
                                            channelUri,
                                            True,
                                            "OK"))
        Catch ex As Exception
            returnValue = (New TChannelUri(userID,
                                            password,
                                            channelUri,
                                            False,
                                            ex.Message))
        End Try
        Return returnValue
    End Function

    Private Function SetRecords(ByVal userID As String,
                                ByVal password As String,
                                ByVal channelUri As String) As Boolean
        Dim isOK As Boolean = False

        Using _cn As New SqlClient.SqlConnection
            Dim isExists As Boolean = False

            _cn.ConnectionString = String.Format(GetEnviroment.GetSettings("Connection"),
                                                 GetEnviroment.GetSettings("UserID"),
                                                 GetEnviroment.GetSettings("Password"))

            _cn.Open()
            Using _cmd As New SqlClient.SqlCommand
                Dim _dr As SqlClient.SqlDataReader

                _cmd.Connection = _cn
                _cmd.CommandText = "SELECT * FROM Channel WHERE userID=@userID"
                _cmd.Parameters.Add(New SqlClient.SqlParameter("@userID", userID))
                _dr = _cmd.ExecuteReader
                isExists = _dr.Read
                _dr.Close()
            End Using
            Using _cmd As New SqlClient.SqlCommand
                _cmd.Connection = _cn
                _cmd.Parameters.Add(New SqlClient.SqlParameter("@userID", userID))
                _cmd.Parameters.Add(New SqlClient.SqlParameter("@channelUri", channelUri))
                If isExists Then
                    _cmd.CommandText = "UPDATE Channel SET channelUri=@channelUri WHERE userID=@userID"
                Else
                    _cmd.CommandText = "INSERT INTO Channel (userID,channelUri) VALUES (@userID,@channelUri)"
                End If
                _cmd.ExecuteNonQuery()
            End Using
        End Using
        Return isOK
    End Function
End Class
メッセージ送信(Push通知用サービスよりタイル通知を依頼)

それでは登録されている端末に一斉にタイル通知を行うコードを書いてみましょう。記述先はASP.NET MVC 3側になりますが、http POSTができればWebアプリである必要はありません。

注意点は、Push通知は1台1台行う必要がある点です。例えば100人にPush通知するのであれば、Microsoft Push Notification Serviceに対して100回POSTが必要です。できれば常時接続環境、もしくは、インターネット上にホスティングされているサーバーで稼働させているWebアプリから送信するのが良いでしょう。

キャンペーン告知のような不定期に大勢に一斉通知の場合、お勧めは、Windows Azureを活用する事です。キャンペーン告知のPush通知時だけURI受信用のインスタンスとは別にキャンペーン告知用インスタンスを複数立ち上げて通知先をグループ化してパラレルでPush通知処理をすれば短時間で処理が完了し、それぞれの端末にPush通知が届く時間幅が小さくできます。

通知が終わったらキャンペーン告知用インスタンスはインスタンス数を1にするか削除してしまえば費用も抑えられます。

Private Function SendNotification(ByVal channelUri As String,
                                  ByVal counter As Integer,
                                  ByVal backContent As String,
                                  ByVal title As String) As Boolean
    Dim isOK As Boolean = False
    Dim req As Net.HttpWebRequest = CType(Net.WebRequest.Create(channelUri), Net.HttpWebRequest)
    Dim xmldata As XDocument = <?xml version="1.0" encoding="utf-8"?>
                               <wp:Notification xmlns:wp="WPNotification">
                                   <wp:Tile>
                                       <wp:Count><%= counter %></wp:Count>
                                       <wp:Title><%= title %></wp:Title>
                                       <wp:BackTitle>Push Notification</wp:BackTitle>
                                       <wp:BackContent><%= backContent %></wp:BackContent>
                                   </wp:Tile>
                               </wp:Notification>
    Dim notificationMessage As Byte() = Encoding.UTF8.GetBytes(XElement.Parse(xmldata.ToString).ToString)

    req.Method = "POST"
    req.Headers.Add("X-MessageID", Guid.NewGuid.ToString)
    req.ContentLength = notificationMessage.Length
    'タイル通知
    req.ContentType = "text/xml"
    req.Headers.Add("X-WindowsPhone-Target", "token")
    req.Headers.Add("X-NotificationClass", "1")
    Using reqStream As IO.Stream = req.GetRequestStream
        reqStream.Write(notificationMessage, 0, notificationMessage.Length)
        reqStream.Close()
    End Using
    Return isOK
End Function

Push通知依頼の内容はXML文中にしてします指定できる項目としては次の6つがあります。

  • Title
  • BackGroundImage
  • Count
  • BackTitle
  • BackBackGroundImage
  • BackContent

今回はこの中から、Count、Title、BackTitle、BackContentを使っています。

Push通知(Windows Phone)

URIをPush通知用サービスに登録したらスタートボタンでスタートスクリーンに戻ります。

次にアプリケーションリストに移動したらアプリケーションアイコンをタッチアンドホールドして「スタート画面に追加」を選んでアプリケーションをスタートスクリーンに配置します。

image

通知

それではPush通知サービスからMicrosoft Push Notificatin Serviceにメッセージを送ってみましょう。

ほぼタイムラグなくライブタイルにカウンタとタイトルが反映されます。

image

タイル通知

カウンタはバックカラーなどを考慮した配色になっていますが、タイトルはあまり意識していないようでタイルの背景画像の配色によってはまったく読めません。メトロデザイン的にはきっとタイルデザインはもっとシンプルで単色なものなのかもしれませんね。

タイル全体に画像で情報を表示するようなPush通知を作りたい場合、今回のサンプルでは取り扱っていませんが、173 x 173の大きさの画像をPush通知でタイルの背景画像に指定するとよいでしょう。Windows Phoneアプリのローカルリソース(XAP内のファイル)以外にも80KBまでであればPush通知サービス上の画像を指定する事も出来ます。

image

ライブタイルが裏返るとBackContentが表示されます。

image

タイル通知のカウンタ削除

カウンタの値を0にするとタイル上のカウンタ表示が消えます

image

image

メッセージ送信(Push通知用サービスよりトースト通知を依頼)

Push通知のもう1つの方法としてはトースト通知があります。

トースト通知を行うためのMicrosoft Push Notification Serviceに送信するXMLメッセージは次のようなコードになります。

 

Private Function SendToastNotification(ByVal channelUri As String,
                                      ByVal counter As Integer,
                                      ByVal backContent As String,
                                      ByVal title As String) As Boolean
    Dim isOK As Boolean = False
    Dim req As Net.HttpWebRequest = CType(Net.WebRequest.Create(channelUri), Net.HttpWebRequest)
    Dim xmldata As XDocument = <?xml version="1.0" encoding="utf-8"?>
                               <wp:Notification xmlns:wp="WPNotification">
                                   <wp:Toast>
                                       <wp:Text1><%= title %></wp:Text1>
                                       <wp:Text2><%= backContent %></wp:Text2>
                                       <wp:Param>/SubPage.xaml</wp:Param>
                                   </wp:Toast>
                               </wp:Notification>
    Dim notificationMessage As Byte() = Encoding.UTF8.GetBytes(XElement.Parse(xmldata.ToString).ToString)

    req.Method = "POST"
    req.Headers.Add("X-MessageID", Guid.NewGuid.ToString)
    req.ContentLength = notificationMessage.Length
    'トースト通知
    req.ContentType = "text/xml"
    req.Headers.Add("X-WindowsPhone-Target", "toast")
    req.Headers.Add("X-NotificationClass", "2")
    Using reqStream As IO.Stream = req.GetRequestStream
        reqStream.Write(notificationMessage, 0, notificationMessage.Length)
        reqStream.Close()
    End Using
    Return isOK
End Function

先ほどのWebアプリを少し改造して「トースト通知」をサポートしてみました。

image

「トースト通知」をクリックするとメッセージが送信されてWindows Phone上部のところにパンが焼き上がったときのようにトースト通知が飛び出してきます。そしてトースト通知をタップすれば、アプリが起動されてParamに指定したページが自動的に表示されます。Paramを省略された場合はMainPage.xamlが表示されます。

image

「トースト通知」を依頼したのでタイル通知の方には変化がありません。

タイルの初期化

最後にアプリが起動されたときにタイルの表示を元(タイル通知で変更された内容をクリアする)に戻したいと思います。

Windows PhoneアプリのLoadedイベントプロシージャに次のようなコードを記述します。

Private Sub Me_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
    'タイルを初期化
    If Microsoft.Phone.Shell.ShellTile.ActiveTiles.Count > 0 Then
        Dim tile As New StandardTileData
        tile.Title = MyApplication.ApplicationTitle
        tile.BackgroundImage = New Uri("/Background.png", UriKind.Relative)
        Microsoft.Phone.Shell.ShellTile.ActiveTiles(0).Update(tile)
    End If
End Sub

Nyapplication.ApplicationTitleはアセンブリのタイトルを取得してくるように作成した関数です。また、背景イメージもBackground.pngを指定して初期設定イメージにしています。

投稿日時 : 2011年10月5日 6:12

Feedback

# code promo la redoute 2013/03/07 18:20 http://www.k88.fr/

Around the globe there's a chance you're one person, but to at least one character there's a chance you're globally. code promo la redoute http://www.k88.fr/

# destockchine 2013/03/07 18:21 http://www.b77.fr/casquette-c-7.html/

Friendships final when any coworker believes that they have a slight transcendence beyond the many other. destockchine http://www.b77.fr/casquette-c-7.html/

# robenuk 2013/03/07 18:26 http://www.c88.fr/

If you decide to probably would keep the recipe in an enemy, explain to doing it by way of the a pal. robenuk http://www.c88.fr/

# casquette wati b 2013/03/14 7:08 http://www.a44.fr/

Really do not discuss about it your entire health to a single significantly less well-off unlike on your own. casquette wati b http://www.a44.fr/

# pari street 2013/03/15 18:02 http://www.a88.fr/

A new my brother most likely are not a buddy, but a buddy are invariably your my brother. pari street http://www.a88.fr/

# casquette supreme 2013/03/15 20:44 http://www.b44.fr/

Wear‘l rubbish your energy over a mankind/person,who seem to isn‘l able to rubbish his or her's occasion upon you. casquette supreme http://www.b44.fr/

# casquette eroik 2013/03/22 10:53 http://e11.fr/

A for which you decide to buy through provides is bought from you. casquette eroik http://e11.fr/

# new era casquette 2013/03/24 3:55 http://e77.fr/

Romances closing any time each single family member thinks about brand-new areas such as a small transcendency since the more. new era casquette http://e77.fr/

# Destockage vetement 2013/04/04 9:53 http://www.ruenike.com/casquette-c-7.html/

Should you want some sort of management of your really worth, count your family members. Destockage vetement http://www.ruenike.com/casquette-c-7.html/

# destockmania 2013/04/05 14:22 http://www.ruenike.com/vetement-femme-c-16.html/

For no reason look down on, despite the fact that you might be wretched, manuals do not no someone removal in love with your actual satisfaction. destockmania http://www.ruenike.com/vetement-femme-c-16.html/

# Laredoute 2013/04/06 7:55 http://ruezee.com/

In no way scowl, even if you may be pitiful, for those who don't know who is responsible for drifting down gets interested all your smirk. Laredoute http://ruezee.com/

# modatoi 2013/04/07 4:32 http://ruenee.com/

To the world you're likely to be a person, on the contrary to 1 man or woman you're likely to be our society. modatoi http://ruenee.com/

# DZjFbzfJeULpRF 2015/01/10 22:24 varlog

R0tQlz http://www.FyLitCl7Pf7kjQdDUOLQOuaxTXbj5iNG.com

# TNHHPCuObyV 2015/01/26 15:25 Haywood

Who's calling? http://www.medicalreformgroup.ca/newsletters/ oxycodone acetaminophen buy online In support of the United Nations Framework Convention on Climate Change taking place in Copenhagen, the European Environment Agency hosted the 'Bend the Trend' event on Sunday evening to provide a global climate ...

# vFoirsJdbFdz 2015/01/26 15:25 Granville

Just over two years http://www.loakal.com/contact/ will 1mg of klonopin get me high The index rose as high as 83.46 on Monday but its gains weretrimmed after data showed U.S. retail sales rose less thanexpected in June, denting expectations of an imminent reductionin stimulus by the Fed.

# yAcOdrRAIQuVsWMQWoz 2015/01/27 21:10 Geoffrey

I'll put her on http://www.hollandpompgroep.nl/atex order zopiclone online canada That said, one major difference had been resolved -an Afghan request for protection from external aggression,something the U.S. had been reluctant to agree to, in case itrequired offensive action against another ally, Pakistan.

# FLuPtbIvxeT 2015/01/27 21:10 Waldo

this is be cool 8) http://www.engentia.com/open/ buy limovan online To avoid the prying eyes of the paparazzi and to remain within a short drive of the Elysée Palace, he will be taking his summer starting next Monday at the Pavillon de la Lanterne, a hunting lodge built in 1787 for the prince de Poix, Louis XVI's chief bodyguard.

# YmXElzSFAmXQnUS 2015/01/29 2:36 Cornelius

Until August http://www.skeemipesa.ee/author/martin/ clonazepam 1mg cost Why can't I just give birth to a two year-old? It started off as a joke in my head, but now it's become a full-blown mantra. Every time someone asks me when I'm going to have kids, which is probably every other day now &ndash; well, I've been married almost a year, what else am I doing? &ndash; my cunning response is to divert their attention by talking about toddlers and how I wish I could skip to that bit. But I really do.

# TVxQclEiDJRJsO 2015/02/05 18:47 Camila

Insert your card http://www.blue-lemons.com/about levofloxacin online The journalist, Janet Reitman, spent two months interviewing Tsarnaev&rsquo;s friends and family. In her article, she claims that the mother of 19-year-old Dzhokhar and his 26-year-old brother Tamerlan &ndash; who died in a shoot out following the bombing &ndash; pushed her sons towards Islam.

# VZHfwoKOpYCkulwEmW 2015/02/10 6:26 Jaime

A packet of envelopes http://www.theferrerspartnership.com/profile-of-trevor-potter loan hdfc Critics, including Business Secretary Vince Cable, have warned it will stoke a bubble and that the policy is no longer necessary now the market is recovering. The scheme is now due to be launched next week, instead of January.

# QutMnOSoPbYCIJuq 2015/02/10 6:27 Sherwood

What are the hours of work? http://www.groteverhalen.info/index.php/agenda personal credit rating information Wilmer Stith, co-manager of the Wilmington Broad Market BondFund, said none of the data would move the Fed's hand closer totrimming its large-scale purchases of Treasuries andmortgage-backed securities.

# UqaXaTXFuBGrGDAxS 2015/02/10 12:17 Gustavo

What do you do? http://www.fixadoptsave.org/take-the-pledge/ Oral Nizoral "Illegal surveillance practices intercepting the communication and data of citizens, companies and members of the Brazilian government constitute a serious affront to national sovereignty and individual rights, and are incompatible with democratic cooperation between friendly nations," the Brazilian government said in a statement.

# BblsxYJTETa 2015/02/11 14:32 Everett

I can't stand football http://compostcrew.com/faq/ 90dayloan "Man of Steel" was released by Warner Bros., Sony/Columbiareleased "This is the End," "The Purge" and "Fast & Furious 6"were distributed by Universal and Lionsgate/Summit distributed"Now You See Me."

# ggoAcNNZXebvOCA 2015/02/24 11:00 Emma

I'd like to send this to http://www.streamsweden.com/konsulttjanster/ propranolol sa 80 mg cap myl But their kids and even grandchildren have different attitudes. And the new wealthy class may have very different social values then their parents and grandparents. Maybe they really would think they deserve to survive and thrive at all costs and the rest be dammed. But where they are going to bury the losers is a question?

# vxaUPripOjWVv 2015/02/25 14:08 Geoffrey

I'm not interested in football http://martinimandate.com/tag/sherry/ gabapentin 800 mg tablet Still, Gibson and White managed to come up with a splashy, colorful and surprisingly realistic looking charger; one with white buttons and a USB port contained on a bright, meticulously detailed orange background.

# vmrpyveRkmJOlbAx 2015/02/26 17:33 Dwight

Gloomy tales http://www.nude-webdesign.com/website-design-development/ aripiprazole cost walmart 7.26General merchandise 54.75 54.88 55.16 54.80 54.96 54.92 Department stores 14.46 14.38 14.56 14.44 14.63 15.27Misc store retailers 10.54 10.43 10.60 10.49 10.68 10.12Non-store retailers 37.92 37.73 37.30 37.23 36.74 34.40Food/drink services 45.88 45.72 45.83 45.48 45.77 44.19Excluding autos/

# dNSqgTfKsCySXWgXZ 2015/02/26 17:33 Phillip

I didn't go to university http://www.transformatlab.eu/participants buy online cheap bimatoprost "The hotel is no longer functioning as a business. The staff is starting to leave. They have closed the front desk, switched off the computers," he said. "All they have done is caused panic by saying they are going to start rationing, turn off power and cut water."

# aJvNMCIpEPCrCYfnNVS 2015/02/28 3:46 Eldridge

On another call http://www.bethelhebrew.org/about-us Buy Cardura Humanity&rsquo;s hopes to avoid extinction ride on 250-foot-tall metal behemoths called Jaegers, whose job description amounts to &ldquo;knocking great big monsters dead on their knees.&rdquo; You know, the old alley-oop treatment.

# UfRCCSSKczNoJZ 2015/02/28 3:46 Andre

magic story very thanks http://www.bethelhebrew.org/about-us Cardura 8 Mg An SNP spokesman said: "In 2012, the Labour vote was split between official Labour candidates and rebel Labour candidates because of their internal fighting, which enabled the SNP to just beat Labour in first preferences by a handful of votes.

# VdlPMqcKhXT 2015/04/07 19:34 Nicolas

I have my own business http://www.europanova.eu/contact/ latisse (bimatoprost ophthalmic solution) 0.03 Mansfield and Ashfield Chad provides news, events and sport features from the Mansfield area. For the best up to date information relating to Mansfield and the surrounding areas visit us at Mansfield and Ashfield Chad regularly or bookmark this page.

# BFEDmSVurCg 2015/04/07 19:34 Leonardo

Is there ? http://www.sandiegowebworks.com/quote.shtml albuterol salbutamol LONDON � Britain's Victoria & Albert Museum says it has bought a working gun made on a 3-D printer, which sparked alarm among anti-firearms campaigners when it was unveiled in the United States.

# montre rolex oyster perpetual Datejust 2 automatique prix minimum 2017/07/21 11:26 dexphiubgzjqtefsypweujy@hotmal.com

Great! Thanks Chris…very anxiously awaiting your private label products ??
montre rolex oyster perpetual Datejust 2 automatique prix minimum http://www.finewristwatchshop.com/fr/rolex-datejust-36mm-jubilee-steel-and-pink-gold-diamond-watch-domed-bezel-white-dial-116201wdj-p808/

# rolex oyster perpetual Datejust II acier discount 2017/07/21 11:27 denuktkizefsqprxsqzeddg@hotmal.com

Online snare directory. Combine your purlieus to our directory for free. Do not wipe the entries setakowa.
rolex oyster perpetual Datejust II acier discount http://www.montresmarqueclassic.ru/fr/rolex-datejust-ii-41mm-white-gold-watches-fluted-bezel-blue-index-dial-116334blio-p59/

# ロレックスコピー 2023/06/05 14:49 coxAcquic

海外直営店直接買い付け!★ 2023年注文割引開催中,全部の商品割引10% ★ 在庫情報随時更新! ★ 実物写真、付属品を完備する。 ★ 100%を厳守する。 ★ 送料は無料です(日本全国)!★ お客さんたちも大好評です★ 経営方針: 品質を重視、納期も厳守、信用第一!税関の没収する商品は再度無料にして発送します}}}}}}
https://www.bagssjp.com/product/detail-7145.html
https://www.bagssjp.com/product/detail-11307.html
https://www.bagssjp.com/product/detail-11375.html
https://www.bagssjp.com/product/detail-11509.html
https://www.bagssjp.com/product/detail-5682.html

タイトル
名前
Url
コメント