-
Notifications
You must be signed in to change notification settings - Fork 997
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add method to API that takes STPPaymentIntentParams and confirms them #986
Conversation
29867d2
to
dc9c943
Compare
9baa1b9
to
9b7bfa9
Compare
…entSecret Still needs implementation of `STPPaymentIntent description`, and better tests for decoding from JSON response
dc9c943
to
1ed8e33
Compare
9b7bfa9
to
9ea11c7
Compare
I'm omitting our normal enum to string helper methods, and instead reaching directly into the `allResponseFields` dictionary. I think this is slightly preferable, because `Unknown` enum values will be represented as the actual string value instead, which may help with debugging. Also logging the `shipping` and `nextSourceAction` fields, even though those aren't exposed by the class yet.
Adding a canceled_at time to the JSON, otherwise the test that the allResponseFields matches the json object fails - because we strip null values out.
Still missing `description` implementation and test for it
Includes functional test of the API method. Does not include analytics call
9ea11c7
to
42b009f
Compare
This also needs review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
overall looks good. Just a couple small comments
/** | ||
Confirms the PaymentIntent object with the provided params object. | ||
|
||
At a minimum, the params object must include the `clientSecret`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add docs as to what happens if it does not? completion called immediately with failure?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I want to promise/document what'll happen. This is a nonnull
property, there's an assertion that it's not nil
, and if they got past both of those I believe the web service call would happen and fail with an error.
|
||
This should be a boolean NSNumber, so that it can be `nil` | ||
*/ | ||
@property (nonatomic, strong, nullable, readwrite) NSNumber *saveSourceToCustomer; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the behavior if it is nil? Same as @no? If that's the case could this just be a bool, if not add docs describing behavior
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is important this is NSNumber
- I started with bool
because that's way friendlier, but quickly realized my mistake.
If nil
, then it leaves the PaymentIntent.save_source_to_customer
field unchanged.
If we forced it to be YES
/NO
, then the client app would have to decide what the value is, and it takes control away from their backend (or it forces the app developer to retrieve the PaymentIntent
just to read this value to prevent overwriting the existing value).
This is true of every parameter that's nullable
, and I don't think that's something that needs to be documented specifically on this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Stripe/STPAPIClient.m
Outdated
- (void)confirmPaymentIntentWithParams:(STPPaymentIntentParams *)paymentIntentParams | ||
completion:(STPPaymentIntentCompletionBlock)completion { | ||
NSString *secret = paymentIntentParams.clientSecret; | ||
NSCAssert(secret != nil, @"'secret' is required to confirm a PaymentIntent"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so is the intended behavior in release to just let the api request fail because of missing clientSecret
instead of manually short-circuiting at this point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is following the same pattern used by createSourceWithParams:
, createTokenWithParameters:
, retrieveSourceWithId:
, etc.
I think assertions may be enabled in Release builds.
ENABLE_NS_ASSERTIONS = YES |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joeydong-stripe had a similar question about the retrieve method, and it might be that we want to change the way we do this in a future PR. https://github.com/stripe/stripe-ios/pull/985/files#r201145333
#import "STPPaymentIntentParams.h" | ||
#import "STPPaymentIntent+Private.h" | ||
|
||
@implementation STPPaymentIntentParams |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll cast a vote to call this STPPaymentIntentParameters
but happy either way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better to be consistent with the other "Params" classes for Connect Account, Legal Entity, Source, Bank Account, and Card
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah noticed that later so that makes sense
Stripe/STPPaymentIntentParams.m
Outdated
- (instancetype)initWithClientSecret:(NSString *)clientSecret { | ||
self = [super init]; | ||
if (self) { | ||
_clientSecret = clientSecret; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be a copy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great catch, thanks!
|
||
#import "STPPaymentIntentParams.h" | ||
#import "STPPaymentIntent+Private.h" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find it useful to include NS_ASSUME_NONNULL_BEGIN/END in the .m files as well. It makes sure your implementation matches your interface!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that'd be a good addition to our STYLEGUIDE.md
and a nice enhancement to make.
I found very few implementation files in this project actually had it, and I didn't find any documentation about sticking it into the implementation. The stuff from Apple that I found only recommends putting it into headers.
- (void)testInit { | ||
for (STPPaymentIntentParams *params in @[[[STPPaymentIntentParams alloc] initWithClientSecret:@"secret"], | ||
[[STPPaymentIntentParams alloc] init], | ||
[STPPaymentIntentParams new], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no personal preference but mixing alloc] init]
and new]
right next to each other reads a bit weird :P
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this explicit to test that new
actually calls alloc] init]
? Seems like that's out of scope of something we need to test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intention is to verify that all the ways that an STPPaymentIntentParams
can be constructed are available, and yield an object with a non-nil clientSecret
(since nil
triggers an assert in confirm
).
I don't think it adds a lot of value here, but it's also really cheap to include.
new
sometimes behaves differently from init
in this codebase (even though it does end up calling it). I was thinking of #886 in particular, where we mark STPCard init
unavailable with the intent of preventing instantiation, but using new
is a workaround/hole.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the great review.
I think my answer to most of these is "that's the way the existing code does things", so my preference is to land as-is and write up any improvements as separate JIRAs to be prioritized against our other work, but let me know if you think any of them are high enough priority to include.
/** | ||
Confirms the PaymentIntent object with the provided params object. | ||
|
||
At a minimum, the params object must include the `clientSecret`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I want to promise/document what'll happen. This is a nonnull
property, there's an assertion that it's not nil
, and if they got past both of those I believe the web service call would happen and fail with an error.
|
||
This should be a boolean NSNumber, so that it can be `nil` | ||
*/ | ||
@property (nonatomic, strong, nullable, readwrite) NSNumber *saveSourceToCustomer; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is important this is NSNumber
- I started with bool
because that's way friendlier, but quickly realized my mistake.
If nil
, then it leaves the PaymentIntent.save_source_to_customer
field unchanged.
If we forced it to be YES
/NO
, then the client app would have to decide what the value is, and it takes control away from their backend (or it forces the app developer to retrieve the PaymentIntent
just to read this value to prevent overwriting the existing value).
This is true of every parameter that's nullable
, and I don't think that's something that needs to be documented specifically on this one.
Stripe/STPAPIClient.m
Outdated
- (void)confirmPaymentIntentWithParams:(STPPaymentIntentParams *)paymentIntentParams | ||
completion:(STPPaymentIntentCompletionBlock)completion { | ||
NSString *secret = paymentIntentParams.clientSecret; | ||
NSCAssert(secret != nil, @"'secret' is required to confirm a PaymentIntent"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is following the same pattern used by createSourceWithParams:
, createTokenWithParameters:
, retrieveSourceWithId:
, etc.
I think assertions may be enabled in Release builds.
ENABLE_NS_ASSERTIONS = YES |
Stripe/STPAPIClient.m
Outdated
- (void)confirmPaymentIntentWithParams:(STPPaymentIntentParams *)paymentIntentParams | ||
completion:(STPPaymentIntentCompletionBlock)completion { | ||
NSString *secret = paymentIntentParams.clientSecret; | ||
NSCAssert(secret != nil, @"'secret' is required to confirm a PaymentIntent"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joeydong-stripe had a similar question about the retrieve method, and it might be that we want to change the way we do this in a future PR. https://github.com/stripe/stripe-ios/pull/985/files#r201145333
|
||
#import "STPPaymentIntentParams.h" | ||
#import "STPPaymentIntent+Private.h" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that'd be a good addition to our STYLEGUIDE.md
and a nice enhancement to make.
I found very few implementation files in this project actually had it, and I didn't find any documentation about sticking it into the implementation. The stuff from Apple that I found only recommends putting it into headers.
#import "STPPaymentIntentParams.h" | ||
#import "STPPaymentIntent+Private.h" | ||
|
||
@implementation STPPaymentIntentParams |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better to be consistent with the other "Params" classes for Connect Account, Legal Entity, Source, Bank Account, and Card
Stripe/STPPaymentIntentParams.m
Outdated
- (instancetype)initWithClientSecret:(NSString *)clientSecret { | ||
self = [super init]; | ||
if (self) { | ||
_clientSecret = clientSecret; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great catch, thanks!
- (void)testInit { | ||
for (STPPaymentIntentParams *params in @[[[STPPaymentIntentParams alloc] initWithClientSecret:@"secret"], | ||
[[STPPaymentIntentParams alloc] init], | ||
[STPPaymentIntentParams new], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intention is to verify that all the ways that an STPPaymentIntentParams
can be constructed are available, and yield an object with a non-nil clientSecret
(since nil
triggers an assert in confirm
).
I don't think it adds a lot of value here, but it's also really cheap to include.
new
sometimes behaves differently from init
in this codebase (even though it does end up calling it). I was thinking of #886 in particular, where we mark STPCard init
unavailable with the intent of preventing instantiation, but using new
is a workaround/hole.
…m-paymentintent Conflicts: Stripe.xcodeproj/project.pbxproj Stripe/PublicHeaders/STPAPIClient.h Stripe/PublicHeaders/STPBlocks.h Stripe/PublicHeaders/STPPaymentIntent.h Stripe/PublicHeaders/Stripe.h Stripe/STPAPIClient.m Tests/Tests/STPPaymentIntentFunctionalTest.m
…to pass manual install test
Sounds good to me. Land away! |
Summary
Adding support for
/v1/payment_intents/:id/confirm
This method takes a STPPaymentIntentParams object, which may have STPSourceParams or a
Source id, among other fields.
Motivation
IOS-792
Testing
Added tests. This is part of a series of PRs, starting with #985 (which this relies on),
and this was also tested in the sample app.