定期課金

定期課金とは、特定の顧客に毎月、毎年などの一定間隔で自動的に課金を行う機能です。 WebPayでは、定期課金を実施するための、Recursionオブジェクトが準備されており、 他のオブジェクトと同様に、原則的にAPIから制御をおこないます。

定期課金を行う

Recursionオブジェクトは 1つのCustomerオブジェクトを結びつけ、定期的にChargeオブジェクトの作成(課金)を行います。 1人の顧客の定期課金の契約に対して、1つのRecursionオブジェクトが準備されることになります。

定期課金オブジェクトを作成する

他のオブジェクトと同様にRecursionオブジェクトを作成でき、ユニークなidが割り当てられます。 定期課金を作成するためには、事前に課金をする対象となる顧客(Customer)オブジェクトを作成し、定期課金に用いるカードの情報を紐付けておく必要があります。 毎回の課金内容を指定する"amount"、"currency"、期間を指定する"period"も必須パラメータです。 例えば、以下は 「idが"cus_4lOag156Rfh10nU"である顧客に対して毎月400円の定期課金を開始する」 ためのコードとなります。

$
curl "https://api.webpay.jp/v1/recursions" \
-u "test_secret_eHn4TTgsGguBcW764a2KA8Yd": \
-d "amount=32400" \
-d "currency=jpy" \
-d "customer=cus_4lOag156Rfh10nU" \
-d "period=month" \
-d "description=cus_7WM5FA4U4eNP16M / 定期課金"
>>
require 'webpay'
webpay = WebPay.new('test_secret_eHn4TTgsGguBcW764a2KA8Yd')
webpay.recursion.create(
   amount: 32400,
   currency: "jpy",
   customer: "cus_4lOag156Rfh10nU",
   period: :month,
   description: "cus_7WM5FA4U4eNP16M / 定期課金"
)
php >
require "vendor/autoload.php";
use WebPay\WebPay;
$webpay = new WebPay('test_secret_eHn4TTgsGguBcW764a2KA8Yd');
$webpay->recursion->create(array(
   "amount"=>32400,
   "currency"=>"jpy",
   "customer"=>"cus_4lOag156Rfh10nU",
   "period"=>"month",
   "description"=>"cus_7WM5FA4U4eNP16M / 定期課金"
));
>
import jp.webpay.webpay.WebPay;
WebPay webpay = new WebPay("test_secret_eHn4TTgsGguBcW764a2KA8Yd");
webpay.recursion.createRequest()
        .amount(32400)
        .currency("jpy")
        .customer("cus_4lOag156Rfh10nU")
        .period(:month)
        .description("cus_7WM5FA4U4eNP16M / 定期課金")
        .execute();
>>>
import webpay
client = webpay.WebPay('test_secret_eHn4TTgsGguBcW764a2KA8Yd')
client.recursion.create(
  amount=32400,
  currency="jpy",
  customer="cus_4lOag156Rfh10nU",
  period=:month,
  description="cus_7WM5FA4U4eNP16M / 定期課金"
  )
>
var WebPay = require('webpay');
webpay = new WebPay('test_secret_eHn4TTgsGguBcW764a2KA8Yd');
webpay.recursion.create({
  amount: 32400,
  currency: "jpy",
  customer: "cus_4lOag156Rfh10nU",
  period: "month",
  description: "cus_7WM5FA4U4eNP16M / 定期課金"
}, function(err, res) { ... });

というような操作で、新しくRecursionオブジェクトが作られ、 作成されたオブジェクトのidである"rec_7WM5FA4sd6QU1wD" を用いて

$
curl "https://api.webpay.jp/v1/recursions/rec_7WM5FA4sd6QU1wD" \
-u "test_secret_eHn4TTgsGguBcW764a2KA8Yd":
>>
require 'webpay'
webpay = WebPay.new('test_secret_eHn4TTgsGguBcW764a2KA8Yd')
webpay.recursion.retrieve("rec_7WM5FA4sd6QU1wD")
php >
require "vendor/autoload.php";
use WebPay\WebPay;
$webpay = new WebPay('test_secret_eHn4TTgsGguBcW764a2KA8Yd');
$webpay->recursion->retrieve("rec_7WM5FA4sd6QU1wD");
>
import jp.webpay.webpay.WebPay;
WebPay webpay = new WebPay("test_secret_eHn4TTgsGguBcW764a2KA8Yd");
webpay.recursion.retrieve("rec_7WM5FA4sd6QU1wD");
>>>
import webpay
client = webpay.WebPay('test_secret_eHn4TTgsGguBcW764a2KA8Yd')
client.recursion.retrieve("rec_7WM5FA4sd6QU1wD")
>
var WebPay = require('webpay');
webpay = new WebPay('test_secret_eHn4TTgsGguBcW764a2KA8Yd');
webpay.recursion.retrieve("rec_7WM5FA4sd6QU1wD", function(err, res) { ... });

