Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
a924de2
Initial commit
Jun 22, 2015
63943eb
Empty project
Jun 22, 2015
1f621b6
empty class
Jun 22, 2015
69c7f39
Working implementation and example
Jun 23, 2015
245ed9d
Adding the react-component keyword
Jun 23, 2015
da2a9f1
Adding repository key
Jun 23, 2015
5adeb17
Updating package again
Jun 23, 2015
25ab41d
Directionssssss
Jun 23, 2015
85ffab0
Passing back payment confirmation details, updating test user account…
Jun 23, 2015
df4c844
More directionsssss
Jun 23, 2015
85729a1
Update README.md
Jun 23, 2015
9b879d5
Update README.md
Jun 23, 2015
b2d2432
Update README.md
Jun 24, 2015
099dc7a
Added react-native .gitignore
amiuhle Jan 13, 2016
54b4d41
Merge in MattFoley/react-native-paypal
amiuhle Jan 13, 2016
ad1336f
Android and iOS sections in README
amiuhle Jan 13, 2016
1e8f13d
Renamed ReactPaypal => ios
amiuhle Jan 13, 2016
e3714f6
Created MFLReactNativePayPal.xcodeproj
amiuhle Jan 13, 2016
0653d9b
Create license.md
Jan 13, 2016
fb64299
Rename license.md to LICENSE.md
Jan 13, 2016
bb41bde
Update LICENSE.md
Jan 13, 2016
0408873
PayPal iOS 2.13.0
amiuhle Jan 14, 2016
dbcab7c
Added PayPalMobile and CardIO
amiuhle Jan 14, 2016
e73c131
Other Linker Flags
amiuhle Jan 14, 2016
f29a992
Merge remote-tracking branch 'ios/master' into merge-ios
amiuhle Jan 14, 2016
e84d3f1
Moved license to ios folder
amiuhle Jan 14, 2016
10a81e1
Removed test project
amiuhle Jan 14, 2016
988a09a
Merge branch 'paypal-sdk' into ios
amiuhle Jan 14, 2016
f5ddd9a
Simple payment working in iOS
amiuhle Jan 14, 2016
62e9827
Updated package.json with information from deleted ios/package.json
amiuhle Jan 14, 2016
2ecfd0c
Removed ios/index.ios.js
amiuhle Jan 14, 2016
95a4831
Updated README with iOS installation instructions
amiuhle Jan 14, 2016
5ca3a94
Finished installation instructions for iOS
amiuhle Jan 14, 2016
18e20ed
Using strings for price in iOS
amiuhle Jan 15, 2016
c6e0c8d
Merge branch 'paypal-android-sdk-2.13.0' into ios
amiuhle Jan 25, 2016
a2519ae
added support for future payments
nezaidu Apr 21, 2016
ed18ce4
Merge remote-tracking branch 'zeroseven/ios' into future_payments
nezaidu Apr 27, 2016
86d6707
merged ios implementation. added future payments in ios
nezaidu Apr 27, 2016
46169ae
ios future payments now receive arguments
nezaidu Jun 10, 2016
652f4d8
minor fixes
nezaidu Aug 29, 2016
0b1daed
added method for sharing paypal profile on android
nezaidu Sep 2, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,38 @@
# OSX
#
.DS_Store

# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace

# Android/IJ
#
.idea
.gradle
local.properties

# node.js
#
node_modules/
npm-debug.log

/android/build
/android/react-native-paypal.iml
/.tern-port
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "ios/lib/Paypal"]
path = ios/lib/Paypal
url = [email protected]:paypal/PayPal-iOS-SDK.git
41 changes: 38 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ A React Native interface for the PayPal Payment UI

# Setup

Android
-------

1. Add react-navive-paypal to your project

``` bash
Expand Down Expand Up @@ -145,7 +148,39 @@ PayPal.paymentRequest(...).catch(function (error_code) {
})
```

iOS
---

### TODO:
- Automated tests
- iOS version
- Future payment (subscriptions)

* [ ] Refactor & cleanup
* [ ] Automated tests
* [ ] Future payment (subscriptions)

### Installation

Currently you have to install via `npm` from GitHub (or change the version specifier in `package.json` to `zeroseven/react-native-paypal#ios`):

```shell
npm install --save zeroseven/react-native-paypal#ios
```

#### Install the PayPal-iOS-SDK

You then have to install the PayPal-iOS-SDK into `node_modules/react-native-paypal/ios/lib/Paypal`

Here's a one-liner to download and unpack version `2.13.0`:

```shell
mkdir -p node_modules/react-native-paypal/ios/lib/Paypal && curl -L --progress https://github.com/paypal/PayPal-iOS-SDK/archive/2.13.0.tar.gz | tar -xz - -C node_modules/react-native-paypal/ios/lib/Paypal --strip-components=1
```

