Stripe Webhook Response - stripe-payments

Why i got Customer id and invoice id cus_0000000000000 and in_0000000000000 like these? in stripe webhook response.
I am checking my events and response in my account in this i got response 200 ok,but got customer id and invoice id got like these.why? i am checking send test webhook event at this i got response like these.
public function actionStripeHook() {
if (Yii::app()->request->isPostRequest) {
try {
$postdata = file_get_contents("php://input");
$event = json_decode($postdata);
switch ($event->type) {
case 'invoice.payment_succeeded':
Yii::log('', 'trace', 'stripe');
Yii::log('==================================', 'trace', 'stripe');
Yii::log('==== Event (' . $event->type . ') ====', 'trace', 'stripe');
Yii::log('==================================', 'trace', 'stripe');
$customer_id = $event->data->object->customer;
$customer = Stripe_Customer::retrieve($customer_id);
$invoice = Stripe_Invoice::retrieve($event->data->object->id);
}
What's Wrong in my code Its my action in Webhook endpoint in stripe,I got event type invoice.payment_succeeeed its coming from that case,but cant get customer id and invoice id correctly in my Response.why?

Nothing is wrong with your code -- the "Send test webhook" button sends a correctly formatted JSON event, but all the resources IDs are xxx_000000000.
The "Send test webhook" button is mostly useful for testing connectivity between Stripe and your webhook handler. If you want to test actual functionality, you should generate the events "organically", i.e. by sending the requests that will trigger the events you want.
For instance, to generate an invoice.payment_succeeded event, you should:
create a customer, with a valid card (e.g. 4242424242424242)
create a subscription for this customer
Upon creating the subscription, an invoice will be created and payment will be immediately attempted. If the payment is successful, then an invoice.payment_succeeded event will be emitted (with valid IDs).

Related

Creating Stripe transfers at the same time as creating Payment intent

I'm using Stripe and am trying to implement the scenario described here
The frontend is making a call to the backend that has this code
var service = new PaymentIntentService();
var createOptions = new PaymentIntentCreateOptions
{
PaymentMethodTypes = new List<string>
{
"card",
},
Amount = (long?)(payment.Amount * 100),
Currency = "EUR"
};
var result = await service.CreateAsync(createOptions);
return result.ClientSecret
In the documentation it says that the below code should be run "later" but it doesn't specify when. In my case I would prefer submitting the transfers to Stripe as soon as possible and preferably connecting them to the above payment so the transfers would be automatically handled by Stripe when the payment is done.
As I read the documentation (https://stripe.com/docs/api/transfers/create#create_transfer-source_transaction) SourceTransaction could be used for this.
var transferService = new TransferService();
var transfer1Options = new TransferCreateOptions
{
Amount = 100,
Currency = "eur",
Destination = "{{CONNECTED_STRIPE_ACCOUNT_ID}}",
SourceTransaction = result.Id
};
var transfer1 = transferService.Create(transfer1Options);
The result -variable contains a Charges -list but that is empty and when doing the above, i.e. adding the payment intent's id to SourceTransaction property, I get an error that the charge does not exist.
In the documentation it says that the below code should be run "later" but it doesn't specify when
It's whenever you are ready to make the transfer, after the payment has succeeded, essentially.
As I read the documentation (https://stripe.com/docs/api/transfers/create#create_transfer-source_transaction) SourceTransaction could be used for this.
Yep, you should definitely use source_transaction here! Otherwise the transfers won't succeed since the funds would not be available yet.
The result -variable contains a Charges -list but that is empty and when doing the above, i.e. adding the payment intent's id to SourceTransaction property, I get an error that the charge does not exist.
The value to pass to source_transaction is indeed the intent.charges.data[0].id , of a PaymentIntent that has succeeded and has a Charge.
You don't have a Charge ID because you haven't actually processed a payment yet. Creating a PaymentIntent doesn't process a payment.
You have to do the normal full PaymentIntent integration by building a form that collects payment details and 'confirms' the PaymentIntent, that's the action that processes the payment, and after that succeeds, the charges array will have a Charge in it that can be used for the transfer. For example you might create the transfer as part of handling the payment_intent.payment_succeeded webhook event.
https://stripe.com/docs/payments/accept-a-payment?platform=web&ui=elements

Stripe update subscription and add new payment method with 3d secure

I created a subscription as described on https://stripe.com/docs/billing/subscriptions/elements but now I want to give the user the choice to change the plan on the subscription and use another payment method, ex 3d Secure card. However if I update the subscription to get a client secret for a new payment intent as following:
func (c *Client) UpdateSubscription(s *models.Subscription) (*models.Subscription, error) {
sps := &stripe.SubscriptionParams{
DefaultPaymentMethod: stripe.String(s.PaymentMethodId),
CancelAtPeriodEnd: stripe.Bool(false),
ProrationBehavior: stripe.String(string(stripe.SubscriptionProrationBehaviorAlwaysInvoice)),
}
if s.CreatePaymentIntent {
s.PaymentBehavior = "allow_incomplete"
sps.PaymentBehavior = stripe.String(s.PaymentBehavior)
sps.AddExpand("latest_invoice.payment_intent")
} else if s.ItemID != "" {
sps.Items = []*stripe.SubscriptionItemsParams{
{Price: stripe.String(s.PriceID)},
{ID: stripe.String(s.ItemID), Deleted: stripe.Bool(true)},
}
}
ss, err := sub.Update(s.ID, sps)
if ss.LatestInvoice != nil && ss.LatestInvoice.PaymentIntent != nil {
s.PaymentIntentClientSecret = ss.LatestInvoice.PaymentIntent.ClientSecret
}
return s, err
}
the PaymentIntentClientSecret is the same for the subscription which means it is already processed.
Stripe 'confirm card' API is throwing error payment_intent_unexpected_state https://stripe.com/docs/error-codes/payment-intent-unexpected-state and that's probably because I used that payment intent previously to create the subscription. However I still need a new payment intent to authorise the new card.
What is the status of the PaymentIntent that you are getting these errors on?
It looks like you are properly updating the Subscription’s Price and PaymentMethod as well as creating a new Invoice for this proration. If that is the case, the Invoice may automatically be getting paid on that update. So this error might be happening because you are trying to confirm a PaymentIntent that has already successfully charged your customer.
I think it would be good to check the status of the LatestInvoice’s PaymentIntent when you get the updated Subscription object in your function.
If the status is succeeded you can simply send the customer back that updating their subscription was successful.
If the status is requires_action you should send the PaymentIntent’s client secret back to your client side and call handleCardAction[1] to allow your customer to resolve whatever action may need to be taken (3DS Auth, etc)
If the status is requires_payment_method the new card was declined and you should have your customer input new credit card info to try to update the subscription’s PaymentMethod again.
[1]https://stripe.com/docs/js/payment_intents/handle_card_action

Stripe update customer payment method

I am getting the following error message when I update a Stripe client: Error: Received unknown parameter: payment_method My code:
var customer = await stripe.customers.update(
user.stripe_id,
{payment_method: req.body.paymentMethodId}
);
How do I update a Stripe client's payment method? I tried using source, but source doesn't accept a paymentMethodId.
To update a customer’s payment method you can use invoice_settings.default_payment_method (https://stripe.com/docs/api/customers/update#update_customer-invoice_settings-default_payment_method). This sets the default PaymentMethod for the customer’s future Invoices and Subscriptions only.
If what you are trying to do is attach a new payment method to the customer than you will want to do something like this.
const paymentMethod = await stripe.paymentMethods.attach(
'pm_1IwABt2eZvKYlo2CRqildJzv',
{customer: 'cus_4QEipX9Dj5Om1P'}
);
(https://stripe.com/docs/api/payment_methods/attach)

How do I differentiate between an initial payment and a recurring one using webhooks for Stripe?

Here's a summary of what I've found in relation to the question:
https://stripe.com/docs/billing/subscriptions/overview#subscription-events
Each event object will have a type key associated with it to identify the event that has just occurred. Typically we’ll want to run a check on this to determine any actions (e.g. switch statement) & for Node implementations, it may look like this:
router.post("/webhook", bodyParser.raw({ type: "application/json" }), (req, res) => {
let event;
try {
event = req.body;
} catch (err) {
res.status(400).send("Webhook error: ${err.message}");
}
switch(event.type) {
// Subscription created
case "customer.subscription.created":
const subCreated = event.data.object;
// Do stuff, e.g. email success
break;
// Recurring payments
case "invoice.paid":
const invPaid = event.data.object;
// Do other stuff
break;
default:
return res.status(400).end();
}
res.json({ received: true });
});
Subscription Payment events:
Will trigger the invoice.created & invoice.finalized events; they occur before the payment_intent.created & payment_intent.succeeded events.
If we only want to take action on a successful payment then payment_intent.succeeded is the correct event. If we want to wait until the invoice has completed then we’d observe the invoice.paid event.
New Payments
Will create a new subscription associated with the customer and will trigger the customer.subscription.created event; this event occurs last i.e. after a payment has succeeded.
Recurring Payments
Will not trigger the above event but will move through the same lifecycle as any other subscription payment event so it would sufficient to just observe the invoice.paid event only (see the code above for the flow)
But from what I've found, the event customer.subscription.created occurs last on the initial payment, so the code I have above will run for both as multiple events are emitted for each, so how do I differentiate between the two?
Thanks!
The initial Invoice from a new subscription will have a billing_reason of subscription_create, Invoices that are created by the Subscription renewing/recurring will have a value of subscription_cycle. You can interrogate that attribute and go from there:
https://stripe.com/docs/api/invoices/object#invoice_object-billing_reason

Twilio Outbound Call API - How to place records on outbound call receiver's voicemail?

Suppose I am placing automatic call to restaurant owners for orders, if restaurant owners did not pick up the phone, I want to record the TWIML Response and place into restaurant owner's voicemail. I have seen documentation about voicemail for inbound call, but how to do for outbound call?
router.post('/voice', (request, response) => {
var parentSpeech = request.query.parentSpeech
const twiml = new VoiceResponse();
/** helper function to set up a <Gather> */
function gather() {
const gatherNode = twiml.gather({ numDigits: 1 });
gatherNode.say(parentSpeech);
// If the user doesn't enter input, loop
twiml.redirect("/twilio/voice?parentSpeech=" + parentSpeech);
}
// If the user entered digits, process their request
if (request.body.Digits) {
switch (request.body.Digits) {
case '1':
twiml.say('You have accepted the order. An email notification will be sent to you and customer shortly. Thank you for using FoodieBee and have a nice day!');
break;
case '2':
twiml.say('You have rejected the order. An email notification will be sent to you and customer shortly. Thank you for using FoodieBee and have a nice day!');
break;
default:
twiml.redirect("/twilio/voice?parentSpeech=" + parentSpeech);
break;
}
} else {
// If no input was sent, use the <Gather> verb to collect user input
gather();
}
// Render the response as XML in reply to the webhook request
response.type('text/xml');
response.send(twiml.toString());
});
Above is the code that works fine when restaurant owner pickup the phone. I am trying to place this twiml response into receiver's voicemail if they didn't pick up the phone.
Not so sure if you still need it but Param MACHINE DETECTION = DetectMessageEnd seems to be what you need.

Resources