で、詳細な情報を閲覧できます。各プロパティの内容は APIドキュメント をご覧ください。

定期課金の対象となっている顧客オブジェクトは、課金の失敗をさけるため、削除ができなくなります。 顧客オブジェクトを削除する場合には、事前にその顧客に設定されているすべての定期課金を削除してください。

定期課金オブジェクトを削除する

Recursionオブジェクトを削除することで、定期課金の処理を停止することができます。削除後以降の自動課金が行われなくなります。なお、Recursionオブジェクトの更新は出来ないようになっているため 定期課金の金額などを変更したい場合には一度削除して、新たな金額で新規作成する必要があります。

$
curl "https://api.webpay.jp/v1/recursions/rec_7WM5FA4sd6QU1wD" \
-u "test_secret_eHn4TTgsGguBcW764a2KA8Yd": \
-X DELETE
>>
require 'webpay'
webpay = WebPay.new('test_secret_eHn4TTgsGguBcW764a2KA8Yd')
webpay.recursion.delete(id: "rec_7WM5FA4sd6QU1wD")
php >
require "vendor/autoload.php";
use WebPay\WebPay;
$webpay = new WebPay('test_secret_eHn4TTgsGguBcW764a2KA8Yd');
$webpay->recursion->delete(array("id"=>"rec_7WM5FA4sd6QU1wD"));
>
import jp.webpay.webpay.WebPay;
WebPay webpay = new WebPay("test_secret_eHn4TTgsGguBcW764a2KA8Yd");
webpay.recursion.delete("rec_7WM5FA4sd6QU1wD");
>>>
import webpay
client = webpay.WebPay('test_secret_eHn4TTgsGguBcW764a2KA8Yd')
client.recursion.delete(id="rec_7WM5FA4sd6QU1wD")
>
var WebPay = require('webpay');
webpay = new WebPay('test_secret_eHn4TTgsGguBcW764a2KA8Yd');
webpay.recursion.delete({id: "rec_7WM5FA4sd6QU1wD"}, function(err, res) { ... });

自動課金のタイミング

自動的に行われる課金のタイミングが、意図するタイミングと異なっていないか十分に確認してください。

初回の課金

Recursionオブジェクトが作成されたタイミングで、初回の課金が試行されます。 成功、失敗にかかわらず、作成されたRecursionオブジェクトがレスポンスされます。 状態が「一時停止中("suspended")」になっているかで成功したかどうかを判断できます。 失敗した場合は次回以降の課金が行われませんので、定期課金の再開を参考に情報を修正してください。

作成時に"first_scheduled"パラメータを指定することで、任意の時点から開始することも可能です。 過去の時刻を指定した場合、作成時に課金が試行され、以降はその時刻から1周期後に定期的に課金が行われます。 未来の時刻を指定した場合、作成時には課金が行われず、指定時刻に最初の課金が試行されます。

2回目以降の課金

2回目の課金のタイミングは、指定されたperiodに従い、monthであれば初回実施日の翌月同日、yearであれば翌年同日に行われます。 以降、毎月同日、毎年同日に行われますが、具体的に次回がいつ実施予定であるかについては、next_scheduledというプロパティを確認してください。

また、月末や、うるう年の扱いに注意してください。 月毎を指定し、最初の課金が3/31におこなわれた場合、次回は4/30の同時刻になります。その次は5/30の同時刻になります。 年毎を指定し、最初の課金が2016/2/29におこなわれた場合、次回以降は各年の2/28になります。

実行タイミングの誤差

実施予定日についてはnext_scheduledというプロパティには秒単位で記録されていますが、一定時間内に行える課金処理の回数が制限されているため、実際の課金実行が指定時刻より遅れる場合があります。 通常は数分以内ですが、月末、月初など特にリクエストが集中するタイミングでは10分以上になることもあります。 ただし、 課金実施後にスケジュールされる次の実施予定日は、前の実施予定日から1周期として設定される ので、実際の課金を行った時間へのずれには影響を受けません。

過去のスケジュールを指定する

"first_scheduled"パラメータには、1周期前(periodがmonthなら1ヶ月前、yearなら1年前)以降の時刻を設定できます。 もし、過去の時刻が設定された場合には、作成後直ちに課金が試行され、成功時に設定される次の実施予定日は 指定した過去の時刻から1周期 となります。例えば、2014年4月中旬に、periodに"month"、first_scheduledに日本時間の2014年4月1日の正午となるUNIXタイムスタンプ"1396321200"を指定して作成されたRecursionオブジェクトは 作成後直ちに4月1日分の課金を試行し、成功後には2014年5月1日の正午となるUNIXタイムスタンプ"1398913200"がnext_scheduledに設定されます。 月の途中からの利用開始でも1ヶ月分を徴収し、翌月以降は月初に徴収を行いたいという場合などに利用できます。