Include PayPal as normally, following their directions. Their integration steps and iOS SDK can be found [here](https://github.com/paypal/PayPal-iOS-SDK). After doing that, also drag MFLReactNativePayPal.h and MFLReactNativePayPal.m into your project.

#### Add `MFLReactNativePayPal.xcodeproj`

Add `node_modules/react-native-paypal/ios/MFLReactNativePayPal.xcodeproj`
to the `Libraries` group in iOS and link `libMFLReactNativePayPal.a` as described in Step 2 of the
[React Native Manual Linking docs](https://facebook.github.io/react-native/docs/linking-libraries-ios.html#manual-linking).

Follow steps 4 and 5 of [the PayPal instalation instructions](https://github.com/paypal/PayPal-iOS-SDK#if-you-dont-use-cocoapods-then), as well as the [additional steps here](https://github.com/paypal/PayPal-iOS-SDK#with-or-without-cocoapods). **This has to be done for the main app, not for the library you included.**
158 changes: 151 additions & 7 deletions android/src/main/java/br/com/vizir/rn/paypal/PayPal.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,34 @@
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;

import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.Promise;

import com.paypal.android.sdk.payments.PayPalAuthorization;
import com.paypal.android.sdk.payments.PayPalConfiguration;
import com.paypal.android.sdk.payments.PayPalPayment;
import com.paypal.android.sdk.payments.PayPalService;
import com.paypal.android.sdk.payments.PaymentActivity;
import com.paypal.android.sdk.payments.PaymentConfirmation;
import com.paypal.android.sdk.payments.PayPalFuturePaymentActivity;
import com.paypal.android.sdk.payments.PayPalProfileSharingActivity;
import com.paypal.android.sdk.payments.PayPalOAuthScopes;

import java.util.Map;
import java.util.HashMap;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class PayPal extends ReactContextBaseJavaModule {
private final int paymentIntentRequestCode;

private static final String ERROR_USER_CANCELLED = "USER_CANCELLED";
private static final String ERROR_INVALID_CONFIG = "INVALID_CONFIG";

Expand All @@ -33,11 +40,14 @@ public class PayPal extends ReactContextBaseJavaModule {
private Context activityContext;
private Activity currentActivity;

public PayPal(ReactApplicationContext reactContext, Context activityContext, int requestCode) {
private static final int REQUEST_CODE_PAYMENT = 179 + 1;
private static final int REQUEST_CODE_FUTURE_PAYMENT = 179 + 2;
private static final int REQUEST_CODE_PROFILE_SHARING = 179 + 3;

public PayPal(ReactApplicationContext reactContext, Context activityContext) {
super(reactContext);
this.activityContext = activityContext;
this.currentActivity = (Activity)activityContext;
this.paymentIntentRequestCode = requestCode;
}

@Override
Expand All @@ -57,6 +67,90 @@ public String getName() {
return constants;
}

@ReactMethod
public void getMetadataId(
final Callback successCallback,
final Callback errorCallback
) {
try {
String metadataId = PayPalConfiguration.getClientMetadataId(currentActivity);
successCallback.invoke(metadataId);
} catch (Exception e) {
errorCallback.invoke(e);
}
}

@ReactMethod
public void shareProfile(
final ReadableMap payPalParameters,
final Callback successCallback,
final Callback errorCallback
) {
this.successCallback = successCallback;
this.errorCallback = errorCallback;

final String environment = payPalParameters.getString("environment");
final String clientId = payPalParameters.getString("clientId");
final String merchantName = payPalParameters.getString("merchantName");
final String policyUri = payPalParameters.getString("policyUri");
final String agreementUri = payPalParameters.getString("agreementUri");

PayPalConfiguration config = new PayPalConfiguration()
.environment(environment)
.clientId(clientId)
.merchantName(merchantName)
.merchantPrivacyPolicyUri(Uri.parse(policyUri))
.merchantUserAgreementUri(Uri.parse(agreementUri));

// start service
Intent serviceIntent = new Intent(currentActivity, PayPalService.class);
serviceIntent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
currentActivity.startService(serviceIntent);

// // start activity
Intent activityIntent =
new Intent(activityContext, PayPalProfileSharingActivity.class)
.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config)
.putExtra(PayPalProfileSharingActivity.EXTRA_REQUESTED_SCOPES, getOauthScopes());

currentActivity.startActivityForResult(activityIntent, REQUEST_CODE_PROFILE_SHARING);
}

@ReactMethod
public void futurePayment(
final ReadableMap payPalParameters,
final Callback successCallback,
final Callback errorCallback
) {
this.successCallback = successCallback;
this.errorCallback = errorCallback;

final String environment = payPalParameters.getString("environment");
final String clientId = payPalParameters.getString("clientId");
final String merchantName = payPalParameters.getString("merchantName");
final String policyUri = payPalParameters.getString("policyUri");
final String agreementUri = payPalParameters.getString("agreementUri");

PayPalConfiguration config = new PayPalConfiguration()
.environment(environment)
.clientId(clientId)
.merchantName(merchantName)
.merchantPrivacyPolicyUri(Uri.parse(policyUri))
.merchantUserAgreementUri(Uri.parse(agreementUri));

// start service
Intent serviceIntent = new Intent(currentActivity, PayPalService.class);
serviceIntent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
currentActivity.startService(serviceIntent);

// // start activity
Intent activityIntent =
new Intent(activityContext, PayPalFuturePaymentActivity.class)
.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);

currentActivity.startActivityForResult(activityIntent, REQUEST_CODE_FUTURE_PAYMENT);
}

@ReactMethod
public void paymentRequest(
final ReadableMap payPalParameters,
Expand Down Expand Up @@ -86,7 +180,7 @@ public void paymentRequest(
.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config)
.putExtra(PaymentActivity.EXTRA_PAYMENT, thingToBuy);

currentActivity.startActivityForResult(intent, paymentIntentRequestCode);
currentActivity.startActivityForResult(intent, REQUEST_CODE_PAYMENT);
}

private void startPayPalService(PayPalConfiguration config) {
Expand All @@ -95,9 +189,47 @@ private void startPayPalService(PayPalConfiguration config) {
currentActivity.startService(intent);
}

public void handleActivityResult(final int requestCode, final int resultCode, final Intent data) {
if (requestCode != paymentIntentRequestCode) { return; }
private PayPalOAuthScopes getOauthScopes() {
/* create the set of required scopes
* Note: see https://developer.paypal.com/docs/integration/direct/identity/attributes/ for mapping between the
* attributes you select for this app in the PayPal developer portal and the scopes required here.
*/
Set<String> scopes = new HashSet<String>(
Arrays.asList(PayPalOAuthScopes.PAYPAL_SCOPE_EMAIL, PayPalOAuthScopes.PAYPAL_SCOPE_ADDRESS) );
return new PayPalOAuthScopes(scopes);
}

private void handleShareProfileActivityResult(final int resultCode, final Intent data) {
if (resultCode == Activity.RESULT_OK) {
PayPalAuthorization auth = data
.getParcelableExtra(PayPalProfileSharingActivity.EXTRA_RESULT_AUTHORIZATION);
if (auth != null) {
String authorization_code = auth.getAuthorizationCode();
successCallback.invoke(authorization_code);
}
} else if (resultCode == Activity.RESULT_CANCELED) {
errorCallback.invoke(ERROR_USER_CANCELLED);
} else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) {
errorCallback.invoke(ERROR_INVALID_CONFIG);
}
}

private void handleFutureActivityResult(final int resultCode, final Intent data) {
if (resultCode == Activity.RESULT_OK) {
PayPalAuthorization auth = data
.getParcelableExtra(PayPalFuturePaymentActivity.EXTRA_RESULT_AUTHORIZATION);
if (auth != null) {
String authorization_code = auth.getAuthorizationCode();
successCallback.invoke(authorization_code);
}
} else if (resultCode == Activity.RESULT_CANCELED) {
errorCallback.invoke(ERROR_USER_CANCELLED);
} else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) {
errorCallback.invoke(ERROR_INVALID_CONFIG);
}
}

private void handlePaymentActivityResult(final int resultCode, final Intent data) {
if (resultCode == Activity.RESULT_OK) {
PaymentConfirmation confirm =
data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION);
Expand All @@ -112,6 +244,18 @@ public void handleActivityResult(final int requestCode, final int resultCode, fi
} else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) {
errorCallback.invoke(ERROR_INVALID_CONFIG);
}
}

public void handleActivityResult(final int requestCode, final int resultCode, final Intent data) {
if (requestCode == REQUEST_CODE_FUTURE_PAYMENT) {
handleFutureActivityResult(resultCode, data);
} else if (requestCode == REQUEST_CODE_PAYMENT) {
handlePaymentActivityResult(resultCode, data);
} else if (requestCode == REQUEST_CODE_PROFILE_SHARING) {
handleShareProfileActivityResult(resultCode, data);
} else {
return;
}

currentActivity.stopService(new Intent(currentActivity, PayPalService.class));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.content.Intent;
import android.content.Context;
import android.util.Log;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
Expand All @@ -16,17 +17,15 @@
public class PayPalPackage implements ReactPackage {
private Context context;
private PayPal paypalModule;
private int paymentIntentRequestCode;

public PayPalPackage(Context activityContext, int paymentIntentRequestCode) {
public PayPalPackage(Context activityContext) {
context = activityContext;
this.paymentIntentRequestCode = paymentIntentRequestCode;
}

@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
paypalModule = new PayPal(reactContext, context, paymentIntentRequestCode);
paypalModule = new PayPal(reactContext, context);

modules.add(paypalModule);
return modules;
Expand Down
Loading