-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Stripe Checkout and Customer Billing Portal support (#7)
This PR aims to close #6. In addition to Stripe Checkout and Customer Billing Portal support, it's worth noting that I also added the ability to show a List of LineItems with each invoice. This was helpful for processing `invoice.paid` webhook events.
- Loading branch information
1 parent
39682f5
commit 97cbdc0
Showing
13 changed files
with
366 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
require "../../spec_helper" | ||
|
||
describe Stripe::BillingPortal::Session do | ||
it "create billing portal session" do | ||
WebMock.stub(:post, "https://api.stripe.com/v1/billing_portal/sessions") | ||
.to_return(status: 200, body: File.read("spec/support/create_billing_portal_session.json"), headers: {"Content-Type" => "application/json"}) | ||
|
||
billing_portal_session = Stripe::BillingPortal::Session.create(customer: "cus_Ie0yEXsGjNVKMT") | ||
|
||
billing_portal_session.id.should eq("bps_1I31kfBIZW9yg15I3FuLNDpj") | ||
billing_portal_session.url.should_not be_nil | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
require "../../spec_helper" | ||
|
||
describe Stripe::Checkout::Session do | ||
it "create checkout session" do | ||
WebMock.stub(:post, "https://api.stripe.com/v1/checkout/sessions") | ||
.to_return(status: 200, body: File.read("spec/support/create_checkout_session.json"), headers: {"Content-Type" => "application/json"}) | ||
|
||
checkout_session = Stripe::Checkout::Session.create(mode: "payment", payment_method_types: ["card"], cancel_url: "https://test.com", success_url: "https://test.com", line_items: [{quantity: 1, price: "price_1234awioejawef"}]) | ||
checkout_session.id.should eq("cs_test_UlX36aKH1SdPk4Mtwp9z5S3Lkr7aIhbFbyQaCWev0aqX7mdmElg32LGr") | ||
end | ||
|
||
it "retrieve checkout session" do | ||
WebMock.stub(:get, "https://api.stripe.com/v1/checkout/sessions/asddad") | ||
.to_return(status: 200, body: File.read("spec/support/retrieve_checkout_session.json"), headers: {"Content-Type" => "application/json"}) | ||
|
||
checkout_session = Stripe::Checkout::Session.retrieve("asddad") | ||
checkout_session.id.should eq("cs_test_Kkhdy5G3NRigIiMZr198DxpXUxirwrM1xFqGEt5zk5PH3AzDy7krza7g") | ||
end | ||
|
||
it "listing checkout sessions" do | ||
WebMock.stub(:get, "https://api.stripe.com/v1/checkout/sessions") | ||
.to_return(status: 200, body: File.read("spec/support/list_checkout_sessions.json"), headers: {"Content-Type" => "application/json"}) | ||
|
||
checkout_sessions = Stripe::Checkout::Session.list | ||
checkout_sessions.first.id.should eq("cs_test_Kkhdy5G3NRigIiMZr198DxpXUxirwrM1xFqGEt5zk5PH3AzDy7krza7g") | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"id": "bps_1I31kfBIZW9yg15I3FuLNDpj", | ||
"object": "billing_portal.session", | ||
"created": 1609085149, | ||
"customer": "cus_Ie0yEXsGjNVKMT", | ||
"livemode": true, | ||
"return_url": "https://example.com/account", | ||
"url": "https://billing.stripe.com/session/{SESSION_SECRET}" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{ | ||
"id": "cs_test_UlX36aKH1SdPk4Mtwp9z5S3Lkr7aIhbFbyQaCWev0aqX7mdmElg32LGr", | ||
"object": "checkout.session", | ||
"allow_promotion_codes": null, | ||
"amount_subtotal": null, | ||
"amount_total": null, | ||
"billing_address_collection": null, | ||
"cancel_url": "https://example.com/cancel", | ||
"client_reference_id": null, | ||
"currency": null, | ||
"customer": null, | ||
"customer_email": null, | ||
"livemode": false, | ||
"locale": null, | ||
"metadata": {}, | ||
"mode": "payment", | ||
"payment_intent": "pi_1DjL5b2eZvKYlo2CPRMUEHyq", | ||
"payment_method_types": [ | ||
"card" | ||
], | ||
"payment_status": "unpaid", | ||
"setup_intent": null, | ||
"shipping": null, | ||
"shipping_address_collection": null, | ||
"submit_type": null, | ||
"subscription": null, | ||
"success_url": "https://example.com/success", | ||
"total_details": null, | ||
"line_items": [ | ||
{ | ||
"price": "price_H5ggYwtDq4fbrJ", | ||
"quantity": 2 | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
{ | ||
"object": "list", | ||
"url": "/v1/checkout/sessions", | ||
"has_more": false, | ||
"data": [ | ||
{ | ||
"id": "cs_test_Kkhdy5G3NRigIiMZr198DxpXUxirwrM1xFqGEt5zk5PH3AzDy7krza7g", | ||
"object": "checkout.session", | ||
"allow_promotion_codes": null, | ||
"amount_subtotal": null, | ||
"amount_total": null, | ||
"billing_address_collection": null, | ||
"cancel_url": "https://example.com/cancel", | ||
"client_reference_id": null, | ||
"currency": null, | ||
"customer": null, | ||
"customer_email": null, | ||
"livemode": false, | ||
"locale": null, | ||
"metadata": {}, | ||
"mode": "payment", | ||
"payment_intent": "pi_1DjL5b2eZvKYlo2CPRMUEHyq", | ||
"payment_method_types": ["card"], | ||
"payment_status": "unpaid", | ||
"setup_intent": null, | ||
"shipping": null, | ||
"shipping_address_collection": null, | ||
"submit_type": null, | ||
"subscription": null, | ||
"success_url": "https://example.com/success", | ||
"total_details": null | ||
}, | ||
{ | ||
"id": "cs_test_Kkhdy5G3NRigIiMZr198DxpXUxirwrM1xFqGEt5zk5PH3AzDy7krza7x", | ||
"object": "checkout.session", | ||
"allow_promotion_codes": null, | ||
"amount_subtotal": null, | ||
"amount_total": null, | ||
"billing_address_collection": null, | ||
"cancel_url": "https://example.com/cancel", | ||
"client_reference_id": null, | ||
"currency": null, | ||
"customer": null, | ||
"customer_email": null, | ||
"livemode": false, | ||
"locale": null, | ||
"metadata": {}, | ||
"mode": "payment", | ||
"payment_intent": "pi_1DjL5b2eZvKYlo2CPxMUEHyq", | ||
"payment_method_types": ["card"], | ||
"payment_status": "unpaid", | ||
"setup_intent": null, | ||
"shipping": null, | ||
"shipping_address_collection": null, | ||
"submit_type": null, | ||
"subscription": null, | ||
"success_url": "https://example.com/success", | ||
"total_details": null | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"id": "cs_test_Kkhdy5G3NRigIiMZr198DxpXUxirwrM1xFqGEt5zk5PH3AzDy7krza7g", | ||
"object": "checkout.session", | ||
"allow_promotion_codes": null, | ||
"amount_subtotal": null, | ||
"amount_total": null, | ||
"billing_address_collection": null, | ||
"cancel_url": "https://example.com/cancel", | ||
"client_reference_id": null, | ||
"currency": null, | ||
"customer": null, | ||
"customer_email": null, | ||
"livemode": false, | ||
"locale": null, | ||
"metadata": {}, | ||
"mode": "payment", | ||
"payment_intent": "pi_1DjL5b2eZvKYlo2CPRMUEHyq", | ||
"payment_method_types": [ | ||
"card" | ||
], | ||
"payment_status": "unpaid", | ||
"setup_intent": null, | ||
"shipping": null, | ||
"shipping_address_collection": null, | ||
"submit_type": null, | ||
"subscription": null, | ||
"success_url": "https://example.com/success", | ||
"total_details": null | ||
} |
25 changes: 25 additions & 0 deletions
25
src/stripe/methods/core/billing_portal/sessions/create_session.cr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# https://stripe.com/docs/api/customer_portal/create | ||
class Stripe::BillingPortal::Session | ||
def self.create( | ||
customer : String | Stripe::Customer, | ||
return_url : String? = nil, | ||
expand : Array(String)? = nil | ||
) : Stripe::BillingPortal::Session | ||
customer = customer.id if customer.is_a?(Customer) | ||
|
||
io = IO::Memory.new | ||
builder = ParamsBuilder.new(io) | ||
|
||
{% for x in %w(customer return_url expand) %} | ||
builder.add({{x}}, {{x.id}}) unless {{x.id}}.nil? | ||
{% end %} | ||
|
||
response = Stripe.client.post("/v1/billing_portal/sessions", form: io.to_s) | ||
|
||
if response.status_code == 200 | ||
return Stripe::BillingPortal::Session.from_json(response.body) | ||
else | ||
raise Error.from_json(response.body, "error") | ||
end | ||
end | ||
end |
31 changes: 31 additions & 0 deletions
31
src/stripe/methods/core/checkout/sessions/create_session.cr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# https://stripe.com/docs/api/checkout/sessions/create | ||
class Stripe::Checkout::Session | ||
def self.create( | ||
mode : String | Stripe::Checkout::Session::Mode, | ||
payment_method_types : Array(String), | ||
cancel_url : String, | ||
success_url : String, | ||
client_reference_id : String? = nil, | ||
customer : String? | Stripe::Customer? = nil, | ||
customer_email : String? = nil, | ||
line_items : Array(NamedTuple(quantity: Int32, price: String))? = nil, | ||
expand : Array(String)? = nil | ||
) : Stripe::Checkout::Session | ||
customer = customer.not_nil!.id if customer.is_a?(Customer) | ||
|
||
io = IO::Memory.new | ||
builder = ParamsBuilder.new(io) | ||
|
||
{% for x in %w(mode payment_method_types cancel_url success_url client_reference_id customer customer_email line_items expand) %} | ||
builder.add({{x}}, {{x.id}}) unless {{x.id}}.nil? | ||
{% end %} | ||
|
||
response = Stripe.client.post("/v1/checkout/sessions", form: io.to_s) | ||
|
||
if response.status_code == 200 | ||
return Stripe::Checkout::Session.from_json(response.body) | ||
else | ||
raise Error.from_json(response.body, "error") | ||
end | ||
end | ||
end |
25 changes: 25 additions & 0 deletions
25
src/stripe/methods/core/checkout/sessions/list_sessions.cr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# https://stripe.com/docs/api/checkout/sessions/list | ||
class Stripe::Checkout::Session | ||
def self.list( | ||
payment_intent : String? | Stripe::PaymentIntent? = nil, | ||
subscription : String? | Stripe::Subscription? = nil, | ||
limit : Int32? = nil, | ||
starting_after : String? = nil, | ||
ending_before : String? = nil | ||
) : List(Stripe::Checkout::Session) | ||
io = IO::Memory.new | ||
builder = ParamsBuilder.new(io) | ||
|
||
{% for x in %w(payment_intent subscription limit starting_after ending_before) %} | ||
builder.add({{x}}, {{x.id}}) unless {{x.id}}.nil? | ||
{% end %} | ||
|
||
response = Stripe.client.get("/v1/checkout/sessions", form: io.to_s) | ||
|
||
if response.status_code == 200 | ||
return List(Stripe::Checkout::Session).from_json(response.body) | ||
else | ||
raise Error.from_json(response.body, "error") | ||
end | ||
end | ||
end |
16 changes: 16 additions & 0 deletions
16
src/stripe/methods/core/checkout/sessions/retrieve_session.cr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# https://stripe.com/docs/api/checkout/sessions/retrieve | ||
class Stripe::Checkout::Session | ||
def self.retrieve(id : String) | ||
response = Stripe.client.get("/v1/checkout/sessions/#{id}") | ||
|
||
if response.status_code == 200 | ||
return Stripe::Checkout::Session.from_json(response.body) | ||
else | ||
raise Error.from_json(response.body, "error") | ||
end | ||
end | ||
|
||
def self.retrieve(session : Session) | ||
retrieve(session.id) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# https://stripe.com/docs/api/customer_portal | ||
class Stripe::BillingPortal::Session | ||
include JSON::Serializable | ||
|
||
getter id : String | ||
getter object : String? = "billing_portal.session" | ||
|
||
getter return_url : String | ||
|
||
getter customer : String? | Stripe::Customer? | ||
|
||
@[JSON::Field(converter: Time::EpochConverter)] | ||
getter created : Time? | ||
|
||
getter livemode : Bool? | ||
|
||
getter url : String? | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# https://stripe.com/docs/api/checkout/sessions/object | ||
class Stripe::Checkout::Session | ||
include JSON::Serializable | ||
|
||
enum Mode | ||
Payment | ||
Setup | ||
Subscription | ||
end | ||
|
||
enum PaymentStatus | ||
Paid | ||
Unpaid | ||
NoPaymentRequired | ||
end | ||
|
||
enum BillingAddressCollection | ||
Auto | ||
Required | ||
end | ||
|
||
enum SubmitType | ||
Auto | ||
Pay | ||
Book | ||
Donate | ||
end | ||
|
||
getter id : String | ||
getter object : String? = "checkout.session" | ||
|
||
@[JSON::Field(converter: Enum::StringConverter(Stripe::Checkout::Session::Mode))] | ||
getter mode : String | Mode | ||
getter payment_method_types : Array(String) | ||
|
||
getter cancel_url : String | ||
getter success_url : String | ||
|
||
getter client_reference_id : String? | ||
getter customer : String? | Stripe::Customer? | ||
getter customer_email : String? | ||
|
||
getter line_items : Array(Hash(String, String | Int32))? | ||
|
||
getter metadata : Hash(String, String)? | ||
|
||
getter payment_intent : String? | Stripe::PaymentIntent? | ||
@[JSON::Field(converter: Enum::StringConverter(Stripe::Checkout::Session::PaymentStatus))] | ||
getter payment_status : PaymentStatus | ||
|
||
getter subscription : String? | Stripe::Subscription? | ||
|
||
getter allow_promotion_codes : Bool? | ||
|
||
getter amount_subtotal : Int32? | ||
getter amount_total : Int32? | ||
|
||
@[JSON::Field(converter: Enum::StringConverter(Stripe::Checkout::Session::BillingAddressCollection))] | ||
getter billing_address_collection : BillingAddressCollection? | ||
|
||
getter currency : String? | ||
|
||
getter livemode : Bool? | ||
|
||
getter setup_intent : String? | Stripe::SetupIntent? | ||
|
||
getter shipping : Hash(String, String | Hash(String, String))? | ||
|
||
getter shipping_address_collection : Hash(String, Array(String))? | ||
|
||
@[JSON::Field(converter: Enum::StringConverter(Stripe::Checkout::Session::SubmitType))] | ||
getter submit_type : SubmitType? | ||
|
||
getter subscription : String? | Stripe::Subscription? | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters