Skip to content

Commit

Permalink
feat: add tokenizeCard method
Browse files Browse the repository at this point in the history
  • Loading branch information
mlazari committed Jan 6, 2023
1 parent 833b82c commit af56ae5
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 0 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,24 @@ BraintreeDropIn.fetchMostRecentPaymentMethod(clientToken)
});
```

### Tokenize card

```javascript
import BraintreeDropIn from 'react-native-braintree-dropin-ui';

BraintreeDropIn.tokenizeCard(clientToken, {
number: '4111111111111111',
expirationMonth: '10',
expirationYear: '23',
cvv: '123',
postalCode: '12345',
})
.then(cardNonce => console.log(cardNonce))
.catch((error) => {
// Handle error
});
```

### Custom Fonts
```
BraintreeDropIn.show({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;

import com.braintreepayments.api.BraintreeClient;
import com.braintreepayments.api.Card;
import com.braintreepayments.api.CardClient;
import com.braintreepayments.api.DropInClient;
import com.braintreepayments.api.DropInListener;
import com.braintreepayments.api.DropInPaymentMethod;
Expand Down Expand Up @@ -176,6 +179,52 @@ public void fetchMostRecentPaymentMethod(final String clientToken, final Promise
});
}

@ReactMethod
public void tokenizeCard(final String clientToken, final ReadableMap cardInfo, final Promise promise) {
if (clientToken == null) {
promise.reject("NO_CLIENT_TOKEN", "You must provide a client token");
return;
}

if (
!cardInfo.hasKey("number") ||
!cardInfo.hasKey("expirationMonth") ||
!cardInfo.hasKey("expirationYear") ||
!cardInfo.hasKey("cvv") ||
!cardInfo.hasKey("postalCode")
) {
promise.reject("INVALID_CARD_INFO", "Invalid card info");
return;
}

Activity currentActivity = getCurrentActivity();

if (currentActivity == null) {
promise.reject("NO_ACTIVITY", "There is no current activity");
return;
}

BraintreeClient braintreeClient = new BraintreeClient(getCurrentActivity(), clientToken);
CardClient cardClient = new CardClient(braintreeClient);

Card card = new Card();
card.setNumber(cardInfo.getString("number"));
card.setExpirationMonth(cardInfo.getString("expirationMonth"));
card.setExpirationYear(cardInfo.getString("expirationYear"));
card.setCvv(cardInfo.getString("cvv"));
card.setPostalCode(cardInfo.getString("postalCode"));

cardClient.tokenize(card, (cardNonce, error) -> {
if (error != null) {
promise.reject(error.getMessage(), error.getMessage());
} else if (cardNonce == null) {
promise.reject("NO_CARD_NONCE", "Card nonce is null");
} else {
promise.resolve(cardNonce.getString());
}
});
}

private void resolvePayment(DropInResult dropInResult, Promise promise) {
String deviceData = dropInResult.getDeviceData();
PaymentMethodNonce paymentMethodNonce = dropInResult.getPaymentMethodNonce();
Expand Down
9 changes: 9 additions & 0 deletions index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ type ShowOptions = {|
boldFontFamily?: string,
|};

type CardInfo = {|
number: string,
expirationMonth: string,
expirationYear: string,
cvv: string,
postalCode: string,
|};

type ShowResult = {|
nonce: string,
description: string,
Expand All @@ -30,4 +38,5 @@ type ShowResult = {|
declare module.exports: {
show: (options: ShowOptions) => Promise<ShowResult>,
fetchMostRecentPaymentMethod: (clientToken: string) => Promise<ShowResult>,
tokenizeCard: (clientToken: string, cardInfo: CardInfo) => Promise<string>,
};
35 changes: 35 additions & 0 deletions ios/RNBraintreeDropIn.m
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,41 @@ - (dispatch_queue_t)methodQueue
}];
}

RCT_EXPORT_METHOD(tokenizeCard:(NSString*)clientToken
info:(NSDictionary*)cardInfo
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
NSString *number = cardInfo[@"number"];
NSString *expirationMonth = cardInfo[@"expirationMonth"];
NSString *expirationYear = cardInfo[@"expirationYear"];
NSString *cvv = cardInfo[@"cvv"];
NSString *postalCode = cardInfo[@"postalCode"];

if (!number || !expirationMonth || !expirationYear || !cvv || !postalCode) {
reject(@"INVALID_CARD_INFO", @"Invalid card info", nil);
return;
}

BTAPIClient *braintreeClient = [[BTAPIClient alloc] initWithAuthorization:clientToken];
BTCardClient *cardClient = [[BTCardClient alloc] initWithAPIClient:braintreeClient];
BTCard *card = [[BTCard alloc] init];
card.number = number;
card.expirationMonth = expirationMonth;
card.expirationYear = expirationYear;
card.cvv = cvv;
card.postalCode = postalCode;

[cardClient tokenizeCard:card
completion:^(BTCardNonce *tokenizedCard, NSError *error) {
if (error == nil) {
resolve(tokenizedCard.nonce);
} else {
reject(@"TOKENIZE_ERROR", @"Error tokenizing card.", error);
}
}];
}

- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
didAuthorizePayment:(PKPayment *)payment
handler:(nonnull void (^)(PKPaymentAuthorizationResult * _Nonnull))completion
Expand Down

0 comments on commit af56ae5

Please sign in to comment.