├── .github
└── ISSUE_TEMPLATE.md
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SampleApp-Kotlin
├── .gitignore
├── README.md
├── build.gradle
├── debug.keystore
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── paypal
│ │ └── example
│ │ └── paypalandroidsdkexample
│ │ └── SampleActivity.kt
│ └── res
│ ├── drawable-hdpi
│ └── ic_launcher.png
│ ├── drawable-mdpi
│ └── ic_launcher.png
│ ├── drawable-xhdpi
│ └── ic_launcher.png
│ ├── drawable-xxxhdpi
│ └── ic_launcher.png
│ ├── layout
│ └── activity_main.xml
│ ├── values-sw600dp
│ └── dimens.xml
│ ├── values-sw720dp-land
│ └── dimens.xml
│ └── values
│ ├── dimens.xml
│ └── strings.xml
├── SampleApp
├── .gitignore
├── README.md
├── build.gradle
├── debug.keystore
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── paypal
│ │ └── example
│ │ └── paypalandroidsdkexample
│ │ └── test
│ │ ├── PaymentTest.java
│ │ └── TestHelper.java
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── paypal
│ │ └── example
│ │ └── paypalandroidsdkexample
│ │ └── SampleActivity.java
│ └── res
│ ├── drawable-hdpi
│ └── ic_launcher.png
│ ├── drawable-mdpi
│ └── ic_launcher.png
│ ├── drawable-xhdpi
│ └── ic_launcher.png
│ ├── drawable-xxxhdpi
│ └── ic_launcher.png
│ ├── layout
│ └── activity_main.xml
│ ├── values-sw600dp
│ └── dimens.xml
│ ├── values-sw720dp-land
│ └── dimens.xml
│ └── values
│ ├── dimens.xml
│ └── strings.xml
├── aars
└── PayPalAndroidSDK-2.16.0.aar
├── acknowledgments.md
└── docs
├── future_payment_error_codes.md
├── future_payments_mobile.md
├── future_payments_server.md
├── ja
├── README.md
├── future_payment_error_codes.md
├── future_payments_mobile.md
├── future_payments_server.md
├── profile_sharing_mobile.md
├── profile_sharing_server.md
└── single_payment.md
├── profile_sharing_mobile.md
├── profile_sharing_server.md
├── single_payment.md
└── supplemental_errors.md
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 | ### General information
3 |
4 | * SDK/Library version:
5 | * Environment:
6 | * `PayPal-Debug-ID` values:
7 | * Android Version and Device:
8 |
9 | ### Issue description
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | PayPal Android SDK release notes
2 | ================================
3 |
4 | 2.16.0
5 | ------
6 | * Return transactionId on success [#402](https://github.com/paypal/PayPal-Android-SDK/issues/402).
7 | * Update translations.
8 | * Update SSL pinning cerificates.
9 |
10 | 2.15.3
11 | ------
12 | * Update risk-component to 3.5.7.
13 |
14 | 2.15.2
15 | ------
16 | * Add mandatory res folder in aar during release [#383](https://github.com/paypal/PayPal-Android-SDK/issues/383).
17 | * Updated card.io to 5.5.0.
18 | * Updated okhttp to 3.6.0.
19 |
20 | 2.15.1
21 | ------
22 | * Removed trustall trustmanager to resolve google play security issue [#364](https://github.com/paypal/PayPal-Android-SDK/issues/364).
23 | * Shows amount properly in all devices [#357](https://github.com/paypal/PayPal-Android-SDK/issues/357).
24 |
25 | 2.15.0
26 | ------
27 | * Add support for third-party receivers [iOS #140](https://github.com/paypal/PayPal-iOS-SDK/issues/140). Available as an optional property, `PayPalPayment.payeeEmail()`. This property is only available for PayPal payments, not Direct Credit Card (DCC) payments.
28 | * Direct Credit Card (DCC) payments are now deprecated in this SDK. Please use [Braintree Payments](https://www.braintreepayments.com/), a PayPal Company, which is the easiest way to accept PayPal, credit cards, and many other payment methods. All new integrations should [disable direct credit card payments](README.md#disabling-direct-credit-card-payments).
29 | * Update card.io to 5.4.2.
30 |
31 | 2.14.6
32 | ------
33 | * Fix issue where okhttp cannot find the `TrustManager` [#341](https://github.com/paypal/PayPal-Android-SDK/issues/341).
34 | * Update card.io to 5.4.1.
35 |
36 | 2.14.5
37 | ------
38 | * Update okhttp dependency to 3.4.1.
39 | * Fix crash when app does not have READ_PHONE_STATE permission [#321](https://github.com/paypal/PayPal-Android-SDK/issues/321).
40 |
41 | 2.14.4
42 | ------
43 | * Minor bug fixes.
44 | * Updated gradle version to 2.14.
45 | * Include `org.json.*` exceptions in default proguard file [#299](https://github.com/paypal/PayPal-Android-SDK/issues/299).
46 |
47 | 2.14.3
48 | ------
49 | * Update card.io to 5.4.0.
50 | * Update okhttp dependency to 3.3.1.
51 |
52 | 2.14.2
53 | ------
54 | * Added a new Kotlin SampleApp!
55 | * Update card.io to 5.3.4.
56 | * Update build tools.
57 |
58 | 2.14.1
59 | ------
60 | * Update card.io to 5.3.2.
61 | * Add proguard config to aar file.
62 | * Minor bug fixes.
63 |
64 | 2.14.0
65 | ------
66 | * Update `minSdkVersion` to 16. This is the minimum Android version to communicate over TLSv1.2, which is required to support [a Payment Card Industry (PCI) Council mandate](http://blog.pcisecuritystandards.org/migrating-from-ssl-and-early-tls). All organizations that handle credit card information are required to comply with this standard. As part of this obligation, [PayPal is updating its services](https://github.com/paypal/tls-update) to require TLSv1.2 for all HTTPS connections. To override the minSdkVersion, please see [the readme](README.md#override-minsdkversion).
67 | * Update okhttp dependency to 3.2.0.
68 | * Fix issue related to non-ascii characters in user agent [#271](https://github.com/paypal/PayPal-Android-SDK/issues/271).
69 |
70 | 2.13.3
71 | ------
72 | * Update okhttp dependency to 3.1.2.
73 | * Really fixes issue related to okhttp 3.1.2 [#258](https://github.com/paypal/PayPal-Android-SDK/issues/258).
74 |
75 | 2.13.2
76 | ------
77 | * Fixes issue related to okhttp 3.1.2 [#258](https://github.com/paypal/PayPal-Android-SDK/issues/258).
78 |
79 | 2.13.1
80 | ------
81 | * Fix issue preventing the SDK from app-switching to newer versions of the PayPal App.
82 |
83 | 2.13.0
84 | ------
85 | * Fix sandbox pinning issue [#228](https://github.com/paypal/PayPal-Android-SDK/issues/228).
86 | * Allow complete removal of card.io dependency, effectively disabling direct credit card payments [#226](https://github.com/paypal/PayPal-Android-SDK/issues/226) & [#234](https://github.com/paypal/PayPal-Android-SDK/issues/234).
87 | * Update okhttp dependency to 3.0.1.
88 | * Update card.io to 5.3.0.
89 |
90 | 2.12.5
91 | ------
92 | * Update okhttp dependency to 2.7.2.
93 | * Clean up manifest permissions [#233](https://github.com/paypal/PayPal-Android-SDK/issues/233).
94 | * Minor bug fixes.
95 |
96 | 2.12.4
97 | ------
98 | * Documentation Updates for Maven based integrations.
99 | * Disabled `allowBackup` in Manifest.
100 |
101 | 2.12.3
102 | ------
103 | * SDK is now available at Maven Central [#14](https://github.com/paypal/PayPal-Android-SDK/issues/14) & [#208](https://github.com/paypal/PayPal-Android-SDK/issues/208).
104 | * `com.paypal.sdk:paypal-android-sdk:2.12.3`.
105 |
106 | 2.12.2
107 | ------
108 | * Enable aar packaging.
109 | * Ability to push to maven.
110 |
111 | 2.12.1
112 | ------
113 | * Fix bug introduced in 2.12.0 that caused older devices to fail prematurely.
114 |
115 | 2.12.0
116 | ------
117 | * Allow TLSv1.2 for API 16-19 devices, and add a special error message if PayPal requires TLSv1.2 but the device cannot comply.
118 | * Add a LogCat warning during PayPalService initialization when an Android version < API 16 (JELLY_BEAN) is detected.
119 |
120 | 2.11.2
121 | ------
122 | * Minor bug fixes.
123 | * Update card.io to 5.1.2.
124 |
125 | 2.11.1
126 | ------
127 | * Fix crash in `PayPalService.onDestroy()` [#212](https://github.com/paypal/PayPal-Android-SDK/issues/212).
128 | * Fix case where shipping address selections were inadvertently displayed to the user [#213](https://github.com/paypal/PayPal-Android-SDK/issues/213).
129 | * Decrease minSdkVersion back down to 10 (GINGERBREAD_MR1).
130 | * Convert SampleApp to only use Gradle builds.
131 |
132 | 2.11.0
133 | ------
134 | * Target Android 23 (M).
135 | * Update card.io to 5.1.1 (supports new Android 23 Permissions). Note: this version of card.io contains support for more processor architectures. Please be sure to grab the entire contents of this SDK, including all up-to-date card.io `*.so` files within the `/libs` folder to ensure that card.io will continue to work on these architectures.
136 | * Increase minSdkVersion to 11 (HONEYCOMB).
137 | * Update all networking to use HttpURLConnection instead of Apache's HTTP Client.
138 | * Set all obfuscated classes to use lower case as a workaround for [an Android Tools issue](https://code.google.com/p/android/issues/detail?id=187210).
139 |
140 | 2.10.1
141 | ------
142 | * Minor bug fixes.
143 |
144 | 2.10.0
145 | ------
146 | * Fixed behavior where `retrieve_shipping_address ` is disabled and no `shipping address` is provided from the app, so it will not default to the PayPal account `shipping address`.
147 |
148 | 2.9.11
149 | ------
150 | * Minor bug fixes.
151 |
152 | 2.9.10
153 | ------
154 | * Minor bug fixes.
155 |
156 | 2.9.9
157 | -----
158 | * Fix rare crash when making a single payment [#179](https://github.com/paypal/PayPal-Android-SDK/issues/179).
159 | * Minor bug fixes.
160 |
161 | 2.9.8
162 | -----
163 | * Fix rare crash in `PayPalService` [#166](https://github.com/paypal/PayPal-Android-SDK/issues/166).
164 | * Minor bug fixes.
165 |
166 | 2.9.7
167 | -----
168 | * Fix rare instance of PAYMENT_CREATION_ERROR.
169 | * Fix rare crashing issue on some devices when checking permissions [#167](https://github.com/paypal/PayPal-Android-SDK/issues/167).
170 | * Upgrade build tools.
171 |
172 | 2.9.6
173 | -----
174 | * Fix issue where card.io compatibility was being checked even if credit cards are disabled [#173](https://github.com/paypal/PayPal-Android-SDK/issues/173).
175 | * Update card.io to 5.0.1.
176 |
177 | 2.9.5
178 | -----
179 | * Update sample app build tools version to 1.2.2, compileSdkVersion to 22, and build tools version to 22.0.1.
180 | * Minor bug fixes to the consent screen.
181 |
182 | 2.9.4
183 | -----
184 | * Fix rare NPE issue [#163](https://github.com/paypal/PayPal-Android-SDK/issues/163).
185 |
186 | 2.9.3
187 | -----
188 | * Remove dependency on the [Android Support Library](http://developer.android.com/tools/support-library/index.html).
189 | * Fix NoClassDefFoundError issue with AdvertisingIdClient [#157](https://github.com/paypal/PayPal-Android-SDK/issues/157).
190 | * Fix ClassCastException issue with GsmCellLocation [#160](https://github.com/paypal/PayPal-Android-SDK/issues/160).
191 | * Minor bug fixes.
192 |
193 | 2.9.2
194 | -----
195 | * Minor bug fixes.
196 |
197 | 2.9.1
198 | -----
199 | * Fix crashing issue on Android `2.3.*` devices [#159](https://github.com/paypal/PayPal-Android-SDK/issues/159).
200 | * Fix `PayPalService.clearAllUserData()` to clear all environments when `PayPalService` is not running [#155](https://github.com/paypal/PayPal-Android-SDK/issues/155). If `PayPalService` is running, the v4 support library is still required to clear the current user data.
201 | * Fix issue with `PayPalService.clearAllUserData()` not actually clearing the current user [#156](https://github.com/paypal/PayPal-Android-SDK/issues/156).
202 | * Add some helpful logging to `PayPalService.clearAllUserData()`.
203 | * Minor bug fixes.
204 |
205 | 2.9.0
206 | -----
207 | * Add `PayPalService.clearAllUserData(Context)` [#88](https://github.com/paypal/PayPal-Android-SDK/issues/88). Note: this method requires the use of the [Android Support Library](http://developer.android.com/tools/support-library/index.html), due to its use of `LocalBroadcastManager`. This SDK can still be used without the support library, but this method will not function.
208 | * Fix validation of `PayPalItem`: `sku` is no longer required, currencies and amounts have more strict validation [#153](https://github.com/paypal/PayPal-Android-SDK/issues/153).
209 | * Fix issue where too many profile sharing attributes were shown to the user.
210 | * Change name of `ENVIRONMENT_NO_NETWORK` merchant.
211 | * Minor bug fixes.
212 |
213 | 2.8.8
214 | -----
215 | * Change "Send Payment" button to "Pay". (see https://github.com/paypal/PayPal-iOS-SDK/issues/174).
216 | * Minor bug fixes.
217 | * Update card.io to 5.0.0.
218 |
219 | 2.8.7
220 | -----
221 | * Enforce required permissions: `ACCESS_NETWORK_STATE` and `INTERNET`.
222 | * Gracefully handle devices that do not return network state.
223 | * Better null handling.
224 |
225 | 2.8.6
226 | -----
227 | * Update card.io to 4.0.1.
228 | * Add button allowing user to create a new PayPal account.
229 | * Add more public logging.
230 | * Minor UI tweaks.
231 |
232 | 2.8.5
233 | -----
234 | * Update card.io to 4.0.0.
235 | * Update sample app build tools version to 1.0.1.
236 | * Minor bug fixes.
237 |
238 | 2.8.4
239 | -----
240 | * Fix issue where resource is not properly closed [#125](https://github.com/paypal/PayPal-Android-SDK/issues/125).
241 | * Add even better error messages in all locales.
242 |
243 | 2.8.3
244 | -----
245 | * Fix ClassNotFoundException issue in Parcelable classes.
246 | * Add better error messages for some common errors.
247 | * Minor bug fixes.
248 | * Fix several docs and SampleApp issues.
249 |
250 | 2.8.2
251 | -----
252 | * Fix consent privacy policy and user agreement links, and update the mock link urls.
253 | * Fix issue where the service would not properly restart after being backgrounded [#117](https://github.com/paypal/PayPal-Android-SDK/issues/117).
254 | It is now recommended that developers pass the `PayPalConfiguration` object into the PayPal activities, in addition to `PayPalService`.
255 | Update the documentation and sample app with the suggested modifications.
256 | * Add documentation on correct `httpcomponents` dependencies, which addresses [#113](https://github.com/paypal/PayPal-Android-SDK/issues/113).
257 | * Update Visa branding.
258 | * Minor bug fixes.
259 |
260 | 2.8.1
261 | -----
262 | * Fix issue where consent was not working for new users (bug introduced in 2.8.0).
263 | * Remove unneeded ACCESS_WIFI_STATE from integration docs.
264 | * Update sample app build tools version to 1.0.0.
265 |
266 | 2.8.0
267 | -----
268 | * Allow login by users who have enabled two-factor authentication on their PayPal accounts.
269 | * Update `Paypal-Application-Correlation-Id` header to `PayPal-Client-Metadata-Id`,
270 | and deprecate `PayPalConfiguration.getApplicationCorrelationId()` in favor
271 | of `PayPalConfiguration.getClientMetadataId()`.
272 | * Update sample app build tools version.
273 | * Minor bug fixes.
274 |
275 | 2.7.3
276 | -----
277 | * Fix single payments issue affecting cross-app integrations.
278 |
279 | 2.7.2
280 | -----
281 | * Add additional logging for exceptions on threads.
282 | * Update sample app gradle wrapper to 2.2.1.
283 | * Update sample app build tools version.
284 |
285 | 2.7.1
286 | -----
287 | * Fix validation issue related to android:process [#114](https://github.com/paypal/PayPal-Android-SDK/issues/114).
288 | * Minor bug fixes.
289 | * Update sample app build tools version.
290 | * Remove some old files.
291 |
292 | 2.7.0
293 | -----
294 | * Add support for Russian Rubles.
295 | * Add gradle files to Sample App.
296 | * Minor fixes to the Consent Activity.
297 |
298 | 2.6.1
299 | -----
300 | * Minor improvements relevant only to select partners.
301 | * Minor bug fixes.
302 |
303 | 2.6.0
304 | -----
305 | * Streamline Profile Sharing for cases where a user has previously authorized sharing.
306 | * Update card.io library to 3.2.0.
307 | * Update all targets to android-21.
308 | * Minor bug fixes.
309 |
310 | 2.5.6
311 | -----
312 | * Minor bug fixes.
313 |
314 | 2.5.5
315 | -----
316 | * Fix issue with some PayPal Credit funding instruments [#97](https://github.com/paypal/PayPal-Android-SDK/issues/97).
317 |
318 | 2.5.4
319 | -----
320 | * Fix issue that kept some apps from authorizing properly.
321 | * The SDK now rejects fractional amounts for HUF, JPY, TWD currencies (previously fractional amounts were rounded).
322 |
323 |
324 | 2.5.3
325 | -----
326 | * Update card.io library (adds Diners Club and China UnionPay support).
327 | * Fix Cursor not closing problem reported in Strict mode [#87](https://github.com/paypal/PayPal-Android-SDK/issues/87).
328 | * Minor bug fixes.
329 |
330 | 2.5.2
331 | -----
332 | * Update Sample App icons.
333 | * Minor bug fixes.
334 |
335 | 2.5.1
336 | -----
337 | * Fix layout xml issue in SampleApp [#89](https://github.com/paypal/PayPal-Android-SDK/issues/89).
338 |
339 | 2.5.0
340 | -----
341 | * Add support for payment intent value `order` to create a payment for later authorization and capture via server calls.
342 | * For single payments, an individual `PayPalItem` may be negative (for discounts, coupons, etc.).
343 | * Add `invoiceNumber`, `custom`, and `softDescriptor` as optional properties on `PayPalPayment`.
344 |
345 | 2.4.0
346 | -----
347 | * Add [Profile Sharing](https://github.com/paypal/PayPal-Android-SDK/blob/master/docs/profile_sharing_mobile.md) feature.
348 | * Developer selects requested account profile attributes.
349 | * User may consent to sharing the requested profile data.
350 | * Fix sluggish performance in Payment Method selection on devices with slower cameras (Nexus 10).
351 | * Fix issue [#77: Invalid path on some devices](https://github.com/paypal/PayPal-Android-SDK/issues/77).
352 |
353 | 2.3.5
354 | ----
355 | * Hotfix for issue on live/sandbox environment introduced in 2.3.4.
356 |
357 | 2.3.4
358 | ----
359 | * Fix issue [#83: App freezes when calling startService](https://github.com/paypal/PayPal-Android-SDK/issues/83) for realsies this time.
360 | * Restrict phone/pin login where appropriate.
361 |
362 | 2.3.3
363 | ----
364 | * Fix issue [#83: App freezes when calling startService](https://github.com/paypal/PayPal-Android-SDK/issues/83).
365 | * Minor bug fixes.
366 |
367 | 2.3.2
368 | ----
369 | * Re-add Version class for Cordova backward compatibility.
370 |
371 | 2.3.1
372 | ----
373 | * Support display of Pay After Delivery funding options.
374 | * Minor bug fixes.
375 |
376 | 2.3.0
377 | ----
378 | * Add user funding option selection.
379 | * Add app-controlled user shipping address selection (including support for the app to add a new shipping address).
380 | * Rename zh-Hant_HK -> zh-Hant so that HK is chosen by default for other regions.
381 |
382 | 2.2.2
383 | -----
384 | * Add translations for Thai.
385 | * Fix bnCode validation to accept underscores and hyphens.
386 |
387 | 2.2.1
388 | -----
389 | * Fix SampleApp code related to multiple item support.
390 | * Add instructions for using SDK in Gradle projects.
391 | * Fix issues associated with how the PayPalService was being managed.
392 |
393 | 2.2.0
394 | -----
395 | * Add support for multiple items per payment.
396 | * Update PayPal logo.
397 | * Update card.io library to 3.1.5.
398 |
399 | 2.1.0
400 | -----
401 | * Add integration with PayPal Wallet App (available only on the Samsung app store).
402 | * In live environment, if the newly released PayPal Wallet app with authenticator is present on a user's device, the PayPal Wallet app will log the user in to the SDK.
403 | * Fix issue where some email addresses would not be accepted.
404 | * Fix some Spanish translations.
405 | * Fix possible NPE in payment confirmation flow.
406 |
407 | 2.0.3
408 | -----
409 | * Add return of `authorization_id` to SDK's payment response when payment intent is authorization. The `authorization_id` will be used to capture funds via server calls.
410 | * Add `PayPalConfig.getLibraryVersion()`.
411 | * Add support for Arabic and Malay languages.
412 | * Add proper handling of right-to-left languages (Hebrew and Arabic).
413 | * Improve user experience when user must log in again (informational dialog is displayed).
414 |
415 | 2.0.2
416 | -----
417 | * Minor bug fixes.
418 |
419 | 2.0.1
420 | -----
421 | * Fix values for product_name and build_time returned by SDK.
422 |
423 | 2.0.0
424 | -----
425 | * Add Future Payment with PayPal support. Users can now authenticate and consent within an app using the SDK. A user no longer needs to repeatedly enter credentials.
426 | * Introduce a `PayPalFuturePaymentActivity`, which returns a `PayPalAuthorization` object.
427 | * Changes to payment feature:
428 | * Change backend to use PayPal's new REST APIs for all SDK functions. Now there is a single way to verify both credit card and PayPal payments.
429 | * Introduce `PayPalPaymentDetails` to support payment details, including line-item subtotal amount, tax amount, and shipping amount.
430 | * Single payments now include a payment`intent` to distinguish between:
431 | 1. immediate payment processing
432 | 2. payment authorization only, with subsequent payment capture from the merchant's server.
433 | * Use `PayPalConfiguration` object for common configuration across both single payment and future payment use cases.
434 | * For API errors, logging will now provide additional information, including a PayPal Debug-ID for MTS investigations.
435 | * Add support for directional controller interaction (for set-top boxes, game consoles, etc.).
436 | * Resolves issues with PayPal user passwords containing special characters.
437 |
438 | 1.2.6
439 | -----
440 | * Fix issue where PaymentActivity.EXTRA_DEFAULT_USER_EMAIL was not being handled properly in all cases [47](https://github.com/paypal/PayPal-Android-SDK/issues/47).
441 |
442 | 1.2.5
443 | -----
444 | * Refactor code to eliminate spurious error message in LogCat [40](https://github.com/paypal/PayPal-Android-SDK/issues/40).
445 | * Fix validation of PayPalPayment.shortDescription where some credit card payments caused incorrect JSONException [41](https://github.com/paypal/PayPal-Android-SDK/issues/41).
446 | * Eliminate source of potential NPE [37](https://github.com/paypal/PayPal-Android-SDK/issues/37).
447 | * Update card.io lib to 3.1.4 (includes fixes for potential NPEs).
448 |
449 | 1.2.4
450 | -----
451 | * Fix NumberFormatException on some payments in locales that use comma for decimal separator [34](https://github.com/paypal/PayPal-Android-SDK/issues/34).
452 |
453 | 1.2.3
454 | -----
455 | * Fix issue where invalid currency amounts could be sent to the PayPal server.
456 |
457 | 1.2.2
458 | -----
459 | * Fix login page layout issue [20](https://github.com/paypal/PayPal-Android-SDK/issues/20).
460 | * Add some login error logging.
461 |
462 | 1.2.1
463 | -----
464 | * Update card.io library to 3.1.3.
465 | * Fix issue [#11: release/debug UI differences](https://github.com/paypal/PayPal-Android-SDK/issues/11).
466 |
467 | 1.2.0
468 | -----
469 | * Eliminate the final "Complete" screen.
470 | * Fix Hebrew phone settings detection bug.
471 | * Update card.io library to 3.1.2.
472 |
473 | 1.1.2
474 | -----
475 | * Re-add `Version` class.
476 | * Update card.io library to 3.1.1.
477 | * Support all currencies that are currently accepted by the REST APIs. See [README](README.md) for details.
478 | * Fix various localizations.
479 | * Additional localization: ko (Korean).
480 | * Minor UI cleanup (including [issue 4](https://github.com/paypal/PayPal-Android-SDK/issues/4)).
481 |
482 | 1.1.1
483 | -----
484 | * Skipped.
485 |
486 | 1.1.0
487 | -----
488 | * Bug fixes.
489 | * Update card.io to 3.1.0.
490 | * Add translations of all strings into ~20 languages, in addition to American English.
491 | - Translation choice is controlled by `EXTRA_LANGUAGE_OR_LOCALE` in PaymentActivity.
492 | - The translations that a few developers had previously created for their own apps will no longer be used by the SDK.
493 | - NOTE: Default language, if not set by your app, will now be based upon the device's current language setting.
494 |
495 | 1.0.3
496 | -----
497 | * Bug fixes.
498 |
499 | 1.0.2
500 | -----
501 | * Several small fixes & improvements.
502 |
503 | 1.0.1
504 | -----
505 | * Update card.io to 3.0.5.
506 | * Minor UI improvements.
507 | * Other small fixes.
508 |
509 | 1.0.0
510 | -----
511 | * First release!
512 |
513 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribute to the PayPal Android SDK
2 |
3 | We love your contributions. If you're looking to submit changes to the sample app or documentation available within this repo, feel free to submit a PR.
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The PayPal Android SDK Sample App is released under the BSD License:
2 |
3 | Copyright (c) 2014-2016 PayPal Holdings, Inc.
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 | 2. Redistributions in binary form must reproduce the above copyright notice,
12 | this list of conditions and the following disclaimer in the documentation
13 | and/or other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 | The views and conclusions contained in the software and documentation are those
27 | of the authors and should not be interpreted as representing official policies,
28 | either expressed or implied, of the FreeBSD Project.
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **Important**: This PayPal Android SDK is Deprecated. The APIs powering them will remain operational long enough for merchants to migrate, but the SDKs themselves will no longer be updated. Please use the [PayPal Android Checkout SDK](https://github.com/paypal/android-checkout-sdk). Reference the [Developer Documentation](https://developer.paypal.com/docs/business/native-checkout/android/) for getting started.
2 |
3 | PayPal Android SDK
4 | ==================
5 |
6 | The PayPal Android SDK makes it easy to add PayPal payments to mobile apps.
7 |
8 | *This documentation is available in Japanese: [日本語のドキュメント](docs/ja/README.md).*
9 |
10 | ## Contents
11 |
12 | - [Use Cases](#use-cases)
13 | - [Integration with the PayPal Wallet App](#integration-with-the-paypal-wallet-app)
14 | - [Requirements](#requirements)
15 | - [Add the SDK to Your Project](#add-the-sdk-to-your-project)
16 | - [Credentials](#credentials)
17 | - [International Support](#international-support)
18 | - [Disabling Direct Credit Card Payments](#disabling-direct-credit-card-payments)
19 | - [Override `minSdkVersion`](#override-minsdkversion)
20 | - [Testing](#testing)
21 | - [Documentation](#documentation)
22 | - [Usability](#usability)
23 | - [Next Steps](#next-steps)
24 | - [Contributing](#contributing)
25 | - [License](#license)
26 |
27 | ## Add the SDK to Your Project
28 |
29 | The PayPal Android SDK is now available at [Maven Repository](https://repo1.maven.org/maven2/com/paypal/sdk/paypal-android-sdk/). The latest version is available via `mavenCentral()`:
30 |
31 | ```groovy
32 | compile 'com.paypal.sdk:paypal-android-sdk:2.16.0'
33 | ```
34 |
35 |
36 | ## Use Cases
37 |
38 | The SDK supports two use cases for making payments - **Single Payment** and **Future Payments** - and a third use case for obtaining information about the customer - **Profile Sharing**.
39 |
40 |
41 | ### Single Payment
42 |
43 | Receive a one-time payment from a customer's PayPal account or payment card (scanned with [card.io](https://www.card.io/)). This can be either (1) an **immediate** payment which your servers should subsequently **verify**, or (2) an **authorization** for a payment which your servers must subsequently **capture**, or (3) a payment for an **order** which your servers must subsequently **authorize** and **capture**:
44 |
45 | 1. [Accept a Single Payment](docs/single_payment.md) and receive back a proof of payment.
46 | 2. On your server, [Verify the Payment](https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/), [Capture the Payment](https://developer.paypal.com/webapps/developer/docs/integration/direct/capture-payment/#capture-the-payment), or [Process the Order](https://developer.paypal.com/webapps/developer/docs/integration/direct/create-process-order/) (PayPal Developer site) using PayPal's API.
47 |
48 | *Note:* Direct Credit Card (DCC) payments are now deprecated in this SDK. Please use [Braintree Payments](https://www.braintreepayments.com/), a PayPal Company, which is the easiest way to accept PayPal, credit cards, and many other payment methods. All new integrations should [disable direct credit card payments](#disabling-direct-credit-card-payments).
49 |
50 |
51 | ### Future Payments
52 |
53 | Your customer logs in to PayPal just one time and consents to future payments:
54 |
55 | 1. [Obtain Customer Consent](docs/future_payments_mobile.md#obtain-customer-consent) to receive an authorization code.
56 | 2. On your server, use this authorization code to [Obtain OAuth2 Tokens](docs/future_payments_server.md#obtain-oauth2-tokens).
57 |
58 | Later, when that customer initiates a payment:
59 |
60 | 1. [Obtain a Client Metadata ID](docs/future_payments_mobile.md#obtain-an-application-correlation-id) that you'll pass to your server.
61 | 2. On your server, [Create a Payment](docs/future_payments_server.md#create-a-payment) using your OAuth2 tokens, the Client Metadata ID, and PayPal's API.
62 |
63 | ### Profile Sharing
64 |
65 | Your customer logs in to PayPal and consents to PayPal sharing information with you:
66 |
67 | 1. [Obtain Customer Consent](docs/profile_sharing_mobile.md#obtain-customer-consent) to receive an authorization code.
68 | 2. On your server, use this authorization code to [Obtain OAuth2 Tokens](docs/profile_sharing_server.md#obtain-oauth2-tokens).
69 | 3. On your server, [Retrieve Customer Information](docs/profile_sharing_server.md#retrieve-customer-information) using your OAuth2 tokens and PayPal's API.
70 |
71 |
72 | ## Integration with the PayPal Wallet App
73 |
74 | The SDK will now use the newest version of the PayPal Wallet App if present on the device to log in to a customer account. No additional configuration is required to enable this feature. This integration enables device-specific PayPal [FIDO](https://fidoalliance.org/) integrations, including login by fingerprint on the Galaxy S5. In addition, a user who logged in to the PayPal Wallet App and checked "Keep me logged in" may not need to log-in again when paying with your app. For more information on how this all works, please read the [blog post](http://www.embedded.com/design/real-world-applications/4430305/Implementing-Android-based-fingerprint-authentication-for-online-payments) from one of our architects.
75 |
76 | ### Limitations
77 |
78 | * The integration will _not_ be enabled in any of the [testing](#testing) modes, as the Wallet app does not support this developer testing environment.
79 |
80 | ## Requirements
81 |
82 | * Android 4.1.x (API 16) or later
83 | * Phone or tablet
84 |
85 | ## Credentials
86 |
87 | Your mobile integration requires different `client_id` values for each environment: Live and Test (Sandbox).
88 |
89 | Your server integrations for verifying or creating payments will also require the corresponding `client_secret` for each `client_id`.
90 |
91 | You can obtain these PayPal API credentials by visiting the [Applications page on the PayPal Developer site](https://developer.paypal.com/webapps/developer/applications) and logging in with your PayPal account.
92 |
93 | ### Sandbox
94 |
95 | Once logged in on this Applications page, you will be assigned **test credentials**, including Client ID, which will let you test your Android integration against the PayPal Sandbox.
96 |
97 | While testing your app, when logging in to PayPal in the SDK's UI you should use a *personal* Sandbox account email and password. I.e., not your Sandbox *business* credentials.
98 |
99 | You can create both business and personal Sandbox accounts on the [Sandbox accounts](https://developer.paypal.com/webapps/developer/applications/accounts) page.
100 |
101 | #### Sandbox and TLSv1.2
102 |
103 | PayPal will be upgrading the endpoint that the PayPal Android SDK uses to communicate with PayPal servers on Jan 18th, 2016. If you're testing on sandbox with a version of the PayPal Android SDK older than 2.13.0, then you'll start seeing communication failures when using Android devices >= API 16, and < API 20. Please upgrade to a version [2.13.0](https://github.com/paypal/PayPal-Android-SDK/releases) or higher to fix these errors.
104 |
105 | If you're testing on a device older than API 16, Android will not be able to communicate with PayPal, no matter what version of the SDK you use.
106 |
107 | These TLS changes coincides with the TLSv1.2 security mandate outlined [here](https://www.paypal-knowledge.com/infocenter/index?page=content&widgetview=true&id=FAQ1914&viewlocale=en_US), and will be followed by a similar change to the Production endpoints at some later date. For any questions or concerns, please [create an issue](https://github.com/paypal/PayPal-Android-SDK/issues/).
108 |
109 | ### Live
110 |
111 | To obtain your **live** credentials, you will need to have a business account. If you don't yet have a business account, there is a link at the bottom of that same Applications page that will get you started.
112 |
113 |
114 | ## International Support
115 |
116 | ### Localizations
117 |
118 | The SDK has built-in translations for many languages and locales. See [javadoc](http://paypal.github.io/PayPal-Android-SDK/) files for a complete list.
119 |
120 | ### Currencies
121 |
122 | The SDK supports multiple currencies. See [the REST API country and currency documentation](https://developer.paypal.com/webapps/developer/docs/integration/direct/rest_api_payment_country_currency_support/) for a complete, up-to-date list.
123 |
124 | ## Disabling Direct Credit Card Payments
125 |
126 | Disabling Direct Credit Card Payments is now preferred. To completely disable Direct Credit Card (DCC) payments, exclude the card.io library in your application `build.gradle`:
127 | ```groovy
128 | dependencies {
129 | compile('com.paypal.sdk:paypal-android-sdk:2.16.0') {
130 | exclude group: 'io.card'
131 | }
132 | }
133 | ```
134 |
135 | ## Override `minSdkVersion`
136 |
137 | As of release `2.14.0`, the `minSdkVersion` has been increased to 16. If you prefer to have your app on a lower `minSdkVersion` and want to leverage the latest SDK, please disable PayPal for versions below API 16, add `xmlns:tools="http://schemas.android.com/tools` inside the manifest's xml declaration, and add the following snippet to your `AndroidManifest.xml`:
138 |
139 | ```xml
140 |
141 | ```
142 |
143 | See the [Android manifest merger docs](http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger) for more information.
144 |
145 | ## Testing
146 |
147 | During development, use `environment()` in the `PayPalConfiguration` object to change the environment. Set it to either `ENVIRONMENT_NO_NETWORK` or `ENVIRONMENT_SANDBOX` to avoid moving real money.
148 |
149 |
150 | ## Documentation
151 |
152 | * These docs in the SDK, which include an overview of usage, step-by-step integration instructions, and sample code.
153 | * The sample app included in this SDK.
154 | * There are [javadocs](http://paypal.github.io/PayPal-Android-SDK/) available.
155 | * The [PayPal Developer Docs](https://developer.paypal.com/docs), which cover error codes and server-side integration instructions.
156 |
157 |
158 | ## Usability
159 |
160 | User interface appearance and behavior is set within the library itself. For the sake of usability and user experience consistency, apps should not attempt to modify the SDK's behavior beyond the documented methods.
161 |
162 |
163 | ## Next Steps
164 |
165 | Depending on your use case, you can now:
166 |
167 | * [Accept a single payment](docs/single_payment.md)
168 | * [Obtain user consent](docs/future_payments_mobile.md) to [create future payments](docs/future_payments_server.md).
169 |
170 |
171 | ## Contributing
172 |
173 | Please read our [contributing guidelines](CONTRIBUTING.md) prior to submitting a Pull Request.
174 |
175 | ## License
176 |
177 | Please refer to this repo's [license file](LICENSE).
178 |
--------------------------------------------------------------------------------
/SampleApp-Kotlin/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Gradle files
16 | .gradle/
17 | build/
18 |
19 | # Local configuration file (sdk path, etc)
20 | local.properties
21 |
22 | # Eclipse settings files
23 | .settings/
24 |
25 | # IntelliJ project files
26 | *.iml
27 | *.ipr
28 | *.iws
29 | .idea/
30 |
31 | # Misc
32 | .DS_Store
33 |
--------------------------------------------------------------------------------
/SampleApp-Kotlin/README.md:
--------------------------------------------------------------------------------
1 | PayPal Android SDK Sample App - Kotlin
2 | =============================
3 |
4 | This is the PayPal Android SDK Sample App using the Kotlin Language.
5 |
--------------------------------------------------------------------------------
/SampleApp-Kotlin/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.1.50'
3 | repositories {
4 | jcenter()
5 | mavenCentral()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.2.0'
9 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
10 | }
11 | }
12 |
13 | repositories {
14 | jcenter()
15 | mavenCentral()
16 | }
17 |
18 | apply plugin: 'com.android.application'
19 | apply plugin: 'kotlin-android'
20 |
21 | android {
22 | compileSdkVersion 26
23 | buildToolsVersion '24.0.1'
24 |
25 | defaultConfig {
26 | minSdkVersion 18
27 | targetSdkVersion 26
28 | }
29 |
30 | signingConfigs {
31 | debug {
32 | storeFile file('debug.keystore')
33 | storePassword 'android'
34 | keyAlias 'androiddebugkey'
35 | keyPassword 'android'
36 | }
37 | release {
38 | storeFile file('debug.keystore')
39 | storePassword 'android'
40 | keyAlias 'androiddebugkey'
41 | keyPassword 'android'
42 | }
43 | }
44 |
45 | // Only for SampleApp.
46 | // It is failing because the okio version and okhttp is not found, which is expected.
47 | lintOptions {
48 | abortOnError false
49 | }
50 |
51 |
52 | buildTypes {
53 | debug {
54 | applicationIdSuffix ".debug"
55 | signingConfig signingConfigs.debug
56 | }
57 |
58 | release{
59 | minifyEnabled true
60 | proguardFile getDefaultProguardFile('proguard-android.txt')
61 | signingConfig signingConfigs.release
62 | }
63 | }
64 |
65 | android.applicationVariants.all { variant ->
66 | variant.outputs.each { output ->
67 | def outputFile = output.outputFile
68 | if (outputFile != null && outputFile.name.endsWith('.apk')) {
69 | output.outputFile = new File(outputFile.parent, "paypal-sample-app-${variant.name}.apk")
70 | }
71 | }
72 | }
73 |
74 | sourceSets {
75 | main.java.srcDirs += 'src/main/kotlin'
76 | }
77 | }
78 |
79 | dependencies {
80 | if (parent != null) {
81 | compile project(path: ':androidSDK', configuration: 'generalDebug')
82 | } else {
83 | compile('com.paypal.sdk:paypal-android-sdk:2.16.0')
84 | }
85 | compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
86 | }
87 |
88 | task wrapper(type: Wrapper) {
89 | gradleVersion = '2.14'
90 | }
91 |
--------------------------------------------------------------------------------
/SampleApp-Kotlin/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/PayPal-Android-SDK/f7534f0951ae0ad1a7127069bac59a9ba8a23bec/SampleApp-Kotlin/debug.keystore
--------------------------------------------------------------------------------
/SampleApp-Kotlin/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/PayPal-Android-SDK/f7534f0951ae0ad1a7127069bac59a9ba8a23bec/SampleApp-Kotlin/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/SampleApp-Kotlin/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Jun 29 16:07:52 CDT 2016
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip
7 |
--------------------------------------------------------------------------------
/SampleApp-Kotlin/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/SampleApp-Kotlin/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/SampleApp-Kotlin/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/SampleApp-Kotlin/src/main/java/com/paypal/example/paypalandroidsdkexample/SampleActivity.kt:
--------------------------------------------------------------------------------
1 | package com.paypal.example.paypalandroidsdkexample
2 |
3 | import com.paypal.android.sdk.payments.PayPalAuthorization
4 | import com.paypal.android.sdk.payments.PayPalConfiguration
5 | import com.paypal.android.sdk.payments.PayPalFuturePaymentActivity
6 | import com.paypal.android.sdk.payments.PayPalItem
7 | import com.paypal.android.sdk.payments.PayPalOAuthScopes
8 | import com.paypal.android.sdk.payments.PayPalPayment
9 | import com.paypal.android.sdk.payments.PayPalPaymentDetails
10 | import com.paypal.android.sdk.payments.PayPalProfileSharingActivity
11 | import com.paypal.android.sdk.payments.PayPalService
12 | import com.paypal.android.sdk.payments.PaymentActivity
13 | import com.paypal.android.sdk.payments.PaymentConfirmation
14 | import com.paypal.android.sdk.payments.ShippingAddress
15 |
16 |
17 | import android.app.Activity
18 | import android.content.Intent
19 | import android.net.Uri
20 | import android.os.Bundle
21 | import android.util.Log
22 | import android.view.View
23 | import android.widget.TextView
24 | import android.widget.Toast
25 |
26 | import org.json.JSONException
27 |
28 | import java.math.BigDecimal
29 | import java.util.Arrays
30 | import java.util.HashSet
31 |
32 | /**
33 | * Basic sample using the SDK to make a payment or consent to future payments.
34 | *
35 | * For sample mobile backend interactions, see
36 | * https://github.com/paypal/rest-api-sdk-python/tree/master/samples/mobile_backend
37 | */
38 | class SampleActivity : Activity() {
39 |
40 | override fun onCreate(savedInstanceState: Bundle?) {
41 | super.onCreate(savedInstanceState)
42 | setContentView(R.layout.activity_main)
43 |
44 | val intent = Intent(this, PayPalService::class.java)
45 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config)
46 | startService(intent)
47 | }
48 |
49 | fun onBuyPressed(pressed: View) {
50 | /*
51 | * PAYMENT_INTENT_SALE will cause the payment to complete immediately.
52 | * Change PAYMENT_INTENT_SALE to
53 | * - PAYMENT_INTENT_AUTHORIZE to only authorize payment and capture funds later.
54 | * - PAYMENT_INTENT_ORDER to create a payment for authorization and capture
55 | * later via calls from your server.
56 | *
57 | * Also, to include additional payment details and an item list, see getStuffToBuy() below.
58 | */
59 | val thingToBuy = getThingToBuy(PayPalPayment.PAYMENT_INTENT_SALE)
60 |
61 | /*
62 | * See getStuffToBuy(..) for examples of some available payment options.
63 | */
64 |
65 | val intent = Intent(this@SampleActivity, PaymentActivity::class.java)
66 |
67 | // send the same configuration for restart resiliency
68 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config)
69 |
70 | intent.putExtra(PaymentActivity.EXTRA_PAYMENT, thingToBuy)
71 |
72 | startActivityForResult(intent, REQUEST_CODE_PAYMENT)
73 | }
74 |
75 | private fun getThingToBuy(paymentIntent: String): PayPalPayment {
76 | return PayPalPayment(BigDecimal("1.75"), "USD", "sample item",
77 | paymentIntent)
78 | }
79 |
80 | /*
81 | * This method shows use of optional payment details and item list.
82 | */
83 | private fun getStuffToBuy(paymentIntent: String): PayPalPayment {
84 | //--- include an item list, payment amount details
85 | val items = arrayOf(
86 | PayPalItem("sample item #1", 2, BigDecimal("87.50"), "USD", "sku-12345678"),
87 | PayPalItem("free sample item #2", 1, BigDecimal("0.00"), "USD", "sku-zero-price"),
88 | PayPalItem("sample item #3 with a longer name", 6, BigDecimal("37.99"), "USD", "sku-33333")
89 | )
90 | val subtotal = PayPalItem.getItemTotal(items)
91 | val shipping = BigDecimal("7.21")
92 | val tax = BigDecimal("4.67")
93 | val paymentDetails = PayPalPaymentDetails(shipping, subtotal, tax)
94 | val amount = subtotal.add(shipping).add(tax)
95 | val payment = PayPalPayment(amount, "USD", "sample item", paymentIntent)
96 | payment.items(items).paymentDetails(paymentDetails)
97 |
98 | //--- set other optional fields like invoice_number, custom field, and soft_descriptor
99 | payment.custom("This is text that will be associated with the payment that the app can use.")
100 |
101 | return payment
102 | }
103 |
104 | /*
105 | * Add app-provided shipping address to payment
106 | */
107 | private fun addAppProvidedShippingAddress(paypalPayment: PayPalPayment) {
108 | val shippingAddress = ShippingAddress()
109 | .recipientName("Mom Parker")
110 | .line1("52 North Main St.")
111 | .city("Austin")
112 | .state("TX")
113 | .postalCode("78729")
114 | .countryCode("US")
115 | paypalPayment.providedShippingAddress(shippingAddress)
116 | }
117 |
118 | /*
119 | * Enable retrieval of shipping addresses from buyer's PayPal account
120 | */
121 | private fun enableShippingAddressRetrieval(paypalPayment: PayPalPayment, enable: Boolean) {
122 | paypalPayment.enablePayPalShippingAddressesRetrieval(enable)
123 | }
124 |
125 | fun onFuturePaymentPressed(pressed: View) {
126 | val intent = Intent(this@SampleActivity, PayPalFuturePaymentActivity::class.java)
127 |
128 | // send the same configuration for restart resiliency
129 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config)
130 |
131 | startActivityForResult(intent, REQUEST_CODE_FUTURE_PAYMENT)
132 | }
133 |
134 | fun onProfileSharingPressed(pressed: View) {
135 | val intent = Intent(this@SampleActivity, PayPalProfileSharingActivity::class.java)
136 |
137 | // send the same configuration for restart resiliency
138 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config)
139 |
140 | intent.putExtra(PayPalProfileSharingActivity.EXTRA_REQUESTED_SCOPES, oauthScopes)
141 |
142 | startActivityForResult(intent, REQUEST_CODE_PROFILE_SHARING)
143 | }
144 |
145 | private /* create the set of required scopes
146 | * Note: see https://developer.paypal.com/docs/integration/direct/identity/attributes/ for mapping between the
147 | * attributes you select for this app in the PayPal developer portal and the scopes required here.
148 | */ val oauthScopes: PayPalOAuthScopes
149 | get() {
150 | val scopes = HashSet(
151 | Arrays.asList(
152 | PayPalOAuthScopes.PAYPAL_SCOPE_EMAIL,
153 | PayPalOAuthScopes.PAYPAL_SCOPE_ADDRESS
154 | )
155 | )
156 | return PayPalOAuthScopes(scopes)
157 | }
158 |
159 | protected fun displayResultText(result: String) {
160 | var resultView:TextView = findViewById(R.id.txtResult)
161 | resultView.text = "Result : " + result
162 | Toast.makeText(
163 | applicationContext,
164 | result, Toast.LENGTH_LONG).show()
165 | }
166 |
167 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
168 | if (requestCode == REQUEST_CODE_PAYMENT) {
169 | if (resultCode == Activity.RESULT_OK) {
170 | val confirm = data?.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION)
171 | if (confirm != null) {
172 | try {
173 | Log.i(TAG, confirm.toJSONObject().toString(4))
174 | Log.i(TAG, confirm.payment.toJSONObject().toString(4))
175 | /**
176 | * TODO: send 'confirm' (and possibly confirm.getPayment() to your server for verification
177 | * or consent completion.
178 | * See https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/
179 | * for more details.
180 |
181 | * For sample mobile backend interactions, see
182 | * https://github.com/paypal/rest-api-sdk-python/tree/master/samples/mobile_backend
183 | */
184 | displayResultText("PaymentConfirmation info received from PayPal")
185 |
186 |
187 | } catch (e: JSONException) {
188 | Log.e(TAG, "an extremely unlikely failure occurred: ", e)
189 | }
190 |
191 | }
192 | } else if (resultCode == Activity.RESULT_CANCELED) {
193 | Log.i(TAG, "The user canceled.")
194 | } else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) {
195 | Log.i(
196 | TAG,
197 | "An invalid Payment or PayPalConfiguration was submitted. Please see the docs.")
198 | }
199 | } else if (requestCode == REQUEST_CODE_FUTURE_PAYMENT) {
200 | if (resultCode == Activity.RESULT_OK) {
201 | val auth = data?.getParcelableExtra(PayPalFuturePaymentActivity.EXTRA_RESULT_AUTHORIZATION)
202 | if (auth != null) {
203 | try {
204 | Log.i("FuturePaymentExample", auth.toJSONObject().toString(4))
205 |
206 | val authorization_code = auth.authorizationCode
207 | Log.i("FuturePaymentExample", authorization_code)
208 |
209 | sendAuthorizationToServer(auth)
210 | displayResultText("Future Payment code received from PayPal")
211 |
212 | } catch (e: JSONException) {
213 | Log.e("FuturePaymentExample", "an extremely unlikely failure occurred: ", e)
214 | }
215 |
216 | }
217 | } else if (resultCode == Activity.RESULT_CANCELED) {
218 | Log.i("FuturePaymentExample", "The user canceled.")
219 | } else if (resultCode == PayPalFuturePaymentActivity.RESULT_EXTRAS_INVALID) {
220 | Log.i(
221 | "FuturePaymentExample",
222 | "Probably the attempt to previously start the PayPalService had an invalid PayPalConfiguration. Please see the docs.")
223 | }
224 | } else if (requestCode == REQUEST_CODE_PROFILE_SHARING) {
225 | if (resultCode == Activity.RESULT_OK) {
226 | val auth = data?.getParcelableExtra(PayPalProfileSharingActivity.EXTRA_RESULT_AUTHORIZATION)
227 | if (auth != null) {
228 | try {
229 | Log.i("ProfileSharingExample", auth.toJSONObject().toString(4))
230 |
231 | val authorization_code = auth.authorizationCode
232 | Log.i("ProfileSharingExample", authorization_code)
233 |
234 | sendAuthorizationToServer(auth)
235 | displayResultText("Profile Sharing code received from PayPal")
236 |
237 | } catch (e: JSONException) {
238 | Log.e("ProfileSharingExample", "an extremely unlikely failure occurred: ", e)
239 | }
240 |
241 | }
242 | } else if (resultCode == Activity.RESULT_CANCELED) {
243 | Log.i("ProfileSharingExample", "The user canceled.")
244 | } else if (resultCode == PayPalFuturePaymentActivity.RESULT_EXTRAS_INVALID) {
245 | Log.i(
246 | "ProfileSharingExample",
247 | "Probably the attempt to previously start the PayPalService had an invalid PayPalConfiguration. Please see the docs.")
248 | }
249 | }
250 | }
251 |
252 | private fun sendAuthorizationToServer(authorization: PayPalAuthorization) {
253 |
254 | /**
255 | * TODO: Send the authorization response to your server, where it can
256 | * exchange the authorization code for OAuth access and refresh tokens.
257 |
258 | * Your server must then store these tokens, so that your server code
259 | * can execute payments for this user in the future.
260 |
261 | * A more complete example that includes the required app-server to
262 | * PayPal-server integration is available from
263 | * https://github.com/paypal/rest-api-sdk-python/tree/master/samples/mobile_backend
264 | */
265 |
266 | }
267 |
268 | fun onFuturePaymentPurchasePressed(pressed: View) {
269 | // Get the Client Metadata ID from the SDK
270 | val metadataId = PayPalConfiguration.getClientMetadataId(this)
271 |
272 | Log.i("FuturePaymentExample", "Client Metadata ID: " + metadataId)
273 |
274 | // TODO: Send metadataId and transaction details to your server for processing with
275 | // PayPal...
276 | displayResultText("Client Metadata Id received from SDK")
277 | }
278 |
279 | public override fun onDestroy() {
280 | // Stop service when done
281 | stopService(Intent(this, PayPalService::class.java))
282 | super.onDestroy()
283 | }
284 |
285 | companion object {
286 | private val TAG = "paymentExample"
287 | /**
288 | * - Set to PayPalConfiguration.ENVIRONMENT_PRODUCTION to move real money.
289 |
290 | * - Set to PayPalConfiguration.ENVIRONMENT_SANDBOX to use your test credentials
291 | * from https://developer.paypal.com
292 |
293 | * - Set to PayPalConfiguration.ENVIRONMENT_NO_NETWORK to kick the tires
294 | * without communicating to PayPal's servers.
295 | */
296 | private val CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_NO_NETWORK
297 |
298 | // note that these credentials will differ between live & sandbox environments.
299 | private val CONFIG_CLIENT_ID = "credentials from developer.paypal.com"
300 |
301 | private val REQUEST_CODE_PAYMENT = 1
302 | private val REQUEST_CODE_FUTURE_PAYMENT = 2
303 | private val REQUEST_CODE_PROFILE_SHARING = 3
304 |
305 | private val config = PayPalConfiguration()
306 | .environment(CONFIG_ENVIRONMENT)
307 | .clientId(CONFIG_CLIENT_ID)
308 | .merchantName("Example Merchant")
309 | .merchantPrivacyPolicyUri(Uri.parse("https://www.example.com/privacy"))
310 | .merchantUserAgreementUri(Uri.parse("https://www.example.com/legal"))
311 | }
312 | }
313 |
--------------------------------------------------------------------------------
/SampleApp-Kotlin/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/PayPal-Android-SDK/f7534f0951ae0ad1a7127069bac59a9ba8a23bec/SampleApp-Kotlin/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleApp-Kotlin/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/PayPal-Android-SDK/f7534f0951ae0ad1a7127069bac59a9ba8a23bec/SampleApp-Kotlin/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleApp-Kotlin/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/PayPal-Android-SDK/f7534f0951ae0ad1a7127069bac59a9ba8a23bec/SampleApp-Kotlin/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleApp-Kotlin/src/main/res/drawable-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/PayPal-Android-SDK/f7534f0951ae0ad1a7127069bac59a9ba8a23bec/SampleApp-Kotlin/src/main/res/drawable-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleApp-Kotlin/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
18 |
19 |
26 |
27 |
34 |
35 |
42 |
43 |
50 |
51 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/SampleApp-Kotlin/src/main/res/values-sw600dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SampleApp-Kotlin/src/main/res/values-sw720dp-land/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | 128dp
8 |
9 |
10 |
--------------------------------------------------------------------------------
/SampleApp-Kotlin/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 10dip
4 | 10dip
5 |
6 |
--------------------------------------------------------------------------------
/SampleApp-Kotlin/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | PayPal SDK Example
5 |
6 |
7 |
--------------------------------------------------------------------------------
/SampleApp/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Gradle files
16 | .gradle/
17 | build/
18 |
19 | # Local configuration file (sdk path, etc)
20 | local.properties
21 |
22 | # Eclipse settings files
23 | .settings/
24 |
25 | # IntelliJ project files
26 | *.iml
27 | *.ipr
28 | *.iws
29 | .idea/
30 |
31 | # Misc
32 | .DS_Store
33 |
--------------------------------------------------------------------------------
/SampleApp/README.md:
--------------------------------------------------------------------------------
1 | PayPal Android SDK Sample App
2 | =============================
3 |
4 | All users can build this sample app as-is.
5 |
--------------------------------------------------------------------------------
/SampleApp/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | jcenter()
4 | mavenCentral()
5 | }
6 | dependencies {
7 | classpath 'com.android.tools.build:gradle:2.2.0'
8 | }
9 | }
10 |
11 | repositories {
12 | maven {
13 | // Used for downloading dependency com.github.lkorth:device-automator
14 | url "https://jitpack.io"
15 | }
16 | jcenter()
17 | mavenCentral()
18 | }
19 |
20 | apply plugin: 'com.android.application'
21 |
22 | android {
23 | compileSdkVersion 26
24 | buildToolsVersion '24.0.1'
25 |
26 | defaultConfig {
27 | minSdkVersion 18
28 | targetSdkVersion 26
29 | testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
30 | }
31 |
32 | signingConfigs {
33 | debug {
34 | storeFile file('debug.keystore')
35 | storePassword 'android'
36 | keyAlias 'androiddebugkey'
37 | keyPassword 'android'
38 | }
39 | release {
40 | storeFile file('debug.keystore')
41 | storePassword 'android'
42 | keyAlias 'androiddebugkey'
43 | keyPassword 'android'
44 | }
45 | }
46 |
47 | // Only for SampleApp.
48 | // It is failing because the okio version and okhttp is not found, which is expected.
49 | lintOptions {
50 | abortOnError false
51 | }
52 |
53 |
54 | buildTypes {
55 | debug {
56 | applicationIdSuffix ".debug"
57 | signingConfig signingConfigs.debug
58 | }
59 |
60 | release{
61 | minifyEnabled true
62 | proguardFile getDefaultProguardFile('proguard-android.txt')
63 | signingConfig signingConfigs.release
64 | }
65 | }
66 |
67 | android.applicationVariants.all { variant ->
68 | variant.outputs.each { output ->
69 | def outputFile = output.outputFile
70 | if (outputFile != null && outputFile.name.endsWith('.apk')) {
71 | output.outputFile = new File(outputFile.parent, "paypal-sample-app-${variant.name}.apk")
72 | }
73 | }
74 | }
75 |
76 | productFlavors {
77 | general
78 | partner
79 | }
80 | }
81 |
82 | configurations.all {
83 | resolutionStrategy.force 'com.android.support:support-annotations:24.0.0'
84 | }
85 |
86 |
87 | dependencies {
88 | if (parent != null) {
89 | generalCompile project(path: ':androidSDK', configuration: 'generalDebug')
90 | partnerCompile project(path: ':androidSDK', configuration: 'partnerDebug')
91 | } else {
92 | compile('com.paypal.sdk:paypal-android-sdk:2.16.0')
93 | }
94 | compile 'com.google.android.gms:play-services-wallet:8.4.0'
95 |
96 | testCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
97 | androidTestCompile 'com.github.lkorth:device-automator:30238040d8'
98 | testCompile 'com.google.dexmaker:dexmaker-mockito:1.1'
99 | testCompile 'com.android.support.test.espresso:espresso-intents:2.2.1'
100 | testCompile 'com.android.support.test.espresso:espresso-web:2.2.1'
101 | testCompile 'com.android.support.test:runner:0.4.1'
102 | testCompile 'com.android.support.test:rules:0.4.1'
103 | }
104 |
105 | task wrapper(type: Wrapper) {
106 | gradleVersion = '2.14.1'
107 | }
108 |
--------------------------------------------------------------------------------
/SampleApp/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/PayPal-Android-SDK/f7534f0951ae0ad1a7127069bac59a9ba8a23bec/SampleApp/debug.keystore
--------------------------------------------------------------------------------
/SampleApp/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/PayPal-Android-SDK/f7534f0951ae0ad1a7127069bac59a9ba8a23bec/SampleApp/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/SampleApp/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Sep 22 16:47:15 CDT 2016
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip
7 |
--------------------------------------------------------------------------------
/SampleApp/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn ( ) {
37 | echo "$*"
38 | }
39 |
40 | die ( ) {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/SampleApp/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/SampleApp/src/androidTest/java/com/paypal/example/paypalandroidsdkexample/test/PaymentTest.java:
--------------------------------------------------------------------------------
1 | package com.paypal.example.paypalandroidsdkexample.test;
2 |
3 | import android.test.suitebuilder.annotation.LargeTest;
4 |
5 | import org.junit.Before;
6 | import org.junit.Test;
7 | import org.junit.runner.RunWith;
8 |
9 | import android.support.test.runner.AndroidJUnit4;
10 |
11 | import static com.lukekorth.deviceautomator.AutomatorAction.click;
12 | import static com.lukekorth.deviceautomator.AutomatorAssertion.text;
13 | import static com.lukekorth.deviceautomator.UiObjectMatcher.withText;
14 | import static com.lukekorth.deviceautomator.UiObjectMatcher.withTextStartingWith;
15 | import static com.paypal.example.paypalandroidsdkexample.test.TestHelper.onDeviceWithScreenShot;
16 | import static com.paypal.example.paypalandroidsdkexample.test.TestHelper.onLogin;
17 | import static com.paypal.example.paypalandroidsdkexample.test.TestHelper.onAgree;
18 | import static com.paypal.example.paypalandroidsdkexample.test.TestHelper.takeScreenshot;
19 | import static org.hamcrest.CoreMatchers.containsString;
20 |
21 |
22 | @RunWith(AndroidJUnit4.class)
23 | @LargeTest
24 | public class PaymentTest {
25 |
26 | @Before
27 | public void setup() {
28 | TestHelper.setup();
29 | }
30 |
31 | /**
32 | * Makes a Single Payment
33 | */
34 | @Test(timeout = 60000)
35 | public void buyAThing() {
36 | onDeviceWithScreenShot(withText("Buy a Thing")).perform(click());
37 | onDeviceWithScreenShot(withText("Pay with")).perform(click());
38 | onLogin();
39 | // Payment Confirmation
40 | onDeviceWithScreenShot(withText("Pay")).perform(click());
41 | // Confirm Result Success
42 | onDeviceWithScreenShot(withTextStartingWith("Result :")).check(text(containsString("PaymentConfirmation")));
43 | }
44 |
45 | /**
46 | * Gets a Future Payment Consent
47 | */
48 | @Test(timeout = 60000)
49 | public void futurePaymentConsent() {
50 | takeScreenshot("futurePaymentConsent");
51 | onDeviceWithScreenShot(withText("Future Payment Consent")).perform(click());
52 | onLogin();
53 | onAgree();
54 | // Confirm Result Success
55 | onDeviceWithScreenShot(withTextStartingWith("Result :")).check(text(containsString("Future Payment")));
56 |
57 | }
58 |
59 | /**
60 | * Makes a Future Payment Purchase
61 | */
62 | @Test(timeout = 60000)
63 | public void futurePaymentPurchase() {
64 | takeScreenshot("futurePaymentPurchase");
65 | onDeviceWithScreenShot(withText("Future Payment Purchase")).perform(click());
66 | // Confirm Result Success
67 | onDeviceWithScreenShot(withTextStartingWith("Result :")).check(text(containsString("Client Metadata Id")));
68 | }
69 |
70 | /**
71 | * Gets Profile Sharing Consent
72 | */
73 | @Test(timeout = 60000)
74 | public void profileSharingConsent() {
75 | takeScreenshot("profileSharingConsent");
76 | onDeviceWithScreenShot(withText("Profile Sharing Consent")).perform(click());
77 | onLogin();
78 | onAgree();
79 | // Confirm Result Success
80 | onDeviceWithScreenShot(withTextStartingWith("Result :")).check(text(containsString("Profile Sharing code")));
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/SampleApp/src/androidTest/java/com/paypal/example/paypalandroidsdkexample/test/TestHelper.java:
--------------------------------------------------------------------------------
1 | package com.paypal.example.paypalandroidsdkexample.test;
2 |
3 | import android.app.Activity;
4 | import android.graphics.Bitmap;
5 | import android.os.Environment;
6 | import android.preference.PreferenceManager;
7 | import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
8 | import android.support.test.runner.lifecycle.Stage;
9 | import android.text.format.DateFormat;
10 | import android.view.View;
11 |
12 | import com.lukekorth.deviceautomator.DeviceAutomator;
13 | import com.lukekorth.deviceautomator.UiObjectMatcher;
14 |
15 | import java.io.File;
16 | import java.io.FileNotFoundException;
17 | import java.io.FileOutputStream;
18 | import java.io.OutputStream;
19 | import java.util.Collection;
20 | import java.util.Date;
21 | import java.util.Iterator;
22 |
23 | import static android.support.test.InstrumentationRegistry.getInstrumentation;
24 | import static android.support.test.InstrumentationRegistry.getTargetContext;
25 | import static com.lukekorth.deviceautomator.AutomatorAction.click;
26 | import static com.lukekorth.deviceautomator.AutomatorAction.setText;
27 | import static com.lukekorth.deviceautomator.DeviceAutomator.onDevice;
28 | import static com.lukekorth.deviceautomator.UiObjectMatcher.withContentDescription;
29 | import static com.lukekorth.deviceautomator.UiObjectMatcher.withText;
30 |
31 | /**
32 | * This helper class provides with methods to help write better tests.
33 | */
34 | public abstract class TestHelper {
35 |
36 | public static final String PAYPAL_SAMPLE_APP_PACKAGE_NAME = "com.paypal.example.paypalandroidsdkexample.debug";
37 | public static final String PAYPAL_SANDBOX_USERNAME = "sample@buy.com";
38 | public static final String PAYPAL_SANDBOX_PASSWORD = "123123123";
39 |
40 | public static void setup() {
41 | PreferenceManager.getDefaultSharedPreferences(getTargetContext())
42 | .edit()
43 | .clear()
44 | .commit();
45 | onDevice().onHomeScreen().launchApp(PAYPAL_SAMPLE_APP_PACKAGE_NAME);
46 | }
47 |
48 | public static DeviceAutomator onDeviceWithScreenShot() {
49 | DeviceAutomator result = onDevice();
50 | takeScreenshot(null);
51 | return result;
52 | }
53 |
54 | public static DeviceAutomator onDeviceWithScreenShot(UiObjectMatcher matcher) {
55 | DeviceAutomator result = onDevice(matcher);
56 | takeScreenshot(null);
57 | return result;
58 | }
59 |
60 | public static void takeScreenshot(String name) {
61 | if (name == null) {
62 | Date now = new Date();
63 | DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);
64 | name = String.valueOf(now.getTime());
65 | }
66 | // In Testdroid Cloud, taken screenshots are always stored
67 | // under /test-screenshots/ folder and this ensures those screenshots
68 | // be shown under Test Results
69 | String path =
70 | Environment.getExternalStorageDirectory().getAbsolutePath() + "/test-screenshots/" + name + ".png";
71 | OutputStream out = null;
72 |
73 | try {
74 | View scrView = getActivityInstance().getWindow().getDecorView().getRootView();
75 | scrView.setDrawingCacheEnabled(true);
76 | Bitmap bm = scrView.getDrawingCache();
77 | Bitmap bitmap = Bitmap.createBitmap(bm);
78 | scrView.setDrawingCacheEnabled(false);
79 |
80 | File imageFile = new File(path);
81 | out = new FileOutputStream(imageFile);
82 | bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
83 | out.flush();
84 | } catch (Exception ex) {
85 | // Ignore any exceptions as this is just for debugging purposes
86 | } finally {
87 | try {
88 | if (out != null) {
89 | out.close();
90 | }
91 | } catch (Exception ex) {
92 | // Nothing to do here
93 | }
94 | }
95 | }
96 |
97 | public static Activity getActivityInstance() {
98 | final Activity[] currentActivity = new Activity[1];
99 | getInstrumentation().waitForIdleSync();
100 | getInstrumentation().runOnMainSync(new Runnable() {
101 | public void run() {
102 | Collection resumedActivities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED);
103 | Iterator iterator = resumedActivities.iterator();
104 | while (iterator.hasNext()) {
105 | currentActivity[0] = (Activity) iterator.next();
106 | }
107 | }
108 | });
109 | return currentActivity[0];
110 | }
111 |
112 | public static void onLogin() {
113 | onDeviceWithScreenShot(withContentDescription("Email")).perform(click(), setText(PAYPAL_SANDBOX_USERNAME));
114 | onDeviceWithScreenShot().pressDPadDown().typeText(PAYPAL_SANDBOX_PASSWORD);
115 | onDeviceWithScreenShot(withText("Log In")).perform(click());
116 | }
117 |
118 | public static void onAgree() {
119 | try {
120 | onDeviceWithScreenShot(withText("Agree")).perform(click());
121 | } catch (RuntimeException ex) {
122 | // This may mean, he has already agreed to it before.
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/SampleApp/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/SampleApp/src/main/java/com/paypal/example/paypalandroidsdkexample/SampleActivity.java:
--------------------------------------------------------------------------------
1 | package com.paypal.example.paypalandroidsdkexample;
2 |
3 | import com.paypal.android.sdk.payments.PayPalAuthorization;
4 | import com.paypal.android.sdk.payments.PayPalConfiguration;
5 | import com.paypal.android.sdk.payments.PayPalFuturePaymentActivity;
6 | import com.paypal.android.sdk.payments.PayPalItem;
7 | import com.paypal.android.sdk.payments.PayPalOAuthScopes;
8 | import com.paypal.android.sdk.payments.PayPalPayment;
9 | import com.paypal.android.sdk.payments.PayPalPaymentDetails;
10 | import com.paypal.android.sdk.payments.PayPalProfileSharingActivity;
11 | import com.paypal.android.sdk.payments.PayPalService;
12 | import com.paypal.android.sdk.payments.PaymentActivity;
13 | import com.paypal.android.sdk.payments.PaymentConfirmation;
14 | import com.paypal.android.sdk.payments.ShippingAddress;
15 |
16 |
17 | import android.app.Activity;
18 | import android.content.Intent;
19 | import android.net.Uri;
20 | import android.os.Bundle;
21 | import android.util.Log;
22 | import android.view.View;
23 | import android.widget.TextView;
24 | import android.widget.Toast;
25 |
26 | import org.json.JSONException;
27 |
28 | import java.math.BigDecimal;
29 | import java.util.Arrays;
30 | import java.util.HashSet;
31 | import java.util.Set;
32 |
33 | /**
34 | *
35 | * THIS FILE IS OVERWRITTEN BY `androidSDK/src/sampleAppJava.
36 | * ANY UPDATES TO THIS FILE WILL BE REMOVED IN RELEASES.
37 | *
38 | * Basic sample using the SDK to make a payment or consent to future payments.
39 | *
40 | * For sample mobile backend interactions, see
41 | * https://github.com/paypal/rest-api-sdk-python/tree/master/samples/mobile_backend
42 | */
43 | public class SampleActivity extends Activity {
44 | private static final String TAG = "paymentExample";
45 | /**
46 | * - Set to PayPalConfiguration.ENVIRONMENT_PRODUCTION to move real money.
47 | *
48 | * - Set to PayPalConfiguration.ENVIRONMENT_SANDBOX to use your test credentials
49 | * from https://developer.paypal.com
50 | *
51 | * - Set to PayPalConfiguration.ENVIRONMENT_NO_NETWORK to kick the tires
52 | * without communicating to PayPal's servers.
53 | */
54 | private static final String CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_NO_NETWORK;
55 |
56 | // note that these credentials will differ between live & sandbox environments.
57 | private static final String CONFIG_CLIENT_ID = "credentials from developer.paypal.com";
58 |
59 | private static final int REQUEST_CODE_PAYMENT = 1;
60 | private static final int REQUEST_CODE_FUTURE_PAYMENT = 2;
61 | private static final int REQUEST_CODE_PROFILE_SHARING = 3;
62 |
63 | private static PayPalConfiguration config = new PayPalConfiguration()
64 | .environment(CONFIG_ENVIRONMENT)
65 | .clientId(CONFIG_CLIENT_ID)
66 | // The following are only used in PayPalFuturePaymentActivity.
67 | .merchantName("Example Merchant")
68 | .merchantPrivacyPolicyUri(Uri.parse("https://www.example.com/privacy"))
69 | .merchantUserAgreementUri(Uri.parse("https://www.example.com/legal"));
70 |
71 | @Override
72 | protected void onCreate(Bundle savedInstanceState) {
73 | super.onCreate(savedInstanceState);
74 | setContentView(R.layout.activity_main);
75 |
76 | Intent intent = new Intent(this, PayPalService.class);
77 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
78 | startService(intent);
79 | }
80 |
81 | public void onBuyPressed(View pressed) {
82 | /*
83 | * PAYMENT_INTENT_SALE will cause the payment to complete immediately.
84 | * Change PAYMENT_INTENT_SALE to
85 | * - PAYMENT_INTENT_AUTHORIZE to only authorize payment and capture funds later.
86 | * - PAYMENT_INTENT_ORDER to create a payment for authorization and capture
87 | * later via calls from your server.
88 | *
89 | * Also, to include additional payment details and an item list, see getStuffToBuy() below.
90 | */
91 | PayPalPayment thingToBuy = getThingToBuy(PayPalPayment.PAYMENT_INTENT_SALE);
92 |
93 | /*
94 | * See getStuffToBuy(..) for examples of some available payment options.
95 | */
96 |
97 | Intent intent = new Intent(SampleActivity.this, PaymentActivity.class);
98 |
99 | // send the same configuration for restart resiliency
100 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
101 |
102 | intent.putExtra(PaymentActivity.EXTRA_PAYMENT, thingToBuy);
103 |
104 | startActivityForResult(intent, REQUEST_CODE_PAYMENT);
105 | }
106 |
107 | private PayPalPayment getThingToBuy(String paymentIntent) {
108 | return new PayPalPayment(new BigDecimal("0.01"), "USD", "sample item",
109 | paymentIntent);
110 | }
111 |
112 | /*
113 | * This method shows use of optional payment details and item list.
114 | */
115 | private PayPalPayment getStuffToBuy(String paymentIntent) {
116 | //--- include an item list, payment amount details
117 | PayPalItem[] items =
118 | {
119 | new PayPalItem("sample item #1", 2, new BigDecimal("87.50"), "USD",
120 | "sku-12345678"),
121 | new PayPalItem("free sample item #2", 1, new BigDecimal("0.00"),
122 | "USD", "sku-zero-price"),
123 | new PayPalItem("sample item #3 with a longer name", 6, new BigDecimal("37.99"),
124 | "USD", "sku-33333")
125 | };
126 | BigDecimal subtotal = PayPalItem.getItemTotal(items);
127 | BigDecimal shipping = new BigDecimal("7.21");
128 | BigDecimal tax = new BigDecimal("4.67");
129 | PayPalPaymentDetails paymentDetails = new PayPalPaymentDetails(shipping, subtotal, tax);
130 | BigDecimal amount = subtotal.add(shipping).add(tax);
131 | PayPalPayment payment = new PayPalPayment(amount, "USD", "sample item", paymentIntent);
132 | payment.items(items).paymentDetails(paymentDetails);
133 |
134 | //--- set other optional fields like invoice_number, custom field, and soft_descriptor
135 | payment.custom("This is text that will be associated with the payment that the app can use.");
136 |
137 | return payment;
138 | }
139 |
140 | /*
141 | * Add app-provided shipping address to payment
142 | */
143 | private void addAppProvidedShippingAddress(PayPalPayment paypalPayment) {
144 | ShippingAddress shippingAddress =
145 | new ShippingAddress().recipientName("Mom Parker").line1("52 North Main St.")
146 | .city("Austin").state("TX").postalCode("78729").countryCode("US");
147 | paypalPayment.providedShippingAddress(shippingAddress);
148 | }
149 |
150 | /*
151 | * Enable retrieval of shipping addresses from buyer's PayPal account
152 | */
153 | private void enableShippingAddressRetrieval(PayPalPayment paypalPayment, boolean enable) {
154 | paypalPayment.enablePayPalShippingAddressesRetrieval(enable);
155 | }
156 |
157 | public void onFuturePaymentPressed(View pressed) {
158 | Intent intent = new Intent(SampleActivity.this, PayPalFuturePaymentActivity.class);
159 |
160 | // send the same configuration for restart resiliency
161 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
162 |
163 | startActivityForResult(intent, REQUEST_CODE_FUTURE_PAYMENT);
164 | }
165 |
166 | public void onProfileSharingPressed(View pressed) {
167 | Intent intent = new Intent(SampleActivity.this, PayPalProfileSharingActivity.class);
168 |
169 | // send the same configuration for restart resiliency
170 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
171 |
172 | intent.putExtra(PayPalProfileSharingActivity.EXTRA_REQUESTED_SCOPES, getOauthScopes());
173 |
174 | startActivityForResult(intent, REQUEST_CODE_PROFILE_SHARING);
175 | }
176 |
177 | private PayPalOAuthScopes getOauthScopes() {
178 | /* create the set of required scopes
179 | * Note: see https://developer.paypal.com/docs/integration/direct/identity/attributes/ for mapping between the
180 | * attributes you select for this app in the PayPal developer portal and the scopes required here.
181 | */
182 | Set scopes = new HashSet(
183 | Arrays.asList(PayPalOAuthScopes.PAYPAL_SCOPE_EMAIL, PayPalOAuthScopes.PAYPAL_SCOPE_ADDRESS) );
184 | return new PayPalOAuthScopes(scopes);
185 | }
186 |
187 | protected void displayResultText(String result) {
188 | ((TextView)findViewById(R.id.txtResult)).setText("Result : " + result);
189 | Toast.makeText(
190 | getApplicationContext(),
191 | result, Toast.LENGTH_LONG)
192 | .show();
193 | }
194 |
195 | @Override
196 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
197 | if (requestCode == REQUEST_CODE_PAYMENT) {
198 | if (resultCode == Activity.RESULT_OK) {
199 | PaymentConfirmation confirm =
200 | data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION);
201 | if (confirm != null) {
202 | try {
203 | Log.i(TAG, confirm.toJSONObject().toString(4));
204 | Log.i(TAG, confirm.getPayment().toJSONObject().toString(4));
205 | /**
206 | * TODO: send 'confirm' (and possibly confirm.getPayment() to your server for verification
207 | * or consent completion.
208 | * See https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/
209 | * for more details.
210 | *
211 | * For sample mobile backend interactions, see
212 | * https://github.com/paypal/rest-api-sdk-python/tree/master/samples/mobile_backend
213 | */
214 | displayResultText("PaymentConfirmation info received from PayPal");
215 |
216 |
217 | } catch (JSONException e) {
218 | Log.e(TAG, "an extremely unlikely failure occurred: ", e);
219 | }
220 | }
221 | } else if (resultCode == Activity.RESULT_CANCELED) {
222 | Log.i(TAG, "The user canceled.");
223 | } else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) {
224 | Log.i(
225 | TAG,
226 | "An invalid Payment or PayPalConfiguration was submitted. Please see the docs.");
227 | }
228 | } else if (requestCode == REQUEST_CODE_FUTURE_PAYMENT) {
229 | if (resultCode == Activity.RESULT_OK) {
230 | PayPalAuthorization auth =
231 | data.getParcelableExtra(PayPalFuturePaymentActivity.EXTRA_RESULT_AUTHORIZATION);
232 | if (auth != null) {
233 | try {
234 | Log.i("FuturePaymentExample", auth.toJSONObject().toString(4));
235 |
236 | String authorization_code = auth.getAuthorizationCode();
237 | Log.i("FuturePaymentExample", authorization_code);
238 |
239 | sendAuthorizationToServer(auth);
240 | displayResultText("Future Payment code received from PayPal");
241 |
242 | } catch (JSONException e) {
243 | Log.e("FuturePaymentExample", "an extremely unlikely failure occurred: ", e);
244 | }
245 | }
246 | } else if (resultCode == Activity.RESULT_CANCELED) {
247 | Log.i("FuturePaymentExample", "The user canceled.");
248 | } else if (resultCode == PayPalFuturePaymentActivity.RESULT_EXTRAS_INVALID) {
249 | Log.i(
250 | "FuturePaymentExample",
251 | "Probably the attempt to previously start the PayPalService had an invalid PayPalConfiguration. Please see the docs.");
252 | }
253 | } else if (requestCode == REQUEST_CODE_PROFILE_SHARING) {
254 | if (resultCode == Activity.RESULT_OK) {
255 | PayPalAuthorization auth =
256 | data.getParcelableExtra(PayPalProfileSharingActivity.EXTRA_RESULT_AUTHORIZATION);
257 | if (auth != null) {
258 | try {
259 | Log.i("ProfileSharingExample", auth.toJSONObject().toString(4));
260 |
261 | String authorization_code = auth.getAuthorizationCode();
262 | Log.i("ProfileSharingExample", authorization_code);
263 |
264 | sendAuthorizationToServer(auth);
265 | displayResultText("Profile Sharing code received from PayPal");
266 |
267 | } catch (JSONException e) {
268 | Log.e("ProfileSharingExample", "an extremely unlikely failure occurred: ", e);
269 | }
270 | }
271 | } else if (resultCode == Activity.RESULT_CANCELED) {
272 | Log.i("ProfileSharingExample", "The user canceled.");
273 | } else if (resultCode == PayPalFuturePaymentActivity.RESULT_EXTRAS_INVALID) {
274 | Log.i(
275 | "ProfileSharingExample",
276 | "Probably the attempt to previously start the PayPalService had an invalid PayPalConfiguration. Please see the docs.");
277 | }
278 | }
279 | }
280 |
281 | private void sendAuthorizationToServer(PayPalAuthorization authorization) {
282 |
283 | /**
284 | * TODO: Send the authorization response to your server, where it can
285 | * exchange the authorization code for OAuth access and refresh tokens.
286 | *
287 | * Your server must then store these tokens, so that your server code
288 | * can execute payments for this user in the future.
289 | *
290 | * A more complete example that includes the required app-server to
291 | * PayPal-server integration is available from
292 | * https://github.com/paypal/rest-api-sdk-python/tree/master/samples/mobile_backend
293 | */
294 |
295 | }
296 |
297 | public void onFuturePaymentPurchasePressed(View pressed) {
298 | // Get the Client Metadata ID from the SDK
299 | String metadataId = PayPalConfiguration.getClientMetadataId(this);
300 |
301 | Log.i("FuturePaymentExample", "Client Metadata ID: " + metadataId);
302 |
303 | // TODO: Send metadataId and transaction details to your server for processing with
304 | // PayPal...
305 | displayResultText("Client Metadata Id received from SDK");
306 | }
307 |
308 | @Override
309 | public void onDestroy() {
310 | // Stop service when done
311 | stopService(new Intent(this, PayPalService.class));
312 | super.onDestroy();
313 | }
314 | }
315 |
--------------------------------------------------------------------------------
/SampleApp/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/PayPal-Android-SDK/f7534f0951ae0ad1a7127069bac59a9ba8a23bec/SampleApp/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleApp/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/PayPal-Android-SDK/f7534f0951ae0ad1a7127069bac59a9ba8a23bec/SampleApp/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleApp/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/PayPal-Android-SDK/f7534f0951ae0ad1a7127069bac59a9ba8a23bec/SampleApp/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleApp/src/main/res/drawable-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/PayPal-Android-SDK/f7534f0951ae0ad1a7127069bac59a9ba8a23bec/SampleApp/src/main/res/drawable-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleApp/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
18 |
19 |
26 |
27 |
34 |
35 |
42 |
43 |
50 |
51 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/SampleApp/src/main/res/values-sw600dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SampleApp/src/main/res/values-sw720dp-land/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | 128dp
8 |
9 |
10 |
--------------------------------------------------------------------------------
/SampleApp/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 10dip
4 | 10dip
5 |
6 |
--------------------------------------------------------------------------------
/SampleApp/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | PayPal SDK Example
5 |
6 |
7 |
--------------------------------------------------------------------------------
/aars/PayPalAndroidSDK-2.16.0.aar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/PayPal-Android-SDK/f7534f0951ae0ad1a7127069bac59a9ba8a23bec/aars/PayPalAndroidSDK-2.16.0.aar
--------------------------------------------------------------------------------
/acknowledgments.md:
--------------------------------------------------------------------------------
1 | Summary
2 | -------
3 |
4 | The PayPal Android SDK uses code from the following libraries:
5 |
6 | * PayPal's [card.io](https://github.com/card-io)
7 | * Willow Garage's [OpenCV](http://opencv.willowgarage.com/wiki/)
8 | * [Eigen](http://eigen.tuxfamily.org)
9 | * [Mersenne Twister](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html)
10 | * Square's [OkHttp](http://square.github.io/okhttp/)
11 | * Apache Commons' [Commons Lang](http://commons.apache.org/proper/commons-lang/)
12 |
13 |
14 | Full licenses
15 | -------------
16 |
17 | PayPal's card.io, MIT license:
18 |
19 | Copyright (c) 2013-2015 PayPal
20 |
21 | Permission is hereby granted, free of charge, to any person obtaining a copy
22 | of this software and associated documentation files (the "Software"), to deal
23 | in the Software without restriction, including without limitation the rights
24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 | copies of the Software, and to permit persons to whom the Software is
26 | furnished to do so, subject to the following conditions:
27 |
28 | The above copyright notice and this permission notice shall be included in
29 | all copies or substantial portions of the Software.
30 |
31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37 | THE SOFTWARE.
38 |
39 |
40 | Willow Garage's OpenCV, BSD license:
41 |
42 | Actual license text not provided -- [the OpenCV website](http://opencv.willowgarage.com/wiki/) says:
43 |
44 | "OpenCV is released under a BSD license, it is free for both academic and commercial use."
45 |
46 | with links to http://opensource.org/licenses/bsd-license.php and http://en.wikipedia.org/wiki/BSD_licenses
47 |
48 |
49 | Eigen: MPLv2 license text can be found at [http://www.mozilla.org/MPL/2.0/](http://www.mozilla.org/MPL/2.0/); the source code is available at [https://bitbucket.org/eigen/eigen/](https://bitbucket.org/eigen/eigen/) or via [http://eigen.tuxfamily.org/](http://eigen.tuxfamily.org/)
50 |
51 |
52 | Makoto Matsumoto and Takuji Nishimura's [Mersenne Twister](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html)
53 |
54 | Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
55 | All rights reserved.
56 |
57 | Redistribution and use in source and binary forms, with or without
58 | modification, are permitted provided that the following conditions
59 | are met:
60 |
61 | 1. Redistributions of source code must retain the above copyright
62 | notice, this list of conditions and the following disclaimer.
63 |
64 | 2. Redistributions in binary form must reproduce the above copyright
65 | notice, this list of conditions and the following disclaimer in the
66 | documentation and/or other materials provided with the distribution.
67 |
68 | 3. The names of its contributors may not be used to endorse or promote
69 | products derived from this software without specific prior written
70 | permission.
71 |
72 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
73 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
74 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
75 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
76 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
77 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
78 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
79 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
80 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
81 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
82 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
83 |
84 |
85 | Square OkHttp, Apache 2.0 license:
86 |
87 | Copyright 2014 Square, Inc.
88 |
89 | Licensed under the Apache License, Version 2.0 (the "License");
90 | you may not use this file except in compliance with the License.
91 | You may obtain a copy of the License at
92 |
93 | http://www.apache.org/licenses/LICENSE-2.0
94 |
95 | Unless required by applicable law or agreed to in writing, software
96 | distributed under the License is distributed on an "AS IS" BASIS,
97 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
98 | See the License for the specific language governing permissions and
99 | limitations under the License.
100 |
101 |
102 | Apache Commons Lang, Apache 2.0 license:
103 |
104 | Licensed to the Apache Software Foundation (ASF) under one or more
105 | contributor license agreements. See the NOTICE file distributed with
106 | this work for additional information regarding copyright ownership.
107 | The ASF licenses this file to You under the Apache License, Version 2.0
108 | (the "License"); you may not use this file except in compliance with
109 | the License. You may obtain a copy of the License at
110 |
111 | http://www.apache.org/licenses/LICENSE-2.0
112 |
113 | Unless required by applicable law or agreed to in writing, software
114 | distributed under the License is distributed on an "AS IS" BASIS,
115 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
116 | See the License for the specific language governing permissions and
117 | limitations under the License.
118 |
--------------------------------------------------------------------------------
/docs/future_payment_error_codes.md:
--------------------------------------------------------------------------------
1 | # Error Codes related to Future Payments
2 |
3 | The following error codes supplement the [REST Payment API error codes](https://developer.paypal.com/webapps/developer/docs/api/#errors).
4 |
5 | ##### invalid_request
6 |
7 | **Internal error**
8 |
9 | This payment cannot be completed through PayPal.
10 |
11 | _or_
12 |
13 | **Invalid access token**
14 |
15 | Access token is invalid or expired. The access token needs to be refreshed using the original request token.
16 |
17 | _or_
18 |
19 | **Invalid refresh token**
20 |
21 | Refresh token is invalid or expired. Obtain consent from the user and get a new refresh token to replace your expired or invalid refresh token.
22 |
23 | ##### REQUIRED_SCOPE_MISSING
24 |
25 | **Access token does not have required scope**
26 |
27 | Obtain user consent using the correct scope required for this type of request.
28 |
29 | ##### INSUFFICIENT_FUNDS
30 |
31 | **Buyer cannot pay - insufficient funds**
32 |
33 | Buyer needs to add a valid funding instrument (e.g. credit card or bank account) to their PayPal account.
34 |
35 | ##### TRANSACTION_REFUSED_PAYEE_PREFERENCE
36 |
37 | **Merchant profile preference is set to automatically deny certain transactions**
38 |
39 | The merchant account preferences are set to deny this particular kind of transaction.
40 |
41 | ##### INVALID_FACILITATOR_CONFIGURATION
42 |
43 | **This transaction cannot be processed due to an invalid facilitator configuration.**
44 |
45 | You must have the right account configuration to process this kind of transaction.
46 |
47 |
--------------------------------------------------------------------------------
/docs/future_payments_mobile.md:
--------------------------------------------------------------------------------
1 | Future Payments Mobile Integration
2 | ==================================
3 |
4 | This section will show how to obtain a user's authorized consent for future payments using their PayPal account.
5 |
6 | _If you haven't already, see the [README](../README.md) for an initial overview and instructions for adding the SDK to your project._
7 |
8 |
9 | Overview
10 | --------
11 |
12 | Your app will use the mobile SDK to obtain two pieces of information at different times.
13 |
14 | First, you must [obtain customer consent](#obtain-customer-consent) to take payments from their PayPal account. How this works:
15 |
16 | * The PayPal Android SDK...
17 | 1. Presents UI for your user to authenticate using their PayPal account.
18 | 2. Asks your user to consent to [OAuth access token scope](http://tools.ietf.org/html/rfc6749#page-23) to use PayPal for future payments.
19 | 3. Returns an OAuth2 authorization code to your app.
20 | * Your app...
21 | 1. Receives an OAuth2 authorization code from the SDK.
22 | 2. Sends the authorization code to your server, which then [exchanges the code for OAuth2 access and refresh tokens](future_payments_server.md#obtain-oauth2-tokens).
23 |
24 | Later, when initiating a pre-consented payment, you must [obtain a Client Metadata ID](#obtain-an-application-correlation-id). How this works:
25 |
26 | * The PayPal Android SDK...
27 | * Provides a Cient Metadata ID.
28 | * Your app...
29 | * Sends the client metadata ID and transaction information to your server.
30 | * Your server then [uses its OAuth2 tokens, Client Metadata ID, and transaction info to create a payment](future_payments_server.md).
31 |
32 |
33 |
34 | Obtain Customer Consent
35 | -----------------------
36 |
37 | The sample app provides a more complete example. However, at minimum, you must:
38 |
39 | 1. Add PayPal Android SDK dependency to your `build.gradle` file as shown in README.md
40 |
41 | 1. Create a `PayPalConfiguration` object. This object allows you to configure various aspects of the SDK.
42 |
43 | ```java
44 | private static PayPalConfiguration config = new PayPalConfiguration()
45 |
46 | // Start with mock environment. When ready, switch to sandbox (ENVIRONMENT_SANDBOX)
47 | // or live (ENVIRONMENT_PRODUCTION)
48 | .environment(PayPalConfiguration.ENVIRONMENT_NO_NETWORK)
49 |
50 | .clientId("")
51 |
52 | // Minimally, you will need to set three merchant information properties.
53 | // These should be the same values that you provided to PayPal when you registered your app.
54 | .merchantName("Example Store")
55 | .merchantPrivacyPolicyUri(Uri.parse("https://www.example.com/privacy"))
56 | .merchantUserAgreementUri(Uri.parse("https://www.example.com/legal"));
57 | ```
58 |
59 | 2. Start `PayPalService` when your activity is created and stop it upon destruction:
60 |
61 | ```java
62 | @Override
63 | protected void onCreate(Bundle savedInstanceState) {
64 | super.onCreate(savedInstanceState);
65 | setContentView(R.layout.activity_main);
66 |
67 | Intent intent = new Intent(this, PayPalService.class);
68 |
69 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
70 |
71 | startService(intent);
72 | }
73 |
74 | @Override
75 | public void onDestroy() {
76 | stopService(new Intent(this, PayPalService.class));
77 | super.onDestroy();
78 | }
79 | ```
80 |
81 | 3. Launch the PayPal Future Payment activity, for example, when a button is pressed:
82 |
83 | ```java
84 | public void onFuturePaymentPressed(View pressed) {
85 | Intent intent = new Intent(SampleActivity.this, PayPalFuturePaymentActivity.class);
86 |
87 | // send the same configuration for restart resiliency
88 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
89 |
90 | startActivityForResult(intent, REQUEST_CODE_FUTURE_PAYMENT);
91 | }
92 | ```
93 |
94 | 4. Implement `onActivityResult()`:
95 |
96 | ```java
97 | @Override
98 | protected void onActivityResult (int requestCode, int resultCode, Intent data) {
99 | if (resultCode == Activity.RESULT_OK) {
100 | PayPalAuthorization auth = data
101 | .getParcelableExtra(PayPalFuturePaymentActivity.EXTRA_RESULT_AUTHORIZATION);
102 | if (auth != null) {
103 | try {
104 | String authorization_code = auth.getAuthorizationCode();
105 |
106 | sendAuthorizationToServer(auth);
107 |
108 | } catch (JSONException e) {
109 | Log.e("FuturePaymentExample", "an extremely unlikely failure occurred: ", e);
110 | }
111 | }
112 | } else if (resultCode == Activity.RESULT_CANCELED) {
113 | Log.i("FuturePaymentExample", "The user canceled.");
114 | } else if (resultCode == PayPalFuturePaymentActivity.RESULT_EXTRAS_INVALID) {
115 | Log.i("FuturePaymentExample",
116 | "Probably the attempt to previously start the PayPalService had an invalid PayPalConfiguration. Please see the docs.");
117 | }
118 | }
119 | ```
120 |
121 | 5. Send the authorization response to your server in order to complete the process.
122 |
123 | ```java
124 | private void sendAuthorizationToServer(PayPalAuthorization authorization) {
125 |
126 | // TODO:
127 | // Send the authorization response to your server, where it can exchange the authorization code
128 | // for OAuth access and refresh tokens.
129 | //
130 | // Your server must then store these tokens, so that your server code can execute payments
131 | // for this user in the future.
132 |
133 | }
134 | ```
135 |
136 | Obtain a Client Metadata ID
137 | -----------------------
138 |
139 | When initiating a pre-consented payment (a "future payment") from a mobile device, your mobile application must obtain a Client Metadata Id from the Mobile SDK to pass to your server. Your server must include this Client Metadata ID in its payment request sent to PayPal.
140 |
141 | PayPal uses this Client Metadata ID to verify that the payment is originating from a valid, user-consented device+application. This helps reduce fraud and decrease declines. **PayPal does not provide any loss protection for transactions that do not correctly supply a Client Metadata ID.**
142 |
143 | **Do not cache or store this value.**
144 |
145 | Example:
146 |
147 | ```java
148 | public void onFuturePaymentPurchasePressed(View pressed) {
149 | // Get the Client Metadata ID from the SDK
150 | String metadataId = PayPalConfiguration.getClientMetadataId(this);
151 |
152 | // TODO: Send metadataId and transaction details to your server for processing with
153 | // PayPal...
154 | }
155 | ```
156 |
157 |
158 | When your server makes its payment request to PayPal, it must include a `PayPal-Client-Metadata-Id` HTTP header with this Client Metadata ID value obtained from the SDK.
159 |
160 |
161 | Next Steps
162 | ----------
163 |
164 | Read [Future Payments Server-Side Integration](future_payments_server.md) to exchange the authorization code for OAuth2 tokens and create payments with an access token and a Metadata ID.
165 |
166 |
--------------------------------------------------------------------------------
/docs/future_payments_server.md:
--------------------------------------------------------------------------------
1 | Future Payments Server-Side Integration
2 | =======================================
3 |
4 | Once a user has authorized your app to use their PayPal account, you can then use that authorization to obtain tokens that let you create future payments from that user.
5 |
6 | This document covers how to:
7 |
8 | 1. [Obtain OAuth2 Tokens](#obtain-oauth2-tokens)
9 | 2. [Create a Payment](#create-a-payment) using those tokens
10 |
11 | _See [Future Payments](future_payments_mobile.md) to let users authenticate and consent to future payments in your app._
12 |
13 |
14 | Obtain OAuth2 Tokens
15 | --------------------
16 |
17 | 1. [Obtain an Authorization Code](#obtain-an-authorization-code)
18 | 2. [Exchange Authorization Code for Refresh / Access Tokens](#exchange-authorization-code-for-refresh--access-tokens)
19 |
20 | ### Obtain an Authorization Code
21 |
22 | The Mobile SDK provides [an API to obtain user consent for future payments](future_payments_mobile.md). Integrate the SDK into your app and use it to authenticate the user and obtain the user's consent. The SDK handles authentication and authorization with the PayPal authentication server, and returns an OAuth2 authorization code to your application.
23 |
24 | This authorization response is a JSON Object. Example:
25 |
26 | ```json
27 | {
28 | "response_type": "paypal_authorization_code",
29 | "response": {
30 | "code": "EBYhRW3ncivudQn8UopLp4A28xIlqPDpAoqd7biDLpeGCPvORHjP1Fh4CbFPgKMGCHejdDwe9w1uDWnjPCp1lkaFBjVmjvjpFtnr6z1YeBbmfZYqa9faQT_71dmgZhMIFVkbi4yO7hk0LBHXt_wtdsw",
31 | },
32 | "client": {
33 | "environment": "live",
34 | "paypal_sdk_version": "2.0.0",
35 | "platform": "Android",
36 | "product_name": "PayPal Android SDK"
37 | }
38 | }
39 | ```
40 |
41 | Your application is responsible for communicating this authorization response to your server. Your server should exchange the authorization code for refresh and access tokens, as described in the next section.
42 |
43 |
44 | ### Exchange Authorization Code for Refresh / Access Tokens
45 |
46 | Once your server has obtained the authorization code, you can use it to get a long-lived refresh token and short-lived access token. The interaction between your server and the PayPal APIs is a standard [OAuth2 Authorization Code Grant Access Request](http://tools.ietf.org/html/rfc6749#section-4.1.3).
47 |
48 | The authorization code is very short-lived. You should exchange it for a refresh and access token **immediately**.
49 |
50 | The refresh token is long-lived (currently 10 years). You should store it securely.
51 |
52 | Note that all returned code and token values should be considered variable length, and may increase in length in the future, so do not assume a fixed maximum.
53 |
54 |
55 | #### Request
56 |
57 | ```bash
58 | curl 'https://api.paypal.com/v1/oauth2/token' \
59 | -H "Content-Type: application/x-www-form-urlencoded" \
60 | -H "Authorization: Basic QWZV...==" \
61 | -d 'grant_type=authorization_code&response_type=token&redirect_uri=urn:ietf:wg:oauth:2.0:oob&code=EBYhRW3ncivudQn8UopLp4A28...'
62 | ```
63 |
64 | * `grant_type`: Token grant type. Value must be set to `authorization_code`.
65 | * `redirect_uri`: Redirect uri. Value must be set to `urn:ietf:wg:oauth:2.0:oob`.
66 | * `code`: Authorization code previously received from the authorization server.
67 |
68 | #### Response
69 |
70 | ```JSON
71 | {
72 | "access_token": "6oyryV79E.KtpAvPudpI8VIko.ntdPikU9HCDfg0tO0",
73 | "expires_in": 28800,
74 | "refresh_token": "MFYQJTPW3zlCAjznPs2D0VQlQXwiEfTesR-dRiU_qhbUngzxR3NmeBxqKELcmGtSI739R-awwvOyGVO1LJbowy7n8Ul3vsf5HQDTCzUlDylqBvW0",
75 | "scope": "https://api.paypal.com/v1/payments/.* https://uri.paypal.com/services/payments/futurepayments",
76 | "token_type": "Bearer"
77 | }
78 | ```
79 |
80 | * `access_token`: The access token issued by the authorization server.
81 | * `expires_in`: The lifetime of the access token in seconds. After the access token expires, use the `refresh_token` to [refresh the access token](#refresh-an-access-token).
82 | * `refresh_token`: The refresh token, which can be used to obtain new access tokens using the same authorization grant, as described in [OAuth2.0 RFC6749 - Section 6](http://tools.ietf.org/html/rfc6749#section-6).
83 | * `scope`: A list of space-separated scope-values associated with this refresh token.
84 | * `token_type`: The type of the token issued as described in [OAuth2.0 RFC6749 - Section 7.1](http://tools.ietf.org/html/rfc6749#section-7.1). Value is case insensitive.
85 |
86 |
87 | Create a Payment
88 | ----------------
89 |
90 | When a user who has granted consent later initiates a payment, your server code will need to:
91 |
92 | 1. Look up the user's refresh token and [use it to get a new access token](#refresh-an-access-token)
93 | 2. [Create a payment using that valid access token](#create-a-payment-using-a-valid-access-token)
94 |
95 | ### Refresh an Access Token
96 |
97 | As mentioned earlier, an access token is only valid for a limited time. Once it expires, you'll need to get a new access token using the refresh token.
98 |
99 | #### Request
100 |
101 | ```bash
102 | curl 'https://api.paypal.com/v1/oauth2/token' \
103 | -H "Content-Type: application/x-www-form-urlencoded" \
104 | -H "Authorization: Basic QWZVa...==" \
105 | -d 'grant_type=refresh_token&refresh_token=MFYQ...'
106 | ```
107 |
108 | * `grant_type`: Token grant type. Value must be set to `refresh_token`. **Required.**
109 | * `refresh_token`: Refresh token previously received along with the access token that is to be refreshed. **Required.**
110 |
111 | #### Response
112 |
113 | ```JSON
114 | {
115 | "access_token": "WfXdnxmyJtdF4q59ofxuQuAAk6eEV-Njm6puht3Nk3w",
116 | "app_id": "APP-3TS46380HB829954H",
117 | "expires_in": 28800,
118 | "scope": "https://api.paypal.com/v1/payments/.* https://uri.paypal.com/services/payments/futurepayments",
119 | "token_type": "Bearer"
120 | }
121 | ```
122 |
123 |
124 | ### Create a Payment Using a Valid Access Token
125 |
126 | Use an access token as the value of the HTTP `Authorization` header to complete the payment, e.g.
127 |
128 | ```
129 | Authorization: Bearer YOUR_ACCESS_TOKEN
130 | ```
131 |
132 | When creating a payment, you can either do a direct sale or an authorization that you later capture.
133 |
134 | Tips:
135 |
136 | * For more information, see [creating a payment](https://developer.paypal.com/webapps/developer/docs/api/#create-a-payment).
137 |
138 | * When a payment is initiated from a mobile device, all payment API requests should include the `PayPal-Client-Metadata-Id` header value obtained using the [Mobile SDK](future_payments_mobile.md#obtain-an-application-correlation-id).
139 |
140 | * Unlike the standard REST API docs that demonstrate a one time payment, a future payment doesn't require you to separately [get payment approval](https://developer.paypal.com/webapps/developer/docs/integration/web/accept-paypal-payment/#get-payment-approval) after getting initial user consent. The payment is pre-approved by the user.
141 |
142 |
143 | ### Example: Authorize then Capture
144 |
145 | For example, to first [authorize the payment](https://developer.paypal.com/webapps/developer/docs/integration/direct/capture-payment/#authorize-the-payment), use a request similar to this:
146 |
147 | #### Request
148 |
149 | ```bash
150 | curl 'https://api.paypal.com/v1/payments/payment' \
151 | -H "Content-Type: application/json" \
152 | -H "PayPal-Client-Metadata-Id: c2edbd6e97b14ff2b19ddb8eec9d264c" \
153 | -H "Authorization: Bearer WfXdnxmyJtdF4q59ofxuQuAAk6eEV-Njm6puht3Nk3w" \
154 | -d '{
155 | "intent":"authorize",
156 | "payer":{
157 | "payment_method":"paypal"
158 | },
159 | "transactions":[
160 | {
161 | "amount":{
162 | "currency":"USD",
163 | "total":"1.88"
164 | },
165 | "description":"future of sauces"
166 | }
167 | ]
168 | }'
169 | ```
170 |
171 | #### Response
172 |
173 | ```JSON
174 | {
175 | "create_time": "2013-10-01T00:43:25Z",
176 | "id": "PAY-2C433581AX997613HKJFBVLI",
177 | "intent": "authorize",
178 | "links": [
179 | {
180 | "href": "https://api.paypal.com/v1/payments/payment/PAY-2C433581AX997613HKJFBVLI",
181 | "method": "GET",
182 | "rel": "self"
183 | }
184 | ],
185 | "payer": {
186 | "payer_info": {
187 | "email": "tnm10@paypal.com",
188 | "first_name": "George",
189 | "last_name": "Martin",
190 | "payer_id": "QLR7PGAJCMCA8"
191 | },
192 | "payment_method": "paypal"
193 | },
194 | "state": "approved",
195 | "transactions": [
196 | {
197 | "amount": {
198 | "currency": "USD",
199 | "details": {
200 | "subtotal": "1.88"
201 | },
202 | "total": "1.88"
203 | },
204 | "description": "future of sauces",
205 | "related_resources": [
206 | {
207 | "authorization": {
208 | "amount": {
209 | "currency": "USD",
210 | "details": {
211 | "subtotal": "1.88"
212 | },
213 | "total": "1.88"
214 | },
215 | "create_time": "2013-10-01T00:43:25Z",
216 | "id": "4TD55050SV609544L",
217 | "links": [
218 | {
219 | "href": "https://api.paypal.com/v1/payments/authorization/4TD55050SV609544L",
220 | "method": "GET",
221 | "rel": "self"
222 | },
223 | {
224 | "href": "https://api.paypal.com/v1/payments/authorization/4TD55050SV609544L/capture",
225 | "method": "POST",
226 | "rel": "capture"
227 | },
228 | {
229 | "href": "https://api.paypal.com/v1/payments/authorization/4TD55050SV609544L/void",
230 | "method": "POST",
231 | "rel": "void"
232 | },
233 | {
234 | "href": "https://api.paypal.com/v1/payments/authorization/4TD55050SV609544L/reauthorize",
235 | "method": "POST",
236 | "rel": "reauthorize"
237 | },
238 | {
239 | "href": "https://api.paypal.com/v1/payments/payment/PAY-2C433581AX997613HKJFBVLI",
240 | "method": "GET",
241 | "rel": "parent_payment"
242 | }
243 | ],
244 | "parent_payment": "PAY-2C433581AX997613HKJFBVLI",
245 | "state": "authorized",
246 | "update_time": "2013-10-01T00:43:28Z",
247 | "valid_until": "2013-10-30T00:43:25Z"
248 | }
249 | }
250 | ]
251 | }
252 | ],
253 | "update_time": "2013-10-01T00:43:28Z"
254 | }
255 | ```
256 |
257 | Once your service is complete or goods provided, you would then [capture the payment](https://developer.paypal.com/webapps/developer/docs/integration/direct/capture-payment/#capture-the-payment):
258 |
259 | #### Request
260 |
261 | ```bash
262 | curl 'https://api.paypal.com/v1/payments/authorization/4TD55050SV609544L/capture' \
263 | -H "Content-Type: application/json" \
264 | -H "PayPal-Client-Metadata-Id: c2edbd6e97b14ff2b19ddb8eec9d264c" \
265 | -H "Authorization: Bearer WfXdnxmyJtdF4q59ofxuQuAAk6eEV-Njm6puht3Nk3w" \
266 | -d '{
267 | "amount":{
268 | "currency":"USD",
269 | "total":"1.50"
270 | },
271 | "is_final_capture":true
272 | }'
273 | ```
274 |
275 | #### Response
276 |
277 | ```JSON
278 | {
279 | "amount": {
280 | "currency": "USD",
281 | "total": "1.50"
282 | },
283 | "create_time": "2013-10-01T00:43:28Z",
284 | "id": "9BS66645698646420",
285 | "is_final_capture": true,
286 | "links": [
287 | {
288 | "href": "https://api.paypal.com/v1/payments/capture/9BS66645698646420",
289 | "method": "GET",
290 | "rel": "self"
291 | },
292 | {
293 | "href": "https://api.paypal.com/v1/payments/capture/9BS66645698646420/refund",
294 | "method": "POST",
295 | "rel": "refund"
296 | },
297 | {
298 | "href": "https://api.paypal.com/v1/payments/authorization/4TD55050SV609544L",
299 | "method": "GET",
300 | "rel": "authorization"
301 | },
302 | {
303 | "href": "https://api.paypal.com/v1/payments/payment/PAY-2C433581AX997613HKJFBVLI",
304 | "method": "GET",
305 | "rel": "parent_payment"
306 | }
307 | ],
308 | "parent_payment": "PAY-2C433581AX997613HKJFBVLI",
309 | "state": "completed",
310 | "update_time": "2013-10-01T00:43:30Z"
311 | }
312 | ```
313 |
314 | The sale is complete when the `state` is shown as `completed`.
315 |
316 |
317 | ### Refunds and Voids
318 |
319 | For refunds and voids, simply use an access token obtained via a [client_credentials request](https://developer.paypal.com/webapps/developer/docs/api/#authentication--headers). (Do not use the user-authorized access token generated from a refresh token, as it will not have sufficient scope.)
320 |
321 | Related information:
322 |
323 | - [Get an access token (for refunds and voids) ](https://developer.paypal.com/webapps/developer/docs/integration/direct/make-your-first-call/#get-an-access-token).
324 | - [Look up a completed sale](https://developer.paypal.com/docs/api/#look-up-a-sale)
325 | - [Refund a direct sale](https://developer.paypal.com/docs/api/#refund-a-sale)
326 | - [Look up an authorization](https://developer.paypal.com/docs/api/#look-up-an-authorization)
327 | - [Void an authorization](https://developer.paypal.com/docs/api/#void-an-authorization)
328 | - [Reauthorize a payment](https://developer.paypal.com/docs/api/#reauthorize-a-payment)
329 | - [Look up a captured payment](https://developer.paypal.com/docs/api/#look-up-a-captured-payment)
330 | - [Refund a captured payment](https://developer.paypal.com/docs/api/#refund-a-captured-payment)
331 |
--------------------------------------------------------------------------------
/docs/ja/README.md:
--------------------------------------------------------------------------------
1 | PayPal Android SDK
2 | ==================
3 |
4 | PayPal Android SDKを使用すると、モバイルアプリにPayPalおよびクレジットカード支払いの機能を簡単に追加できます。
5 |
6 | ## 目次
7 |
8 | - [ユースケース](#use-cases)
9 | - [PayPalウォレットアプリとの統合](#integration-with-the-paypal-wallet-app)
10 | - [要件](#requirements)
11 | - [プロジェクトにSDKを追加する](#add-the-sdk-to-your-project)
12 | - [認証情報](#credentials)
13 | - [海外サポート](#international-support)
14 | - [card.ioカードスキャンの無効化](#disabling-cardio-card-scanning)
15 | - [テスト](#testing)
16 | - [ドキュメント](#documentation)
17 | - [ユーザビリティ](#usability)
18 | - [PayPal Android SDK 2.0への移行](#moving-to-paypal-android-sdk-20)
19 | - [次のステップ](#next-steps)
20 |
21 |
22 | ### 1件の支払い(Single Payment)
23 |
24 | お客さまのPayPalアカウントまたは([card.io](https://www.card.io/)でスキャンされた)決済カードから即時支払いを受け取ります。
25 |
26 | 1. [1件の支払いを受諾](single_payment.md)して支払い証明を受け取ります。2. ご使用のサーバーで、PayPalのAPIを使用して[支払いを認証](https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/) (PayPalデベロッパーサイト)します。
27 |
28 |
29 | ### 今後の支払い(Future Payments)
30 |
31 | お客さまは、一度だけPayPalにログインして今後の支払いに同意します。
32 | 1. [お客さまの同意を得て](future_payments_mobile.md#obtain-customer-consent)承認コードを受け取ります。2. ご使用のサーバーで、この承認コードを使用して[OAuth2トークンを取得](future_payments_server.md#obtain-oauth2-tokens)します。
33 |
34 | この後、お客さまが支払いを開始すると以下のプロセスに進みます。
35 |
36 | 1. サーバーに渡す[アプリケーション相関IDを取得](future_payments_mobile.md#obtain-an-application-correlation-id)します。
37 | 2. お使いのサーバーで、OAuth2トークン、アプリケーション相関ID、およびPayPalのAPIを使用して[支払いを作成](future_payments_server.md#create-a-payment)します。
38 |
39 | ###個人設定の共有
40 |
41 | お客さまは、PayPalにログインして、PayPalが貴社と情報を共有することに同意します。
42 |
43 | 1. [お客さまの同意を得て](profile_sharing_mobile.md#obtain-customer-consent)承認コードを取得します。2. ご使用のサーバーで、この承認コードを使用して[OAuth2トークンを取得](profile_sharing_server.md#obtain-oauth2-tokens)します。3. ご使用のサーバーで、OAuth2トークンとPayPalのAPIを使用して、[顧客情報を検索](profile_sharing_server.md#retrieve-customer-information)します。
44 |
45 |
46 | ## PayPalウォレットアプリとの統合
47 |
48 | SDKは、デバイスにPayPalウォレットアプリの最新バージョン([Samsung App Store](apps.samsung.com/mars/topApps/topAppsDetail.as?categoryId=G000019679&productId=000000794995)でのみ入手可能)がインストールされている場合はそれを使用して、お客さまのアカウントにログインするようになります。この機能を有効にするため、追加構成を行う必要はありません。この統合により、Galaxy S5の指紋認証ログインを含む端末固有のPayPal [FIDO](https://fidoalliance.org/)との統合が有効になります。さらに、PayPalウォレットアプリにログインして[ログインしたままにする]にチェックを入れたユーザーは、アプリでの支払い時に再度ログインする必要がありません。この機能についての詳細は、PayPalアーキテクトの[ブログポスト](http://www.embedded.com/design/real-world-applications/4430305/Implementing-Android-based-fingerprint-authentication-for-online-payments)を参照してください。
49 |
50 | ### 制限
51 |
52 | * サポートされるアプリは、[Samsung App Store](apps.samsung.com/mars/topApps/topAppsDetail.as?categoryId=G000019679&productId=000000794995)でのみ入手できます。Google PlayストアのバージョンのPayPalウォレットアプリは、まだこの統合をサポートしていません。* ウォレットアプリはデベロッパーのテスト環境に対応して_いない_ため、統合は[テスト](#testing)モードでは無効です。
53 |
54 | ## 要件
55 |
56 | * Android 2.2またはそれ以降
57 | * card.ioカードスキャニング(armv7デバイスでのみ使用可能)
58 | * 電話またはタブレット
59 |
60 |
61 | ## プロジェクトにSDKを追加する
62 |
63 | 1. このrepoをダウンロードまたはコピーします。SDKには、.jar、スタティックライブラリ、リリースノート、ライセンス許諾書が含まれています。サンプルアプリも含まれています。2. SDKの`libs`ディレクトリのコンテンツを自分のプロジェクトの`libs`ディレクトリにコピーします。これらのファイルへのパスは重要です。誤りがあるとSDKが機能しません。(_注:_ Gradleを使用している場合は、SDK jarファイルを自分のプロジェクトの`libs`ディレクトリにコピーして、プロジェクトに`ライブラリとして追加`し、最後に*.soファイルを含むSDKフォルダを`src/main/jniLibs`にコピーしてください)。
64 | 3. `acknowledgments.md`から、オープンソースライセンス許諾書を自分のアプリの許諾書に追加します。
65 |
66 |
67 | ## 認証情報
68 |
69 | モバイル統合では、本番用とテスト用(Sandbox)にそれぞれ異なる`client_id`値が必要です。
70 |
71 | 支払いを認証または作成するためのサーバー統合では、各`client_id`に対応する`client_secret`も必要です。
72 |
73 | PayPal API認証情報は、[PayPalデベロッパーサイトのアプリケーションページ](https://developer.paypal.com/webapps/developer/applications)を開いて、自分のPayPalアカウントでログインすると入手できます。
74 |
75 | ### Sandbox
76 |
77 | このアプリケーションページにログインすると、**テスト用認証情報**が割り当てられます。これには、PayPal SandboxへのAndroidの統合をテストするためのクライアントIDが含まれています。
78 |
79 | アプリのテスト中にSDKのUIでPayPalにログインする場合は、*パーソナル*Sandboxアカウントのメールアドレスとパスワードを使用する必要があります。Sandbox用*ビジネス*アカウントの認証情報は使いません。
80 |
81 | [Sandboxアカウント](https://developer.paypal.com/webapps/developer/applications/accounts)ページで、Sandbox用のビジネスアカウントとパーソナルアカウントを作成できます。
82 |
83 | ### 本番環境
84 |
85 | **本番用**認証情報を入手するには、ビジネスアカウントが必要です。ビジネスアカウントをまだお持ちでない場合は、同じアプリケーションページの下部にリンクがあり、ここからアカウントを開設できます。
86 |
87 |
88 | ## 海外サポート
89 |
90 | ### ローカライズ
91 |
92 | SDKには、多数の言語およびロケールの翻訳が組み込まれています。完全なリストは、[javadoc](http://paypal.github.io/PayPal-Android-SDK/)ファイルで参照できます。
93 |
94 | ### 通貨
95 |
96 | SDKでは複数の通貨に対応しています。完全な最新リストは、[REST APIの国と通貨に関するドキュメント](https://developer.paypal.com/webapps/developer/docs/integration/direct/rest_api_payment_country_currency_support/)で参照してください。
97 |
98 | クレジットカードとPayPal支払いでは対応通貨が異なりますのでご注意ください。`PaymentActivity.EXTRA_SKIP_CREDIT_CARD` intent extraを使用してクレジットカード決済の受付けを無効にしない限り、**取引を、両方の支払いタイプで対応している通貨に限定することをおすすめします。** 現在両方で対応している通貨は、USD、GBP、CAD、EUR、JPYです。
99 |
100 | ユーザーが選択した支払いタイプで対応していない通貨を使用してアプリが取引を開始した場合、SDKはユーザーにエラーを表示し、コンソールログにメッセージを出力します。
101 |
102 |
103 | ## card.ioによるカードスキャンの無効化
104 |
105 | 今後の支払いではcard.ioによるカードスキャンが不要なため、カメラスキャナライブラリを削除しておいたほうが安全です。`lib`ディレクトリの`armeabi`、`armeabi-v7a`、`mips`、および`x86`の各フォルダを削除します。
106 |
107 | 1件の支払いは、カードスキャンをせず、手動入力でクレジットカードに対応するよう設定できます。これを行うには、上記と同じライブラリを削除し、`AndroidManifest.xml`から`android.permission.CAMERA`と`android.permission.VIBRATE`の許可を削除してください。クレジットカードのサポートを完全に無効にする場合は、上記の手順で許可とSDKのフットプリントを減らし、`PayPalConfiguration`の初期化に以下を追加してください。
108 | ```
109 | config.acceptCreditCards(false);
110 | ```
111 |
112 | ## テスト
113 |
114 | 開発中は、`PayPalConfiguration`オブジェクトで`environment()`を使用して環境を変更してください。実際に資金が移動されないよう、`ENVIRONMENT_NO_NETWORK`または`ENVIRONMENT_SANDBOX`に設定します。
115 |
116 |
117 | ## ドキュメント
118 |
119 | * 使用方法の概要、統合手順をステップごとに記載した説明書、サンプルコードを含むドキュメントがSDKに用意されています。* このSDKにはサンプルアプリが含まれています。* [javadocs](http://paypal.github.io/PayPal-Android-SDK/)が用意されています。* エラーコードとサーバー側の統合手順が記載された[PayPalデベロッパードキュメント](https://developer.paypal.com/docs)。
120 |
121 |
122 | ## ユーザビリティ
123 |
124 | ユーザーインターフェイスの外観と動作は、ライブラリ内で設定されます。ユーザビリティとユーザーエクスペリエンスの一貫性を保つため、ドキュメントに記載された方法以外でアプリがSDKの動作を変更することはおすすめしません。
125 |
126 |
127 | ## PayPal Android SDK 2.0への移行
128 |
129 |
130 | ### 1.xからのアップグレード
131 |
132 | メジャーバージョンの変更として、2.0で導入されるAPIは、1.x統合との下位互換性がありません。ただし、SDKは、1件の支払いについて、これまでのすべての機能を引き続きサポートしています。アップグレードは簡単です。
133 |
134 | * `PayPalPaymentActivity`の支払い固有のextra以外のextraの多くは`PayPalConfiguration`クラスに移動しています。サービススタートアップはそのような構成オブジェクトを取得するよう変更されています。
135 |
136 |
137 |
138 | ### 旧ライブラリ
139 |
140 | PayPalは、これまでの「Mobile Payments Libraries」(MPL)から新しいPayPal AndroidおよびiOS SDKに移行中です。
141 | 新しいモバイルSDKはPayPal REST APIに基づいています。これまでのMPLはアダプティブペイメントAPIを使用しています。
142 |
143 | 第三者、並行型、チェーン型の支払いなどの機能が使えるようになるまでは、必要に応じてMPLを使用できます。
144 |
145 | - [GitHubのMPL](https://github.com/paypal/sdk-packages/tree/gh-pages/MPL)
146 | - [MPLに関するドキュメント](https://developer.paypal.com/webapps/developer/docs/classic/mobile/gs_MPL/)
147 |
148 | MPLに関する問題は、[sdk-packages repo](https://github.com/paypal/sdk-packages/)に提出してください。
149 |
150 | 既存のエクスプレス チェックアウトを統合しているデベロッパーまたは追加機能が必要なデベロッパーは、WebViewで[モバイルエクスプレス チェックアウト](https://developer.paypal.com/webapps/developer/docs/classic/mobile/gs_MEC/)の使用を検討することができます。
151 |
152 |
153 | ## 次のステップ
154 |
155 | ユースケースに応じて、以下が可能です:
156 |
157 | * [1件の支払いを受ける](single_payment.md)
158 | * [今後の支払いを作成](future_payments_server.md)ために[ユーザーの同意を得る](future_payments_mobile.md)
159 |
--------------------------------------------------------------------------------
/docs/ja/future_payment_error_codes.md:
--------------------------------------------------------------------------------
1 | # 今後の支払い(Future Payments)に関するエラーコード
2 |
3 | 以下のエラーコードは、[REST決済APIエラーコード](https://developer.paypal.com/webapps/developer/docs/api/#errors)の補足です。
4 |
5 | ##### invalid_request
6 |
7 | **内部エラー**
8 |
9 | この支払いは、PayPalでは完了できません。
10 |
11 | _または_
12 |
13 | **アクセストークンが無効です**
14 |
15 | アクセストークンが無効または期限切れです。アクセストークンは、元のリクエストトークンを使用して更新する必要があります。
16 |
17 | _または_
18 |
19 | **リフレッシュトークンが無効です**
20 |
21 | リフレッシュトークンが無効または期限切れです。ユーザーの同意を得て、期限切れまたは無効なリフレッシュトークンを置き換える新しいリフレッシュトークンを取得してください。
22 |
23 | ##### REQUIRED_SCOPE_MISSING
24 |
25 | **アクセストークンに必要なスコープがありません**
26 |
27 | このタイプのリクエストに必要な正しいスコープを使用して、ユーザーの同意を得てください。
28 |
29 | ##### INSUFFICIENT_FUNDS
30 |
31 | **買い手は支払えません - 資金不足です**
32 |
33 | 買い手は、有効な支払い方法(クレジットカードや銀行口座など)をPayPalアカウントに追加する必要があります。
34 |
35 | ##### TRANSACTION_REFUSED_PAYEE_PREFERENCE
36 |
37 | **マーチャントの個人設定で特定取引の自動拒否が設定されています**
38 |
39 | マーチャントのアカウントは、この特定タイプの取引を拒否するよう設定されています。
40 |
41 | ##### INVALID_FACILITATOR_CONFIGURATION
42 |
43 | **この取引は無効なファシリテーター設定により処理できません。**
44 |
45 | この種類の取引を処理するには、適切なアカウント設定が必要です。
46 |
47 |
--------------------------------------------------------------------------------
/docs/ja/future_payments_mobile.md:
--------------------------------------------------------------------------------
1 | 今後の支払い(Future Payments)のためのモバイルの統合
2 | ==================================
3 |
4 | ここでは、PayPalアカウントを使用して今後の支払いを行うためにユーザーの同意を得る方法を説明します。
5 |
6 | _まだ実行していない場合は、プロジェクトにSDKを追加するための基本的な概要と手順の[README](README.md)を参照してください。_
7 |
8 |
9 | 概要
10 | --------
11 |
12 | ご使用のアプリは、モバイルSDKを使って異なるタイミングで2つの情報を取得します。
13 |
14 | 最初に、PayPalアカウントからの支払いを受け取るため、[お客さまの同意を得る](#obtain-customer-consent)必要があります。これは以下のように実行されます。
15 |
16 | * PayPal Android SDKは
17 | 1. ユーザーがPayPalアカウントの使用を承認するためのUIを表示します。
18 | 2. 今後の支払いでPayPalを使用するための[OAuthアクセストークンスコープ](http://tools.ietf.org/html/rfc6749#page-23)に対する同意をユーザーに求めます。
19 | 3. アプリに、OAuth2の認可コードを返します。
20 | * アプリは
21 | 1. SDKからOAuth2の認可コードを受け取ります。
22 | 2. サーバーに認可コードを送ります。サーバーは[コードをOAuth2のアクセストークンおよびリフレッシュトークンと交換](future_payments_server.md#obtain-oauth2-tokens)します。
23 |
24 | 後に、事前承認された支払いの開始時に、[アプリケーション相関IDを取得する](#obtain-an-application-correlation-id)必要があります。これは以下のように実行されます。
25 |
26 | * PayPal Android SDKは
27 | * アプリケーション相関IDを提供します。
28 | * アプリは
29 | * 相関IDと取引情報をサーバーに送ります。
30 | * サーバーは、[OAuth2のトークン、アプリケーション相関ID、および取引情報を使用して支払いを作成](future_payments_server.md)します。
31 |
32 |
33 |
34 | お客さまの同意を得る
35 | -----------------------
36 |
37 | サンプルアプリには、より完全な例が用意されています。ただし、最低限以下を行う必要があります。
38 |
39 | 1. `AndroidManifest.xml`ファイルに許可を追加します。
40 | ```xml
41 |
42 |
43 |
44 |
45 | ```
46 |
47 | 1. `AndroidManifest.xml`ファイルの``タグでSDKのサービスとアクティビティを宣言します。
48 | ```xml
49 |
51 |
52 |
53 |
54 |
55 |
56 | ```
57 |
58 | 1. `PayPalConfiguration`オブジェクトを作成します。このオブジェクトにより、SDKのさまざまな側面を設定できます。
59 |
60 | ```java
61 | private static PayPalConfiguration config = new PayPalConfiguration()
62 |
63 | // モック環境で開始します。準備完了後、sandbox (ENVIRONMENT_SANDBOX)
64 | // または本番 (ENVIRONMENT_PRODUCTION)環境に切り替えます。
65 | .environment(PayPalConfiguration.ENVIRONMENT_NO_NETWORK)
66 |
67 | .clientId("")
68 |
69 | // 最低限3つのマーチャント情報プロパティを設定する必要があります。
70 | // これらは、アプリを登録した際にPayPalに提供した値と同じである必要があります。
71 | .merchantName("Example Store")
72 | .merchantPrivacyPolicyUri(Uri.parse("https://www.example.com/privacy"))
73 | .merchantUserAgreementUri(Uri.parse("https://www.example.com/legal"));
74 | ```
75 |
76 | 2. アクティビティの作成時に`PayPalService`を開始し、破棄の際に停止します。
77 |
78 | ```java
79 | @Override
80 | protected void onCreate(Bundle savedInstanceState) {
81 | super.onCreate(savedInstanceState);
82 | setContentView(R.layout.activity_main);
83 |
84 | Intent intent = new Intent(this, PayPalService.class);
85 |
86 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
87 |
88 | startService(intent);
89 | }
90 |
91 | @Override
92 | public void onDestroy() {
93 | stopService(new Intent(this, PayPalService.class));
94 | super.onDestroy();
95 | }
96 | ```
97 |
98 | 3. PayPalの今後の支払いアクティビティを、たとえばボタンが押された場合などに起動します。
99 |
100 | ```java
101 | public void onFuturePaymentPressed(View pressed) {
102 | Intent intent = new Intent(SampleActivity.this, PayPalFuturePaymentActivity.class);
103 |
104 | startActivityForResult(intent, REQUEST_CODE_FUTURE_PAYMENT);
105 | }
106 | ```
107 |
108 | 4. `onActivityResult()`を実装します。
109 |
110 | ```java
111 | @Override
112 | protected void onActivityResult (int requestCode, int resultCode, Intent data) {
113 | if (resultCode == Activity.RESULT_OK) {
114 | PayPalAuthorization auth = data
115 | .getParcelableExtra(PayPalFuturePaymentActivity.EXTRA_RESULT_AUTHORIZATION);
116 | if (auth != null) {
117 | try {
118 | String authorization_code = auth.getAuthorizationCode();
119 |
120 | sendAuthorizationToServer(auth);
121 |
122 | } catch (JSONException e) {
123 | Log.e("FuturePaymentExample", "非常にまれなエラーが発生しました: ", e);
124 | }
125 | }
126 | } else if (resultCode == Activity.RESULT_CANCELED) {
127 | Log.i("FuturePaymentExample", "ユーザーがキャンセルしました。");
128 | } else if (resultCode == PayPalFuturePaymentActivity.RESULT_EXTRAS_INVALID) {
129 | Log.i("FuturePaymentExample",
130 | "PayPalServiceを前に開始するための処理で、無効なPayPalConfigurationが含まれていた可能性があります。ドキュメントを参照してください。");
131 | }
132 | }
133 | ```
134 |
135 | 5. プロセスを完了するため、サーバーに認可応答を送信します。
136 |
137 | ```java
138 | private void sendAuthorizationToServer(PayPalAuthorization authorization) {
139 |
140 | // TODO:
141 | // 認可応答をサーバーに送信します。サーバーは認可コードを
142 | // OAuthのアクセストークンおよびリフレッシュトークンと交換できます。
143 | //
144 | // サーバーはこれらのトークンを保管するので、サーバーコードは、今後このユーザーの
145 | // 支払いを実行できます。
146 |
147 | }
148 | ```
149 |
150 | アプリケーション相関IDの取得
151 | -----------------------
152 |
153 | モバイル端末から事前承認された支払い(「今後の支払い」)を開始する場合、モバイルアプリは、アプリケーション相関IDをモバイルSDKから取得し、サーバーに渡す必要があります。サーバーは、PayPalに送信する支払いリクエストにこのアプリケーション相関IDを含める必要があります。
154 |
155 | PayPalは、このアプリケーション相関IDを使用して、ユーザーが同意した有効な端末およびアプリから支払いが行われていることを認証します。これは、不正取引や拒否を減らすことに役立ちます。**PayPalは、適切にアプリケーション相関IDを提供しない取引での損失についてはいっさい保護しません。**
156 |
157 | **この値をキャッシュまたは格納しないでください。**
158 |
159 | 例
160 |
161 | ```java
162 | public void onFuturePaymentPurchasePressed(View pressed) {
163 | // SDKからアプリケーション相関IDを取得します。
164 | String metadataId = PayPalConfiguration.getClientMetadataId(this);
165 |
166 | // TODO: PayPalでの処理のため、相関IDと取引の詳細をサーバーに
167 | // 送信します。
168 | }
169 | ```
170 |
171 |
172 | サーバーは、PayPalへの支払いリクエストを作成する際、HTTPヘッダー`PayPal-Client-Metadata-Id`に、SDKから取得したこのアプリケーション相関IDの値を含める必要があります。
173 |
174 |
175 | 次の手順
176 | ----------
177 |
178 | [今後の支払いのためのサーバー側の統合](future_payments_server.md)を読み、認可コードとOAuth2のトークンを交換して、アクセストークンと相関IDにより支払いを作成します。
179 |
180 |
--------------------------------------------------------------------------------
/docs/ja/future_payments_server.md:
--------------------------------------------------------------------------------
1 | 今後の支払い(Future Payments)のためのサーバー側の統合
2 | =======================================
3 |
4 | ユーザーが、自分のPayPalアカウントの使用をアプリに承認すると、この承認を使用して、そのユーザーからの今後の支払いを作成するトークンを取得できます。
5 |
6 | このドキュメントには以下の方法が記載されています。
7 |
8 | 1. [OAuth2のトークンを取得する](#obtain-oauth2-tokens)
9 | 2. 取得したトークンを使用して[支払いを作成する](#create-a-payment)
10 |
11 | _ユーザーに、アプリで今後の支払いを承認し、同意してもらうには、[今後の支払い](future_payments_mobile.md)を参照してください。_
12 |
13 |
14 | OAuth2のトークンを取得する
15 | --------------------
16 |
17 | 1. [認可コードを取得する](#obtain-an-authorization-code)
18 | 2. [認可コードとリフレッシュ/アクセストークンを交換する](#exchange-authorization-code-for-refresh--access-tokens)
19 |
20 | ### 認可コードを取得する
21 |
22 | モバイルSDKは、[今後の支払いについてユーザーの承認を得るためのAPI](future_payments_mobile.md)を提供しています。アプリにSDKを統合し、それを使ってユーザーを認証し、ユーザーの同意を得ます。SDKは、PayPal認証サーバーで認証および承認を処理し、OAuth2の認可コードをアプリに返します。
23 |
24 | この認可応答はJSONオブジェクトです。例
25 |
26 | ```json
27 | {
28 | "response_type": "paypal_authorization_code",
29 | "response": {
30 | "code": "EBYhRW3ncivudQn8UopLp4A28xIlqPDpAoqd7biDLpeGCPvORHjP1Fh4CbFPgKMGCHejdDwe9w1uDWnjPCp1lkaFBjVmjvjpFtnr6z1YeBbmfZYqa9faQT_71dmgZhMIFVkbi4yO7hk0LBHXt_wtdsw",
31 | },
32 | "client": {
33 | "environment": "live",
34 | "paypal_sdk_version": "2.0.0",
35 | "platform": "Android",
36 | "product_name": "PayPal Android SDK"
37 | }
38 | }
39 | ```
40 |
41 | アプリは、この認可応答をサーバーに送信する必要があります。サーバーは、次のセクションで説明するように、認可コードと、リフレッシュトークンおよびアクセストークンを交換する必要があります。
42 |
43 |
44 | ### 認可コードとリフレッシュ/アクセストークンを交換する
45 |
46 | サーバーが認可コードを取得すると、これを使用して、有効期限の長いリフレッシュトークンと有効期限の短いアクセストークンを取得できるようになります。サーバーとPayPal APIの通信は、標準的な[OAuth2の認可コードグラントアクセスリクエスト](http://tools.ietf.org/html/rfc6749#section-4.1.3)です。
47 |
48 | 認可コードには、非常に短い有効期限が設定されています。**ただちに**認可コードをリフレッシュトークンとアクセストークンに交換する必要があります。
49 |
50 | リフレッシュトークンの有効期限は長く、現在のところ10年です。安全に保管する必要があります。
51 |
52 | 返されるコードやトークンの値はすべて可変長として扱ってください。今後さらに長くなる可能性がありますので、最大長が固定されているものとして扱わないでください。
53 |
54 |
55 | #### リクエスト
56 |
57 | ```bash
58 | curl 'https://api.paypal.com/v1/oauth2/token' \
59 | -H "Content-Type: application/x-www-form-urlencoded" \
60 | -H "Authorization: Basic QWZV...==" \
61 | -d 'grant_type=authorization_code&response_type=token&redirect_uri=urn:ietf:wg:oauth:2.0:oob&code=EBYhRW3ncivudQn8UopLp4A28...'
62 | ```
63 |
64 | * `grant_type`: トークンのグラントタイプです。値は`authorization_code`に設定する必要があります。
65 | * `redirect_uri`: リダイレクトURLです。値は`urn:ietf:wg:oauth:2.0:oob`に設定する必要があります。
66 | * `code`: 認可サーバーから以前に受信した認可コードです。
67 |
68 | #### 応答
69 |
70 | ```JSON
71 | {
72 | "access_token": "6oyryV79E.KtpAvPudpI8VIko.ntdPikU9HCDfg0tO0",
73 | "expires_in": 28800,
74 | "refresh_token": "MFYQJTPW3zlCAjznPs2D0VQlQXwiEfTesR-dRiU_qhbUngzxR3NmeBxqKELcmGtSI739R-awwvOyGVO1LJbowy7n8Ul3vsf5HQDTCzUlDylqBvW0",
75 | "scope": "https://api.paypal.com/v1/payments/.* https://uri.paypal.com/services/payments/futurepayments",
76 | "token_type": "Bearer"
77 | }
78 | ```
79 |
80 | * `access_token`: 認可サーバーによって発行されたアクセストークンです。
81 | * `expires_in`: アクセストークンの秒単位での有効期限です。アクセストークンの期限切れ後、`refresh_token`を使用して[アクセストークンを更新](#refresh-an-access-token)します。
82 | * `refresh_token`: リフレッシュトークン。[OAuth2.0 RFC6749 - セクション6](http://tools.ietf.org/html/rfc6749#section-6)で説明されているように、これにより、同じ認可グラントを使用する新しいアクセストークンを取得することができます。
83 | * `scope`: このリフレッシュトークンに関連するスコープ値をスペースで区切ったリストです。
84 | * `token_type`: [OAuth2.0 RFC6749 - セクション7.1](http://tools.ietf.org/html/rfc6749#section-7.1)で説明されているタイプの発行済みトークンです。値は、大文字と小文字が区別されます。
85 |
86 |
87 | 支払いの作成
88 | ----------------
89 |
90 | 今度の支払いについて同意したユーザーが支払いを開始した場合、サーバーコードで以下を実行する必要があります。
91 |
92 | 1. ユーザーのリフレッシュトークンを検索し、[そのトークンを使用して新しいアクセストークンを取得](#refresh-an-access-token)する
93 | 2. [有効なアクセストークンを使用して支払いを作成する](#create-a-payment-using-a-valid-access-token)
94 |
95 | ### アクセストークンの更新
96 |
97 | 前述したように、アクセストークンには有効期限があります。アクセストークンの期限が切れた場合は、リフレッシュトークンを使用して新しいアクセストークンを取得する必要があります。
98 |
99 | #### リクエスト
100 |
101 | ```bash
102 | curl 'https://api.paypal.com/v1/oauth2/token' \
103 | -H "Content-Type: application/x-www-form-urlencoded" \
104 | -H "Authorization: Basic QWZVa...==" \
105 | -d 'grant_type=refresh_token&refresh_token=MFYQ...'
106 | ```
107 |
108 | * `grant_type`: トークンのグラントタイプです。値は`refresh_token`に設定する必要があります。**必須です。**
109 | * `refresh_token`: 更新されるアクセストークンとともに以前に受信したリフレッシュトークンです。**必須です。**
110 |
111 | #### 応答
112 |
113 | ```JSON
114 | {
115 | "access_token": "WfXdnxmyJtdF4q59ofxuQuAAk6eEV-Njm6puht3Nk3w",
116 | "app_id": "APP-3TS46380HB829954H",
117 | "expires_in": 28800,
118 | "scope": "https://api.paypal.com/v1/payments/.* https://uri.paypal.com/services/payments/futurepayments",
119 | "token_type": "Bearer"
120 | }
121 | ```
122 |
123 |
124 | ### 有効なアクセストークンを使用した支払いの作成
125 |
126 | 次のように、アクセストークンをHTTPの`Authorization`ヘッダーの値として使用して支払いを完了します。
127 |
128 | ```
129 | Authorization: Bearer YOUR_ACCESS_TOKEN
130 | ```
131 |
132 | 支払いの作成時に、直接の販売や後日支払いを回収する承認を行うことができます。
133 |
134 | ヒント:
135 |
136 | * 詳細は[支払いの作成](https://developer.paypal.com/webapps/developer/docs/api/#create-a-payment)を参照してください。
137 |
138 | * モバイル端末から支払いが開始された場合、すべての決済APIリクエストに、[モバイルSDK]を使用して取得された`PayPal-Client-Metadata-Id`ヘッダー値(future_payments_mobile.md#obtain-an-application-correlation-id)が含まれる必要があります。
139 |
140 | * 1回払いの実例を示す標準的なREST APIのドキュメントとは異なり、今後の支払いでは、最初にユーザーの同意を得た後は、そのつど[支払いの承認を得る](https://developer.paypal.com/webapps/developer/docs/integration/web/accept-paypal-payment/#get-payment-approval)必要はありません。支払いは、ユーザーによって事前承認されています。
141 |
142 |
143 | ### 例: 承認と回収
144 |
145 | たとえば、最初に[支払いを承認する](https://developer.paypal.com/webapps/developer/docs/integration/direct/capture-payment/#authorize-the-payment)には、リクエストを次のように使用します。
146 |
147 | #### リクエスト
148 |
149 | ```bash
150 | curl 'https://api.paypal.com/v1/payments/payment' \
151 | -H "Content-Type: application/json" \
152 | -H "PayPal-Client-Metadata-Id: c2edbd6e97b14ff2b19ddb8eec9d264c" \
153 | -H "Authorization: Bearer WfXdnxmyJtdF4q59ofxuQuAAk6eEV-Njm6puht3Nk3w" \
154 | -d '{
155 | "intent":"authorize",
156 | "payer":{
157 | "payment_method":"paypal"
158 | },
159 | "transactions":[
160 | {
161 | "amount":{
162 | "currency":"USD",
163 | "total":"1.88"
164 | },
165 | "description":"future of sauces"
166 | }
167 | ]
168 | }'
169 | ```
170 |
171 | #### 応答
172 |
173 | ```JSON
174 | {
175 | "create_time": "2013-10-01T00:43:25Z",
176 | "id": "PAY-2C433581AX997613HKJFBVLI",
177 | "intent": "authorize",
178 | "links": [
179 | {
180 | "href": "https://api.paypal.com/v1/payments/payment/PAY-2C433581AX997613HKJFBVLI",
181 | "method": "GET",
182 | "rel": "self"
183 | }
184 | ],
185 | "payer": {
186 | "payer_info": {
187 | "email": "tnm10@paypal.com",
188 | "first_name": "George",
189 | "last_name": "Martin",
190 | "payer_id": "QLR7PGAJCMCA8"
191 | },
192 | "payment_method": "paypal"
193 | },
194 | "state": "approved",
195 | "transactions": [
196 | {
197 | "amount": {
198 | "currency": "USD",
199 | "details": {
200 | "subtotal": "1.88"
201 | },
202 | "total": "1.88"
203 | },
204 | "description": "future of sauces",
205 | "related_resources": [
206 | {
207 | "authorization": {
208 | "amount": {
209 | "currency": "USD",
210 | "details": {
211 | "subtotal": "1.88"
212 | },
213 | "total": "1.88"
214 | },
215 | "create_time": "2013-10-01T00:43:25Z",
216 | "id": "4TD55050SV609544L",
217 | "links": [
218 | {
219 | "href": "https://api.paypal.com/v1/payments/authorization/4TD55050SV609544L",
220 | "method": "GET",
221 | "rel": "self"
222 | },
223 | {
224 | "href": "https://api.paypal.com/v1/payments/authorization/4TD55050SV609544L/capture",
225 | "method": "POST",
226 | "rel": "capture"
227 | },
228 | {
229 | "href": "https://api.paypal.com/v1/payments/authorization/4TD55050SV609544L/void",
230 | "method": "POST",
231 | "rel": "void"
232 | },
233 | {
234 | "href": "https://api.paypal.com/v1/payments/authorization/4TD55050SV609544L/reauthorize",
235 | "method": "POST",
236 | "rel": "reauthorize"
237 | },
238 | {
239 | "href": "https://api.paypal.com/v1/payments/payment/PAY-2C433581AX997613HKJFBVLI",
240 | "method": "GET",
241 | "rel": "parent_payment"
242 | }
243 | ],
244 | "parent_payment": "PAY-2C433581AX997613HKJFBVLI",
245 | "state": "authorized",
246 | "update_time": "2013-10-01T00:43:28Z",
247 | "valid_until": "2013-10-30T00:43:25Z"
248 | }
249 | }
250 | ]
251 | }
252 | ],
253 | "update_time": "2013-10-01T00:43:28Z"
254 | }
255 | ```
256 |
257 | サービスの完了または商品の提供後、[支払いを回収](https://developer.paypal.com/webapps/developer/docs/integration/direct/capture-payment/#capture-the-payment)します。
258 |
259 | #### リクエスト
260 |
261 | ```bash
262 | curl 'https://api.paypal.com/v1/payments/authorization/4TD55050SV609544L/capture' \
263 | -H "Content-Type: application/json" \
264 | -H "PayPal-Client-Metadata-Id: c2edbd6e97b14ff2b19ddb8eec9d264c" \
265 | -H "Authorization: Bearer WfXdnxmyJtdF4q59ofxuQuAAk6eEV-Njm6puht3Nk3w" \
266 | -d '{
267 | "amount":{
268 | "currency":"USD",
269 | "total":"1.50"
270 | },
271 | "is_final_capture":true
272 | }'
273 | ```
274 |
275 | #### 応答
276 |
277 | ```JSON
278 | {
279 | "amount": {
280 | "currency": "USD",
281 | "total": "1.50"
282 | },
283 | "create_time": "2013-10-01T00:43:28Z",
284 | "id": "9BS66645698646420",
285 | "is_final_capture": true,
286 | "links": [
287 | {
288 | "href": "https://api.paypal.com/v1/payments/capture/9BS66645698646420",
289 | "method": "GET",
290 | "rel": "self"
291 | },
292 | {
293 | "href": "https://api.paypal.com/v1/payments/capture/9BS66645698646420/refund",
294 | "method": "POST",
295 | "rel": "refund"
296 | },
297 | {
298 | "href": "https://api.paypal.com/v1/payments/authorization/4TD55050SV609544L",
299 | "method": "GET",
300 | "rel": "authorization"
301 | },
302 | {
303 | "href": "https://api.paypal.com/v1/payments/payment/PAY-2C433581AX997613HKJFBVLI",
304 | "method": "GET",
305 | "rel": "parent_payment"
306 | }
307 | ],
308 | "parent_payment": "PAY-2C433581AX997613HKJFBVLI",
309 | "state": "completed",
310 | "update_time": "2013-10-01T00:43:30Z"
311 | }
312 | ```
313 |
314 | `state`が`completed`と表示されると、販売は完了です。
315 |
316 |
317 | ### 返金と取り消し
318 |
319 | 返金および取り消しの場合は、[client_credentialsリクエスト](https://developer.paypal.com/webapps/developer/docs/api/#authentication--headers)で取得したアクセストークンを使用します。(リフレッシュトークンから生成され、ユーザーが認証したアクセストークンは、スコープが十分でないため、使用しないでください。)
320 |
321 | 関連情報:
322 |
323 | - [アクセストークンの取得(返金と取り消しの場合) ](https://developer.paypal.com/webapps/developer/docs/integration/direct/make-your-first-call/#get-an-access-token)
324 | - [完了した販売の検索](https://developer.paypal.com/docs/api/#look-up-a-sale)
325 | - [直接販売の返金](https://developer.paypal.com/docs/api/#refund-a-sale)
326 | - [承認の検索](https://developer.paypal.com/docs/api/#look-up-an-authorization)
327 | - [承認の取り消し](https://developer.paypal.com/docs/api/#void-an-authorization)
328 | - [支払いの再承認](https://developer.paypal.com/docs/api/#reauthorize-a-payment)
329 | - [回収した支払いの検索](https://developer.paypal.com/docs/api/#look-up-a-captured-payment)
330 | - [回収した支払いの返金](https://developer.paypal.com/docs/api/#refund-a-captured-payment)
331 |
--------------------------------------------------------------------------------
/docs/ja/profile_sharing_mobile.md:
--------------------------------------------------------------------------------
1 | 個人設定共有のためのモバイルの統合
2 | ==================================
3 |
4 | ここでは、PayPalアカウントの個人設定を共有するためにユーザーの同意を得る方法を説明します。
5 |
6 | _まだ実行していない場合は、プロジェクトにSDKを追加するための基本的な概要と手順の[README](README.md)を参照してください。_
7 |
8 |
9 | 概要
10 | --------
11 |
12 | PayPalアカウントの情報を共有するため、[お客さまの同意を得る](#obtain-customer-consent)必要があります。これは以下のように実行されます。
13 |
14 | * PayPalデベロッパーサイトで
15 | 1. お客さまに共有を求める情報を指定します。
16 | * PayPal Android SDKは
17 | 1. ユーザーがPayPalアカウントの使用を承認するためのUIを表示します。
18 | 2. PayPalを使用して個人設定を共有するための[OAuthアクセストークンスコープ](http://tools.ietf.org/html/rfc6749#page-23)に対する同意をユーザーに求めます。
19 | 3. アプリに、OAuth2の認可コードを返します。
20 | * アプリは
21 | 1. SDKのリクエストで必要なスコープを指定します。
22 | 2. SDKからOAuth2の認可コードを受け取ります。
23 | 3. サーバーに認可コードを送ります。サーバーは[コードをOAuth2のアクセストークンおよびリフレッシュトークンと交換](profile_sharing_server.md#obtain-oauth2-tokens)します。
24 | 4. サーバーは、[OAuth2のトークンを使用してPayPalから該当する顧客情報を要求](profile_sharing_server.md)します。
25 |
26 | **注:**
27 | 1. PayPal Android SDKで使用できるスコープ値の完全なリストは`PayPalOAuthScopes`を参照してください。
28 | 2. 使用できるスコープ属性の完全なリストは、[PayPalユーザー属性によるログイン](https://developer.paypal.com/docs/integration/direct/identity/attributes/)を参照してください。
29 |
30 |
31 | 共有する情報の指定
32 | ---------------------------------------
33 |
34 | 1. [PayPalデベロッパーサイト](https://developer.paypal.com)にログインします。
35 | 2. [アプリ](https://developer.paypal.com/webapps/developer/applications/myapps)を選択します。
36 | 3. `APP CAPABILITIES`の下で、`Log In with PayPal`を選択して`Advanced options`をクリックします。
37 | 4. `Information requested from customers`の下で、共有する必要がある項目(スコープ属性)を選択します。
38 | 5. `Links shown on customer consent page`の下にプライバシーポリシーおよびユーザー規約のURLを入力すると、[`PayPalConfiguration`オブジェクト](#obtain-customer-consent)に入力する対応URLが無効になります。
39 |
40 |
41 | お客さまの同意を得る
42 | -----------------------
43 |
44 | サンプルアプリには、より完全な例が用意されています。ただし、最低限以下を行う必要があります。
45 |
46 | 1. `AndroidManifest.xml`ファイルに許可を追加します。
47 | ```xml
48 |
49 |
50 |
51 | ```
52 |
53 | 1. `AndroidManifest.xml`ファイルの``タグでSDKのサービスとアクティビティを宣言します。
54 | ```xml
55 |
57 |
58 |
59 |
60 |
61 | ```
62 |
63 | 1. `PayPalConfiguration`オブジェクトを作成します。このオブジェクトにより、SDKのさまざまな側面を設定できます。
64 |
65 | ```java
66 | private static PayPalConfiguration config = new PayPalConfiguration()
67 |
68 | // モック環境で開始します。準備完了後、sandbox (ENVIRONMENT_SANDBOX)
69 | // または本番 (ENVIRONMENT_PRODUCTION)環境に切り替えます。
70 | .environment(PayPalConfiguration.ENVIRONMENT_NO_NETWORK)
71 |
72 | .clientId("")
73 |
74 | // 最低限3つのマーチャント情報プロパティを設定する必要があります。
75 | // これらは、アプリを登録した際にPayPalに提供した値と同じである必要があります。
76 | .merchantName("Example Store")
77 | .merchantPrivacyPolicyUri(Uri.parse("https://www.example.com/privacy"))
78 | .merchantUserAgreementUri(Uri.parse("https://www.example.com/legal"));
79 | ```
80 |
81 | 2. アクティビティの作成時に`PayPalService`を開始し、破棄の際に停止します。
82 |
83 | ```java
84 | @Override
85 | protected void onCreate(Bundle savedInstanceState) {
86 | super.onCreate(savedInstanceState);
87 | setContentView(R.layout.activity_main);
88 |
89 | Intent intent = new Intent(this, PayPalService.class);
90 |
91 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
92 |
93 | startService(intent);
94 | }
95 |
96 | @Override
97 | public void onDestroy() {
98 | stopService(new Intent(this, PayPalService.class));
99 | super.onDestroy();
100 | }
101 | ```
102 |
103 | 3. PayPalの個人設定の共有アクティビティを、たとえばボタンが押された場合などに起動します。
104 |
105 | ```java
106 | public void onProfileSharingPressed(View pressed) {
107 | Intent intent = new Intent(SampleActivity.this, PayPalProfileSharingActivity.class);
108 | intent.putExtra(PayPalProfileSharingActivity.EXTRA_REQUESTED_SCOPES, getOauthScopes());
109 | startActivityForResult(intent, REQUEST_CODE_PROFILE_SHARING);
110 | }
111 | ```
112 |
113 | 一連のスコープ名で`PayPalOAuthScopes`が初期化されます。
114 |
115 | ```java
116 | private PayPalOAuthScopes getOauthScopes() {
117 | /* 必要なスコープセットの作成
118 | * 注: このアプリで選択する属性とここで必要なスコープ間のマッピングについては、
119 | * PayPalデベロッパーサイトのhttps://developer.paypal.com/docs/integration/direct/identity/attributes/を参照してください。
120 | */
121 | Set scopes = new HashSet(
122 | Arrays.asList(PayPalOAuthScopes.PAYPAL_SCOPE_EMAIL, PayPalOAuthScopes.PAYPAL_SCOPE_ADDRESS) );
123 | return new PayPalOAuthScopes(scopes);
124 | }
125 | ```
126 |
127 | 4. `onActivityResult()`を実装します。
128 |
129 | ```java
130 | @Override
131 | protected void onActivityResult (int requestCode, int resultCode, Intent data) {
132 | if (resultCode == Activity.RESULT_OK) {
133 | PayPalAuthorization auth = data
134 | .getParcelableExtra(PayPalProfileSharingActivity.EXTRA_RESULT_AUTHORIZATION);
135 | if (auth != null) {
136 | try {
137 | String authorization_code = auth.getAuthorizationCode();
138 |
139 | sendAuthorizationToServer(auth);
140 |
141 | } catch (JSONException e) {
142 | Log.e("ProfileSharingExample", "非常にまれなエラーが発生しました: ", e);
143 | }
144 | }
145 | } else if (resultCode == Activity.RESULT_CANCELED) {
146 | Log.i("ProfileSharingExample", "ユーザーがキャンセルしました。");
147 | } else if (resultCode == PayPalProfileSharingActivity.RESULT_EXTRAS_INVALID) {
148 | Log.i("ProfileSharingExample",
149 | "PayPalServiceを前に開始するための処理で無効なPayPalConfigurationが含まれていた可能性があります。ドキュメントを参照してください。");
150 | }
151 | }
152 | ```
153 |
154 | 5. プロセスを完了するため、サーバーに認可応答を送信します。
155 |
156 | ```java
157 | private void sendAuthorizationToServer(PayPalAuthorization authorization) {
158 |
159 | // TODO:
160 | // 認可応答をサーバーに送信します。サーバーは認可コードを
161 | // OAuthのアクセストークンおよびリフレッシュトークンと交換できます。
162 | //
163 | // サーバーはこれらのトークンを保管するので、サーバーコードは、これを使用して、
164 | // 今後ユーザーの個人設定データを取得できます。
165 |
166 | }
167 | ```
168 |
169 |
170 | 次の手順
171 | ----------
172 | [個人設定共有のためのサーバー側の統合](profile_sharing_server.md)を読んで、認可コードとOAuth2のトークンを交換して、PayPalから顧客情報を取り出します。
173 |
--------------------------------------------------------------------------------
/docs/ja/profile_sharing_server.md:
--------------------------------------------------------------------------------
1 | 個人設定共有のためのサーバー側の統合
2 | =======================================
3 |
4 | ユーザーが、自分のPayPalアカウントの使用をアプリに承認すると、この承認を使用して、そのユーザーのPayPal情報を取り出すトークンを取得できます。
5 |
6 | このドキュメントには以下の方法が記載されています。
7 |
8 | 1. [OAuth2のトークンを取得する](#obtain-oauth2-tokens)
9 | 2. 取得したトークンを使用して[顧客情報を取得する](#retrieve-customer-information)
10 |
11 | _ユーザーに、アプリで個人設定の共有を承認し、同意してもらうには、[個人設定の共有](profile_sharing_mobile.md)を参照してください。_
12 |
13 |
14 | OAuth2のトークンを取得する
15 | --------------------
16 |
17 | 1. [認可コードを取得する](#obtain-an-authorization-code)
18 | 2. [認可コードとリフレッシュ/アクセストークンを交換する](#exchange-authorization-code-for-refresh--access-tokens)
19 | ### 認可コードを取得する
20 |
21 | モバイルSDKは、[個人設定の共有についてユーザーの同意を得るためのAPI](profile_sharing_mobile.md)を提供しています。アプリにSDKを統合し、それを使ってユーザーを認証し、ユーザーの同意を得ます。SDKは、PayPal認証サーバーで認証および承認を処理し、OAuth2の認可コードをアプリに返します。
22 |
23 | この認可応答はJSONオブジェクトです。例
24 |
25 | ```json
26 | {
27 | "response_type": "authorization_code",
28 | "response": {
29 | "code": "EBYhRW3ncivudQn8UopLp4A28xIlqPDpAoqd7biDLpeGCPvORHjP1Fh4CbFPgKMGCHejdDwe9w1uDWnjPCp1lkaFBjVmjvjpFtnr6z1YeBbmfZYqa9faQT_71dmgZhMIFVkbi4yO7hk0LBHXt_wtdsw",
30 | },
31 | "client": {
32 | "environment": "live",
33 | "paypal_sdk_version": "2.0.0",
34 | "platform": "iOS",
35 | "product_name": "PayPal iOS SDK"
36 | }
37 | }
38 | ```
39 |
40 | アプリは、この認可応答をサーバーに送信する必要があります。サーバーは、次のセクションで説明するように、認可コードと、リフレッシュトークンおよびアクセストークンを交換する必要があります。
41 |
42 |
43 | ### 認可コードとリフレッシュ/アクセストークンを交換する
44 |
45 | サーバーが認可コードを取得すると、これを使用して、有効期限の長いリフレッシュトークンと有効期限の短いアクセストークンを取得できるようになります。サーバーとPayPal APIの通信は、標準的な[OAuth2の認可コードグラントアクセスリクエスト](http://tools.ietf.org/html/rfc6749#section-4.1.3)です。
46 |
47 | 認可コードには、非常に短い有効期限が設定されています。**ただちに**認可コードをリフレッシュトークンとアクセストークンに交換する必要があります。
48 |
49 | リフレッシュトークンの有効期限は長く、現在のところ10年です。安全に保管する必要があります。
50 |
51 | 返されるコードやトークンの値はすべて可変長として扱ってください。今後さらに長くなる可能性がありますので、最大長が固定されているものとして扱わないでください。
52 |
53 |
54 | #### リクエスト
55 |
56 | ```bash
57 | curl 'https://api.paypal.com/v1/oauth2/token' \
58 | -H "Content-Type: application/x-www-form-urlencoded" \
59 | -H "Authorization: Basic QWZV...==" \
60 | -d 'grant_type=authorization_code&response_type=token&redirect_uri=urn:ietf:wg:oauth:2.0:oob&code=EBYhRW3ncivudQn8UopLp4A28...'
61 | ```
62 |
63 | * `grant_type`: トークンのグラントタイプです。値は`authorization_code`に設定する必要があります。
64 | * `redirect_uri`: リダイレクトURLです。値は`urn:ietf:wg:oauth:2.0:oob`に設定する必要があります。
65 | * `code`: 認可サーバーから以前に受信した認可コードです。
66 |
67 | #### 応答
68 |
69 | ```JSON
70 | {
71 | "access_token": "6oyryV79E.KtpAvPudpI8VIko.ntdPikU9HCDfg0tO0",
72 | "expires_in": 900,
73 | "refresh_token": "MFYQJTPW3zlCAjznPs2D0VQlQXwiEfTesR-dRiU_qhbUngzxR3NmeBxqKELcmGtSI739R-awwvOyGVO1LJbowy7n8Ul3vsf5HQDTCzUlDylqBvW0",
74 | "scope": "https://api.paypal.com/v1/payments/.* https://uri.paypal.com/services/payments/futurepayments",
75 | "token_type": "Bearer"
76 | }
77 | ```
78 |
79 | * `access_token`: 認可サーバーによって発行されたアクセストークンです。
80 | * `expires_in`: アクセストークンの秒単位での有効期限です。アクセストークンの期限切れ後、`refresh_token`を使用して[アクセストークンを更新](#refresh-an-access-token)します。
81 | * `refresh_token`: リフレッシュトークン。[OAuth2.0 RFC6749 - セクション6](http://tools.ietf.org/html/rfc6749#section-6)で説明されているように、これにより、同じ認可グラントを使用する新しいアクセストークンを取得することができます。
82 | * `scope`: このリフレッシュトークンに関連するスコープ値をスペースで区切ったリストです。
83 | * `token_type`: [OAuth2.0 RFC6749 - セクション7.1](http://tools.ietf.org/html/rfc6749#section-7.1)で説明されているタイプの発行済みトークンです。値は、大文字と小文字が区別されます。
84 |
85 |
86 | 顧客情報の取得
87 | -----------------------------
88 |
89 | サーバーが、同意を得ているユーザーのPayPal情報を取り出す必要がある場合、サーバーコードで以下を実行する必要があります。
90 |
91 | 1. ユーザーのリフレッシュトークンを検索し、[それを使用して新しいアクセストークンを取得](#refresh-an-access-token)する
92 | 2. [有効なアクセストークンを使用して顧客情報を取り出す](#retrieve-customer-information-using-a-valid-access-token)
93 |
94 | ### アクセストークンの更新
95 |
96 | 前述したように、アクセストークンには有効期限があります。アクセストークンの期限が切れた場合は、リフレッシュトークンを使用して新しいアクセストークンを取得する必要があります。
97 |
98 | #### リクエスト
99 |
100 | ```bash
101 | curl 'https://api.paypal.com/v1/oauth2/token' \
102 | -H "Content-Type: application/x-www-form-urlencoded" \
103 | -H "Authorization: Basic QWZVa...==" \
104 | -d 'grant_type=refresh_token&refresh_token=MFYQ...'
105 | ```
106 |
107 | * `grant_type`: トークンのグラントタイプです。値は`refresh_token`に設定する必要があります。**必須です。**
108 | * `refresh_token`: 更新されるアクセストークンとともに以前に受信したリフレッシュトークンです。**必須です。**
109 |
110 | #### 応答
111 |
112 | ```JSON
113 | {
114 | "access_token": "WfXdnxmyJtdF4q59ofxuQuAAk6eEV-Njm6puht3Nk3w",
115 | "app_id": "APP-3TS46380HB829954H",
116 | "expires_in": 900,
117 | "scope": "https://api.paypal.com/v1/payments/.* https://uri.paypal.com/services/payments/futurepayments",
118 | "token_type": "Bearer"
119 | }
120 | ```
121 |
122 |
123 | ### 有効なアクセストークンを使用した顧客情報の取得
124 |
125 | HTTPの`Authorization`ヘッダーの値としてアクセストークンを使用して、次のように情報を取り出します。
126 |
127 | ```
128 | Authorization: Bearer YOUR_ACCESS_TOKEN
129 | ```
130 |
131 | * 詳細は、[ユーザー情報の取得](https://developer.paypal.com/docs/api/#get-user-information)を参照してください。
132 |
133 | たとえば、ユーザーが共有に同意した全情報を取得する場合は、リクエストを次のように使用します。
134 |
135 | #### リクエスト
136 |
137 | ```bash
138 | curl -v https://api.paypal.com/v1/identity/openidconnect/userinfo/?schema=openid \
139 | -H "Content-Type:application/json" \
140 | -H "Authorization: Bearer WfXdnxmyJtdF4q59ofxuQuAAk6eEV-Njm6puht3Nk3w"
141 | ```
142 |
143 | #### 応答
144 |
145 | ```JSON
146 | {
147 | "address":{
148 | "postal_code":"95131",
149 | "locality":"San Jose",
150 | "region":"CA",
151 | "country":"US",
152 | "street_address":"3 Main St"
153 | },
154 | "family_name":"Smith",
155 | "language":"en_US",
156 | "phone_number":"4082560980",
157 | "locale":"en_US",
158 | "name":"Roger Smith",
159 | "email":"rsmith@somewhere.com",
160 | "account_type":"PERSONAL",
161 | "birthday":"1982-08-02",
162 | "given_name":"Roger",
163 | "user_id":"https://www.paypal.com/webapps/auth/identity/user/jG8zVpn2toXCPmzNffW1WTRLA2KOhPXYybeTM9p3ct0"
164 | }
165 | ```
166 |
167 |
168 | 関連情報:
169 |
170 | - [アクセストークンの取得](https://developer.paypal.com/webapps/developer/docs/integration/direct/make-your-first-call/#get-an-access-token)
171 | - [PayPalインテグレーションガイドによるログイン](https://developer.paypal.com/docs/integration/direct/identity/log-in-with-paypal/)
172 | - [ユーザー情報の入手](https://developer.paypal.com/docs/api/#get-user-information)
173 |
--------------------------------------------------------------------------------
/docs/ja/single_payment.md:
--------------------------------------------------------------------------------
1 | 1件の支払い
2 | ==============
3 |
4 | お客さまから、PayPalまたは[card.io](https://www.card.io/)を使用した決済カードによる1件の即時支払いを受け取ります。
5 |
6 | _まだ実行していない場合は、プロジェクトにSDKを追加するための基本的な概要と手順の[README](README.md)を参照してください。_
7 |
8 | 概要
9 | --------
10 |
11 | * PayPal Android SDKは
12 | 1. ユーザーから支払い情報を収集するためのUIを表示します。
13 | 2. PayPalと支払いを調整します。
14 | 3. アプリに支払い証明を返します。
15 | * コードは
16 | 1. PayPal Android SDKから支払い証明を受信します。
17 | 2.[認証のため、サーバーに支払い証明を送信](https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/)します。
18 | 3. ユーザーに商品またはサービスを提供します。
19 |
20 | _オプションとして、アプリで、PayPal Android SDKがユーザーに**配送先住所**を選ばせるように指定することもできます。_
21 |
22 | * コードは
23 | 1. PayPal Android SDKに、アプリで提供された配送先住所および/またはユーザーのPayPalアカウントに登録されている配送先住所を表示するよう命令します。
24 | * PayPal Android SDKは
25 | 1. ユーザーが、表示された配送先住所を確認して選択できるようにします。
26 | 2. 選択された配送先住所を、PayPalのサーバーに送信される支払い情報に追加します。
27 | * サーバーは
28 | 1. 支払いを[認証](https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/)または[回収](https://developer.paypal.com/webapps/developer/docs/integration/direct/capture-payment/#capture-the-payment)する際に、支払い情報から配送先住所を取得します。
29 |
30 |
31 | サンプルコード
32 | -----------
33 |
34 | サンプルアプリには、より完全な例が用意されています。ただし、最低限以下を行う必要があります。
35 | 1. `AndroidManifest.xml`ファイルに許可を追加します。
36 | ```xml
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | ```
48 |
49 | 1. `AndroidManifest.xml`ファイルの``タグでSDKのサービスとアクティビティを宣言します。
50 | ```xml
51 |
53 |
54 |
55 |
56 |
57 |
58 |
60 |
61 | ```
62 |
63 | 1. `PayPalConfiguration`オブジェクトを作成します。
64 | ```java
65 | private static PayPalConfiguration config = new PayPalConfiguration()
66 |
67 | // モック環境で開始します。準備完了後、sandbox (ENVIRONMENT_SANDBOX)
68 | // または本番(ENVIRONMENT_PRODUCTION)環境に切り替えます。
69 | .environment(PayPalConfiguration.ENVIRONMENT_NO_NETWORK)
70 |
71 | .clientId("");
72 | ```
73 |
74 | 2. アクティビティの作成時に`PayPalService`を開始し、破棄の際に停止します。
75 |
76 | ```java
77 | @Override
78 | protected void onCreate(Bundle savedInstanceState) {
79 | super.onCreate(savedInstanceState);
80 | setContentView(R.layout.activity_main);
81 |
82 | Intent intent = new Intent(this, PayPalService.class);
83 |
84 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
85 |
86 | startService(intent);
87 | }
88 |
89 | @Override
90 | public void onDestroy() {
91 | stopService(new Intent(this, PayPalService.class));
92 | super.onDestroy();
93 | }
94 | ```
95 |
96 | 3. 支払いを作成して、支払いインテントを、たとえばボタンが押された場合などに起動します。
97 |
98 | ```java
99 | public void onBuyPressed(View pressed) {
100 |
101 | // PAYMENT_INTENT_SALEにより、ただちに支払いが完了します。
102 | // PAYMENT_INTENT_SALEを以下に変更します。
103 | // - 支払い承認のみを行い後で資金回収を行うPAYMENT_INTENT_AUTHORIZE
104 | // - 承認用に支払いを作成し後でサーバーからのコールにより回収する
105 | // PAYMENT_INTENT_ORDER
106 |
107 | PayPalPayment payment = new PayPalPayment(new BigDecimal("1.75"), "USD", "sample item",
108 | PayPalPayment.PAYMENT_INTENT_SALE);
109 |
110 | Intent intent = new Intent(this, PaymentActivity.class);
111 |
112 | intent.putExtra(PaymentActivity.EXTRA_PAYMENT, payment);
113 |
114 | startActivityForResult(intent, 0);
115 | }
116 | ```
117 | _注: 支払いのために配送先住所を入力するには、サンプルアプリの**addAppProvidedShippingAddress(...)**を参照してください。ユーザーのPayPalアカウントから配送先住所を取得できるようにするには、サンプルアプリの**enableShippingAddressRetrieval(...)**を参照してください。_
118 |
119 | 4. `onActivityResult()`を実装します。
120 |
121 | ```java
122 | @Override
123 | protected void onActivityResult (int requestCode, int resultCode, Intent data) {
124 | if (resultCode == Activity.RESULT_OK) {
125 | PaymentConfirmation confirm = data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION);
126 | if (confirm != null) {
127 | try {
128 | Log.i("paymentExample", confirm.toJSONObject().toString(4));
129 |
130 | // TODO: 認証のため、サーバーに'confirm'を送信します。
131 | // 詳細はhttps://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/
132 | // を参照してください。
133 |
134 | } catch (JSONException e) {
135 | Log.e("paymentExample", "非常にまれなエラーが発生しました: ", e);
136 | }
137 | }
138 | }
139 | else if (resultCode == Activity.RESULT_CANCELED) {
140 | Log.i("paymentExample", "ユーザーがキャンセルしました。");
141 | }
142 | else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) {
143 | Log.i("paymentExample", "無効な支払いまたはPayPalConfigurationが送信されました。ドキュメントを参照してください。");
144 | }
145 | }
146 | ```
147 |
148 | 5. 注文から発送までの処理(フルフィルメント)などの業務に必要な処理に加え、[認証のため、支払い証明をサーバーに送信](https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/)します。
149 |
150 |
151 | **ヒント:** この時点で支払いは完了し、ユーザーには請求済みです。サーバーにアクセスできない場合は、支払い証明を保存し、しばらくしてから再実行してください。
152 |
153 | ### ヒント
154 |
155 | モバイルネットワークの接続は安定していません。最終的に確実にサーバーに接続するため、支払い証明を保存しておいてください。
156 |
157 | 次の手順
158 | ----------
159 |
160 | **不正の防止** 必ず[支払い証明を認証](https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/)してください。
161 |
--------------------------------------------------------------------------------
/docs/profile_sharing_mobile.md:
--------------------------------------------------------------------------------
1 | Profile Sharing Mobile Integration
2 | ==================================
3 |
4 | This section will show how to obtain a user's authorized consent for profile sharing from their PayPal account.
5 |
6 | _If you haven't already, see the [README](../README.md) for an initial overview and instructions for adding the SDK to your project._
7 |
8 |
9 | Overview
10 | --------
11 |
12 | You must [obtain customer consent](#obtain-customer-consent) to share information from their PayPal account. How this works:
13 |
14 | * On the PayPal Developer site...
15 | 1. Specify the pieces of information that you wish your customers to share with you.
16 | * The PayPal Android SDK...
17 | 1. Presents UI for your user to authenticate using their PayPal account.
18 | 2. Asks your user to consent to [OAuth access token scope](http://tools.ietf.org/html/rfc6749#page-23) to use PayPal for profile sharing.
19 | 3. Returns an OAuth2 authorization code to your app.
20 | * Your app...
21 | 1. Specifies the required scopes in SDK request
22 | 2. Receives an OAuth2 authorization code from the SDK.
23 | 3. Sends the authorization code to your server, which then [exchanges the code for OAuth2 access and refresh tokens](profile_sharing_server.md#obtain-oauth2-tokens).
24 | 4. Your server then [uses its OAuth2 tokens to request the relevant customer information from PayPal](profile_sharing_server.md).
25 |
26 | **Notes:**
27 | 1. See `PayPalOAuthScopes` for a complete list of scope-values available to the PayPal Android SDK.
28 | 2. See [Log In with PayPal user attributes](https://developer.paypal.com/docs/integration/direct/identity/attributes/) for a complete list of available scope attributes.
29 |
30 |
31 | Specify Desired Information for Sharing
32 | ---------------------------------------
33 |
34 | 1. Log in to the [PayPal Developer site](https://developer.paypal.com).
35 | 2. Select [your app](https://developer.paypal.com/webapps/developer/applications/myapps).
36 | 3. Under `APP CAPABILITIES` select `Log In with PayPal`, and click `Advanced options`.
37 | 4. Under `Information requested from customers` select the items ("scope attributes") you wish to have shared.
38 | 5. If you provide Privacy Policy and User Agreement URLs under `Links shown on customer consent page`, these will override the corresponding URLs that you provide below in the [`PayPalConfiguration` object](#obtain-customer-consent).
39 |
40 |
41 | Obtain Customer Consent
42 | -----------------------
43 |
44 | The sample app provides a more complete example. However, at minimum, you must:
45 |
46 | 1. Add PayPal Android SDK dependency to your `build.gradle` file as shown in README.md
47 |
48 | 1. Create a `PayPalConfiguration` object. This object allows you to configure various aspects of the SDK.
49 |
50 | ```java
51 | private static PayPalConfiguration config = new PayPalConfiguration()
52 |
53 | // Start with mock environment. When ready, switch to sandbox (ENVIRONMENT_SANDBOX)
54 | // or live (ENVIRONMENT_PRODUCTION)
55 | .environment(PayPalConfiguration.ENVIRONMENT_NO_NETWORK)
56 |
57 | .clientId("")
58 |
59 | // Minimally, you will need to set three merchant information properties.
60 | // These should be the same values that you provided to PayPal when you registered your app.
61 | .merchantName("Example Store")
62 | .merchantPrivacyPolicyUri(Uri.parse("https://www.example.com/privacy"))
63 | .merchantUserAgreementUri(Uri.parse("https://www.example.com/legal"));
64 | ```
65 |
66 | 2. Start `PayPalService` when your activity is created and stop it upon destruction:
67 |
68 | ```java
69 | @Override
70 | protected void onCreate(Bundle savedInstanceState) {
71 | super.onCreate(savedInstanceState);
72 | setContentView(R.layout.activity_main);
73 |
74 | Intent intent = new Intent(this, PayPalService.class);
75 |
76 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
77 |
78 | startService(intent);
79 | }
80 |
81 | @Override
82 | public void onDestroy() {
83 | stopService(new Intent(this, PayPalService.class));
84 | super.onDestroy();
85 | }
86 | ```
87 |
88 | 3. Launch the PayPal Profile Sharing activity, for example, when a button is pressed:
89 |
90 | ```java
91 | public void onProfileSharingPressed(View pressed) {
92 | Intent intent = new Intent(SampleActivity.this, PayPalProfileSharingActivity.class);
93 |
94 | // send the same configuration for restart resiliency
95 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
96 |
97 | intent.putExtra(PayPalProfileSharingActivity.EXTRA_REQUESTED_SCOPES, getOauthScopes());
98 |
99 | startActivityForResult(intent, REQUEST_CODE_PROFILE_SHARING);
100 | }
101 | ```
102 |
103 | The `PayPalOAuthScopes` are initialized with a set of scope names:
104 |
105 | ```java
106 | private PayPalOAuthScopes getOauthScopes() {
107 | /* create the set of required scopes
108 | * Note: see https://developer.paypal.com/docs/integration/direct/identity/attributes/ for mapping between the
109 | * attributes you select for this app in the PayPal developer portal and the scopes required here.
110 | */
111 | Set scopes = new HashSet(
112 | Arrays.asList(PayPalOAuthScopes.PAYPAL_SCOPE_EMAIL, PayPalOAuthScopes.PAYPAL_SCOPE_ADDRESS) );
113 | return new PayPalOAuthScopes(scopes);
114 | }
115 | ```
116 |
117 | 4. Implement `onActivityResult()`:
118 |
119 | ```java
120 | @Override
121 | protected void onActivityResult (int requestCode, int resultCode, Intent data) {
122 | if (resultCode == Activity.RESULT_OK) {
123 | PayPalAuthorization auth = data
124 | .getParcelableExtra(PayPalProfileSharingActivity.EXTRA_RESULT_AUTHORIZATION);
125 | if (auth != null) {
126 | try {
127 | String authorization_code = auth.getAuthorizationCode();
128 |
129 | sendAuthorizationToServer(auth);
130 |
131 | } catch (JSONException e) {
132 | Log.e("ProfileSharingExample", "an extremely unlikely failure occurred: ", e);
133 | }
134 | }
135 | } else if (resultCode == Activity.RESULT_CANCELED) {
136 | Log.i("ProfileSharingExample", "The user canceled.");
137 | } else if (resultCode == PayPalProfileSharingActivity.RESULT_EXTRAS_INVALID) {
138 | Log.i("ProfileSharingExample",
139 | "Probably the attempt to previously start the PayPalService had an invalid PayPalConfiguration. Please see the docs.");
140 | }
141 | }
142 | ```
143 |
144 | 5. Send the authorization response to your server in order to complete the process.
145 |
146 | ```java
147 | private void sendAuthorizationToServer(PayPalAuthorization authorization) {
148 |
149 | // TODO:
150 | // Send the authorization response to your server, where it can exchange the authorization code
151 | // for OAuth access and refresh tokens.
152 | //
153 | // Your server must then store these tokens, so that your server code can use it
154 | // for getting user profile data in the future.
155 |
156 | }
157 | ```
158 |
159 |
160 | Next Steps
161 | ----------
162 |
163 | Read [Profile Sharing Server-Side Integration](profile_sharing_server.md) to exchange the authorization code for OAuth2 tokens and retrieve the customer information from PayPal.
164 |
--------------------------------------------------------------------------------
/docs/profile_sharing_server.md:
--------------------------------------------------------------------------------
1 | Profile Sharing Server-Side Integration
2 | =======================================
3 |
4 | Once a user has authorized your app to use their PayPal account, you can then use that authorization to obtain tokens that let you retrieve PayPal information for that user.
5 |
6 | This document covers how to:
7 |
8 | 1. [Obtain OAuth2 Tokens](#obtain-oauth2-tokens)
9 | 2. [Retrieve Customer Information](#retrieve-customer-information) using those tokens
10 |
11 | _See [Profile Sharing](profile_sharing_mobile.md) to let users authenticate and consent to profile sharing in your app._
12 |
13 |
14 | Obtain OAuth2 Tokens
15 | --------------------
16 |
17 | 1. [Obtain an Authorization Code](#obtain-an-authorization-code)
18 | 2. [Exchange Authorization Code for Refresh / Access Tokens](#exchange-authorization-code-for-refresh--access-tokens)
19 |
20 | ### Obtain an Authorization Code
21 |
22 | The Mobile SDK provides [an API to obtain user consent for profile sharing](profile_sharing_mobile.md). Integrate the SDK into your app and use it to authenticate the user and obtain the user's consent. The SDK handles authentication and authorization with the PayPal authentication server, and returns an OAuth2 authorization code to your application.
23 |
24 | This authorization response is a JSON Object. Example:
25 |
26 | ```json
27 | {
28 | "response_type": "authorization_code",
29 | "response": {
30 | "code": "EBYhRW3ncivudQn8UopLp4A28xIlqPDpAoqd7biDLpeGCPvORHjP1Fh4CbFPgKMGCHejdDwe9w1uDWnjPCp1lkaFBjVmjvjpFtnr6z1YeBbmfZYqa9faQT_71dmgZhMIFVkbi4yO7hk0LBHXt_wtdsw",
31 | },
32 | "client": {
33 | "environment": "live",
34 | "paypal_sdk_version": "2.0.0",
35 | "platform": "iOS",
36 | "product_name": "PayPal iOS SDK"
37 | }
38 | }
39 | ```
40 |
41 | Your application is responsible for communicating this authorization response to your server. Your server should exchange the authorization code for refresh and access tokens, as described in the next section.
42 |
43 |
44 | ### Exchange Authorization Code for Refresh / Access Tokens
45 |
46 | Once your server has obtained the authorization code, you can use it to get a long-lived refresh token and short-lived access token. The interaction between your server and the PayPal APIs is a standard [OAuth2 Authorization Code Grant Access Request](http://tools.ietf.org/html/rfc6749#section-4.1.3).
47 |
48 | The authorization code is very short-lived. You should exchange it for a refresh and access token **immediately**.
49 |
50 | The refresh token is long-lived (currently 10 years). You should store it securely.
51 |
52 | Note that all returned code and token values should be considered variable length, and may increase in length in the future, so do not assume a fixed maximum.
53 |
54 |
55 | #### Request
56 |
57 | ```bash
58 | curl 'https://api.paypal.com/v1/oauth2/token' \
59 | -H "Content-Type: application/x-www-form-urlencoded" \
60 | -H "Authorization: Basic QWZV...==" \
61 | -d 'grant_type=authorization_code&response_type=token&redirect_uri=urn:ietf:wg:oauth:2.0:oob&code=EBYhRW3ncivudQn8UopLp4A28...'
62 | ```
63 |
64 | * `grant_type`: Token grant type. Value must be set to `authorization_code`.
65 | * `redirect_uri`: Redirect uri. Value must be set to `urn:ietf:wg:oauth:2.0:oob`.
66 | * `code`: Authorization code previously received from the authorization server.
67 |
68 | #### Response
69 |
70 | ```JSON
71 | {
72 | "access_token": "6oyryV79E.KtpAvPudpI8VIko.ntdPikU9HCDfg0tO0",
73 | "expires_in": 900,
74 | "refresh_token": "MFYQJTPW3zlCAjznPs2D0VQlQXwiEfTesR-dRiU_qhbUngzxR3NmeBxqKELcmGtSI739R-awwvOyGVO1LJbowy7n8Ul3vsf5HQDTCzUlDylqBvW0",
75 | "scope": "https://api.paypal.com/v1/payments/.* https://uri.paypal.com/services/payments/futurepayments",
76 | "token_type": "Bearer"
77 | }
78 | ```
79 |
80 | * `access_token`: The access token issued by the authorization server.
81 | * `expires_in`: The lifetime of the access token in seconds. After the access token expires, use the `refresh_token` to [refresh the access token](#refresh-an-access-token).
82 | * `refresh_token`: The refresh token, which can be used to obtain new access tokens using the same authorization grant, as described in [OAuth2.0 RFC6749 - Section 6](http://tools.ietf.org/html/rfc6749#section-6).
83 | * `scope`: A list of space-separated scope-values associated with this refresh token.
84 | * `token_type`: The type of the token issued as described in [OAuth2.0 RFC6749 - Section 7.1](http://tools.ietf.org/html/rfc6749#section-7.1). Value is case insensitive.
85 |
86 |
87 | Retrieve Customer Information
88 | -----------------------------
89 |
90 | When your server wishes to retrieve PayPal information for a user who has granted consent, your server code will need to:
91 |
92 | 1. Look up the user's refresh token and [use it to get a new access token](#refresh-an-access-token)
93 | 2. [Retrieve customer information using that valid access token](#retrieve-customer-information-using-a-valid-access-token)
94 |
95 | ### Refresh an Access Token
96 |
97 | As mentioned earlier, an access token is only valid for a limited time. Once it expires, you'll need to get a new access token using the refresh token.
98 |
99 | #### Request
100 |
101 | ```bash
102 | curl 'https://api.paypal.com/v1/oauth2/token' \
103 | -H "Content-Type: application/x-www-form-urlencoded" \
104 | -H "Authorization: Basic QWZVa...==" \
105 | -d 'grant_type=refresh_token&refresh_token=MFYQ...'
106 | ```
107 |
108 | * `grant_type`: Token grant type. Value must be set to `refresh_token`. **Required.**
109 | * `refresh_token`: Refresh token previously received along with the access token that is to be refreshed. **Required.**
110 |
111 | #### Response
112 |
113 | ```JSON
114 | {
115 | "access_token": "WfXdnxmyJtdF4q59ofxuQuAAk6eEV-Njm6puht3Nk3w",
116 | "app_id": "APP-3TS46380HB829954H",
117 | "expires_in": 900,
118 | "scope": "https://api.paypal.com/v1/payments/.* https://uri.paypal.com/services/payments/futurepayments",
119 | "token_type": "Bearer"
120 | }
121 | ```
122 |
123 |
124 | ### Retrieve Customer Information Using a Valid Access Token
125 |
126 | Use an access token as the value of the HTTP `Authorization` header to retrieve the ifnformation, e.g.
127 |
128 | ```
129 | Authorization: Bearer YOUR_ACCESS_TOKEN
130 | ```
131 |
132 | * For more information, see [Get user information](https://developer.paypal.com/docs/api/#get-user-information).
133 |
134 | For example, to obtain all of the information the user consented to share, use a request similar to this:
135 |
136 | #### Request
137 |
138 | ```bash
139 | curl -v https://api.paypal.com/v1/identity/openidconnect/userinfo/?schema=openid \
140 | -H "Content-Type:application/json" \
141 | -H "Authorization: Bearer WfXdnxmyJtdF4q59ofxuQuAAk6eEV-Njm6puht3Nk3w"
142 | ```
143 |
144 | #### Response
145 |
146 | ```JSON
147 | {
148 | "address":{
149 | "postal_code":"95131",
150 | "locality":"San Jose",
151 | "region":"CA",
152 | "country":"US",
153 | "street_address":"3 Main St"
154 | },
155 | "family_name":"Smith",
156 | "language":"en_US",
157 | "phone_number":"4082560980",
158 | "locale":"en_US",
159 | "name":"Roger Smith",
160 | "email":"rsmith@somewhere.com",
161 | "account_type":"PERSONAL",
162 | "birthday":"1982-08-02",
163 | "given_name":"Roger",
164 | "user_id":"https://www.paypal.com/webapps/auth/identity/user/jG8zVpn2toXCPmzNffW1WTRLA2KOhPXYybeTM9p3ct0"
165 | }
166 | ```
167 |
168 |
169 | Related information:
170 |
171 | - [Get an access token](https://developer.paypal.com/webapps/developer/docs/integration/direct/make-your-first-call/#get-an-access-token).
172 | - [Login With PayPal Integration Guide](https://developer.paypal.com/docs/integration/direct/identity/log-in-with-paypal/).
173 | - [Get user information](https://developer.paypal.com/docs/api/#get-user-information).
174 |
--------------------------------------------------------------------------------
/docs/single_payment.md:
--------------------------------------------------------------------------------
1 | Single Payment
2 | ==============
3 |
4 | Receive a single, immediate payment from your customer through PayPal.
5 |
6 | _If you haven't already, see the [README](../README.md) for an initial overview and instructions for adding the SDK to your project._
7 |
8 | Overview
9 | --------
10 |
11 | * The PayPal Android SDK...
12 | 1. Presents UI to gather payment information from the user.
13 | 2. Coordinates payment with PayPal.
14 | 3. Returns a proof of payment to your app.
15 | * Your code...
16 | 1. Receives proof of payment from the PayPal Android SDK.
17 | 2. [Sends proof of payment to your servers for verification](https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/).
18 | 3. Provides the user their goods or services.
19 |
20 | _Optionally, your app can also instruct the PayPal Android SDK to ask the user to pick a **Shipping Address**:_
21 |
22 | * Your code...
23 | 1. Instructs the PayPal Android SDK to display an app-provided Shipping Address and/or the Shipping Addresses already associated with the user's PayPal account.
24 | * The PayPal Android SDK...
25 | 1. Allows the user to examine and choose from the displayed Shipping Address(es).
26 | 2. Adds the chosen Shipping Address to the payment information sent to PayPal's servers.
27 | * Your server...
28 | 1. When [verifying](https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/) or [capturing](https://developer.paypal.com/webapps/developer/docs/integration/direct/capture-payment/#capture-the-payment) the payment, retrieves the Shipping Address from the payment information.
29 |
30 |
31 | Sample Code
32 | -----------
33 |
34 | The sample app provides a more complete example. However, at minimum, you must:
35 |
36 | 1. Add PayPal Android SDK dependency to your `build.gradle` file as shown in README.md
37 |
38 | 1. Create a `PayPalConfiguration` object
39 | ```java
40 | private static PayPalConfiguration config = new PayPalConfiguration()
41 |
42 | // Start with mock environment. When ready, switch to sandbox (ENVIRONMENT_SANDBOX)
43 | // or live (ENVIRONMENT_PRODUCTION)
44 | .environment(PayPalConfiguration.ENVIRONMENT_NO_NETWORK)
45 |
46 | .clientId("");
47 | ```
48 |
49 | 2. Start `PayPalService` when your activity is created and stop it upon destruction:
50 |
51 | ```java
52 | @Override
53 | protected void onCreate(Bundle savedInstanceState) {
54 | super.onCreate(savedInstanceState);
55 | setContentView(R.layout.activity_main);
56 |
57 | Intent intent = new Intent(this, PayPalService.class);
58 |
59 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
60 |
61 | startService(intent);
62 | }
63 |
64 | @Override
65 | public void onDestroy() {
66 | stopService(new Intent(this, PayPalService.class));
67 | super.onDestroy();
68 | }
69 | ```
70 |
71 | 3. Create the payment and launch the payment intent, for example, when a button is pressed:
72 |
73 | ```java
74 | public void onBuyPressed(View pressed) {
75 |
76 | // PAYMENT_INTENT_SALE will cause the payment to complete immediately.
77 | // Change PAYMENT_INTENT_SALE to
78 | // - PAYMENT_INTENT_AUTHORIZE to only authorize payment and capture funds later.
79 | // - PAYMENT_INTENT_ORDER to create a payment for authorization and capture
80 | // later via calls from your server.
81 |
82 | PayPalPayment payment = new PayPalPayment(new BigDecimal("1.75"), "USD", "sample item",
83 | PayPalPayment.PAYMENT_INTENT_SALE);
84 |
85 | Intent intent = new Intent(this, PaymentActivity.class);
86 |
87 | // send the same configuration for restart resiliency
88 | intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
89 |
90 | intent.putExtra(PaymentActivity.EXTRA_PAYMENT, payment);
91 |
92 | startActivityForResult(intent, 0);
93 | }
94 | ```
95 | _Note: To provide a shipping address for the payment, see **addAppProvidedShippingAddress(...)** in the sample app. To enable retrieval of shipping address from the user's PayPal account, see **enableShippingAddressRetrieval(...)** in the sample app._
96 |
97 | 4. Implement `onActivityResult()`:
98 |
99 | ```java
100 | @Override
101 | protected void onActivityResult (int requestCode, int resultCode, Intent data) {
102 | if (resultCode == Activity.RESULT_OK) {
103 | PaymentConfirmation confirm = data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION);
104 | if (confirm != null) {
105 | try {
106 | Log.i("paymentExample", confirm.toJSONObject().toString(4));
107 |
108 | // TODO: send 'confirm' to your server for verification.
109 | // see https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/
110 | // for more details.
111 |
112 | } catch (JSONException e) {
113 | Log.e("paymentExample", "an extremely unlikely failure occurred: ", e);
114 | }
115 | }
116 | }
117 | else if (resultCode == Activity.RESULT_CANCELED) {
118 | Log.i("paymentExample", "The user canceled.");
119 | }
120 | else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) {
121 | Log.i("paymentExample", "An invalid Payment or PayPalConfiguration was submitted. Please see the docs.");
122 | }
123 | }
124 | ```
125 |
126 | 5. [Send the proof of payment to your servers for verification](https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/),
127 | as well as any other processing required for your business, such as fulfillment.
128 |
129 | **Tip:** At this point, the payment has been completed, and the user
130 | has been charged. If you can't reach your server, it is important that you save the proof
131 | of payment and try again later.
132 |
133 | ### Hint
134 |
135 | Mobile networks are unreliable. Save the proof of payment to make sure it eventually reaches your server.
136 |
137 | Next Steps
138 | ----------
139 |
140 | **Avoid fraud!** Be sure to [verify the proof of payment](https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/).
141 |
--------------------------------------------------------------------------------
/docs/supplemental_errors.md:
--------------------------------------------------------------------------------
1 | Supplemental Errors
2 | ===================
3 |
4 | The PayPal REST API errors are documented [here](https://developer.paypal.com/docs/api/#errors). The errors listed on this payge may also be encountered when making payments:
5 |
6 | - **PAYMENT_CREATION_ERROR**
7 | - There was a problem setting up the payment. This error is usually related the payment methods available in the users account and the merchant requirements.
8 | - **PAYMENT_CREATION_ERROR_EXPIRED_PAYMENT_CARD**
9 | - There was a problem setting up the payment. The only card available in the user's account is expired.
10 | - **PAYMENT_CREATION_ERROR_INSTANT_PAYMENT_REQUIRED**
11 | - There was a problem setting up the payment. The payment requires an instant payment but this is not available in the user's account.
12 | - **PAYMENT_CREATION_ERROR_NEED_CONFIRMED_CARD**
13 | - There was a problem setting up the payment. The payment requires a confirmed card but one is not available in the user's account.
14 | - **PAYMENT_CREATION_ERROR_NEED_PHONE_NUMBER**
15 | - There was a problem setting up the payment. The payment requires a phone number but one is not available in the user's account.
16 | - **PAYMENT_CREATION_ERROR_NEED_VALID_FUNDING_INSTRUMENT**
17 | - There was a problem setting up the payment. The user's account does not contain a valid way to make this payment.
18 | - **PAYMENT_CREATION_ERROR_NEGATIVE_BALANCE**
19 | - There was a problem setting up the payment. The user's account balance is negative and no other viable options are present.
20 | - **PAYMENT_CREATION_ERROR_SENDING_LIMIT_REACHED**
21 | - There was a problem setting up the payment. The user's sending limit has been reached at this time.
22 |
--------------------------------------------------------------------------------