OmiseのSchedule APIの使い方について、ざっくり見てみようと思います。
個人的にcurl
をいちいち作ったり覚えたりするのが面倒くさいので、下記のスクリプトを使用しています:
https://github.com/keitaroemotion/omi
なので、omi
というやつが下記の記事にちょこちょこ出てきますが、そいつがビルドしたcurl
コマンドもきちんと書いてあるので、omi
いらない人はそこだけ見てもらっても大丈夫です。
まず、Schedule APIってどんなのあるんだろうってざっと見てみると、
$ omi schedule
omi [schedule] list ... list_all_schedules
omi [schedules] ... list_all_schedules
omi [schedule] create_daily ... charge with days interval
omi [schedule] create_monthly ... charge with months interval
omi [schedule] create_weekly ... charge with weekly interval (ex. Mon, Wed)
omi [schedule] create_zig_zag ... charge with inconsistent day per month
[option: -d dry_run]
[option: -e allows editing the command before execution]
[option: -v allows viewing the execution result]
[option: -l swaps URL into localhost]
[option: count counts the number of result records]
[option: --rich enables rich output]
- list ... 一覧表示
- create_daily ... 日毎の課金
- create_weekly ... 週毎の課金(曜日毎の課金)
- create_monthly ... 月ごとの課金
- create_zig_zag ... 月ごとに課金日が違う課金
とかがあります。
日毎の課金
二日おきに100円課金したい場合、以下のようにやります
$ omi schedule create_daily -e -v amount=100 every=2
curl -s https://api.omise.co/schedules \
-X POST \
-u skey_test_58blr9gmoomin3brx21y6: \
-d "every=2" \
-d "period=day" \
-d "start_date=2018-02-27" \
-d "end_date=2118-02-03" \
-d "charge[customer]=cust_test_5b1t0dd4cpjh32e70ty" \
-d "charge[card]=card_test_5b1t0hjbw1g9xq7m5r1" \
-d "charge[amount]=100" \
-d "charge[description]=Membership fee"
個々のパラメータは以下の意味です。
- every ... 間隔(日毎、週毎、月毎...)
- period ... 間隔の単位(日、週、月)
- start_date ... 課金の開始日 (yyyy-MM-dd)
- end_date ... 課金の終了日 (yyyy-MM-dd)
- charge[customer] ... 課金する顧客のID (
cust_...
) - charge[card] ... 課金する顧客のカードID(
card_...
) - charge[amount] ... 過金額
- charge[description] ... 備考
なので、上記のコマンドを翻訳すると、
every=2
いつも2
period=day
日毎に
start_date=2018-02-27
2018/2/27から
end_date=2118-02-03
2118/2/3までの期間
charge[customer]=cust_test_5b1t0dd4cpjh32e70ty
cust_test_5b1t0dd4cpjh32e70tyの顧客の
charge[card]=card_test_5b1t0hjbw1g9xq7m5r1
card_test_5b1t0hjbw1g9xq7m5r1のカードに対して
charge[amount]=100
100円課金するよ、
つまり2日毎に2018/2/27 - 2118/2/3までの期間、cust_test_5b1t0dd4cpjh32e70ty
さんのcard_test_5b1t0hjbw1g9xq7m5r1
のカードに対して100円課金するということです。
結果は以下のようになります。
{
"object": "schedule",
"id": "schd_test_5b3q4mnj5nqyovnr350",
"livemode": false,
"location": "/schedules/schd_test_5b3q4mnj5nqyovnr350",
"status": "active",
"every": 2,
"period": "day",
"on": {
},
"in_words": "Every 2 day(s)",
"start_date": "2018-02-27",
"end_date": "2118-02-03",
"charge": {
"amount": 100,
"currency": "jpy",
"description": "Membership fee",
"customer": "cust_test_5b1t0dd4cpjh32e70ty",
"card": "card_test_5b1t0hjbw1g9xq7m5r1"
},
"occurrences": {
"object": "list",
"from": "1970-01-01T00:00:00Z",
"to": "2018-02-27T06:18:24Z",
"offset": 0,
"limit": 20,
"total": 1,
"order": null,
"location": "/schedules/schd_test_5b3q4mnj5nqyovnr350/occurrences",
"data": [
{
"object": "occurrence",
"id": "occu_test_5b3q4mnktcyl71pm2p6",
"livemode": false,
"location": "/occurrences/occu_test_5b3q4mnktcyl71pm2p6",
"schedule": "schd_test_5b3q4mnj5nqyovnr350",
"schedule_date": "2018-02-27",
"retry_date": null,
"processed_at": "2018-02-27T06:18:24Z",
"status": "successful",
"message": null,
"result": "chrg_test_5b3q4mojujzoty1ril9",
"created": "2018-02-27T06:18:23Z"
}
]
},
"next_occurrence_dates": [
"2018-03-01",
"2018-03-03",
"2018-03-05",
"2018-03-07",
"2018-03-09",
"2018-03-11",
"2018-03-13",
"2018-03-15",
"2018-03-17",
"2018-03-19",
"2018-03-21",
"2018-03-23",
"2018-03-25",
"2018-03-27",
"2018-03-29",
"2018-03-31",
"2018-04-02",
"2018-04-04",
"2018-04-06",
"2018-04-08",
"2018-04-10",
"2018-04-12",
"2018-04-14",
"2018-04-16",
"2018-04-18",
"2018-04-20",
"2018-04-22",
"2018-04-24",
"2018-04-26",
"2018-04-28"
],
"created": "2018-02-27T06:18:23Z"
}
ごにょごにょ、っと書いてありますが、
"next_occurrence_dates": [
"2018-03-01",
"2018-03-03",
"2018-03-05",
"2018-03-07",
"2018-03-09",
"2018-03-11",
"2018-03-13",
"2018-03-15",
"2018-03-17",
"2018-03-19",
"2018-03-21",
"2018-03-23",
"2018-03-25",
"2018-03-27",
"2018-03-29",
"2018-03-31",
"2018-04-02",
"2018-04-04",
"2018-04-06",
"2018-04-08",
"2018-04-10",
"2018-04-12",
"2018-04-14",
"2018-04-16",
"2018-04-18",
"2018-04-20",
"2018-04-22",
"2018-04-24",
"2018-04-26",
"2018-04-28"
],
このnext_occurence_dates
というところで次いつ課金するか、がある程度のスコープで記述されている、という感じですね。
曜日毎の課金
$ omi schedule create_weekly -e -v amount=100
curl -s https://api.omise.co/schedules \
-X POST \
-u skey_test_58blr9gmoomin3brx21y6: \
-d "every=1" \
-d "period=week" \
-d "on[weekdays][]=monday" \
-d "on[weekdays][]=friday" \
-d "start_date=2018-02-27" \
-d "end_date=2118-02-03" \
-d "charge[customer]=cust_test_5b1t0dd4cpjh32e70ty" \
-d "charge[amount]=100" \
-d "charge[description]=Membership fee"
every=1
毎
period=week
週
on[weekdays][]=monday
月曜日と
on[weekdays][]=friday
金曜日に
start_date=2018-02-27
2/27から
end_date=2118-02-03
100年後の2/3日まで
charge[customer]=cust_test_5b1t0dd4cpjh32e70ty
cust_test_5b1t0dd4cpjh32e70tyさんに
charge[amount]=100
100円課金する
つまり、毎週月金で2/27-100年後の2/3まで、cust_test_5b1t0dd4cpjh32e70ty
さんに(カードは指定してないのでデフォルトカードで)100円課金する
ということになります。結果は、
{
"object": "schedule",
"id": "schd_test_5b3qa9jvwh51rdlag09",
"livemode": false,
"location": "/schedules/schd_test_5b3qa9jvwh51rdlag09",
"status": "active",
"every": 1,
"period": "week",
"on": {
"weekdays": [
"monday",
"friday"
]
},
"in_words": "Every 1 week(s) on Monday and Friday",
"start_date": "2018-02-27",
"end_date": "2118-02-03",
"charge": {
"amount": 100,
"currency": "jpy",
"description": "Membership fee",
"customer": "cust_test_5b1t0dd4cpjh32e70ty",
"card": null
},
"occurrences": {
"object": "list",
"from": "1970-01-01T00:00:00Z",
"to": "2018-02-27T06:34:24Z",
"offset": 0,
"limit": 20,
"total": 0,
"order": null,
"location": "/schedules/schd_test_5b3qa9jvwh51rdlag09/occurrences",
"data": [
]
},
"next_occurrence_dates": [
"2018-03-02",
"2018-03-05",
"2018-03-09",
"2018-03-12",
"2018-03-16",
"2018-03-19",
"2018-03-23",
"2018-03-26",
"2018-03-30",
"2018-04-02",
"2018-04-06",
"2018-04-09",
"2018-04-13",
"2018-04-16",
"2018-04-20",
"2018-04-23",
"2018-04-27",
"2018-04-30",
"2018-05-04",
"2018-05-07",
"2018-05-11",
"2018-05-14",
"2018-05-18",
"2018-05-21",
"2018-05-25",
"2018-05-28",
"2018-06-01",
"2018-06-04",
"2018-06-08",
"2018-06-11"
],
"created": "2018-02-27T06:34:24Z"
}
また、週一回なら、
curl -s https://api.omise.co/schedules \
-X POST \
-u skey_test_58blr9gmoomin3brx21y6: \
-d "every=1" \
-d "period=week" \
-d "on[weekdays][]=monday" \
-d "start_date=2018-02-27" \
-d "end_date=2118-02-03" \
-d "charge[customer]=cust_test_5b1t0dd4cpjh32e70ty" \
-d "charge[amount]=100" \
-d "charge[description]=Membership fee"
月毎の課金
omi schedule create_monthly -e -v amount=100 day=25
curl -s https://api.omise.co/schedules \
-X POST \
-u skey_test_58blr9gmoomin3brx21y6: \
-d "every=1" \
-d "period=month" \
-d "on[days_of_month][]=25" \
-d "start_date=2018-02-27" \
-d "end_date=2118-02-03" \
-d "charge[customer]=cust_test_5b1t0dd4cpjh32e70ty" \
-d "charge[amount]=100" \
-d "charge[description]=Membership fee"
on[days_of_month][]=25
のところで、毎月何日に課金するかが設定されています。
"object": "schedule",
"id": "schd_test_5b3qd0o3vj6k86h4w8k",
"livemode": false,
"location": "/schedules/schd_test_5b3qd0o3vj6k86h4w8k",
"status": "active",
"every": 1,
"period": "month",
"on": {
"days_of_month": [
25
]
},
"in_words": "Every 1 month(s) on the 25th",
"start_date": "2018-02-27",
"end_date": "2118-02-03",
"charge": {
"amount": 100,
"currency": "jpy",
"description": "Membership fee",
"customer": "cust_test_5b1t0dd4cpjh32e70ty",
"card": null
},
"occurrences": {
"object": "list",
"from": "1970-01-01T00:00:00Z",
"to": "2018-02-27T06:42:14Z",
"offset": 0,
"limit": 20,
"total": 0,
"order": null,
"location": "/schedules/schd_test_5b3qd0o3vj6k86h4w8k/occurrences",
"data": [
]
},
"next_occurrence_dates": [
"2018-03-25",
"2018-04-25",
"2018-05-25",
"2018-06-25",
"2018-07-25",
"2018-08-25",
"2018-09-25",
"2018-10-25",
"2018-11-25",
"2018-12-25",
"2019-01-25",
"2019-02-25",
"2019-03-25",
"2019-04-25",
"2019-05-25",
"2019-06-25",
"2019-07-25",
"2019-08-25",
"2019-09-25",
"2019-10-25",
"2019-11-25",
"2019-12-25",
"2020-01-25",
"2020-02-25",
"2020-03-25",
"2020-04-25",
"2020-05-25",
"2020-06-25",
"2020-07-25",
"2020-08-25"
],
"created": "2018-02-27T06:42:13Z"
}
月単位で、一月に複数回の課金
omi schedule create_zig_zag -e -v amount=100
この場合、 everyの値(3) と、 on[days_of_month][]
の個数が一致していることがポイントとなります。このため、月ごとで課金日が 1, 10, 15日
となり、これをループしていく形となります。
curl -s https://api.omise.co/schedules \
-X POST \
-u skey_test_58blr9gmoomin3brx21y6: \
-d "every=3" \
-d "period=month" \
-d "on[days_of_month][]=1" \
-d "on[days_of_month][]=10" \
-d "on[days_of_month][]=15" \
-d "start_date=2018-02-27" \
-d "end_date=2118-02-03" \
-d "charge[customer]=cust_test_5b1t0dd4cpjh32e70ty" \
-d "charge[amount]=100" \
-d "charge[description]=Membership fee"
結果は以下のようになります。
{
"object": "schedule",
"id": "schd_test_5b3qe5yemv2bhxwp4y2",
"livemode": false,
"location": "/schedules/schd_test_5b3qe5yemv2bhxwp4y2",
"status": "active",
"every": 3,
"period": "month",
"on": {
"days_of_month": [
1,
10,
15
]
},
"in_words": "Every 3 month(s) on the 1st, 10th, and 15th",
"start_date": "2018-02-27",
"end_date": "2118-02-03",
"charge": {
"amount": 100,
"currency": "jpy",
"description": "Membership fee",
"customer": "cust_test_5b1t0dd4cpjh32e70ty",
"card": null
},
"occurrences": {
"object": "list",
"from": "1970-01-01T00:00:00Z",
"to": "2018-02-27T06:45:29Z",
"offset": 0,
"limit": 20,
"total": 0,
"order": null,
"location": "/schedules/schd_test_5b3qe5yemv2bhxwp4y2/occurrences",
"data": [
]
},
"next_occurrence_dates": [
"2018-03-01",
"2018-03-10",
"2018-03-15",
"2018-06-01",
"2018-06-10",
"2018-06-15",
"2018-09-01",
"2018-09-10",
"2018-09-15",
"2018-12-01",
"2018-12-10",
"2018-12-15",
"2019-03-01",
"2019-03-10",
"2019-03-15",
"2019-06-01",
"2019-06-10",
"2019-06-15",
"2019-09-01",
"2019-09-10",
"2019-09-15",
"2019-12-01",
"2019-12-10",
"2019-12-15",
"2020-03-01",
"2020-03-10",
"2020-03-15",
"2020-06-01",
"2020-06-10",
"2020-06-15"
],
"created": "2018-02-27T06:45:29Z"
}
定期課金一覧の取得
$ omi schedules
curl -s -X GET https://api.omise.co/schedules \
-u skey_test_58blr9gmoomin3brx21y6:
定期課金の削除(無効化)
厳密にはレコード自体を削除はできないんですが、status: deleted
にして事実上削除した状態にできます。
$ omi schedule delete
curl -s https://api.omise.co/schedules/schd_test_5b3qduov0jfe5i2rycs \
-X DELETE \
-u skey_test_58blr9gmoomin3brx21y6:
{
"object": "schedule",
"id": "schd_test_5b3qduov0jfe5i2rycs",
"livemode": false,
"location": "/schedules/schd_test_5b3qduov0jfe5i2rycs",
"status": "deleted",
"every": 3,
"period": "month",
"on": {
"days_of_month": [
1,
10,
15
]
},
"in_words": "Every 3 month(s) on the 1st, 10th, and 15th",
"start_date": "2019-05-01",
"end_date": "2089-05-01",
"charge": {
"amount": 100,
"currency": "jpy",
"description": "Membership fee",
"customer": "cust_test_5b1t0dd4cpjh32e70ty",
"card": null
},
"occurrences": {
"object": "list",
"from": "1970-01-01T00:00:00Z",
"to": "2018-02-27T07:04:20Z",
"offset": 0,
"limit": 20,
"total": 0,
"order": null,
"location": "/schedules/schd_test_5b3qduov0jfe5i2rycs/occurrences",
"data": [
]
},
"next_occurrence_dates": [
],
"created": "2018-02-27T06:44:35Z"
}
日割り計算とかしたい場合
日割り計算をしたい場合、顧客のアカウント登録時からその月の最後までの計算、チャージの計算、その後でのスケジュール作成などは自分で実装することになります。以下のような感じで実装します。ソースはこちらから入手可能です
#!/usr/bin/env ruby
# March 2018
# Su Mo Tu We Th Fr Sa
# 1 2 3
# 4 5 6 7 8 9 10
# 11 12 13 14[15]16 17
# 18 19 20 21 22 23 24
# 25 26 27 28 29 30 31
#
# This means the days_remained is 17.
# Supposed that the customer is going to be charged with
# 2000 yen...
#
# FOR THE INTENSION TO MAKE IT RECOGNIZABLE TO
# JAPANESE DEVELOPERS, THE TERM "HIWARI" IS USED
# WHICH MEANS CHARGE PER DAY.
#
require 'date'
class Test
def self.assert(expected, real)
if expected != real
abort("expected: #{expected}, real: #{real}")
end
end
end
class User
#
# intentionally refrains from using attr_reader
# so that the structure is easy to be grasped for now
#
def initialize(sign_in_date:, charge_amount:, customer_id:)
@sign_in_date = sign_in_date
@charge_amount = charge_amount
@customer_id = customer_id
@stupidly_large_number = 10000
end
def sign_in_date
@sign_in_date
end
def charge_amount
@charge_amount
end
def customer_id
@customer_id
end
def scheduled_charge_start_date
Date.new(@sign_in_date.year, @sign_in_date.month + 1, 1)
end
def scheduled_charge_end_date
scheduled_charge_start_date + @stupidly_large_number
end
def days_remained
Date.new(sign_in_date.year, sign_in_date.month, -1).day - sign_in_date.day + 1
end
def hiwari_amount_total
days_remained * charge_amount
end
end
def charge(skey, hiwari_amount_total, user)
"curl -s https://api.omise.co/charges \\\n" \
" -X POST \\\n" \
" -u #{skey}: \\\n" \
" -d \"amount=#{hiwari_amount_total}\" \\\n" \
" -d \"currency=jpy\" \\\n" \
" -d \"customer=#{user.customer_id}\""
end
def create_schedule(skey, user, day)
"curl -s https://api.omise.co/schedules\\\n" \
" -X POST \\\n" \
" -u #{skey}: \\\n" \
" -d \"every=1\" \\\n" \
" -d \"period=month\" \\\n" \
" -d \"on[days_of_month][]=#{day}\" \\\n" \
" -d \"start_date=#{user.scheduled_charge_start_date}\" \\\n" \
" -d \"end_date=#{user.scheduled_charge_end_date}\" \\\n" \
" -d \"charge[customer]=#{user.customer_id}\" \\\n" \
" -d \"charge[amount]=#{user.charge_amount}\" \\\n" \
" -d \"charge[description]=Membership fee\""
end
skey = ARGV[0]
#
# Case 1: signin_date: 2018/3/15
#
user = User.new(
sign_in_date: Date.new(2018, 3, 15),
charge_amount: 2000,
customer_id: "cust_test_5b4vkgkeal49aafdo2k"
)
Test.assert 17, user.days_remained
Test.assert 34000, user.hiwari_amount_total
puts charge(skey, user.hiwari_amount_total, user)
Test.assert "2018-04-01", user.scheduled_charge_start_date.to_s
Test.assert "2045-08-17", user.scheduled_charge_end_date.to_s
puts create_schedule(skey, user, "25")
#
# Case 2: signin_date: 2018/3/1
#
user = User.new(
sign_in_date: Date.new(2018, 3, 1),
charge_amount: 100,
customer_id: "cust_test_5b4vkgkeal49aafdo2k"
)
Test.assert 31, user.days_remained
Test.assert 3100, user.hiwari_amount_total
puts charge(skey, user.hiwari_amount_total, user)
Test.assert "2018-04-01", user.scheduled_charge_start_date.to_s
Test.assert "2045-08-17", user.scheduled_charge_end_date.to_s
puts create_schedule(skey, user, "25")
#
# Case 3: signin_date: 2018/3/31
#
user = User.new(
sign_in_date: Date.new(2018, 3, 31),
charge_amount: 100,
customer_id: "cust_test_5b4vkgkeal49aafdo2k"
)
Test.assert 1, user.days_remained
Test.assert 100, user.hiwari_amount_total
puts charge(skey, user.hiwari_amount_total, user)
Test.assert "2018-04-01", user.scheduled_charge_start_date.to_s
Test.assert "2045-08-17", user.scheduled_charge_end_date.to_s
puts create_schedule(skey, user, "25")
初月無料とかしたい場合
初月無料にしたい場合は、顧客の登録の月 + 1からスケジュール課金を始めればいいので、以下のようになります。ソースはこちら
#!/usr/bin/env ruby
# March 2018
# Su Mo Tu We Th Fr Sa
# 1 2 3
# 4 5 6 7 8 9 10
# 11 12 13 14[15]16 17
# 18 19 20 21 22 23 24
# 25 26 27 28 29 30 31
#
require 'date'
class Test
def self.assert(expected, real)
if expected != real
abort("expected: #{expected}, real: #{real}")
end
end
end
class User
#
# intentionally refrains from using attr_reader
# so that the structure is easy to be grasped for now
#
def initialize(sign_in_date:, charge_amount:, customer_id:)
@sign_in_date = sign_in_date
@charge_amount = charge_amount
@customer_id = customer_id
@stupidly_large_number = 10000
end
def sign_in_date
@sign_in_date
end
def charge_amount
@charge_amount
end
def customer_id
@customer_id
end
def scheduled_charge_start_date
Date.new(@sign_in_date.year, @sign_in_date.month + 1, 1)
end
def scheduled_charge_end_date
scheduled_charge_start_date + @stupidly_large_number
end
end
def create_schedule(skey, user, day)
"curl -s https://api.omise.co/schedules\\\n" \
" -X POST \\\n" \
" -u #{skey}: \\\n" \
" -d \"every=1\" \\\n" \
" -d \"period=month\" \\\n" \
" -d \"on[days_of_month][]=#{day}\" \\\n" \
" -d \"start_date=#{user.scheduled_charge_start_date}\" \\\n" \
" -d \"end_date=#{user.scheduled_charge_end_date}\" \\\n" \
" -d \"charge[customer]=#{user.customer_id}\" \\\n" \
" -d \"charge[amount]=#{user.charge_amount}\" \\\n" \
" -d \"charge[description]=Membership fee\""
end
skey = ARGV[0]
#
# Case 1: signin_date: 2018/3/15
# then, the charge starts from 2018/4/1
#
user = User.new(
sign_in_date: Date.new(2018, 3, 15),
charge_amount: 2000,
customer_id: "cust_test_5b4vkgkeal49aafdo2k"
)
Test.assert "2018-04-01", user.scheduled_charge_start_date.to_s
Test.assert "2045-08-17", user.scheduled_charge_end_date.to_s
puts create_schedule(skey, user, "25")
#
# Case 2: signin_date: 2018/3/1
# then, the charge starts from 2018/4/1
#
user = User.new(
sign_in_date: Date.new(2018, 3, 1),
charge_amount: 2000,
customer_id: "cust_test_5b4vkgkeal49aafdo2k"
)
Test.assert "2018-04-01", user.scheduled_charge_start_date.to_s
Test.assert "2045-08-17", user.scheduled_charge_end_date.to_s
puts create_schedule(skey, user, "25")
#
# Case 3: signin_date: 2018/3/31
# then, the charge starts from 2018/4/1
#
user = User.new(
sign_in_date: Date.new(2018, 3, 31),
charge_amount: 2000,
customer_id: "cust_test_5b4vkgkeal49aafdo2k"
)
Test.assert "2018-04-01", user.scheduled_charge_start_date.to_s
Test.assert "2045-08-17", user.scheduled_charge_end_date.to_s
puts create_schedule(skey, user, "25")
定期課金(Schedule)の更新
更新はできません。削除のうえ、新規に作成する必要があります
などなどです。質問はコメントからお願いします