Share via


第 4 章 「注文処理 ~ Order、Pipeline ~」~ Commerce Server 2002 で学ぶ ASP.NET ~

NRI ラーニングネットワーク株式会社
溝端   二三雄

2003 年 2 月 12 日

目次

4-1 バスケットとオーダー (注文処理) のクラス設計 4-1 バスケットとオーダー (注文処理) のクラス設計
   4-1-1 注文までの流れ4-1-1 注文までの流れ
   4-1-2 共通の機能4-1-2 共通の機能
   4-1-3 Orderform クラス4-1-3 Orderform クラス
   4-1-4 クラス固有の機能4-1-4 クラス固有の機能
   4-2 Basket クラス /PurchaseOrder クラスの実装4-2 Basket クラス /PurchaseOrder クラスの実装
   4-2-1 コンストラクタのオーバーロード4-2-1 コンストラクタのオーバーロード
   4-2-2 ストアドプロシージャの実行4-2-2 ストアドプロシージャの実行
4-3 チェックアウト4-3 チェックアウト
   4-3-1 COM+ トランザクション4-3-1 COM+ トランザクション
   4-3-2 .NET アセンブリを COM+ トランザクションに参加させるには4-3-2 .NET アセンブリを COM+ トランザクションに参加させるには
   4-3-3 PipeLineUtil クラスの実装4-3-3 PipeLineUtil クラスの実装
4-4 Microsoft Commerce Server 2002 では4-4 Microsoft Commerce Server 2002 では

オンラインショッピングサイトを構築する上で最も神経を使うのが注文処理の部分ではないでしょうか。ユーザーが注文したはずの商品が届かなかったり、商品を発送したにもかかわらず課金処理が行われなかったりすることは絶対に許されないことです。こういう不具合を回避するために使用するのがトランザクション処理です。この章ではこのトランザクション処理とクラス設計において重要であるクラス継承を中心に解説します。

4-1 バスケットとオーダー (注文処理) のクラス設計

サンプルアプリケーションの機能とクラスライブラリを解説します。オンラインショッピングサイトで買い物をするユーザーは、一度に複数の商品を購入することがよくあります。この操作性を高めるために一般に「バスケット」と呼ばれる機能を使用します。これにより、チェックアウト(課金処理)   やシッピング   (商品の配送)   の指示を一つ一つの商品ごとに行うのではなく、バスケットにまとめられた複数の商品に対して 1 度で指示ができます。

4-1-1 注文までの流れ

第 3 章   商品カタログで解説したように、オンラインショッピングサイトに訪れたユーザーはカタログ内を検索して目的の商品を探します。目的の商品が見つかると以下の流れで商品購入を行います。

  1. 購入したい商品のページで購入する個数を入力し、バスケットに追加する。

  2. 他の商品を購入する場合、同様にバスケットに追加する。

  3. バスケットの内容を確認後、注文処理に進む(今回のサンプルでは BasketPage.aspx で〔注文する〕ボタンをクリックする)。

  4. 商品の発送先を指定する(今回のサンプルではユーザーのプロファイル情報として登録されている住所を既定値として表示します)。

  5. クレジットカード等決済にかかわる情報を入力する(今回のサンプルではこの部分を省略しています)。

  6. 注文処理(チェックアウト)を実行する(今回のサンプルでは AddressList.aspx ページで〔チェックアウト〕ボタンをクリックする)。

  7. サーバー側ではトランザクション処理として注文処理が行われ、正常に終了した場合、注文番号が送信される。電子メールで注文内容を送信する場合もあります。

  8. ユーザーは与えられた注文番号で注文内容を確認できる。商品のトラッキングを提供する場合、この画面で注文商品のステータスとして「出庫中」や「発送中」「受け取り済み」など各商品の状態を確認できるようにします(今回のサンプルでは注文商品のステータスは省略しています)。

以上が商品の購入の流れになります。これらを実現する Web アプリケーションとして今回のサンプルが提供する機能を以下の表にまとめました。

機能名

動作

データ操作

バスケット

商品を追加する

Basket テーブルに追加

商品を削除する

Basket テーブルから削除

注文処理

送付先住所の入力

OrderFormHeader テーブルに追加

注文データを登録し、注文番号を発行する

OrderFormHeader 、 OrderFormLineItems テーブルに追加

 

後処理

Basket テーブルから削除

注文検索

注文番号により注文内容を表示する

OrderFormHeader 、 OrderFormLineItems テーブルから検索

表 4 1 注文処理にかかわる機能

