Related
I want to use stripe payment link system, The payment method can be Card/Wallet
I dont want to use checkout button system, since the payment isnt dynamic
Once the payment is successful (auto subscription or manual checkout) I need to send the activation code to the users email. The next year when the charge is auto debited from card I need to generate the activation key again and send the same for the next year.
I see there are many events in the Stripe payment webhooks, I have used charge.succeeded event listener and it does send me the object (pasted below).
I have one issue here. If I rely on this charge.succeeded object I find no information on which product the purchase is made. There are many products in my system
The response have user supplied email but there is no way I product details in the charge.succeeded object. I have supplied the metadata info in the payment link page as below. I have also supplied the metadata in products as well as metadata in the every pricings
I use this link - https://buy.stripe.com/test_28o3cn6hC5bgdoIcMM
Test card number: 4242 4242 4242 4242
and any dates and CVV number would work.
Webhook responses are captured here - https://docs.google.com/spreadsheets/d/1RjnFnjHvs9ca8tIPoRiNHFUph_npm5pVK2S15wVllzI/edit?usp=sharing
Any help is greatly appreciated
{
"id": "evt_1KWzCbHpIo9Nhh5aYEv7XlY8",
"object": "event",
"api_version": "2017-12-14",
"created": 1645777861,
"data": {
"object": {
"id": "ch_1KWzCaHpIo9Nhh5atK09dpaO",
"object": "charge",
"amount": 100,
"amount_captured": 100,
"amount_refunded": 0,
"application": null,
"application_fee": null,
"application_fee_amount": null,
"balance_transaction": "txn_1KWzCaHpIo9Nhh5anEebLs4X",
"billing_details": {
"address": {
"city": null,
"country": "IN",
"line1": null,
"line2": null,
"postal_code": null,
"state": null
},
"email": "te...#email.com",
"name": "CARDNAME",
"phone": null
},
"calculated_statement_descriptor": "XXXXXXXXXXX",
"captured": true,
"created": 1645777860,
"currency": "inr",
"customer": "cus_LDQ2DBhL2VkPOH",
"description": "Subscription creation",
"destination": null,
"dispute": null,
"disputed": false,
"failure_code": null,
"failure_message": null,
"fraud_details": {
},
"invoice": "in_1KWzCYHpIo9Nhh5ammBkFvU1",
"livemode": false,
"metadata": {
},
"on_behalf_of": null,
"order": null,
"outcome": {
"network_status": "approved_by_network",
"reason": null,
"risk_level": "normal",
"risk_score": 58,
"seller_message": "Payment complete.",
"type": "authorized"
},
"paid": true,
"payment_intent": "pi_1KWzCYHpIo9Nhh5aj6Xgl3tS",
"payment_method": "pm_1KWzCXHpIo9Nhh5aADMKyWPc",
"payment_method_details": {
"card": {
"brand": "visa",
"checks": {
"address_line1_check": null,
"address_postal_code_check": null,
"cvc_check": "pass"
},
"country": "US",
"exp_month": 2,
"exp_year": 2022,
"fingerprint": "MxtsbEBU2BmJbOn4",
"funding": "credit",
"installments": null,
"last4": "4242",
"network": "visa",
"three_d_secure": null,
"wallet": null
},
"type": "card"
},
"receipt_email": null,
"receipt_number": null,
"receipt_url": "https://pay.stripe.com/receipts/acct_1BhpF1HpIo9Nhh5a/ch_1KWzCaHpIo9Nhh5atK09dpaO/rcpt_LDQ2FDPK6fwsEyBOISiDCItSv8JeNbl",
"refunded": false,
"refunds": {
"object": "list",
"data": [
],
"has_more": false,
"total_count": 0,
"url": "/v1/charges/ch_1KWzCaHpIo9Nhh5atK09dpaO/refunds"
},
"review": null,
"shipping": null,
"source": null,
"source_transfer": null,
"statement_descriptor": null,
"statement_descriptor_suffix": null,
"status": "succeeded",
"transfer_data": null,
"transfer_group": null
}
},
"livemode": false,
"pending_webhooks": 1,
"request": {
"id": "req_QzrolSFU0OA7D7",
"idempotency_key": "228c5670-85ea-4047-9f9f-9d1e519ffc2c"
},
"type": "charge.succeeded"
}
a Checkout Session will be generated under the hood when your customer opens a Payment Link. Therefore, you should listen to the checkout.session.completed events, and get the product data from the line_items property of the Checkout Session object.
I have had a similar problem when using a webhook solution in Stripe. Although I had defined meta data in the product it was not shipped, i.e. metadata in JSON was empty.
In my case the solution has been to use the meta data of the price instead (which is defined within the product). For this, just click price section on product page on Stripe website...
...and define meta data on the price page.
There is another interesting post https://stackoverflow.com/a/69117489/10849985 showing that it is event-depending if meta data is provided or not, i.e. some events linked to the webhook inlcude it, others not.
For me the issue was that I was merging the price and products objects together which was overwriting the metadata on the product with the empty metadata of the price object.
To fix this I just made sure the metadata was receiving the values from the product obj
const product = await stripe.products.list();
const price = await stripe.prices.list();
const productData = product.data.map((productData, index) => {
return {
...productData,
...price.data[index],
quantity: 1,
addedToCart: false,
metadata: productData.metadata };
});
My website's users will buy credits using Stripe's single-payment workflow with a checkout session. They can buy single credits or credit packages, like 10 credits package at discount price.
After a successfully payment I want to capture the event with a webhook and update the user balance according to the product and quantity paid by the user.
I'm currently tracking payment_intent.succeeded events and I can see payment and charge information however I can't find any information related to the product ordered. What am I missing? Thank you.
This is an example of the payment intent event I'm capturing:
{
"amount": 5250,
"amount_capturable": 0,
"amount_received": 5250,
"application": null,
"application_fee_amount": null,
"canceled_at": null,
"cancellation_reason": null,
"capture_method": "automatic",
"charges": {
"data": [
{
"amount": 5250,
"amount_captured": 5250,
"amount_refunded": 0,
"application": null,
"application_fee": null,
"application_fee_amount": null,
"balance_transaction": "txn_1HUSonCfZ37XLQD8mLERR2YR",
"billing_details": {
"address": {
"city": null,
"country": "JP",
"line1": null,
"line2": null,
"postal_code": null,
"state": null
},
"email": "xxxx.xxxx.xxxx#gmail.com",
"name": "asd",
"phone": null
},
"calculated_statement_descriptor": "XXX XXXX",
"captured": true,
"created": 1600847712,
"currency": "jpy",
"customer": "cus_I4c27DIUQuvAHQ",
"description": null,
"destination": null,
"dispute": null,
"disputed": false,
"failure_code": null,
"failure_message": null,
"fraud_details": {},
"id": "ch_1HUSomCfZ37XLQD8d133buOK",
"invoice": null,
"livemode": false,
"metadata": {},
"object": "charge",
"on_behalf_of": null,
"order": null,
"outcome": {
"network_status": "approved_by_network",
"reason": null,
"risk_level": "normal",
"risk_score": 39,
"seller_message": "Payment complete.",
"type": "authorized"
},
"paid": true,
"payment_intent": "pi_1HUSoWCfZ37XLQD82vnE1yQT",
"payment_method": "pm_1HUSolCfZ37XLQD8gSn0oy4x",
"payment_method_details": {
"card": {
"brand": "visa",
"checks": {
"address_line1_check": null,
"address_postal_code_check": null,
"cvc_check": "pass"
},
"country": "US",
"exp_month": 11,
"exp_year": 2050,
"fingerprint": "uaJa23vzDgA7fnSC",
"funding": "credit",
"installments": null,
"last4": "4242",
"network": "visa",
"three_d_secure": null,
"wallet": null
},
"type": "card"
},
"receipt_email": null,
"receipt_number": null,
"receipt_url": "https://pay.stripe.com/receipts/acct_1HU77uCfZ37XLQD8/ch_1HUSomCfZ37XLQD8d133buOK/rcpt_I4c233eGeSYOaN9cPvncC4AcU2Sm4s7",
"refunded": false,
"refunds": {},
"review": null,
"shipping": null,
"source": null,
"source_transfer": null,
"statement_descriptor": null,
"statement_descriptor_suffix": null,
"status": "succeeded",
"transfer_data": null,
"transfer_group": null
}
],
"has_more": false,
"object": "list",
"total_count": 1,
"url": "/v1/charges?payment_intent=pi_1HUSoWCfZ37XLQD82vnE1yQT"
},
"client_secret": "pi_1HUSoWCfZ37XLQD82vnE1yQT_secret_XXX",
"confirmation_method": "automatic",
"created": 1600847696,
"currency": "jpy",
"customer": "cus_I4c27DIUQuvAHQ",
"description": null,
"id": "pi_1HUSoWCfZ37XLQD82vnE1yQT",
"invoice": null,
"last_payment_error": null,
"livemode": false,
"metadata": {},
"next_action": null,
"object": "payment_intent",
"on_behalf_of": null,
"payment_method": "pm_1HUSolCfZ37XLQD8gSn0oy4x",
"payment_method_options": {
"card": {
"installments": null,
"network": null,
"request_three_d_secure": "automatic"
}
},
"payment_method_types": [
"card"
],
"receipt_email": null,
"review": null,
"setup_future_usage": null,
"shipping": null,
"source": null,
"statement_descriptor": null,
"statement_descriptor_suffix": null,
"status": "succeeded",
"transfer_data": null,
"transfer_group": null
}
Assuming you've put the product details in the line_items of the Checkout session you created (see guide step), then what you're looking for is how to "fulfill the order" (see guide step), which you can do by listening to checkout.session.completed events.
When you receive an event, the event data will be a Checkout session by id, and you can then retrieve that session and specify expand\[\]=line_items to be able to inspect the line_items for the session.
Update: I modified the above to reflect that line_items is not included by default. You must retrieve the session and include it in an expand.
I try to get the customer email after a payment on Checkout Stripe new interface. The JSON posted by stripe Webhook always send customer_email with null value.
The stripe Checkout page ask for customer email so I don't understand why Stripe send back this value to null.
Though, customer value is not null.
{
"id": "evt_1FItv8Kj5elW7ZcvEuY6",
"object": "event",
"api_version": "2019-03-14",
"created": 1568539286,
"data": {
"object": {
"id": "cs_test_123123123",
"object": "checkout.session",
"billing_address_collection": null,
"cancel_url": "https://www.example.fr/canceled",
"client_reference_id": null,
"customer": "cus_FoWzBx2yusHfs9",
"customer_email": null,
"display_items": [
{
"amount": 1000,
"currency": "eur",
"quantity": 1,
"sku": {
"id": "sku_1234567",
"object": "sku",
"active": true,
"attributes": {
"name": "Product test"
},
"created": 1568538814,
"currency": "eur",
"image": null,
"inventory": {
"quantity": null,
"type": "infinite",
"value": null
},
"livemode": false,
"metadata": {
},
"package_dimensions": null,
"price": 1000,
"product": "prod_FoWr00dX3",
"updated": 1568538814
},
"type": "sku"
}
],
"livemode": false,
"locale": null,
"mode": "payment",
"payment_intent": "pi_1FItj5elW70Z2",
"payment_method_types": [
"card"
],
"setup_intent": null,
"submit_type": null,
"subscription": null,
"success_url": "https://www.example.fr/success"
}
},
"livemode": false,
"pending_webhooks": 1,
"request": {
"id": null,
"idempotency_key": null
},
"type": "checkout.session.completed"
}
The email the customer entered is actually on the Customer object that the CheckoutSession links to. [0] The customer_email field is something else(it's the field that your code might have set to prefill an email into the Session).
So retrieve the Customer object from the API (cus_FoWzBx2yusHfs9) and check the email field there; or retrieve the Session object and expand the Customer field.
[0] - https://stripe.com/docs/api/customers/object#customer_object-email
I am trying to get customer_id of a stripe customer from the response of of charge entity. But response is not providing the customer id in return.
&stripe.Charge JSON: {
"id": "ch_1AxWbTFytruJp2FXW6iuRd1X",
"object": "charge",
"amount": 100,
"amount_refunded": 0,
"application": null,
"application_fee": null,
"balance_transaction": "txn_17JOXKFytruJp2FXS4XNisQd",
"captured": false,
"created": 1504339423,
"currency": "usd",
"customer": null,
"description": "My First Test Charge (created for API docs)",
"destination": null,
"dispute": null,
"failure_code": null,
"failure_message": null,
"fraud_details": {
},
"invoice": null,
"livemode": false,
"metadata": {
},
"on_behalf_of": null,
"order": null,
"outcome": null,
"paid": true,
"receipt_email": null,
"receipt_number": null,
"refunded": false,
"refunds": {
"object": "list",
"data": [
],
"has_more": false,
"total_count": 0,
"url": "/v1/charges/ch_1AxWbTFytruJp2FXW6iuRd1X/refunds"
},
"review": null,
"shipping": null,
"source": {
"id": "card_1AxWPmFytruJp2FXw4m0V0fN",
"object": "card",
"address_city": null,
"address_country": null,
"address_line1": null,
"address_line1_check": null,
"address_line2": null,
"address_state": null,
"address_zip": "10001",
"address_zip_check": "unchecked",
"brand": "Visa",
"country": "US",
"customer": null,
"cvc_check": "unchecked",
"dynamic_last4": null,
"exp_month": 4,
"exp_year": 2024,
"fingerprint": "sNtyd9sZ2vA6o4IM",
"funding": "credit",
"last4": "4242",
"metadata": {
},
"name": "Mandeep",
"tokenization_method": null
},
"source_transfer": null,
"statement_descriptor": null,
"status": "succeeded",
"transfer_group": null
}
But it has a customer field inside the object which is null. Can anyone please tell me why am I getting this null?
What I am trying to do is to make a system where customer can book anonymously on site and while creating the booking the customer gets registered and charged for the total amount of the booking. I need to keep track of the customer's stripe account id and card id. So the problem is if I am creating a customer then I am not able to get its card id but when I am charging the customer then I am not able to get the customer id.
Customer Response:
&stripe.Customer JSON: {
"id": "cus_BKAxGZre2HCNIU",
"object": "customer",
"account_balance": 0,
"created": 1504339424,
"currency": "usd",
"default_source": null,
"delinquent": false,
"description": null,
"discount": null,
"email": null,
"livemode": false,
"metadata": {
},
"shipping": null,
"sources": {
"object": "list",
"data": [
],
"has_more": false,
"total_count": 0,
"url": "/v1/customers/cus_BKAxGZre2HCNIU/sources"
},
"subscriptions": {
"object": "list",
"data": [
],
"has_more": false,
"total_count": 0,
"url": "/v1/customers/cus_BKAxGZre2HCNIU/subscriptions"
}
}
When you create a charge using only the credit card token, no Stripe customer is created, you only create a payment with no associated customer.
So it's normal that you the API returns customer: null.
Instead of charging a credit card, I think you should charge a new customer.
In your backend code, you could handle the payment in 2 steps:
STEP 1: create a new customer, passing the credit card token to store
the customer's card
STEP 2: charge the customer, using the customer ID returned by
STEP 1 API call.
Doing this, you charge the customer with the credit card that is stored in customer's data.
For more details, check here: https://stripe.com/docs/quickstart#saving-card-information
Does it make sense?
You can access card_id while creating new customer using following code (in Golang):
for _, data := range customer.Sources.Values{
card_id = data.ID
}
fmt.Println(card_id)
I spend almost 1 day to figure it out. Actually in customer structure(under stripe package) there are some fields which are having embedded types and such fields are further connected to some other structure in different files. So there is hierarchy to access structure fields like above.
Hope this will solve your problem.
Thanks!
I am using stripe to manage my transactions.
I have a need to add the customer (if not already present) and then add the card to that customer.
Now i have to get token for both processes which i did by
stripe.tokens.create({
card: {
"number": "4242424242424242",
"exp_month": "1",
"exp_year": "2019",
"cvc": "123"
}
}, function (err, token) {
// asynchronously called
if (token != null) {
//Do something
}
else {
//Do something
}
});
Now i am calling this method twice to get new token every time to add customer if not present and to add card to that customer. But every time i get same response as i am sending same information of the card.
1St
{
"id": "tok_16v4mvBR7e7FUB557PD3hOZc",
"object": "token",
"card": {
"id": "card_16v4mvBR7e7FUB55KD06kqJo",
"object": "card",
"address_city": null,
"address_country": null,
"address_line1": null,
"address_line1_check": null,
"address_line2": null,
"address_state": null,
"address_zip": null,
"address_zip_check": null,
"brand": "Diners Club",
"country": null,
"cvc_check": "unchecked",
"dynamic_last4": null,
"exp_month": 10,
"exp_year": 2021,
"fingerprint": "iE2uiiDxUFHRgpt1",
"funding": "credit",
"last4": "5904",
"metadata": {},
"name": null,
"tokenization_method": null
},
"client_ip": "51.25.52.52",
"created": 1444650501,
"livemode": false,
"type": "card",
"used": false
}
2nd
{
"id": "tok_16v4mvBR7e7FUB557PD3hOZc",
"object": "token",
"card": {
"id": "card_16v4mvBR7e7FUB55KD06kqJo",
"object": "card",
"address_city": null,
"address_country": null,
"address_line1": null,
"address_line1_check": null,
"address_line2": null,
"address_state": null,
"address_zip": null,
"address_zip_check": null,
"brand": "Diners Club",
"country": null,
"cvc_check": "unchecked",
"dynamic_last4": null,
"exp_month": 10,
"exp_year": 2021,
"fingerprint": "iE2uiiDxUFHRgpt1",
"funding": "credit",
"last4": "5904",
"metadata": {},
"name": null,
"tokenization_method": null
},
"client_ip": "55.55.55.55",
"created": 1444650501,
"livemode": false,
"type": "card",
"used": false
}
Check every field is same as first.
But if i want to use the same token which i get first time i am getting error
Stripe Error 400 - Cannot use stripe token more than once
So my question is if i am getting the same token again then why it is giving me error in using the token returned first time for adding customer and to add card for that customer.
This could increase my site speed if i do not have to get token again.
From the comments of #Matthew Arkin
I have a need to add the customer (if not already present) and then add the card to that customer.
The Business logic of stipe is such that when you ask user for credit card detail only then it will add customer so they are not different but same procedures.
The stripe Token is a way to encode the following things:
1) A bank account
2) A credit card detail
To get a token you should pass Card information for credit card like here.
Now you can get the same token using stripe.js. the good thing for using stripejs is the a token will be sent instead of a card information.
To add a customer you should supply either the token from stripe.js (or from api) or the card information. using token is what i think is best method.
When you do call stripe using token you automatically create customer with a card. hence customer cannot be created without the card information supplied to stripe.
If you want to add card to existing customer then do following:
**1) Retrieve customer passing customer id **
2) Check customer for null and then add the card for that customer obtaining a token from stripe.js