課金のイベントをキャッチする

Recursionオブジェクトによる課金の実施記録はイベント(Event)オブジェクトに記録されます。 成功時には recursion.succeeded 、失敗時には recursion.failed というtypeのイベントが作成され、 Webhook も発行されますので、実施についての情報が随時必要な場合はご利用ください。

課金失敗により、一時停止した定期課金の再開

自動課金に失敗した場合は、繰り返し課金に失敗することを避けるために、自動課金処理が一時的に停止します。 このとき、定期課金は「一時停止中("suspended")」へと変更され、次回以降の課金は行われなくなります。 問題の原因を判断、解決して、利用者が再試行を明示的に指示しなければなりません。再試行の指示はAPIを利用して行えます。

$
curl "https://api.webpay.jp/v1/recursions/rec_7WM5FA4sd6QU1wD/resume" \
-u "test_secret_eHn4TTgsGguBcW764a2KA8Yd": \
-X POST -H 'Content-Length: 0'
>>
require 'webpay'
webpay = WebPay.new('test_secret_eHn4TTgsGguBcW764a2KA8Yd')
webpay.recursion.resume(id: "rec_7WM5FA4sd6QU1wD")
php >
require "vendor/autoload.php";
use WebPay\WebPay;
$webpay = new WebPay('test_secret_eHn4TTgsGguBcW764a2KA8Yd');
$webpay->recursion->resume(array("id"=>"rec_7WM5FA4sd6QU1wD"));
>
import jp.webpay.webpay.WebPay;
WebPay webpay = new WebPay("test_secret_eHn4TTgsGguBcW764a2KA8Yd");
webpay.recursion.resumeRequest("rec_7WM5FA4sd6QU1wD")
        .execute();
>>>
import webpay
client = webpay.WebPay('test_secret_eHn4TTgsGguBcW764a2KA8Yd')
client.recursion.resume(id="rec_7WM5FA4sd6QU1wD")
>
var WebPay = require('webpay');
webpay = new WebPay('test_secret_eHn4TTgsGguBcW764a2KA8Yd');
webpay.recursion.resume({id: "rec_7WM5FA4sd6QU1wD"}, function(err, res) { ... });

このようにして定期課金を再開すると、 再開した時点で失敗した分の課金を再試行します。(下記の図左側) なお、再試行した場合に再度課金に失敗した場合は、再び一時停止状態へ戻ります。 再試行を希望しない場合(その月の分の課金を作成する必要がない場合)は"retry"パラメータに"false"を指定してください。(下記の図右側)

$
curl "https://api.webpay.jp/v1/recursions/rec_7WM5FA4sd6QU1wD/resume" \
-u "test_secret_eHn4TTgsGguBcW764a2KA8Yd": \
-d "retry=false"
>>
require 'webpay'
webpay = WebPay.new('test_secret_eHn4TTgsGguBcW764a2KA8Yd')
webpay.recursion.resume(retry: false, id: "rec_7WM5FA4sd6QU1wD")
php >
require "vendor/autoload.php";
use WebPay\WebPay;
$webpay = new WebPay('test_secret_eHn4TTgsGguBcW764a2KA8Yd');
$webpay->recursion->resume(array("retry"=>false, "id"=>"rec_7WM5FA4sd6QU1wD"));
>
import jp.webpay.webpay.WebPay;
WebPay webpay = new WebPay("test_secret_eHn4TTgsGguBcW764a2KA8Yd");
webpay.recursion.resumeRequest("rec_7WM5FA4sd6QU1wD")
        .retry(false)
        .execute();
>>>
import webpay
client = webpay.WebPay('test_secret_eHn4TTgsGguBcW764a2KA8Yd')
client.recursion.resume(retry=False, id="rec_7WM5FA4sd6QU1wD")
>
var WebPay = require('webpay');
webpay = new WebPay('test_secret_eHn4TTgsGguBcW764a2KA8Yd');
webpay.recursion.resume({retry: false,id: "rec_7WM5FA4sd6QU1wD"}, function(err, res) { ... });
Recursion_retry

再開の出来ない停止状態

上の方法で定期課金を再開できるのは、一時停止中状態になってから1周期の間です。(periodがmonthなら1ヶ月、yearなら1年) この期日をすぎると、定期課金は「停止("closed")」状態となり、再開できなくなります。 停止後に再度定期課金をする場合は、あらたな定期課金オブジェクトを作成してください。

Recursion_closed