関連するデータベース内のテーブルは以下のとおりです。

図

図 4-1 注文処理にかかわるテーブル

Basket テーブルには   「どのユーザーが、どの商品を、いくつ追加したか」   が保存されています。ただし、商品情報に関しては商品コード   ( ProductId )   だけが保存されています。商品の値段等を入手する場合は ProductId を元に CatalogProducts テーブルにアクセスします。

OrderFormLineItems テーブルには注文番号   ( PoNumber )   に関連付けられた注文情報の詳細データが保存されており、 OrderFormHeader テーブルには注文全体にかかわる情報(注文番号、ユーザー名、送付住所、注文日時)が保存されています。

4-1-2 共通の機能

注文処理にかかわるテーブルを確認すると、 OrderFormLineItems テーブルには Basket テーブルと共通の列があります。また、バスケットに追加した商品の合計金額求めることもあれば、注文商品の合計金額を求める必要もあります。このような共通の性質を持つ機能やデータに関しては、クラス継承を使用して派生クラスとして定義することができます。イメージは以下のとおりです。

図

図 4-2 クラス継承の概念

継承元クラスで合計金額を求めるメソッドや商品番号等のプロパティを設定すれば、それを継承する継承先クラスであるバスケット   ( Basket )   クラスや注文   ( PurchaseOrder )   クラスではそれらを定義する必要はありません。つまり、同じプロパティやメソッドを複数のクラスで定義する必要がある場合、クラス継承を使用すればクラス定義が簡単になります。もし、共通の機能の定義に不具合があった場合でも継承元クラスを修正すればそのクラスを継承するすべての継承先クラスの機能が訂正されたことになります。逆に考えれば、すでに正しく動作することがわかっているクラスを継承してクラス定義をすれば、継承元クラスで定義されている機能に関しては正常に動作することが保障されていることになります。

4-1-3 Orderform クラス

今回のサンプルアプリケーションでも Orderform クラスを継承元クラスとして定義し、 Basket クラスと PurchaseOrder クラスをその継承先クラスとして定義しています。 Orderform クラスは単純な 1 つのクラスではなく、配列を管理する LineItemCollection 型のプロパティを持ち、その中で LineItem 型の配列がプロパティとして定義されています。この構造は第 2 章ユーザー情報の管理   で解説したのと同様です。

図

図 4-3 Orderform クラス

なお、 LineItem クラスのプロパティとして商品名   ( ProductName )   と単価   ( ProductCyListPrice )   が定義されていますが、 Basket テーブルにはこれらの列はありません。また、 OrderFormLineItems テーブルにも商品名   ( ProductName )   列がありません。データベース設計時は正規化を行いこれらの冗長となる列   ( ProductId を元に CatalogProducts テーブルを参照すれば取得可能)   は削除します。しかし、アプリケーションを構築する際に使用するクラスライブラリとしてはこれらが必要になります。なぜなら、バスケットや注文情報を表示する時にはほとんど毎回商品名や単価を表示するからです。データベースのテーブルをそのままクラスとして使用するのではないことに注意してください。正規化されたテーブルとは異なり、クラス   (オブジェクト)   は定義している   「もの」   に対する情報や機能を提供する能力が全て備わっているのが理想です。データベース技術者にとっては非正規化を行うことと似ています。

4-1-4 クラス固有の機能

バスケットとして必要な固有の情報   ( Orderform に定義されていない情報)   や固有の機能は以下のとおりです。

Basket オブジェクト

 

プロパティ

LogonName

メソッド

AddItem

 

RemoveItem

誰のバスケット情報なのかを識別するためにサンプルアプリケーションでは LogonName を使用しています。この LogonName をコンストラクタ引数としてバスケットオブジェクトを作成すれば Basket テーブルに保存されているデータを元にそのユーザーのバスケット情報がオブジェクトとしてインスタンス化されます。また、バスケットに商品を追加したり追加されている商品を削除する機能も必要です。

オーダー固有の情報や機能は以下のとおりです。

PurchaseOrderオブジェクト

 

プロパティ

LogonName

 

PoNumber

 

ShippingAddress

 

OrderDate

今回のサンプルアプリケーションでは注文されたデータは追加されたり削除されることもなく、このオブジェクト固有の機能は存在しません。固有の情報としていくつかの情報がありますが、これらは OrderFormHeader テーブルの構造そのものです。クラス定義のコードを簡単にするためにこれら情報を   1   つ   1   つプロパティとして定義するのではなく、データセット派生クラス   ( DsOrder )   に定義された OrderFormHeaderRow 型のプロパティとして定義しています。参考までに 1 つ 1 つのプロパティとしての定義もサンプルコード内でコメントアウトして記述しています。

