#zishaansunderji-terminal
1 messages ยท Page 1 of 1 (latest)
Just copying your second message here:
The output for most cards come out fine - but for an Interac card has missing fields. Here are 2 transactions I ran with an Interac Debit Card:
Result: {"amount": 206, "brand": null, "cardholderName": null, "chargeId": "ch_3K9y89Fk5BSitd8b0hUQ6l0V", "clientSecret": "pi_3K9y89Fk5BSitd8b0QomLEtC_secret_ee0PO83rNpp0AIMhD056hJYsG", "country": null, "created": "2021-12-23T15:43:17GMT-05:00", "currency": "CAD", "customerId": null, "fingerprint": null, "funding": null, "generatedCardId": null, "lastFour": null, "readMethod": null, "stripeId": "pi_3K9y89Fk5BSitd8b0QomLEtC"}``` Any clues to why that's happening? The dashboard seems to pick them up just fine
Catching up, one sec...
Awesome! Thanks - I hit the 2000 character limit lol
What are the missing fields?
so brand, funding, lastFour, cardHolderName are the main ones I need
and they come out as null
they're fine for the non-Interac cards
Interesting. It looks like most of those fields are being set if the data is present
Yeah and it all goes through fine from what I can see
And when I look at that PaymentIntent, I see them
Other than cardHolderName those are all set on the PI from what I can see.
Terminal.getInstance().processPayment(collectedIntent, object :
PaymentIntentCallback {
override fun onSuccess(@Nonnull confirmedIntent: PaymentIntent) {
val intentMap = Arguments.createMap()
var currency: String? = ""
Log.wtf("Reader payment success: ", "Success!!!");
if (options != null && options.hasKey(constants.CURRENCY)) {
currency = options.getString(constants.CURRENCY)
}
intentMap.putMap(LiveFolders.INTENT, serializePaymentIntent(confirmedIntent, currency))
sendEvent(constants.EVENT_PAYMENT_CREATION, intentMap)
}
sorry for the formatting discord did - but yeah I pass the confirmedIntent which is a response after onSuccess
and it works on other cards
is there any other way I can query the payment intent id to get all that information
it looks like there is a way to retrieve the card from the customer Id and card Id but I can't find the card id when I make a request to get the information server side
Payment intent: {
id: 'pi_3K9y89Fk5BSitd8b0QomLEtC',
object: 'payment_intent',
amount: 206,
amount_capturable: 0,
amount_received: 206,
application: null,
application_fee_amount: 0,
automatic_payment_methods: null,
canceled_at: null,
cancellation_reason: null,
capture_method: 'manual',
charges: {
object: 'list',
data: [ [Object] ],
has_more: false,
total_count: 1,
url: '/v1/charges?payment_intent=pi_3K9y89Fk5BSitd8b0QomLEtC'
},
client_secret: 'pi_3K9y89Fk5BSitd8b0QomLEtC_secret_ee0PO83rNpp0AIMhD056hJYsG',
confirmation_method: 'automatic',
created: 1640292197,
currency: 'cad',
customer: 'cus_KpdOqxY0DbgOVr',
description: 'Terminal Payment at Grub on Grenville',
invoice: null,
last_payment_error: null,
livemode: true,
metadata: {},
next_action: null,
on_behalf_of: 'acct_1K9DSq2HO3lb2TKR',
payment_method: 'pm_1K9y8NFk5BSitd8bih1CtsMP',
payment_method_options: {
card: {
installments: null,
network: null,
request_three_d_secure: 'automatic'
},
card_present: {},
interac_present: {}
},
payment_method_types: [ 'card', 'card_present', 'interac_present' ],
processing: null,
receipt_email: null,
review: null,
setup_future_usage: null,
shipping: null,
source: null,
statement_descriptor: null,
statement_descriptor_suffix: null,
status: 'succeeded',
transfer_data: { destination: 'acct_1K9DSq2HO3lb2TKR' },
transfer_group: 'group_pi_3K9y89Fk5BSitd8b0QomLEtC'
}
Going through line by line but it seems like all the fields that are related to the charge are null. Is it possible there was an issue looking up the charge?
Other than the id it seems
So I should mention that I found out that we don't actually capture the card for Interac because at processPayment it's an Interac thing to capture it on it's own
so maybe it's related to that
so with other cards I capture the payment server side
but that shouldn't really affect this response - unless if i'm missing to set anything important
Payment intent: {
id: 'pi_3K9y5pFk5BSitd8b16xVTCwB',
object: 'payment_intent',
amount: 306,
amount_capturable: 0,
amount_received: 306,
application: null,
application_fee_amount: 0,
automatic_payment_methods: null,
canceled_at: null,
cancellation_reason: null,
capture_method: 'manual',
charges: {
object: 'list',
data: [ [Object] ],
has_more: false,
total_count: 1,
url: '/v1/charges?payment_intent=pi_3K9y5pFk5BSitd8b16xVTCwB'
},
client_secret: 'pi_3K9y5pFk5BSitd8b16xVTCwB_secret_y0ww7oSh1xKX4pCqRyiSBr0VZ',
confirmation_method: 'automatic',
created: 1640292053,
currency: 'cad',
customer: 'cus_KpdMEQGNNJUnEw',
description: 'Terminal Payment at Grub on Grenville',
invoice: null,
last_payment_error: null,
livemode: true,
metadata: {},
next_action: null,
on_behalf_of: 'acct_1K9DSq2HO3lb2TKR',
payment_method: 'pm_1K9y61Fk5BSitd8b0sl3hxTN',
payment_method_options: {
card: {
installments: null,
network: null,
request_three_d_secure: 'automatic'
},
card_present: {},
interac_present: {}
},
payment_method_types: [ 'card', 'card_present', 'interac_present' ],
processing: null,
receipt_email: null,
review: null,
setup_future_usage: null,
shipping: null,
source: null,
statement_descriptor: null,
statement_descriptor_suffix: null,
status: 'succeeded',
transfer_data: { destination: 'acct_1K9DSq2HO3lb2TKR' },
transfer_group: 'group_pi_3K9y5pFk5BSitd8b16xVTCwB'
}
Here's another response using the first example from above
catching up here, give me a min
sounds good!
okay it looks like I can send a request server side to fetch the payment intent information incase the response from the terminal comes back as null for the fields I need - because looking at paymentIntent.charges.data[0].payment_method_details.interac_present gives back this:
Payment intent: {
brand: 'visa',
cardholder_name: null,
country: 'CA',
emv_auth_data: '8A0230308906313534313036910A497E6723CD6608228040',
exp_month: 12,
exp_year: 2023,
fingerprint: 'pkfp6QLrjMexeCe8',
funding: 'debit',
generated_card: null,
last4: '0326',
network: 'interac',
preferred_locales: [ 'en' ],
read_method: 'contact_emv',
receipt: {
account_type: 'checking',
application_cryptogram: '4C6E43C06A77F58A',
application_preferred_name: 'Interac',
authorization_code: '154106 ',
authorization_response_code: '3030',
cardholder_verification_method: 'offline_pin',
dedicated_file_name: 'A0000002771010',
terminal_verification_results: '8080008000',
transaction_status_information: '7800'
}
}
This is a little Node JS code I wrote to make this request:
async function main() {
try {
const paymentIntent = await stripe.paymentIntents.retrieve('pi_3K9y5pFk5BSitd8b16xVTCwB');
console.log('Payment intent: ', paymentIntent.charges.data[0].payment_method_details.interac_present);
} catch (err) {
console.log('ERR: ', err);
}
}
main();
ok so mostly caught up I think, still missing a few pieces
mind resetting for me and starting from the top - you're looking at processPayment() and you get different fields set (or null) for a card_present PaymentIntent vs a interac_present PaymentIntent right?
mind sharing what those PaymentIntent IDs were for each where they were different?
There is a lot shared above so starting fresh so I don't look at the wrong things
yupp exactly
So this is the Interac present examples: pi_3K9y5pFk5BSitd8b16xVTCwB and pi_3K9y89Fk5BSitd8b0QomLEtC
and what is diff between the two?
And this is what I get with a card_present payment intent: {"amount": 206, "brand": "visa", "cardholderName": "SUNDERJI/ZISHAAN K", "chargeId": "ch_3K9zw4Fk5BSitd8b1gUibWKz", "clientSecret": "pi_3K9zw4Fk5BSitd8b1t70z8YT_secret_Of3VlXJjjrVR33JQzeNOI60N8", "country": "CA", "created": "2021-12-23T17:38:56GMT-05:00", "currency": "CAD", "customerId": null, "fingerprint": "2QJ5n3pC0Wp76Ypo", "funding": "credit", "generatedCardId": null, "lastFour": "2027", "readMethod": "contact_emv", "stripeId": "pi_3K9zw4Fk5BSitd8b1t70z8YT"}
There's basically no difference between those 2
is that your serialized output? ^above
Yuppp exactly
gotcha
okay cool
so a transaction is going through successfully after processPayment and onSuccess I start serializing the payment intent I get back
let's look at the raw deserialized PaymentIntent objects we get back from processPayment() and work from there
(looking into the PaymentIntents you shared)
ok so looked at both raw responses in the API and they do have all the fields that you saw null
e.g. brand , funding last4 etc are all present on the PaymentIntent's charge array's first Charge's payment_method_details hash
i.e. what you said here
paymentIntent.charges.data[0].payment_method_details.interac_present gives back this:
now ...
okay sorry that took sometime so this is a new transaction I did as a card present interac
and it's the raw payment intent that came back
and this is the serialized
{"amount": 206, "brand": null, "cardholderName": null, "chargeId": "ch_3KA019Fk5BSitd8b0Hermt6D", "clientSecret": "pi_3KA019Fk5BSitd8b0iBsOM3X_secret_utREGrzURPFArW2rfKVnVH7xI", "country": null, "created": "2021-12-23T17:44:11GMT-05:00", "currency": "CAD", "customerId": null, "fingerprint": null, "funding": null, "generatedCardId": null, "lastFour": null, "readMethod": null, "stripeId": "pi_3KA019Fk5BSitd8b0iBsOM3X"}
one sec, let's take it step by step
here is what I was writing:
from the SCPPaymentIntent you get back on processPayment , that should have a SCPCharge under the charges array
under which you have SCPPaymentMethodDetails
https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPPaymentMethodDetails.html
which has interacPresent which is of type SCPCardPresentDetails and it should have all those fields that you want.
So assuming the SDK does its job right, the API response should get deserialized into those fields/objects correctly
now looking at the raw PaymentIntent object you got back one sec
ok so let's focus on this:
yuppp
that file is the entire SCPPaymentIntent object, and all its sub objects
that does have brand last4 funding etc all on it
so what I said here:
So assuming the SDK does its job right, the API response should get deserialized into those fields/objects correctly
that is happening correctly
oh it's under InteracPresentDetails
so Stripe's SDK gave you an object which has all the things you need
and your serialized object does not
so basically something in your serialization code is incorrect
cuz I think my serialized object is taking the value from cardPresentDetails not InteracPresentDetails
let me check
paymentMethodDetails has 2 sub objects: https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPPaymentMethodDetails.html#/c:objc(cs)SCPPaymentMethodDetails(py)interacPresent
yupp
cardPresent vs interacPresent
gotcha - I didn't know that
makes a ton of sense
thanks a ton!! This was super helpful ๐
you need to look at a different property in your code dependent on what the type is https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPPaymentMethodDetails.html#/c:objc(cs)SCPPaymentMethodDetails(py)type
np! it is what we are here to do!
well really you'll only deal with 2 of them in Terminal
card_present and interac_present
glad to help!