├── .gitignore
├── react-native-paypal.gif
├── android
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── br
│ │ └── com
│ │ └── vizir
│ │ └── rn
│ │ └── paypal
│ │ ├── PayPalPackage.java
│ │ └── PayPal.java
└── build.gradle
├── index.js
├── package.json
├── .eslintrc.json
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /android/build
2 | /.tern-port
3 |
--------------------------------------------------------------------------------
/react-native-paypal.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Vizir/react-native-paypal/HEAD/react-native-paypal.gif
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var {PayPal} = require('react-native').NativeModules;
4 |
5 | var constants = {};
6 | var constantNames = Object.keys(PayPal).filter(p => p == p.toUpperCase());
7 | constantNames.forEach(c => constants[c] = PayPal[c]);
8 |
9 | var functions = {
10 | paymentRequest(payPalParameters) {
11 | return new Promise(function(resolve, reject) {
12 | PayPal.paymentRequest(payPalParameters, resolve, reject);
13 | });
14 | }
15 | };
16 |
17 | var exported = {};
18 | Object.assign(exported, constants, functions);
19 |
20 | module.exports = exported;
21 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-paypal",
3 | "version": "1.0.3",
4 | "description": "Native PayPal payment screen for React Native",
5 | "main": "index.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/vizir/react-native-paypal.git"
9 | },
10 | "keywords": [
11 | "react",
12 | "react-component",
13 | "react-native",
14 | "pay-pal",
15 | "android"
16 | ],
17 | "author": "contato@vizir.com.br",
18 | "license": "MIT",
19 | "bugs": {
20 | "url": "https://github.com/vizir/react-native-paypal/issues"
21 | },
22 | "homepage": "https://github.com/vizir/react-native-paypal"
23 | }
24 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.1"
6 |
7 | defaultConfig {
8 | minSdkVersion 16
9 | targetSdkVersion 22
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false // Set this to true to enable Proguard
16 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
17 | }
18 | }
19 | }
20 |
21 | repositories {
22 | mavenCentral()
23 | }
24 |
25 | dependencies {
26 | compile 'com.facebook.react:react-native:0.18.+'
27 | compile 'com.paypal.sdk:paypal-android-sdk:2.13.0'
28 | }
29 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "indent": [
4 | 2,
5 | 2
6 | ],
7 | "quotes": [
8 | 2,
9 | "single"
10 | ],
11 | "linebreak-style": [
12 | 2,
13 | "unix"
14 | ],
15 | "semi": [
16 | 2,
17 | "always"
18 | ]
19 | },
20 | "env": {
21 | "es6": true,
22 | "browser": false,
23 | "node": true
24 | },
25 | "extends": "eslint:recommended",
26 | "ecmaFeatures": {
27 | "jsx": true,
28 | "experimentalObjectRestSpread": true
29 | },
30 | "plugins": [
31 | "react",
32 | "react-native"
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Vizir Software Studio
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/android/src/main/java/br/com/vizir/rn/paypal/PayPalPackage.java:
--------------------------------------------------------------------------------
1 | package br.com.vizir.rn.paypal;
2 |
3 | import android.content.Intent;
4 | import android.content.Context;
5 |
6 | import com.facebook.react.ReactPackage;
7 | import com.facebook.react.bridge.JavaScriptModule;
8 | import com.facebook.react.bridge.NativeModule;
9 | import com.facebook.react.bridge.ReactApplicationContext;
10 | import com.facebook.react.uimanager.ViewManager;
11 |
12 | import java.util.ArrayList;
13 | import java.util.Collections;
14 | import java.util.List;
15 |
16 | public class PayPalPackage implements ReactPackage {
17 | private Context context;
18 | private PayPal paypalModule;
19 | private int paymentIntentRequestCode;
20 |
21 | public PayPalPackage(Context activityContext, int paymentIntentRequestCode) {
22 | context = activityContext;
23 | this.paymentIntentRequestCode = paymentIntentRequestCode;
24 | }
25 |
26 | @Override
27 | public List createNativeModules(ReactApplicationContext reactContext) {
28 | List modules = new ArrayList<>();
29 | paypalModule = new PayPal(reactContext, context, paymentIntentRequestCode);
30 |
31 | modules.add(paypalModule);
32 | return modules;
33 | }
34 |
35 | @Override
36 | public List> createJSModules() {
37 | return Collections.emptyList();
38 | }
39 |
40 | @Override
41 | public List createViewManagers(ReactApplicationContext reactContext) {
42 | return Collections.emptyList();
43 | }
44 |
45 | public void handleActivityResult(final int requestCode, final int resultCode, final Intent data) {
46 | paypalModule.handleActivityResult(requestCode, resultCode, data);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-paypal
2 |
3 | ***This project is not maintained anymore. Please have a look at https://github.com/MattFoley/react-native-paypal***
4 |
5 | A React Native interface for the PayPal Payment UI
6 |
7 | 
8 |
9 | # Setup
10 |
11 | 1. Add react-navive-paypal to your project
12 |
13 | ``` bash
14 | npm install --save react-native-paypal
15 | ```
16 |
17 | 2. Add the following to android/app/build.gradle
18 |
19 | ``` groovy
20 | dependencies {
21 | // ...
22 | compile project(':react-native-paypal')
23 | }
24 | ```
25 |
26 | 3. Add the following to android/settings.gradle
27 |
28 | ``` groovy
29 | include ':react-native-paypal'
30 | project(':react-native-paypal').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-paypal/android')
31 | ```
32 |
33 | 4. Edit android/src/.../MainActivity.java
34 |
35 | ``` java
36 | // ...
37 | import br.com.vizir.rn.paypal.PayPalPackage; // <--
38 | import br.com.vizir.rn.paypal.PayPal; // <--
39 | import android.content.Intent; // <--
40 |
41 | public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {
42 | // ...
43 | private static final int PAY_PAL_REQUEST_ID = 9; // <-- Can be any unique number
44 | private PayPalPackage payPalPackage; // <--
45 |
46 | @Override
47 | protected void onCreate(Bundle savedInstanceState) {
48 | super.onCreate(savedInstanceState);
49 | // ...
50 | payPalPackage = new PayPalPackage(this, PAY_PAL_REQUEST_ID); // <--
51 |
52 | mReactInstanceManager = ReactInstanceManager.builder()
53 | .setApplication(getApplication())
54 | .setBundleAssetName("index.android.bundle")
55 | .setJSMainModuleName("index.android")
56 | .addPackage(new MainReactPackage())
57 | // ...
58 | .addPackage(payPalPackage) // <--
59 | .setUseDeveloperSupport(BuildConfig.DEBUG)
60 | .setInitialLifecycleState(LifecycleState.RESUMED)
61 | .build();
62 | // ...
63 | }
64 |
65 | // ...
66 |
67 | @Override
68 | public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
69 | super.onActivityResult(requestCode, resultCode, data);
70 | if (requestCode == PAY_PAL_REQUEST_ID) {
71 | payPalPackage.handleActivityResult(requestCode, resultCode, data); // <--
72 | } else {
73 | otherModulesHandlers(requestCode, resultCode, data);
74 | }
75 | }
76 | }
77 | ```
78 |
79 | 5. Usage example:
80 |
81 | ```javascript
82 | var PayPal = require('react-native-paypal');
83 | PayPalAndroid.paymentRequest({
84 | clientId: 'AbyfNDFV53djg6w4yYgiug_JaDfBSUiYI7o6NM9HE1CQ_qk9XxbUX0nwcPXXQHaNAWYtDfphQtWB3q4R',
85 | environment: PayPalAndroid.SANDBOX,
86 | price: '42.00',
87 | currency: 'USD',
88 | description: 'PayPal Test'
89 | }).then((confirm, payment) => console.log('Paid'); /* MUST verify payment in server*/)
90 | .catch((error_code) => console.error('Failed to pay through PayPal'));
91 | ```
92 |
93 | 6. Callback parameters:
94 |
95 | If all goes OK with the payment than the paymentRequest promise is resolved with
96 | the following arguments as JSON strings:
97 | - A confirm:
98 | ``` json
99 | {
100 | "client": {
101 | "environment": "mock",
102 | "paypal_sdk_version": "2.12.4",
103 | "platform": "Android",
104 | "product_name": "PayPal-Android-SDK"
105 | },
106 | "response": {
107 | "create_time": "2014-02-12T22:29:49Z",
108 | "id": "PAY-6RV70583SB702805EKEYSZ6Y",
109 | "intent": "sale",
110 | "state": "approved"
111 | },
112 | "response_type": "payment"
113 | }
114 | ```
115 |
116 | - A payment:
117 | ```json
118 | {
119 | "amount": "1.00",
120 | "currency_code": "USD",
121 | "short_description": "PayPal Test",
122 | "intent": "sale"
123 | }
124 | ```
125 |
126 | Handling callbacks:
127 | ```javascript
128 | PayPal.paymentRequest(...).then(function (payment, confirm) {
129 | sendPaymentToConfirmInServer(payment, confirm);
130 | })
131 | ```
132 |
133 | If anything fails the promise will be notify an error with a code which will be
134 | one of:
135 | - USER\_CANCELLED
136 | - INVALID\_CONFIG
137 |
138 | Handling failures:
139 |
140 | ``` javascript
141 | PayPal.paymentRequest(...).catch(function (error_code) {
142 | if (error_code == PayPal.USER_CANCELLED) {
143 | // User didn't complete the payment
144 | } else if (error_code == PayPal.INVALID_CONFIG) {
145 | // Invalid config was sent to PayPal
146 | }
147 | })
148 | ```
149 |
150 | ### TODO:
151 | - Automated tests
152 | - iOS version
153 | - Future payment (subscriptions)
154 |
--------------------------------------------------------------------------------
/android/src/main/java/br/com/vizir/rn/paypal/PayPal.java:
--------------------------------------------------------------------------------
1 | package br.com.vizir.rn.paypal;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 |
7 | import com.facebook.react.bridge.Callback;
8 | import com.facebook.react.bridge.ReactApplicationContext;
9 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
10 | import com.facebook.react.bridge.ReactMethod;
11 | import com.facebook.react.bridge.ReadableMap;
12 |
13 | import com.paypal.android.sdk.payments.PayPalAuthorization;
14 | import com.paypal.android.sdk.payments.PayPalConfiguration;
15 | import com.paypal.android.sdk.payments.PayPalPayment;
16 | import com.paypal.android.sdk.payments.PayPalService;
17 | import com.paypal.android.sdk.payments.PaymentActivity;
18 | import com.paypal.android.sdk.payments.PaymentConfirmation;
19 |
20 | import java.util.Map;
21 | import java.util.HashMap;
22 | import java.math.BigDecimal;
23 |
24 | public class PayPal extends ReactContextBaseJavaModule {
25 | private final int paymentIntentRequestCode;
26 |
27 | private static final String ERROR_USER_CANCELLED = "USER_CANCELLED";
28 | private static final String ERROR_INVALID_CONFIG = "INVALID_CONFIG";
29 |
30 | private Callback successCallback;
31 | private Callback errorCallback;
32 |
33 | private Context activityContext;
34 | private Activity currentActivity;
35 |
36 | public PayPal(ReactApplicationContext reactContext, Context activityContext, int requestCode) {
37 | super(reactContext);
38 | this.activityContext = activityContext;
39 | this.currentActivity = (Activity)activityContext;
40 | this.paymentIntentRequestCode = requestCode;
41 | }
42 |
43 | @Override
44 | public String getName() {
45 | return "PayPal";
46 | }
47 |
48 | @Override public Map getConstants() {
49 | final Map constants = new HashMap<>();
50 |
51 | constants.put("NO_NETWORK", PayPalConfiguration.ENVIRONMENT_NO_NETWORK);
52 | constants.put("SANDBOX", PayPalConfiguration.ENVIRONMENT_SANDBOX);
53 | constants.put("PRODUCTION", PayPalConfiguration.ENVIRONMENT_PRODUCTION);
54 | constants.put(ERROR_USER_CANCELLED, ERROR_USER_CANCELLED);
55 | constants.put(ERROR_INVALID_CONFIG, ERROR_INVALID_CONFIG);
56 |
57 | return constants;
58 | }
59 |
60 | @ReactMethod
61 | public void paymentRequest(
62 | final ReadableMap payPalParameters,
63 | final Callback successCallback,
64 | final Callback errorCallback
65 | ) {
66 | this.successCallback = successCallback;
67 | this.errorCallback = errorCallback;
68 |
69 | final String environment = payPalParameters.getString("environment");
70 | final String clientId = payPalParameters.getString("clientId");
71 | final String price = payPalParameters.getString("price");
72 | final String currency = payPalParameters.getString("currency");
73 | final String description = payPalParameters.getString("description");
74 |
75 | PayPalConfiguration config =
76 | new PayPalConfiguration().environment(environment).clientId(clientId);
77 |
78 | startPayPalService(config);
79 |
80 | PayPalPayment thingToBuy =
81 | new PayPalPayment(new BigDecimal(price), currency, description,
82 | PayPalPayment.PAYMENT_INTENT_SALE);
83 |
84 | Intent intent =
85 | new Intent(activityContext, PaymentActivity.class)
86 | .putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config)
87 | .putExtra(PaymentActivity.EXTRA_PAYMENT, thingToBuy);
88 |
89 | currentActivity.startActivityForResult(intent, paymentIntentRequestCode);
90 | }
91 |
92 | private void startPayPalService(PayPalConfiguration config) {
93 | Intent intent = new Intent(currentActivity, PayPalService.class);
94 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
95 | currentActivity.startService(intent);
96 | }
97 |
98 | public void handleActivityResult(final int requestCode, final int resultCode, final Intent data) {
99 | if (requestCode != paymentIntentRequestCode) { return; }
100 |
101 | if (resultCode == Activity.RESULT_OK) {
102 | PaymentConfirmation confirm =
103 | data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION);
104 | if (confirm != null) {
105 | successCallback.invoke(
106 | confirm.toJSONObject().toString(),
107 | confirm.getPayment().toJSONObject().toString()
108 | );
109 | }
110 | } else if (resultCode == Activity.RESULT_CANCELED) {
111 | errorCallback.invoke(ERROR_USER_CANCELLED);
112 | } else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) {
113 | errorCallback.invoke(ERROR_INVALID_CONFIG);
114 | }
115 |
116 | currentActivity.stopService(new Intent(currentActivity, PayPalService.class));
117 | }
118 | }
119 |
--------------------------------------------------------------------------------