これまでの内容を総合すると以下のようなクラス設計になります。

図

図 4-4 Order プロジェクト内に定義されたクラスライブラリ

4-2 Basket クラス /PurchaseOrder クラスの実装

4-2-1 コンストラクタのオーバーロード

共通のデータや機能をピックアップし、クラス継承を使用することにより Basket クラスと PurchaseOrder クラスの定義を行いましたが、これらをインスタンス化した場合を考えると、実装に注意が必要です。これらの 2 つのクラスは同じ   「データ構造」   を定義できますが、インスタンス   (オブジェクト)   としては異なる   「データ」   を持つことになります。例えば ProductId プロパティを例に考えると、 Basket オブジェクトには Basket テーブルから取得したデータが保持され、 PurchaseOrder オブジェクトの場合、 OrderFormLineItems テーブルから取得されたデータが保持される必要があります。これを実現するためにコンストラクタのオーバーロードを使用します。

オーバーロードとは引数の数または引数のデータ型が異なる同じ名前のメソッドを複数定義し、どんな引数でメソッドが呼び出されるかによって、処理されるメソッドを変更することができます。これはコンストラクタメソッドにも使用出来ます。

例えば Orderform クラスには以下の 2 つコンストラクタ引数が定義されています。

    Public Sub New(ByVal strUserName As String)
        'Basket を作る
        myLineItem = New LineItemCollection(strUserName)
    End Sub

    Public Sub New(ByVal PONumber As Int32)
        'Orderを作る 
        myLineItem = New LineItemCollection(PONumber)
    End Sub

New キーワードを使用してオブジェクトをインスタンス化する際に、文字列型のユーザー名をコンストラクタ引数に指定した場合、 Basket オブジェクト用の LineItemCollection オブジェクトが作成されます。つまり、 Basket クラスのコンストラクタは以下のようになります。

    Public Sub New(ByVal strUserName As String)
        MyBase.New(strUserName)
        myLogonName = strUserName
    End Sub 

継承元クラスのコンストラクタに引数を渡すためには MyBase キーワードを使用します。

同様に PurchaseOrder クラスのコンストラクタは以下のとおりです。

    Public Sub New(ByVal PONumber As Int32, ByVal LogonName As String)
        MyBase.New(PONumber)
        myLogonName = LogonName
        Dim db As New DBAccess()
        Dim myOrder As DsOrder.OrderFormHeaderDataTable
     ・・・・以下、省略・・・・
    End Sub

MyBase キーワードを使用して派生元クラスのコンストラクタに 32 ビット整数型のコンストラクタ引数   (注文番号)   を指定しています。

同様にコンストラクタのオーバーロードを使用して LineItemCollection クラスがインスタンス化されます。この部分で Basket もしくは OrderFormLineItems のどちらのテーブルからデータを取得するかが振り分けられます。取得したデータは Item プロパティとして定義された LineItem 型変数の配列として追加しています。

Public Class LineItemCollection
    Inherits CollectionBase
    Public Sub New(ByVal strUserName As String)
        'Basketを作成
        Dim myBasket As DsBasket
        Dim rowBasket As DsBasket.BasketRow
        Dim db As New DBAccess()

        myBasket = db.SelectBasketByUserName(strUserName)
        For Each rowBasket In myBasket.Basket.Rows
            Dim aLineItem As New LineItem()
            aLineItem.ProductID = rowBasket.ProductId
            aLineItem.Quantity = rowBasket.Quantity
            aLineItem.ProductName = rowBasket.ProductName
            aLineItem.ProductCyListPrice = rowBasket.CyUnitPrice
            List.Add(aLineItem)
        Next
    End Sub

    Public Sub New(ByVal PONumber As Int32)
        'PurchaseOrderを作成
        Dim myOrders As DsOrder.OrderFormLineItemsDataTable
        Dim rowLineItem As DsOrder.OrderFormLineItemsRow
        Dim db As New DBAccess()

        myOrders = db.SelectPOItemsByPONumber(PONumber)
        If myOrders.Count > 0 Then
            For Each rowLineItem In myOrders
                Dim aLineItem As New LineItem()
                aLineItem.ProductID = rowLineItem.Item(1)
                aLineItem.Quantity = rowLineItem.Quantity
                aLineItem.ProductName = rowLineItem.ProductName
                aLineItem.ProductCyListPrice = rowLineItem.CyLineItemTotal
                List.Add(aLineItem)
            Next
        End If

    End Sub

