tang 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/tang/account/receipts_controller.rb +1 -1
- data/app/jobs/tang/import_subscriptions_job.rb +2 -5
- data/app/models/concerns/tang/customer.rb +2 -3
- data/app/models/tang/coupon.rb +1 -1
- data/app/models/tang/invoice.rb +45 -4
- data/app/models/tang/invoice_item.rb +2 -4
- data/app/models/tang/subscription.rb +20 -8
- data/app/services/tang/create_subscription.rb +3 -3
- data/app/services/tang/fail_invoice.rb +5 -0
- data/app/services/tang/pay_invoice.rb +16 -14
- data/app/views/tang/account/receipts/_receipt.html.erb +1 -1
- data/app/views/tang/admin/payments/index.html.erb +1 -1
- data/app/views/tang/admin/plans/show.html.erb +1 -1
- data/app/views/tang/admin/subscriptions/index.html.erb +1 -1
- data/config/cucumber.yml +1 -1
- data/lib/tang/version.rb +1 -1
- data/spec/fixtures/stripe_webhooks/invoice.created.json +6 -5
- data/spec/fixtures/stripe_webhooks/invoice.payment_succeeded.json +114 -0
- data/spec/requests/stripe_event_spec.rb +4 -2
- data/spec/services/tang/pay_invoice_spec.rb +7 -3
- data/spec/tang_app/app/views/layouts/application.html.erb +1 -1
- data/spec/tang_app/log/test.log +175832 -0
- data/spec/tang_app/public/packs-test/js/application-49b9b6a486f4575192e2.js +654 -0
- data/spec/tang_app/public/packs-test/js/application-49b9b6a486f4575192e2.js.map +1 -0
- data/spec/tang_app/public/packs-test/manifest.json +4 -4
- data/spec/tang_app/tmp/cache/webpacker/last-compilation-digest-test +1 -1
- metadata +14 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3b6a2435aa2257528ac4196b8e9edefe6dc12c928c62d8030890a912d2b31aff
|
4
|
+
data.tar.gz: 96ed85b8c852c51acf3c0f36d0c0e88148339c91bdb3393d7828beb44350a39a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: adf596987d7840506a8557ad4f031ef3ee2d76dd898f37203120c0999a8569d8e4518d123261667e94e01e1d7fb50ccc6574d5626be5e609a88ebdbb7df4f929
|
7
|
+
data.tar.gz: 8fe17103f00686bc4a790d6083a9cb64794ab3b29201e232b5f85472b27edfd711500e2021f144c854e51ff1f601daec7ae44638931a845181c8415fe39b4822
|
@@ -19,11 +19,8 @@ module Tang
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def import_subscription(stripe_subscription)
|
22
|
-
|
23
|
-
|
24
|
-
if customer.present? && plan.present?
|
25
|
-
subscription = Subscription.from_stripe(stripe_subscription, customer, plan)
|
26
|
-
|
22
|
+
subscription = Subscription.from_stripe(stripe_subscription)
|
23
|
+
if subscription.present?
|
27
24
|
# Handle removed discounts
|
28
25
|
subscription.update(coupon: nil, coupon_start: nil) if stripe_subscription.discount.nil?
|
29
26
|
end
|
@@ -64,9 +64,8 @@ module Tang
|
|
64
64
|
my_card.update_from_stripe(stripe_card)
|
65
65
|
end
|
66
66
|
|
67
|
-
def update_subscription_end(
|
68
|
-
|
69
|
-
self.active_until = DateTime.strptime(timestamp, '%s')
|
67
|
+
def update_subscription_end(subscription)
|
68
|
+
self.active_until = subscription.period_end
|
70
69
|
self.save!
|
71
70
|
end
|
72
71
|
|
data/app/models/tang/coupon.rb
CHANGED
@@ -76,7 +76,7 @@ module Tang
|
|
76
76
|
c.duration = stripe_coupon.duration
|
77
77
|
c.duration_in_months = stripe_coupon.duration_in_months
|
78
78
|
c.max_redemptions = stripe_coupon.max_redemptions
|
79
|
-
c.redeem_by = stripe_coupon.redeem_by
|
79
|
+
c.redeem_by = DateTime.strptime(stripe_coupon.redeem_by.to_s, '%s') if stripe_coupon.redeem_by.present?
|
80
80
|
end
|
81
81
|
|
82
82
|
return coupon
|
data/app/models/tang/invoice.rb
CHANGED
@@ -19,6 +19,10 @@ module Tang
|
|
19
19
|
self[:period_start] || created_at
|
20
20
|
end
|
21
21
|
|
22
|
+
def period_start=(val)
|
23
|
+
self[:period_start] = val
|
24
|
+
end
|
25
|
+
|
22
26
|
def period_end
|
23
27
|
if subscription.present?
|
24
28
|
self[:period_end] || subscription.plan.period_days_from(period_start)
|
@@ -27,6 +31,10 @@ module Tang
|
|
27
31
|
end
|
28
32
|
end
|
29
33
|
|
34
|
+
def period_end=(val)
|
35
|
+
self[:period_end] = val
|
36
|
+
end
|
37
|
+
|
30
38
|
def status
|
31
39
|
if charge.present?
|
32
40
|
'paid'
|
@@ -41,9 +49,9 @@ module Tang
|
|
41
49
|
invoice = Invoice.find_or_create_by(stripe_id: stripe_invoice.id) do |i|
|
42
50
|
i.subscription = subscription
|
43
51
|
i.customer = customer
|
44
|
-
i.period_start = stripe_invoice.period_start
|
45
|
-
i.period_end = stripe_invoice.period_end
|
46
|
-
i.date = stripe_invoice.created # changed from date
|
52
|
+
i.period_start = DateTime.strptime(stripe_invoice.period_start.to_s, '%s')
|
53
|
+
i.period_end = DateTime.strptime(stripe_invoice.period_end.to_s, '%s')
|
54
|
+
i.date = DateTime.strptime(stripe_invoice.created.to_s, '%s') # changed from date
|
47
55
|
i.currency = stripe_invoice.currency
|
48
56
|
i.subtotal = stripe_invoice.subtotal
|
49
57
|
# i.tax_percent = stripe_invoice.tax_percent # removed from api, replaced with tax rates
|
@@ -57,11 +65,44 @@ module Tang
|
|
57
65
|
coupon = Coupon.find_by(stripe_id: stripe_invoice.discount.coupon.id)
|
58
66
|
i.coupon = coupon
|
59
67
|
end
|
60
|
-
|
61
68
|
end
|
69
|
+
|
70
|
+
if invoice.update_from_stripe(stripe_invoice)
|
71
|
+
invoice.save
|
72
|
+
end
|
73
|
+
|
62
74
|
return invoice
|
63
75
|
end
|
64
76
|
|
77
|
+
def update_from_stripe(stripe_invoice)
|
78
|
+
changed = false
|
79
|
+
|
80
|
+
stripe_period_start = DateTime.strptime(stripe_invoice.period_start.to_s, '%s')
|
81
|
+
if self[:period_start] != stripe_period_start
|
82
|
+
self.period_start = stripe_period_start
|
83
|
+
changed = true
|
84
|
+
end
|
85
|
+
|
86
|
+
stripe_period_end = DateTime.strptime(stripe_invoice.period_end.to_s, '%s')
|
87
|
+
if self[:period_end] != stripe_period_end
|
88
|
+
self.period_end = stripe_period_end
|
89
|
+
changed = true
|
90
|
+
end
|
91
|
+
|
92
|
+
stripe_created = DateTime.strptime(stripe_invoice.created.to_s, '%s')
|
93
|
+
if self.date != stripe_created
|
94
|
+
self.date = stripe_created
|
95
|
+
changed = true
|
96
|
+
end
|
97
|
+
|
98
|
+
if self.invoice_pdf != stripe_invoice.invoice_pdf
|
99
|
+
self.invoice_pdf = stripe_invoice.invoice_pdf
|
100
|
+
changed = true
|
101
|
+
end
|
102
|
+
|
103
|
+
return changed
|
104
|
+
end
|
105
|
+
|
65
106
|
def self.search(query)
|
66
107
|
invoices = Invoice.none
|
67
108
|
if query.present?
|
@@ -27,10 +27,8 @@ module Tang
|
|
27
27
|
ii.amount = stripe_invoice_item.amount
|
28
28
|
ii.currency = stripe_invoice_item.currency
|
29
29
|
|
30
|
-
period_start = stripe_invoice_item.period.start.to_s
|
31
|
-
ii.
|
32
|
-
period_end = stripe_invoice_item.period.end.to_s
|
33
|
-
ii.period_end = DateTime.strptime(period_end, '%s')
|
30
|
+
ii.period_start = DateTime.strptime(stripe_invoice_item.period.start.to_s, '%s')
|
31
|
+
ii.period_end = DateTime.strptime(stripe_invoice_item.period.end.to_s, '%s')
|
34
32
|
|
35
33
|
ii.plan = plan
|
36
34
|
ii.proration = stripe_invoice_item.proration
|
@@ -48,14 +48,25 @@ module Tang
|
|
48
48
|
|
49
49
|
STATUSES = ['trialing', 'active', 'past_due', 'canceled', 'unpaid']
|
50
50
|
|
51
|
-
def self.from_stripe(stripe_subscription
|
51
|
+
def self.from_stripe(stripe_subscription)
|
52
|
+
customer = Tang.customer_class.find_by(stripe_id: stripe_subscription.customer)
|
53
|
+
plan = Plan.find_by(stripe_id: stripe_subscription.plan.id)
|
54
|
+
if customer.present? && plan.present?
|
55
|
+
subscription = Subscription.build(stripe_subscription, customer, plan)
|
56
|
+
subscription.update(coupon: nil, coupon_start: nil) if stripe_subscription.discount.nil?
|
57
|
+
return subscription
|
58
|
+
end
|
59
|
+
return nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.build(stripe_subscription, customer, plan)
|
52
63
|
subscription = Subscription.find_or_create_by(stripe_id: stripe_subscription.id) do |s|
|
53
64
|
s.customer = customer
|
54
65
|
s.plan = plan
|
55
66
|
s.application_fee_percent = stripe_subscription.application_fee_percent
|
56
67
|
s.quantity = stripe_subscription.quantity
|
57
68
|
# s.tax_percent = stripe_subscription.tax_percent # removed from api in favor of tax rates
|
58
|
-
s.trial_end = stripe_subscription.trial_end
|
69
|
+
s.trial_end = DateTime.strptime(stripe_subscription.trial_end.to_s, '%s') if stripe_subscription.trial_end.present?
|
59
70
|
s.coupon = Coupon.find_by(stripe_id: stripe_subscription.discount.coupon.id) if stripe_subscription.discount.present?
|
60
71
|
s.status = stripe_subscription.status
|
61
72
|
end
|
@@ -63,18 +74,19 @@ module Tang
|
|
63
74
|
end
|
64
75
|
|
65
76
|
def period_start
|
66
|
-
invoice = invoices.last
|
77
|
+
invoice = invoices.order(:date).last
|
67
78
|
if invoice.present?
|
68
|
-
return invoice.period_start
|
79
|
+
# return invoice.period_start
|
80
|
+
return invoice.date
|
69
81
|
end
|
70
82
|
return created_at
|
71
83
|
end
|
72
84
|
|
73
85
|
def period_end
|
74
|
-
invoice = invoices.last
|
75
|
-
if invoice.present?
|
76
|
-
|
77
|
-
end
|
86
|
+
# invoice = invoices.order(:period_start).last
|
87
|
+
# if invoice.present?
|
88
|
+
# return invoice.period_end
|
89
|
+
# end
|
78
90
|
return plan.period_days_from(period_start)
|
79
91
|
end
|
80
92
|
|
@@ -37,7 +37,7 @@ module Tang
|
|
37
37
|
)
|
38
38
|
|
39
39
|
# Finalize customer with subscription and payment method
|
40
|
-
finalize_customer(customer,
|
40
|
+
finalize_customer(customer, subscription, stripe_card)
|
41
41
|
|
42
42
|
rescue Stripe::StripeError => e
|
43
43
|
subscription.errors[:base] << e.message
|
@@ -87,11 +87,11 @@ module Tang
|
|
87
87
|
return stripe_sub
|
88
88
|
end
|
89
89
|
|
90
|
-
def self.finalize_customer(customer,
|
90
|
+
def self.finalize_customer(customer, subscription, stripe_card)
|
91
91
|
# Remove temporary coupon
|
92
92
|
customer.subscription_coupon = nil
|
93
93
|
# Save subscription data to customer
|
94
|
-
customer.update_subscription_end(
|
94
|
+
customer.update_subscription_end(subscription)
|
95
95
|
# Save the payment method
|
96
96
|
customer.update_card_from_stripe(stripe_card)
|
97
97
|
end
|
@@ -13,6 +13,11 @@ module Tang
|
|
13
13
|
|
14
14
|
# update subscription
|
15
15
|
subscription = Subscription.find_by(stripe_id: stripe_invoice.subscription)
|
16
|
+
if subscription.nil?
|
17
|
+
stripe_subscription = Stripe::Subscription.retrieve(stripe_invoice.subscription)
|
18
|
+
subscription = Subscription.from_stripe(stripe_subscription)
|
19
|
+
invoice.update(subscription: subscription)
|
20
|
+
end
|
16
21
|
if subscription.present?
|
17
22
|
subscription.fail! if !subscription.past_due?
|
18
23
|
end
|
@@ -1,7 +1,15 @@
|
|
1
1
|
module Tang
|
2
2
|
class PayInvoice
|
3
3
|
def self.call(stripe_invoice)
|
4
|
-
|
4
|
+
|
5
|
+
# ensure the subscription exists
|
6
|
+
stripe_subscription = Stripe::Subscription.retrieve(stripe_invoice.subscription)
|
7
|
+
subscription = Subscription.find_by(stripe_id: stripe_invoice.subscription)
|
8
|
+
if subscription.nil?
|
9
|
+
subscription = Subscription.from_stripe(stripe_subscription)
|
10
|
+
end
|
11
|
+
|
12
|
+
# create the invoice
|
5
13
|
invoice = Invoice.from_stripe(stripe_invoice)
|
6
14
|
|
7
15
|
# create charge
|
@@ -11,21 +19,15 @@ module Tang
|
|
11
19
|
charge = Charge.from_stripe(stripe_charge, invoice)
|
12
20
|
end
|
13
21
|
|
14
|
-
# update
|
15
|
-
stripe_subscription
|
16
|
-
|
17
|
-
|
18
|
-
if subscription.present?
|
19
|
-
# update discount
|
20
|
-
if stripe_subscription.discount.nil?
|
21
|
-
subscription.update(coupon: nil, coupon_start: nil)
|
22
|
-
end
|
23
|
-
|
24
|
-
# update customer active until
|
25
|
-
customer = subscription.customer
|
26
|
-
customer.update_subscription_end(stripe_subscription)
|
22
|
+
# update discount
|
23
|
+
if stripe_subscription.discount.nil?
|
24
|
+
subscription.update(coupon: nil, coupon_start: nil)
|
27
25
|
end
|
28
26
|
|
27
|
+
# update customer active until
|
28
|
+
customer = subscription.customer
|
29
|
+
customer.update_subscription_end(subscription)
|
30
|
+
|
29
31
|
return charge
|
30
32
|
end
|
31
33
|
end
|
@@ -3,5 +3,5 @@
|
|
3
3
|
<%= link_to 'Download PDF', invoice.invoice_pdf, class: 'btn btn-secondary', target: '_blank' %>
|
4
4
|
</div>
|
5
5
|
<h5 class="list-group-item-heading"><%= number_to_currency(invoice.total.to_f / 100.0) %></h5>
|
6
|
-
<p class="list-group-item-text">Date <%= invoice.
|
6
|
+
<p class="list-group-item-text">Date <%= invoice.date.strftime('%b %d, %Y') %></p>
|
7
7
|
</li>
|
@@ -22,7 +22,7 @@
|
|
22
22
|
<% end %>
|
23
23
|
</td>
|
24
24
|
<td><%= payment.stripe_id %></td>
|
25
|
-
<td><%= payment.invoice.customer.email if payment.invoice.present? %></td>
|
25
|
+
<td><%= payment.invoice.customer.email if payment.invoice.present? && payment.invoice.customer.present? %></td>
|
26
26
|
<td><%= payment.created.strftime('%Y/%m/%d %H:%M:%S') %></td>
|
27
27
|
</tr>
|
28
28
|
<% end %>
|
@@ -43,7 +43,7 @@
|
|
43
43
|
<tbody>
|
44
44
|
<% @plan.subscriptions.where(status: [:trialing, :active, :past_due]).each do |subscription| %>
|
45
45
|
<tr>
|
46
|
-
<td><%= link_to subscription.customer.email, tang.admin_subscription_path(subscription) %></td>
|
46
|
+
<td><%= link_to subscription.customer.email, tang.admin_subscription_path(subscription) if subscription.customer.present? %></td>
|
47
47
|
<td><%= subscription.status %></td>
|
48
48
|
</tr>
|
49
49
|
<% end %>
|
@@ -15,7 +15,7 @@
|
|
15
15
|
<tbody>
|
16
16
|
<% @subscriptions.each do |subscription| %>
|
17
17
|
<tr>
|
18
|
-
<td><%= link_to subscription.customer.email, tang.admin_subscription_path(subscription) %></td>
|
18
|
+
<td><%= link_to subscription.customer.email, tang.admin_subscription_path(subscription) if subscription.customer.present? %></td>
|
19
19
|
<td><%= subscription.status %></td>
|
20
20
|
<td>
|
21
21
|
<%= subscription.plan.name %>
|
data/config/cucumber.yml
CHANGED
@@ -3,6 +3,6 @@ rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
|
|
3
3
|
rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
|
4
4
|
std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags 'not @wip'"
|
5
5
|
%>
|
6
|
-
default: <%= std_opts %> features
|
6
|
+
default: <%= std_opts %> --publish-quiet features
|
7
7
|
wip: --tags @wip:3 --wip features
|
8
8
|
rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags "not @wip"
|
data/lib/tang/version.rb
CHANGED
@@ -3,7 +3,9 @@
|
|
3
3
|
"livemode": false,
|
4
4
|
"id": "evt_00000000000000",
|
5
5
|
"type": "invoice.created",
|
6
|
+
"status": "paid",
|
6
7
|
"object": "event",
|
8
|
+
"api_version": "2020-08-27",
|
7
9
|
"data": {
|
8
10
|
"object": {
|
9
11
|
"created": 1380674206,
|
@@ -30,7 +32,6 @@
|
|
30
32
|
"quantity": 1,
|
31
33
|
"plan": {
|
32
34
|
"interval": "month",
|
33
|
-
"name": "Member's Club",
|
34
35
|
"amount": 100,
|
35
36
|
"currency": "usd",
|
36
37
|
"id": "fkx0AFo",
|
@@ -38,11 +39,11 @@
|
|
38
39
|
"livemode": false,
|
39
40
|
"interval_count": 1,
|
40
41
|
"trial_period_days": null,
|
42
|
+
"product": "pr_00000000000000",
|
41
43
|
"metadata": {}
|
42
44
|
},
|
43
45
|
"description": null,
|
44
|
-
"metadata": null
|
45
|
-
"subscription": "su_00000000000000"
|
46
|
+
"metadata": null
|
46
47
|
}
|
47
48
|
]
|
48
49
|
},
|
@@ -66,8 +67,8 @@
|
|
66
67
|
"subscription": "sub_00000000000000",
|
67
68
|
"metadata": {},
|
68
69
|
"description": null,
|
69
|
-
"
|
70
|
-
"
|
70
|
+
"invoice_pdf": "https://pay.stripe.com/invoice/acct_00000000000000/invst_00000000000000/pdf",
|
71
|
+
"tax": null
|
71
72
|
}
|
72
73
|
}
|
73
74
|
}
|
@@ -0,0 +1,114 @@
|
|
1
|
+
{
|
2
|
+
"created": 1326853478,
|
3
|
+
"livemode": false,
|
4
|
+
"id": "evt_00000000000000",
|
5
|
+
"type": "invoice.payment_succeeded",
|
6
|
+
"object": "event",
|
7
|
+
"api_version": "2020-08-27",
|
8
|
+
"data": {
|
9
|
+
"object": {
|
10
|
+
"id": "in_00000000000000",
|
11
|
+
"object": "invoice",
|
12
|
+
"amount_due": 999,
|
13
|
+
"application_fee": null,
|
14
|
+
"attempt_count": 1,
|
15
|
+
"attempted": true,
|
16
|
+
"charge": "ch_18EcOcLrgDIZ7iq8TaNlErVv",
|
17
|
+
"closed": true,
|
18
|
+
"currency": "eur",
|
19
|
+
"customer": "cus_00000000000000",
|
20
|
+
"created": 1464084258,
|
21
|
+
"description": null,
|
22
|
+
"discount": null,
|
23
|
+
"ending_balance": 0,
|
24
|
+
"forgiven": false,
|
25
|
+
"lines": {
|
26
|
+
"data": [{
|
27
|
+
"id": "sub_00000000000000",
|
28
|
+
"object": "line_item",
|
29
|
+
"amount": 50,
|
30
|
+
"currency": "eur",
|
31
|
+
"description": null,
|
32
|
+
"discountable": true,
|
33
|
+
"livemode": true,
|
34
|
+
"metadata": {},
|
35
|
+
"period": {
|
36
|
+
"start": 1500637196,
|
37
|
+
"end": 1532173196
|
38
|
+
},
|
39
|
+
"plan": {
|
40
|
+
"id": "platinum",
|
41
|
+
"object": "plan",
|
42
|
+
"amount": 500,
|
43
|
+
"created": 1499943145,
|
44
|
+
"currency": "eur",
|
45
|
+
"interval": "month",
|
46
|
+
"interval_count": 1,
|
47
|
+
"livemode": false,
|
48
|
+
"metadata": {},
|
49
|
+
"name": "New Plan Test",
|
50
|
+
"statement_descriptor": null,
|
51
|
+
"trial_period_days": null
|
52
|
+
},
|
53
|
+
"proration": false,
|
54
|
+
"quantity": 1,
|
55
|
+
"subscription": null,
|
56
|
+
"subscription_item": "si_18ZfWyLrgDIZ7iq8fSlSNGIV",
|
57
|
+
"type": "subscription"
|
58
|
+
},
|
59
|
+
{
|
60
|
+
"id": "sub_00000000000000",
|
61
|
+
"object": "line_item",
|
62
|
+
"amount": 50,
|
63
|
+
"currency": "eur",
|
64
|
+
"description": null,
|
65
|
+
"discountable": true,
|
66
|
+
"livemode": true,
|
67
|
+
"metadata": {},
|
68
|
+
"period": {
|
69
|
+
"start": 1500637196,
|
70
|
+
"end": 1532173196
|
71
|
+
},
|
72
|
+
"plan": {
|
73
|
+
"id": "gold",
|
74
|
+
"object": "plan",
|
75
|
+
"amount": 300,
|
76
|
+
"created": 1499943155,
|
77
|
+
"currency": "eur",
|
78
|
+
"interval": "month",
|
79
|
+
"interval_count": 1,
|
80
|
+
"livemode": false,
|
81
|
+
"metadata": {},
|
82
|
+
"name": "New gold Plan Test",
|
83
|
+
"statement_descriptor": null,
|
84
|
+
"trial_period_days": null
|
85
|
+
},
|
86
|
+
"proration": false,
|
87
|
+
"quantity": 1,
|
88
|
+
"subscription": null,
|
89
|
+
"subscription_item": "si_18ZfWyLrgDIZ7iq8fSlSNGIV",
|
90
|
+
"type": "subscription"
|
91
|
+
}],
|
92
|
+
"total_count": 1,
|
93
|
+
"object": "list",
|
94
|
+
"url": "/v1/invoices/in_18EcOcLrgDIZ7iq8zsDkunZ0/lines"
|
95
|
+
},
|
96
|
+
"livemode": false,
|
97
|
+
"metadata": {},
|
98
|
+
"next_payment_attempt": null,
|
99
|
+
"paid": true,
|
100
|
+
"period_end": 1464084258,
|
101
|
+
"period_start": 1464084258,
|
102
|
+
"receipt_number": null,
|
103
|
+
"starting_balance": 0,
|
104
|
+
"statement_descriptor": null,
|
105
|
+
"subscription": "sub_00000000000000",
|
106
|
+
"subtotal": 999,
|
107
|
+
"tax": null,
|
108
|
+
"tax_percent": null,
|
109
|
+
"total": 999,
|
110
|
+
"webhooks_delivered_at": 1464084258,
|
111
|
+
"invoice_pdf": "https://pay.stripe.com/invoice/acct_00000000000000/invst_00000000000000/pdf"
|
112
|
+
}
|
113
|
+
}
|
114
|
+
}
|