仮売上（オーソリ）とユーザ体験

## 更新のおしらせ

本記事はWebPay gemのバージョン2系に即して記述しています。
その後、メジャーバージョンアップを行ったため、メソッド名やエラー名などが変更になっています。
最新の情報は[WebPay公式サイトのRuby APIドキュメント](https://webpay.jp/docs/api/ruby)を参照してください。

## ユーザのがっかりを無くす

昨日の[webpay - 仮売上（オーソリ）を使ったサービス設計 - Qiita [キータ]](http://qiita.com/sowawa/items/dee94157b4921141f061)を少し具体的なところに落として、活用する方法を探ってみます。

例えば、AmazonなどECサイトでの買い物を思い浮かべてみましょう。
購入の最終確認画面まで辿り着き、無事に購入処理を終えて後は商品を待つだけという気分になり離脱した後にメールで「クレジットカードの情報を修正して下さい」はなかなか辛い思いをするのではないでしょうか。

ECサイトには、カードが何故使えなかったかの明確な理由が必ずしも得られるわけではない（往々にして得ることは出来ません）ため、「カード起因で決済に失敗した」以上の事実はユーザに伝えることが出来ません。（もちろん、エラーだからどうして欲しいと伝えることは出来ますね）

それは、利用限度額であったり、海外からの決済が多いため不正使用と判断されたための停止中であったりと理由は様々で、明確に知るにはユーザが自身で契約しているカード会社に問い合わせるまでわかりません。

WebPayの場合だと

```json
{
  "error": {
    "type": "card_error",
    "message": "This card cannot be used",
    "code": "card_declined",
    "param": "number"
  }
}
```

```ruby
WebPay::CardError: This card cannot be used
        from /Users/hmsk/.rbenv/versions/1.9.3-p392/lib/ruby/gems/1.9.1/gems/webpay-2.1.0/lib/webpay/client.rb:47:in `handle_response'
        from /Users/hmsk/.rbenv/versions/1.9.3-p392/lib/ruby/gems/1.9.1/gems/webpay-2.1.0/lib/webpay/client.rb:58:in `block (2 levels) in <class:Client>'
        from /Users/hmsk/.rbenv/versions/1.9.3-p392/lib/ruby/gems/1.9.1/gems/webpay-2.1.0/lib/webpay/operations.rb:20:in `create'
```

のようなエラーがそれに該当します。

では、ECサイトで仮売上げを活用する方法を考えてみます。
後からメールが来るのががっかりであるという前提ならば（私は少なくともそうです）、ユーザがサイトに滞在しているうちに与信の確保を試みて、確定を行う時に実売上（実際の売上げ）化を行えば良いでしょう。

WebPayで行う場合、購入する商品をユーザが決めたあとに、1度仮売上げのChargeの作成を試みます。

```ruby
WebPay::Charge.create(
   amount: 400,
   currency: "jpy",
   card:
     {
       number: "4242-4242-4242-4242",
       exp_month: "11",
       exp_year: "2014",
       cvc: "123",
       name: "KEI KUBO"
     },
   description: "仮売上げの作成",
   capture: false
)
```

この

```ruby
capture: false
```

が仮売上げでのChargeの作成を示します。実際に金取る（`capture`）のは`false`でお願いしますという具合です。

その後ユーザが最終確認を行った際に実売上げ化を行います。
上記でつくられた仮売上なChargeのidが`ch_7Kh4qkgByaeF0wr`だとすると、

```ruby
charge = WebPay::Charge.retrieve("ch_7Kh4qkgByaeF0wr")
charge.capture
```

で完了です。手に入れた仮売上を実売上げ化出来ないということは滅多にないため、ユーザが離脱した後にでも非同期でやってしまうとユーザを決済のリクエスト待ちに付き合わせる必要がなくなるかもしれませんね。

ただし、与信の確保とはいえ、あと一押しで決済が完了してしまう、ほぼ購入に等しい行為です。特定商取引法上、明確な支払い価格と対価（商品やサービス）を明確にユーザに伝えた上で行う必要があります。

![Screenshot 2013-12-11 00.33.17.png](https://qiita-image-store.s3.amazonaws.com/0/48/ab1204d7-64ef-f425-a898-63a5576b5976.png "Screenshot 2013-12-11 00.33.17.png")

もし最終的にキャンセルされた場合や、ページから離脱した場合には

```ruby
charge = WebPay::Charge.retrieve("ch_7Kh4qkgByaeF0wr")
charge.refund
```

として失効させましょう。

また、途中で数量を変更したなど金額に変更が生じた場合には、金額が減った場合に限り減額を行うこともできます。
（増額の場合は、再度与信を新しく確保する必要があるため、失効の上、増額後の金額で再度Chargeを作成することになるでしょう）

```ruby
charge = WebPay::Charge.retrieve("ch_7Kh4qkgByaeF0wr")
charge.refund(amount: 10)
```

ユーザによって増税前のうまい棒が一本減らされた時の処理の様子です。

## 活用される場所

### 支払い時と必要時がずれる

仮売上は、「カードの支払い明細には記録されず、与信枠だけが特定期間確保されている」という状態をつくることが出来るため、
例えばクラウドファンディングのようなサービスに適しています。

出資者が出資を希望した時点では支払い能力があっても、プロジェクトがゴールに辿り着いた際に支払えなくなってしまっていては元も子もありません。

出資を希望した時点で引き落としてしまって、払い戻しを行うというのも手段としては可能かもしれませんが、プロジェクトのゴール時の見返りよりも先にカードの支払い明細に記録、引き落としが行われてしまうので、引き落とし時点では対価が存在せず寄附をしたような体験を与えてしまうかもしれません。

### 決まった日までに確実に売り上げる

定期課金の場合に、引き落とし予定日にユーザから支払いをちゃんと受け取れるように、その前に仮売上げを作成しておくというのも考えられます。

月額課金のウェブサービスで引き落とし実施時や翌月の引き落としの1週間前に翌月分の枠を確保しておくというような処理を行うなどして、失敗した場合にユーザにカード情報を確認してもらうことが出来そうです。

あまりにも先取って確保してしまうのはユーザに迷惑をかけることになりますし、同意や説明の前段をしっかりと取る必要があります。

## 仮売上の失効

仮売上げは特定の期間を満了すると、確保した与信枠が解放されるようになっています。これは決済代行サービスによって期間は異なるのですが、概ね数ヶ月単位で確保することができます。

ちなみにWebPayでは現在最大45日となっており（デフォルトは5日となっていますが、設定画面から変更できます）失効時には`charge.captured`なstatusのイベントがWebHook経由で受け取れます。

必要もなく長い間、金額の大きい与信枠を確保するとユーザの月の限度額の枠を圧迫しかねないので注意が必要です。

## デビットカード

銀行口座などとほぼ直結ともいえるデビットカードの場合、仮売上の作成時点で銀行口座から引き落としが実際に行われてしまうことがあります。勿論仮売上を取り消せばお金を戻すことは出来ますが、クレジットカードと異なって明細に残ってしまうので注意が必要です。