4-2-2 ストアドプロシージャの実行

今回のサンプルアプリケーションではデータベースにアクセスする部分は基本的に DataAccess プロジェクトとして定義し別のアセンブリを作成しています。ただし、このコラムで解説する部分は確認しやすいように各クラス内に定義しました。 Basket クラスの AddItem メソッドと RemoveItem メソッドもそうしています。ここでは AddItem メソッドを参考にストアドプロシージャの呼び出しを解説します。比較しやすいように RemoveItem メソッドは既に解説した T-SQL ステートメントを直接実行する方法で実装しています。

    Public Sub AddItem(ByVal ProductID As String, ByVal qty As Int32)
        Dim db As New DBAccess()
        Dim cn As SqlConnection = New SqlConnection(db.ConStr)

        Dim cmdSaveItem As SqlCommand = New SqlCommand()
        cmdSaveItem.CommandType = CommandType.StoredProcedure
        cmdSaveItem.CommandText = "AddBasket"
        cmdSaveItem.Connection = cn
        cmdSaveItem.Parameters.Add("@LogonName", LogonName)
        cmdSaveItem.Parameters.Add("@ProductID", ProductID)
        cmdSaveItem.Parameters.Add("@Quantity", qty)
        cn.Open()
        cmdSaveItem.ExecuteNonQuery()
        cmdSaveItem.Parameters.Clear()
        cn.Close()
    End Sub

    Public Shared Sub RemoveItem(ByVal ProductID As String)
        Dim db As New DBAccess()
        Dim cn As SqlConnection = New SqlConnection(db.ConStr)
        Dim cmdDeleteItem As SqlCommand = New SqlCommand()
        cmdDeleteItem.CommandType = CommandType.Text
        cmdDeleteItem.CommandText = "DELETE BASKET WHERE ProductId = '" & ProductID & "'"
        cmdDeleteItem.Connection = cn
        cn.Open()
        cmdDeleteItem.ExecuteNonQuery()
        cn.Close()

    End Sub

上記の 2 つのメソッドの定義を比較してみると、ストアドプロシージャを実行するために特別複雑なコードを書く必要がないことがわかります。唯一複雑に見えるのはストアドプロシージャに渡すパラメータの定義部分だけです。コードを見れば理解できる方も多いと思いますが、ストアドプロシージャを呼び出す手順をまとめておきます。

  1. コネクションオブジェクトを作成します。今回は SQL Server 2000 にアクセスするので SqlConnection オブジェクトを使用します。コンストラクタ引数として接続文字列を渡しています。

  2. コマンドオブジェクトを作成します、(1) と同様 SqlCommand オブジェクトを使用します。

  3. SqlCommand オブジェクトの CommandType プロパティに StoredProcedure をセットします。この値は CommandType 列挙体として定義されており、インテリセンスが使用できます。

  4. SqlCommand オブジェクトの CommandText プロパティに実行するストアドプロシージャの名前をセットします。

  5. SqlCommand オブジェクトの Parameters コレクションにストアドプロシージャに渡すパラメータを追加します。SqlCommand オブジェクトの場合、パラメータを追加する順序は関係ありません。その代わり、「パラメータ名 (ストアドプロシージャで定義された名前と同じ名前) と値」 の組み合わせで追加する必要があります。

  6. データベースに接続します。SqlConnection オブジェクトの Open メソッドを使用します。

  7. コマンド (ストアドプロシージャ) を実行します。

  8. データベース接続を切断します。SqlConnection オブジェクトの Close メソッドを使用します。

4-3 チェックアウト

今回のサンプルアプリケーションでは注文処理(チェックアウト)は以下の処理を行います。これらは PipeLine プロジェクトの PipeLineUtil クラスとして定義されています。

  1. 注文データを記録
    OrderFormHeader テーブルに注文データ (ユーザー名、送付先住所、注文日時) を記録(INSERT) します。これにより、Identity 列として定義された PoNumber が割り当てられ、戻り値として取得します。

  2. 注文詳細の取得
    そのユーザーのバスケット情報から注文詳細データを取得します。このデータはDataSetとして受け取ります。

  3. 注文詳細の記録
    OrderFormLineItemsテーブルに (2) で取得した注文詳細データを記録 (INSERT) します。

  4. 注文済みデータの削除
    注文が終了したデータはBasketテーブルから削除します。

