How to get charge id after creating a subscription using Stripe?

Well there is no straight-forward way to do this. There is however a hack to get charge_id for thatsubscription with out waiting for invoice.payment_succeeded callback.

This how I did in Ruby, you can treat this as a pseudo code. May be you can do this using PHP APIs

  # Lets not retrieve all the invoices
  #  use filter
  lower_limit_date = DateTime.strptime(that_subscription.start.to_s, '%s') - 1.hour
  upper_limit_date = 2.hours.from_now

  list_object_of_all_invoices_in_range = Stripe::Invoice.all(
      {
          customer: customer_id,
          date: {
              gt: lower_limit_date.to_i, # Start TimeStamp
              lt: upper_limit_date.to_i # End TimeStamp
          }
      })

  particular_invoice = list_object_of_all_invoices_in_range.data.
      keep_if { |s| s[:subscription] == that_subscription.id }.first

  stripe_charge_id = particular_invoice.charge # gives charge_id

See structure of ListObject for Invoices

Advertisements

Stripe 30 days money back guarantee : Subscription Cancellation

Yes you can  implement 30 days (or X days) money back guarantee using stripe in your system. You need to let the  customer use all the features available in your system. And, if they want to cancel the subscription prior 31st day of the subscription then you need to have logic to handle such scenario.

In such case you need to manually calculate the prorated refund amount and make a manual refund. Stripe does not automatically make refunds on your behalf.

make a refund API call to Stripe. After refund you will have to make another API call for Subscription cancellation

Well, If you would like to cancel the subscription immediately, but keep the subscription active until the end of the billing period (e.g., through the time the customer has already paid for), provide an at_period_end value of true:

customer = Stripe::Customer.retrieve("cus_3R1W8PG2DmsmM9") 
customer.subscriptions.retrieve("sub_3R3PlB2YlJe84a").delete(:at_period_end => true)
  • Stripe sends out a customer.subscription.deleted event when a customer’s subscription is canceled immediately.
  • A customer.subscription.updated event is immediately triggered if you cancel a subscription at the end of the billing period instead, reflecting the change in the subscription’s cancel_at_period_end value. When the subscription is actually canceled at the end of the period, a customer.subscription.deleted event will occur.
  • Note: No refunds will be made; if any refund is applicable you need to manually catch the charge_object and call refund(refundable_amount) in it.
    • When you refund, refunds field in the charge object will be updated
    • If you see in stripe-dashboard; you will see the missing amount will be declared as transaction and processing fees.
    • Status:Partially Refunded
    • stripeshot

Sources

http://stackoverflow.com/questions/24790776/stripe-api-refund-after-subscription-cancelled

https://stripe.com/docs/subscriptions/guide#canceling-subscriptions

Rails : Spree : Get the gateway and other payment information

This post covers tips how you can get the payment objects related to particular order / line items.

line_item = order.line_items.first
payments = order.payments
payment = payment.first
payment_method = payment.payment_method
#<Spree::Gateway::StripeGateway:0x0000000ea51b68
payment.payment_source
=> #<Spree::CreditCard:0x0000000e795190
 id: 5,
 month: "12",
 year: "2019",
 cc_type: "visa",
 last_digits: "4242",
 address_id: nil,
 gateway_customer_profile_id: "cus_83nlvzTDq8eJln",
 gateway_payment_profile_id: "card_17ngACBFSOv6rFJZVfRZYpVT",
 created_at: Fri, 11 Mar 2016 02:38:05 UTC +00:00,

Get all charge objects

Now since Spree::Stripe uses active merchant and it creates separate customer in stripe for every order, so you can get the charge object like

Stripe::Customer.retrieve(‘cus_83nlvzTDq8eJln’).charges

Get single Charge Object

order.payments.first.response_code
# => ch_17pzjwBFSOv6rFJZBbd3YNuS

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

How to mock Stripe::Charge.retrieve using Stripe Mock gem

I created customer, made a subscription on the behalf of the customer. Along with that I generated invoices and expected in the RSpec example like

 

it 'should make sure reward amount in transaction history is equal \
    to amount added by the supporter.' do
  invoice = customer.invoices.first
  invoice.pay
  charge = Stripe::Charge.create(customer: customer.id, amount: invoice.total, currency: 'usd').to_h
  charge[:id] = invoice.charge
  charge = RStruct.new(charge)
  allow(Stripe::Charge).to receive(:retrieve).and_return(charge) # A mock object would be more useful here.
  execution
  expect(TransactionHistory.first.added_rewards).to eq(invoice.total/100.0)
end

Stripe : Callbacks Cheatsheet (Copied for reference)

Source:

Simple One-off Purchases with Charges

1. Customer successfully purchases a single one-off item

The simplest possible starting point. A single one-off purchase.

2. Customer’s card is declined

This event also describes other failure modes, like an invalid expiration date or a failed CVC check if you have the option turned on to decline on a failed check. Continue reading

Issues with Stripe : Mock and solutions

undefined method `api_key=’ for StripeMock:Module

Looks like we dont need to pass API_KEYs if everything we are going to mock everything.

Stripe::InvalidRequestError: No such plan: thepact_monthly

Create a mock plan like

plan_params = {:id => 'thepact_monthly',
               :name => 'StripeMock Default Plan ID',
               :amount => 1900,
               :currency => 'usd',
               :interval => 'month'}
stripe_helper.create_plan(plan_params)

Stripe::InvalidRequestError: You must supply a valid card xoxo

You need to pass ‘source’ attribute as well

subscription = customer.subscriptions.create(
    {
        plan: 'thepact_monthly',
        source: stripe_helper.generate_card_token({name: 'Shiva'})
    })

Stripe : Test : Webhook from one env processed by another

You often have environments like staging, qa, development which use the test secrect and publishable keys of Stripe. So you might run in situation when callbacks for one environment is responded success by another environment and it may create problem in testing.

Instead you can pass environment details in meta data and if that callback is not generated for that environment, just raise an exception.

subscription.metadata = {
                          pact_id: pact.id,
                          # To enable one env to ignore (not return 200)
                          #  for webhook event of another environment
                          app_environment: Rails.env 
                      }
subscription.save