これらの処理が全て正常に終了した場合、注文処理が完了したことになります。しかし、どこかでエラーが発生した場合、それまでに終了した処理を取り消す(ロールバック)必要があります。これを実現するのがトランザクション処理です。トランザクション処理を実現する方法はいくつかありますが、サンプルアプリケーションでは .NET のクラスが COM+ トランザクションを利用する方法を使用しています。

4-3-1 COM+ トランザクション

COM+ の 1 つの機能としてトランザクションマネージャと呼ばれる MS DTC (マイクロソフト分散トランザクションコーディネータ)   による分散トランザクション管理の機能があります。 OLE DB や MSMQ などリソースディスペンサ機能を持った API を使用したコンポーネントをコンポーネントサービスに登録すれば、 MS DTC がトランザクションの管理を行ってくれます。

MS DTC が行うトランザクションの管理とは何を行うのでしょう?最も重要な機能が 1 つのトランザクション内の各処理のコミット / ロールバックをすることです。つまり、 1 つのトランザクション内の全ての処理が終了した時点でコミットを行い、どこかでエラーが発生した場合、そのトランザクション内の終了した処理をロールバックする指示を出します。これにより、トランザクション処理される各コンポーネントの開発者は、他の処理が正常に終了したがどうかの確認等は一切行う必要がありません。自身の処理が正常終了またはエラーになったことを MS DTC に報告( Vote )   するだけで、後は全て MS DTC がコントロールします。

4-3-2 .NET アセンブリを COM+ トランザクションに参加させるには

.NET アセンブリは MS DTC の管理下として動作させることができます。ただし、以下の条件を満たす必要があります。

  • 共有アセンブリとして作成されていること(アセンブリ名としてストロングネームを使用する必要があります)。

  • ServicedComponent クラスから派生したクラスであること。

  • COM+ への登録がさせていること(登録には Regsvc.exe を使用します)。

  • トランザクション属性が指定されていること

Visual Studio .NET では〔トランザクションコンポーネント〕クラスのテンプレートを使用すれば ServicedComponent 派生クラスとしてトランザクション属性が指定されたクラスの雛形が作成されます。

cs4-TranComp.gif

4-3-3 PipeLineUtil クラスの実装

サンプルアプリケーションではトランザクションコンポーネントテンプレートを使用して PipeLineUtil クラスを作成しています。このクラスは必ずトランザクション処理を行うように COM+ サービスに指示をするため、 Transaction 属性で TransactionOption 列挙体の Required を設定しています。

<Transaction(TransactionOption.Required)> _
Public Class PipeLineUtil
    Inherits ServicedComponent
    ・・・・以下、省略・・・・

CheckOut メソッドでは注文処理に必要な 4 つのメソッド( AddPOHeader 、 GetBasketItems 、 AddOrder 、 DeleteBasket )を定義しています。

Public Function CheckOut(ByVal strUserName As String, ByVal strShipTo As String) As Int32
        Dim PONumber As Int32
        Dim basketItems As DsBasket
        Try
            PONumber = AddPOHeader(strUserName, strShipTo)
            basketItems = GetBasketItems(strUserName)
            AddOrder(basketItems, PONumber)
            DeleteBasket(strUserName)
        Catch eException As ApplicationException
            ContextUtil.SetAbort()
            Throw
            Return "0"
        Catch
            ContextUtil.SetAbort()
            Return "0"
        End Try

        ContextUtil.SetComplete()
        Return PONumber
    End Function

注文処理を行う 4 つのメソッドは例外を処理するために、 Try ~ Catch ~ End Try で定義されており、例外が発生した場合 ContextUtil クラスの SetAbort メソッドが実行されます。全ての処理が正常に実行された場合、同じく ContextUtil クラスの SetComplete メソッドが実行されます。この SetAbort/SetComplete メソッドが MS DTC に対して各処理が失敗 / 正常終了   したことを投票   ( Vote )   するメソッドです。つまり、トランザクション処理を実装するために必要な追加のコードはこれだけです。そればかりか .NET には自動トランザクションの機能があるのでメソッドに <AutoComplete> 属性を付ることで、 SetAbort/SetComplete メソッドを呼び出さなくても、例外が発生した場合 SetAbort として、発生しなかった場合 SetComplete として自動的に処理されます。

注文処理を行う 4 つのメソッドは全てストアドプロシージャを実行することでデータベースの処理を行います。このドキュメントには記載しませんが、ストアドプロシージャの呼び出し方法の復習のためにもサンプルプログラムのコードもご確認ください。

寄り道、わき道、まわり道 (5) 手動トランザクション

ADO と同様、 ADO.NET が提供する機能を使用してトランザクション処理を定義することができます。 ADO では Connection オブジェクトのプロパティとして設定していましたが、 ADO.NET では SqlTransaction オブジェクトを使用します。

        Dim cn As New SqlConnection(ConnectionString)
        Dim cmd As New SqlCommand()
        Dim trn As SqlTransaction
        cmd.Connection = cn
        cn.Open()
        trn = cn.BeginTransaction()
        cmd.Transaction = trn
        '・・・・ それぞれの処理を実行 ・・・・

        If ・・・・ Then
            trn.Commit()
        Else
            trn.Rollback()
        End If
寄り道、わき道、まわり道 (6) ストアドプロシージャによるトランザクション

SQL Server のデータベースプログラミングに精通している方であればストアドプロシージャ内でトランザクション処理を定義することができます。

CREATE PROCEDURE CheckOut @LogonName varchar(50),ShipTo varchar(50)
AS
BEGIN TRANSACTION
  処理1(OrderFormHeaderテーブルにINSERT)
  処理2(BasketテーブルをSELECT)
  処理3(OrderFormLineItemsテーブルにINSERT)
  処理4(BasketテーブルからDELETE)
IF (@@error <> 0)
BEGIN
  ROLLBACK TRANSACTION
END
COMMIT TRANSACTION
GO 

ストアドプロシージャの定義がかなり複雑になるので、各処理を別のストアドプロシージャとして定義します。

処理 1 を実行するストアドプロシージャの内容

INSERT INTO OrderFormHeader
(LogonName, OrderDate,ShippingAddress)
VALUES
(@LogonName ,GetDate(),@ShipTo)
RETURN  (SELECT @@identity) 

処理 4 を実行するストアドプロシージャの内容

DELETE FROM basket WHERE LogonName = @LogonName

処理 2 、 3 は少し複雑になります。 @PoNumber 変数は処理 1 を実行した結果   ( Identity 列の値)   が入ります。

INSERT OrderFormLineItems (PoNumber,ProductId,Quantity,CyUnitPrice)
SELECT @PoNumber,,Basket.ProductId,Quantity,CyUnitPrice
FROM Basket,CatalogProducts
WHERE LogonName = @LogonName and Basket.ProductId=CatalogProducts.ProductId 

SQL Server の強力な機能であるストアドプロシージャは実行コストを最小限に抑えることができ、全ての処理が SQL Server 内で実行されるので、ストアドプロシージャとしてトランザクション処理を行うのはパフォーマンスの向上につながります。ただし、ストアドプロシージャは引数として SQL Server で使用できるデータ型しか使用できません。例えば、 Web アプリケーションがデータセットを作成し、その内容を引数にしてストアドプロシージャを実行させることはできません。

4-4 Microsoft Commerce Server 2002 では

サンプルアプリケーションでは、トランザクション処理として注文処理を実行するコードは PipeLine プロジェクトに定義されています。この PipeLine という名前は Microsoft Commerce Server 2002 の機能名と同じです。しかし、 Commerce Server のパイプラインはもっと優れた機能を備えています。注文処理として実行すべき処理内容はシステムごとに異なります。例えばサンプルアプリケーションでは課金処理がまったく実装されていませんが、実際はクレジットカードや電子マネーなど様々な方法で課金を行うのが一般的です。システムごとに異なる処理を各システム構築時に簡単に定義できるように Commerce Server にはパイプラインエディタというツールがあり、 GUI で   「まずこの処理を行い、次にこの処理を行い・・・」   と各処理を並べるだけで開発が終了します。当然、システムへの要求に変更があった場合でも簡単に修正が可能です。

また、いつも同じ商品を購入されるユーザーのためにバスケットに追加した複数の商品をテンプレートとして保存し、次回注文時には一つ一つ検索する手間を省いたり、商品の送付先を複数保存する機能など数多くの機能を利用できるようなクラスライブラリが提供されています。

CS2000.jpg

Fumio Mizobata:  東京を中心に .NET Framework ならびに .NET Enterprise Servers のトレーニングを開発、実施している。その多忙な業務の中、日々夜の街に吸い込まれ、そこでも大活躍しているようだが、実は大阪在住で 2 児の父親でもある。できるだけ多くの技術者のお役に立てる技術を伝達することに喜びを感じているので、トレーナーという職業はまさに天職である。