├── .gitignore
├── LICENSE.txt
├── README.md
├── android
├── v1
│ ├── AndroidManifest.xml
│ ├── README.md
│ ├── ant.properties
│ ├── build.xml
│ ├── ic_launcher-web.png
│ ├── proguard-project.txt
│ ├── project.properties
│ ├── res
│ │ ├── drawable-hdpi
│ │ │ ├── bg.png
│ │ │ ├── bolt.png
│ │ │ ├── button_camera.png
│ │ │ ├── button_camera_pressed.png
│ │ │ ├── button_change_currency.png
│ │ │ ├── button_change_currency_pressed.png
│ │ │ ├── button_orange.png
│ │ │ ├── button_orange_pressed.png
│ │ │ ├── currency_button.xml
│ │ │ ├── gray_bolt.png
│ │ │ ├── green_checkmark.png
│ │ │ ├── header_bar_bg.png
│ │ │ ├── ic_launcher.png
│ │ │ ├── icon.png
│ │ │ ├── logo.png
│ │ │ ├── orange_button.xml
│ │ │ ├── overlay_logo.png
│ │ │ ├── paypal_logo.png
│ │ │ ├── red_cross.png
│ │ │ ├── text_field_bg.png
│ │ │ └── text_field_tall_bg.png
│ │ ├── drawable-ldpi
│ │ │ ├── icon.png
│ │ │ └── overlay_logo.png
│ │ ├── drawable-mdpi
│ │ │ ├── bolt.png
│ │ │ ├── gray_bolt.png
│ │ │ ├── ic_launcher.png
│ │ │ └── overlay_logo.png
│ │ ├── drawable-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── icon.png
│ │ ├── drawable-xxhdpi
│ │ │ └── ic_launcher.png
│ │ ├── layout
│ │ │ ├── home.xml
│ │ │ └── result.xml
│ │ └── values
│ │ │ └── strings.xml
│ └── src
│ │ └── com
│ │ └── pphtest
│ │ ├── MainActivity.java
│ │ └── ResultActivity.java
└── v2
│ ├── .gitignore
│ ├── android_pph_sample
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.txt
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── paypal
│ │ │ └── here
│ │ │ └── sample
│ │ │ ├── AddItem.java
│ │ │ ├── Invoice.java
│ │ │ ├── Item.java
│ │ │ └── PayPalHereLauncher.java
│ │ └── res
│ │ ├── drawable-hdpi
│ │ └── icon.png
│ │ ├── drawable-ldpi
│ │ └── ic_launcher.png
│ │ ├── drawable-mdpi
│ │ └── icon.png
│ │ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ │ ├── layout
│ │ ├── add_item.xml
│ │ └── paypal_here_launcher.xml
│ │ └── values
│ │ ├── strings.xml
│ │ └── styles.xml
│ ├── build.gradle
│ ├── build
│ └── intermediates
│ │ └── model_data.bin
│ ├── gradle.properties
│ ├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ └── settings.gradle
├── docs
├── OrderPaymentStepCart.png
├── OrderPaymentStepComplete.png
├── OrderPaymentStepSelectPayment.png
├── README.md
└── sample.html
├── ios
├── PPHere.xcodeproj
│ └── project.pbxproj
├── PPHere
│ ├── Default-568h@2x.png
│ ├── Default.png
│ ├── Default@2x.png
│ ├── JSONKit.h
│ ├── JSONKit.m
│ ├── PPAppDelegate.h
│ ├── PPAppDelegate.m
│ ├── PPHere-Info.plist
│ ├── PPHere-Prefix.pch
│ ├── PPViewController.h
│ ├── PPViewController.m
│ ├── developer.png
│ ├── en.lproj
│ │ ├── InfoPlist.strings
│ │ └── MainStoryboard.storyboard
│ └── main.m
└── README.md
└── web
├── README.md
├── css
├── bootstrap-responsive.min.css
├── bootstrap.min.css
└── main.css
├── img
├── glyphicons-halflings-white.png
├── glyphicons-halflings.png
└── sphero.jpg
├── index.html
└── js
├── angular.min.js
├── bootstrap.js
├── bootstrap.min.js
└── controller.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | android/.DS_Store
3 | android/v2/.idea/
4 | android/v2/android_pph_sample/android_pph_sample.iml
5 | android/v2/v2.iml
6 | android/v2/build/*
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | PAYPAL, INC.
2 |
3 | SDK LICENSE
4 |
5 | NOTICE TO USER: PayPal, Inc. is providing the Software and Documentation for use under the terms of this Agreement. Any use, reproduction, modification or distribution of the Software or Documentation, or any derivatives or portions hereof, constitutes your acceptance of this Agreement.
6 |
7 | As used in this Agreement, "PayPal" means PayPal, Inc. "Software" means the software code accompanying this agreement. "Documentation" means the documents, specifications and all other items accompanying this Agreement other than the Software.
8 |
9 | 1. LICENSE GRANT Subject to the terms of this Agreement, PayPal hereby grants you a non-exclusive, worldwide, royalty free license to use, reproduce, prepare derivative works from, publicly display, publicly perform, distribute and sublicense the Software for any purpose, provided the copyright notice below appears in a conspicuous location within the source code of the distributed Software and this license is distributed in the supporting documentation of the Software you distribute. Furthermore, you must comply with all third party licenses in order to use the third party software contained in the Software.
10 |
11 | Subject to the terms of this Agreement, PayPal hereby grants you a non-exclusive, worldwide, royalty free license to use, reproduce, publicly display, publicly perform, distribute and sublicense the Documentation for any purpose. You may not modify the Documentation.
12 |
13 | No title to the intellectual property in the Software or Documentation is transferred to you under the terms of this Agreement. You do not acquire any rights to the Software or the Documentation except as expressly set forth in this Agreement.
14 |
15 | If you choose to distribute the Software in a commercial product, you do so with the understanding that you agree to defend, indemnify and hold harmless PayPal and its suppliers against any losses, damages and costs arising from the claims, lawsuits or other legal actions arising out of such distribution. You may distribute the Software in object code form under your own license, provided that your license agreement:
16 |
17 | (a) complies with the terms and conditions of this license agreement;
18 |
19 | (b) effectively disclaims all warranties and conditions, express or implied, on behalf of PayPal;
20 |
21 | (c) effectively excludes all liability for damages on behalf of PayPal;
22 |
23 | (d) states that any provisions that differ from this Agreement are offered by you alone and not PayPal; and
24 |
25 | (e) states that the Software is available from you or PayPal and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.
26 |
27 | 2. DISCLAIMER OF WARRANTY
28 | PAYPAL LICENSES THE SOFTWARE AND DOCUMENTATION TO YOU ONLY ON AN "AS IS" BASIS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. PAYPAL MAKES NO WARRANTY THAT THE SOFTWARE OR DOCUMENTATION WILL BE ERROR-FREE. Each user of the Software or Documentation is solely responsible for determining the appropriateness of using and distributing the Software and Documentation and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs, or equipment, and unavailability or interruption of operations. Use of the Software and Documentation is made with the understanding that PayPal will not provide you with any technical or customer support or maintenance. Some states or jurisdictions do not allow the exclusion of implied warranties or limitations on how long an implied warranty may last, so the above limitations may not apply to you. To the extent permissible, any implied warranties are limited to ninety (90) days.
29 |
30 |
31 | 3. LIMITATION OF LIABILITY
32 | PAYPAL AND ITS SUPPLIERS SHALL NOT BE LIABLE FOR LOSS OR DAMAGE ARISING OUT OF THIS AGREEMENT OR FROM THE USE OF THE SOFTWARE OR DOCUMENTATION. IN NO EVENT WILL PAYPAL OR ITS SUPPLIERS BE LIABLE TO YOU OR ANY THIRD PARTY FOR ANY DIRECT, INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES INCLUDING LOST PROFITS, LOST SAVINGS, COSTS, FEES, OR EXPENSES OF ANY KIND ARISING OUT OF ANY PROVISION OF THIS AGREEMENT OR THE USE OR THE INABILITY TO USE THE SOFTWARE OR DOCUMENTATION, HOWEVER CAUSED AND UNDER ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. PAYPAL'S AGGREGATE LIABILITY AND THAT OF ITS SUPPLIERS UNDER OR IN CONNECTION WITH THIS AGREEMENT SHALL BE LIMITED TO THE AMOUNT PAID BY YOU FOR THE SOFTWARE AND DOCUMENTATION.
33 |
34 | 4. TRADEMARK USAGE
35 | PayPal is a trademark PayPal, Inc. in the United States and other countries. Such trademarks may not be used to endorse or promote any product unless expressly permitted under separate agreement with PayPal.
36 |
37 | 5. TERM
38 | Your rights under this Agreement shall terminate if you fail to comply with any of the material terms or conditions of this Agreement and do not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all your rights under this Agreement terminate, you agree to cease use and distribution of the Software and Documentation as soon as reasonably practicable.
39 |
40 | 6. GOVERNING LAW AND JURISDICTION. This Agreement is governed by the statutes and laws of the State of California, without regard to the conflicts of law principles thereof. If any part of this Agreement is found void and unenforceable, it will not affect the validity of the balance of the Agreement, which shall remain valid and enforceable according to its terms. Any dispute arising out of or related to this Agreement shall be brought in the courts of Santa Clara County, California, USA.
41 |
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | PayPal Here™ Sideloader API
2 | ==================
3 |
4 | This project contains 3 very lightweight samples for Android, iOS & Web that show how PayPal Here™ can be integrated into your own projects using the Sideloader API.
5 | ___
6 | For a brief overview of the API and what you can do with it: Have a look at our [Keynote at the MWC's WIPJam 2013](http://www.slideshare.net/PayPal/mwc-keynote) (at our [SlideShare channel](http://www.slideshare.net/PayPal/)).
7 |
8 | Basically you need either a phone with Android or iOS with our PayPal Here™ app installed. To accept payments using PayPal Here™ you need a valid PayPal merchant account that is registered for PayPal Here™ in the supported countries.
9 |
10 | The Sideloader API uses an url scheme to communicate with PayPal's app and retrieve the payment's result via a callback mechanism.
11 |
12 | Using this allows you to accept payments via:
13 |
14 | * Credit card
15 | * PayPal
16 | * Checkin
17 | * Invoice
18 | * Cash
19 |
20 | Getting Started
21 | ---------------
22 |
23 | [Find the documentation here](docs/README.md)
24 |
25 | License
26 | =====
27 | See [LICENSE.txt](LICENSE.txt)
28 |
--------------------------------------------------------------------------------
/android/v1/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/android/v1/README.md:
--------------------------------------------------------------------------------
1 | PayPal Here™ Sideloader API for Android
2 | ======
3 | This sample is designed to show a very simple payment that allows the item's name & amount.
4 |
5 | After the payment (success or canceled) the user get's redirected to the app to show how the callback can be handled.
6 |
7 | Tech used:
8 | ---
9 | Nothing external being used.
--------------------------------------------------------------------------------
/android/v1/ant.properties:
--------------------------------------------------------------------------------
1 | # This file is used to override default values used by the Ant build system.
2 | #
3 | # This file must be checked into Version Control Systems, as it is
4 | # integral to the build system of your project.
5 |
6 | # This file is only used by the Ant script.
7 |
8 | # You can use this to override default values such as
9 | # 'source.dir' for the location of your java source folder and
10 | # 'out.dir' for the location of your output folder.
11 |
12 | # You can also use it define how the release builds are signed by declaring
13 | # the following properties:
14 | # 'key.store' for the location of your keystore and
15 | # 'key.alias' for the name of the key to use.
16 | # The password will be asked during the build when you use the 'release' target.
17 |
18 |
--------------------------------------------------------------------------------
/android/v1/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
29 |
30 |
31 |
35 |
36 |
37 |
38 |
39 |
40 |
49 |
50 |
51 |
52 |
56 |
57 |
69 |
70 |
71 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/android/v1/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/ic_launcher-web.png
--------------------------------------------------------------------------------
/android/v1/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/android/v1/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-17
15 |
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/bg.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/bolt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/bolt.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/button_camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/button_camera.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/button_camera_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/button_camera_pressed.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/button_change_currency.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/button_change_currency.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/button_change_currency_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/button_change_currency_pressed.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/button_orange.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/button_orange.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/button_orange_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/button_orange_pressed.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/currency_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/gray_bolt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/gray_bolt.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/green_checkmark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/green_checkmark.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/header_bar_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/header_bar_bg.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/logo.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/orange_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/overlay_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/overlay_logo.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/paypal_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/paypal_logo.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/red_cross.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/red_cross.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/text_field_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/text_field_bg.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-hdpi/text_field_tall_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-hdpi/text_field_tall_bg.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-ldpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-ldpi/icon.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-ldpi/overlay_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-ldpi/overlay_logo.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-mdpi/bolt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-mdpi/bolt.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-mdpi/gray_bolt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-mdpi/gray_bolt.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-mdpi/overlay_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-mdpi/overlay_logo.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/android/v1/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v1/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/v1/res/layout/home.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
18 |
19 |
23 |
24 |
35 |
36 |
44 |
45 |
46 |
47 |
48 |
55 |
56 |
66 |
67 |
71 |
72 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/android/v1/res/layout/result.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
24 |
25 |
34 |
35 |
36 |
45 |
46 |
55 |
56 |
61 |
62 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/android/v1/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Here Example
5 | Amount
6 | Name
7 | Continue
8 | Scan
9 | OK
10 | Merchant ID
11 | Username
12 | Password
13 | Save
14 | Retry
15 | Cancel
16 | Accept payment with PayPal Here
17 | Refund
18 | EUR
19 | Settings
20 | Invalid amount.
21 | Transaction\nComplete!
22 | Transaction\nDeclined!
23 | Transaction\nCancelled!
24 | Select currency
25 | Please Wait
26 | Your payment is in progress.
27 | Invalid username or password.\nPlease make sure you have entered your details in settings.
28 | 0.00
29 | Coffee
30 |
31 |
32 |
--------------------------------------------------------------------------------
/android/v1/src/com/pphtest/MainActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 eBay Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.pphtest;
18 |
19 | import java.net.URLEncoder;
20 |
21 | import android.app.Activity;
22 | import android.app.AlertDialog;
23 | import android.app.Dialog;
24 | import android.content.DialogInterface;
25 | import android.content.Intent;
26 | import android.net.Uri;
27 | import android.os.Bundle;
28 | import android.util.Log;
29 | import android.view.View;
30 | import android.widget.Button;
31 | import android.widget.EditText;
32 |
33 | /**
34 | * @author aminaei
35 | * @author tmesserschmidt
36 | */
37 | @SuppressWarnings("deprecation")
38 | public class MainActivity extends Activity {
39 | private final static String TAG = "PPHere";
40 |
41 | private EditText amountText;
42 | private EditText nameText;
43 | private Button currencyButton;
44 | private final int CURRENCY_DIALOG = 1;
45 | private final int INVALID_AMOUNT_DIALOG = 2;
46 | private final CharSequence[] CURRENCIES = {
47 | "AUD", "BRL", "CAD", "CHF", "CZK", "DKK", "EUR", "GBP", "HKD",
48 | "HUF", "ILS", "JPY", "MXN", "MYR", "NOK", "NZD", "PHP", "PLN",
49 | "SEK", "SGD", "THB", "TED", "USD"
50 | };
51 |
52 | /**
53 | * Called when the activity is first created.
54 | */
55 | @Override
56 | public void onCreate(Bundle savedInstanceState) {
57 | super.onCreate(savedInstanceState);
58 | setContentView(R.layout.home);
59 | amountText = (EditText) findViewById(R.id.amountText);
60 | nameText = (EditText) findViewById(R.id.nameText);
61 | currencyButton = (Button) findViewById(R.id.currencyButton);
62 | }
63 |
64 | public void changeCurrency(View view) {
65 | showDialog(CURRENCY_DIALOG);
66 | }
67 |
68 | public void continuePayment(View view) {
69 | String url = "paypalhere://takePayment/?returnUrl={{returnUrl}}&invoice=%7B%22merchantEmail%22%3A%22%22,%22payerEmail%22%3A%22spotireddy-biz%40paypal.com%22,%22itemList%22%3A%7B%22item%22%3A%5B%7B%22name%22%3A%22{{name}}%22,%22description%22%3A%22{{description}}%22,%22quantity%22%3A%221.0%22,%22unitPrice%22%3A%22{{price}}%22,%22taxName%22%3A%22Tax%22,%22taxRate%22%3A%220.0%22%7D%5D%7D,%22currencyCode%22%3A%22{{currency}}%22,%22paymentTerms%22%3A%22DueOnReceipt%22,%22discountPercent%22%3A%220.0%22%7D";
70 | String returnUrl = "hailocabtest://paymentResult/?{result}?Type={Type}&InvoiceId={InvoiceId}&Tip={Tip}&Email={Email}&TxId={TxId}";
71 | String priceString = amountText.getText().toString();
72 | String nameString = nameText.getText().toString();
73 | String currency = currencyButton.getText().toString();
74 |
75 | try {
76 | Float.parseFloat(priceString);
77 | } catch (Exception e) {
78 | showDialog(INVALID_AMOUNT_DIALOG);
79 | return;
80 | }
81 |
82 | returnUrl = URLEncoder.encode(returnUrl);
83 |
84 | url = url.replace("{{returnUrl}}", returnUrl);
85 | url = url.replace("{{price}}", priceString);
86 | url = url.replace("{{name}}", nameString);
87 | url = url.replace("{{description}}", nameString);
88 | url = url.replace("{{currency}}", currency);
89 |
90 | Log.v(TAG, "URL: " + url);
91 |
92 | Intent i = new Intent(Intent.ACTION_VIEW);
93 | i.setData(Uri.parse(url));
94 | startActivity(i);
95 | }
96 |
97 | @Override
98 | protected Dialog onCreateDialog(int id) {
99 | Dialog dialog = null;
100 | AlertDialog.Builder builder = null;
101 | switch (id) {
102 | case CURRENCY_DIALOG:
103 | builder = new AlertDialog.Builder(this);
104 | builder.setTitle(R.string.label_select_currency);
105 | builder.setSingleChoiceItems(CURRENCIES, 6,
106 | new DialogInterface.OnClickListener() {
107 | @Override
108 | public void onClick(DialogInterface dialog, int item) {
109 | currencyButton.setText(CURRENCIES[item]);
110 | dismissDialog(CURRENCY_DIALOG);
111 | }
112 | });
113 | dialog = builder.create();
114 | break;
115 | case INVALID_AMOUNT_DIALOG:
116 | builder = new AlertDialog.Builder(this);
117 | builder.setMessage(R.string.invalid_amount_message)
118 | .setCancelable(false)
119 | .setPositiveButton(R.string.label_ok,
120 | new DialogInterface.OnClickListener() {
121 | @Override
122 | public void onClick(DialogInterface dialog,
123 | int id) {
124 | dismissDialog(INVALID_AMOUNT_DIALOG);
125 | }
126 | });
127 | dialog = builder.create();
128 | break;
129 | }
130 |
131 | return dialog;
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/android/v1/src/com/pphtest/ResultActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 eBay Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.pphtest;
18 |
19 | import android.app.Activity;
20 | import android.net.Uri;
21 | import android.os.Bundle;
22 | import android.view.View;
23 | import android.widget.ImageView;
24 | import android.widget.TextView;
25 |
26 | /**
27 | * @author aminaei
28 | * @author tmesserschmidt
29 | */
30 | public class ResultActivity extends Activity {
31 | private TextView txResultMessageText;
32 | private ImageView txResultImage;
33 |
34 | @Override
35 | public void onCreate(Bundle icicle) {
36 | super.onCreate(icicle);
37 | setContentView(R.layout.result);
38 |
39 | txResultImage = (ImageView) findViewById(R.id.txResultImage);
40 | txResultMessageText = (TextView) findViewById(R.id.txResultMessage);
41 | }
42 |
43 | @Override
44 | protected void onResume() {
45 | super.onResume();
46 | handlePassedData();
47 | }
48 |
49 | public void displayHome(View view) {
50 | finish();
51 | }
52 |
53 | private void handlePassedData() {
54 | Uri data = getIntent().getData();
55 |
56 | if (data != null) {
57 | String host = data.getHost();
58 |
59 | if ("paymentResult".equals(host)) {
60 | String type = data.getQueryParameter("Type");
61 | String invoiceId = data.getQueryParameter("InvoiceId");
62 |
63 | TextView typeLabel = (TextView) findViewById(R.id.paymentTypeLabel);
64 | TextView invoiceIdLabel = (TextView) findViewById(R.id.invoiceIdLabel);
65 |
66 | if ("Cancel".equalsIgnoreCase(type)) {
67 | typeLabel.setText("Payment Cancelled");
68 | invoiceIdLabel.setText("");
69 | txResultImage.setImageResource(R.drawable.red_cross);
70 | txResultMessageText.setText(R.string.message_tx_cancelled);
71 | } else {
72 | typeLabel.setText("Payment Type: " + type);
73 | invoiceIdLabel.setText("Invoice Id: " + invoiceId);
74 | txResultImage.setImageResource(R.drawable.green_checkmark);
75 | txResultMessageText.setText(R.string.message_tx_complete);
76 | }
77 | }
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/android/v2/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea/workspace.xml
4 | .DS_Store
5 |
6 | .idea/
7 | android_pph_sample/android_pph_sample.iml
8 | build/intermediates/gradle_project_sync_data.bin
9 | v2.iml
10 |
11 |
--------------------------------------------------------------------------------
/android/v2/android_pph_sample/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/android/v2/android_pph_sample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'android'
2 |
3 | android {
4 | compileSdkVersion 19
5 | buildToolsVersion '19.1.0'
6 |
7 | defaultConfig {
8 | minSdkVersion 10
9 | targetSdkVersion 19
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | }
14 |
15 | dependencies {
16 | compile 'com.android.support:appcompat-v7:19.1.0',
17 | 'com.google.code.gson:gson:1.7.2'
18 | }
19 |
--------------------------------------------------------------------------------
/android/v2/android_pph_sample/proguard-rules.txt:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/mrakic/Documents/android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the ProGuard
5 | # include property in project.properties.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
--------------------------------------------------------------------------------
/android/v2/android_pph_sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/android/v2/android_pph_sample/src/main/java/com/paypal/here/sample/AddItem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * AddItem.java
3 | * PayPal_Here_Sample
4 | *
5 | * Created by mrakic on 6/16/13 11:33 PM.
6 | * Copyright (c) 2013 X.commerce Developer Tools.
7 | * Please see license.txt
8 | */
9 |
10 | package com.paypal.here.sample;
11 |
12 | import android.app.Activity;
13 | import android.content.Intent;
14 | import android.os.Bundle;
15 | import android.text.TextUtils;
16 | import android.view.View;
17 | import android.widget.EditText;
18 | import android.widget.Toast;
19 |
20 |
21 | public class AddItem extends Activity
22 | {
23 | private EditText _txtName;
24 | private EditText _txtDesc;
25 | private EditText _txtUnitPrice;
26 | private EditText _txtTaxName;
27 | private EditText _txtTaxRate;
28 | private EditText _txtQuantity;
29 | private Item _item;
30 |
31 |
32 | public void onCreate(Bundle savedInstanceState)
33 | {
34 | super.onCreate(savedInstanceState);
35 | setContentView(R.layout.add_item);
36 |
37 | _txtName = (EditText) findViewById(R.id.name);
38 | _txtDesc = (EditText) findViewById(R.id.description);
39 | _txtUnitPrice = (EditText) findViewById(R.id.price);
40 | _txtTaxName = (EditText) findViewById(R.id.tax_name);
41 | _txtTaxRate = (EditText) findViewById(R.id.tax_rate);
42 | _txtQuantity = (EditText) findViewById(R.id.quantity);
43 | }
44 |
45 |
46 | public void addItem(View view)
47 | {
48 | if (validateFields())
49 | {
50 | Intent intent = this.getIntent();
51 | intent.putExtra(Item.class.getSimpleName(), Item.Converter.toBundle(_item));
52 | this.setResult(RESULT_OK, intent);
53 | finish();
54 | }
55 | else
56 | {
57 | Toast toast = Toast.makeText(this, "Required field missing!", Toast.LENGTH_SHORT);
58 | toast.show();
59 | }
60 | }
61 |
62 |
63 | private boolean validateFields()
64 | {
65 | String name = _txtName.getText().toString();
66 | String description = _txtDesc.getText().toString();
67 | String price = _txtUnitPrice.getText().toString();
68 | String taxName = _txtTaxName.getText().toString();
69 | String taxRate = _txtTaxRate.getText().toString();
70 | String quantity = _txtQuantity.getText().toString();
71 |
72 | if (TextUtils.isEmpty(name) || TextUtils.isEmpty(price) || TextUtils.isEmpty(quantity))
73 | {
74 | return false;
75 | }
76 |
77 | if (TextUtils.isEmpty(taxName) || TextUtils.isEmpty(taxRate))
78 | {
79 | _item = new Item(name, description, Double.valueOf(quantity), Double.valueOf(price));
80 | }
81 | else
82 | {
83 | _item = new Item(name, description, Double.valueOf(quantity), taxRate, taxName, Double.valueOf(price));
84 | }
85 |
86 | return true;
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/android/v2/android_pph_sample/src/main/java/com/paypal/here/sample/Invoice.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Invoice.java
3 | * PayPal_Here_Sample
4 | *
5 | * Created by mrakic on 6/16/13 11:28 PM.
6 | * Copyright (c) 2013 X.commerce Developer Tools.
7 | * Please see license.txt
8 | */
9 |
10 | package com.paypal.here.sample;
11 |
12 |
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 | import android.net.Uri;
17 | import com.google.gson.Gson;
18 | import com.google.gson.annotations.SerializedName;
19 | import org.json.JSONArray;
20 | import org.json.JSONException;
21 | import org.json.JSONObject;
22 |
23 | //
24 | // Invoice object to store invoice data
25 | // for more information about the Invoice object, please refer to
26 | // https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_CreateInvoice
27 | //
28 | public class Invoice
29 | {
30 | @SerializedName("paymentTerms")
31 | private String _paymentTerms;
32 | @SerializedName("discountPercent")
33 | private String _discountPercentage;
34 | @SerializedName("currencyCode")
35 | private String _currencyCode;
36 | @SerializedName("merchantEmail")
37 | private String _merchantEmail;
38 | @SerializedName("number")
39 | private String _number;
40 | @SerializedName("payerEmail")
41 | private String _payerEmail; // payerEmail is optional, PayPal Here app will fill the value
42 | @SerializedName("itemList")
43 | private Items _items;
44 |
45 |
46 | public Invoice()
47 | {
48 | _items = new Items();
49 | }
50 |
51 |
52 | public void addItemWithName(String itemName, String description, String taxRate, Double unitPrice, String taxName, Double quantity)
53 | {
54 | Item item = new Item(itemName, description, quantity, taxRate, taxName, unitPrice);
55 | _items.add(item);
56 | }
57 |
58 |
59 | public String getNumber()
60 | {
61 | return _number;
62 | }
63 |
64 |
65 | public void setNumber(String number)
66 | {
67 | _number = number;
68 | }
69 |
70 |
71 | public void addItem(Item item)
72 | {
73 | _items.add(item);
74 | }
75 |
76 |
77 | public String getPaymentTerms()
78 | {
79 | return _paymentTerms;
80 | }
81 |
82 |
83 | public void setPaymentTerms(String paymentTerms)
84 | {
85 | _paymentTerms = paymentTerms;
86 | }
87 |
88 |
89 | public String getDiscountPercentage()
90 | {
91 | return _discountPercentage;
92 | }
93 |
94 |
95 | public void setDiscountPercentage(String discountPercentage)
96 | {
97 | _discountPercentage = discountPercentage;
98 | }
99 |
100 |
101 | public String getCurrencyCode()
102 | {
103 | return _currencyCode;
104 | }
105 |
106 |
107 | public void setCurrencyCode(String currencyCode)
108 | {
109 | _currencyCode = currencyCode;
110 | }
111 |
112 |
113 | public String getMerchantEmail()
114 | {
115 | return _merchantEmail;
116 | }
117 |
118 |
119 | public void setMerchantEmail(String merchantEmail)
120 | {
121 | _merchantEmail = merchantEmail;
122 | }
123 |
124 |
125 | public String getPayerEmail()
126 | {
127 | return _payerEmail;
128 | }
129 |
130 |
131 | public void setPayerEmail(String payerEmail)
132 | {
133 | _payerEmail = payerEmail;
134 | }
135 |
136 |
137 | public List getItemList()
138 | {
139 | return _items._itemList;
140 | }
141 |
142 |
143 | public int getItemsCount()
144 | {
145 | return _items.getItemsCount();
146 | }
147 |
148 |
149 | public static class Items
150 | {
151 | @SerializedName("item")
152 | private List _itemList;
153 |
154 |
155 | public Items()
156 | {
157 | _itemList = new ArrayList();
158 | }
159 |
160 |
161 | public void add(Item item)
162 | {
163 | _itemList.add(item);
164 | }
165 |
166 |
167 | public int getItemsCount()
168 | {
169 | return _itemList.size();
170 | }
171 | }
172 |
173 |
174 | /*
175 | Helper class used to serialize Invoice object to JSON string
176 | e.g.
177 | {
178 | "currencyCode" : "USD",
179 | "discountPercent" : "0",
180 | "itemList" :
181 | {
182 | "item" :
183 | [
184 | {
185 | "description" : "Blue T-shirt",
186 | "name" : "T-Shirt",
187 | "quantity" : 1.0,
188 | "taxName" : "Sales Tax",
189 | "taxRate" : "8.50",
190 | "unitPrice" : 15.99
191 | }
192 | ]
193 | },
194 | "merchantEmail" : "merchant@ebay.com",
195 | "number" : "9876",
196 | "payerEmail" : "foo@bar.com",
197 | "paymentTerms" : "DueOnReceipt"
198 | }
199 | */
200 | public static class Converter
201 | {
202 | public static String serializeToUrlEncodedJSonString(Invoice invoice)
203 | {
204 | Gson gson = new Gson();
205 | String invoiceJson = gson.toJson(invoice);
206 | return Uri.encode(invoiceJson);
207 | }
208 |
209 |
210 | public static String toUrlEncodedJSonString(Invoice invoice)
211 | {
212 | // Create invoice
213 | JSONObject invoiceJson = new JSONObject();
214 | try
215 | {
216 | JSONObject itemList = new JSONObject();
217 | JSONArray itemListArray = new JSONArray();
218 |
219 | List items = invoice.getItemList();
220 | // Create an item
221 | for (Item item : items)
222 | {
223 | JSONObject itemJson = new JSONObject();
224 | itemJson.put("description", item.getDescription());
225 | itemJson.put("taxRate", item.getTaxRate());
226 | itemJson.put("name", item.getName());
227 | itemJson.put("unitPrice", item.getUnitPrice());
228 | itemJson.put("taxName", item.getTaxName());
229 | itemJson.put("quantity", item.getQuantity());
230 | // Add the item to the items lis
231 | itemListArray.put(item);
232 | }
233 | itemList.put("item", itemListArray);
234 |
235 | // Add invoice details including items from above
236 | invoiceJson.put("paymentTerms", invoice.getPaymentTerms());
237 | invoiceJson.put("discountPercent", invoice.getDiscountPercentage());
238 | invoiceJson.put("currencyCode", invoice.getCurrencyCode());
239 | invoiceJson.put("number", invoice.getNumber());
240 | invoiceJson.put("merchantEmail", invoice.getMerchantEmail());
241 | invoiceJson.put("payerEmail", invoice.getPayerEmail());
242 | invoiceJson.put("itemList", itemList);
243 | }
244 | catch (JSONException e)
245 | {
246 | e.printStackTrace();
247 | //handle JSON exception here
248 | }
249 |
250 | return Uri.encode(invoiceJson.toString());
251 | }
252 | }
253 | }
254 |
--------------------------------------------------------------------------------
/android/v2/android_pph_sample/src/main/java/com/paypal/here/sample/Item.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Item.java
3 | * PayPal_Here_Sample
4 | *
5 | * Created by mrakic on 6/16/13 11:33 PM.
6 | * Copyright (c) 2013 X.commerce Developer Tools.
7 | * Please see license.txt
8 | */
9 |
10 | package com.paypal.here.sample;
11 |
12 |
13 | import java.io.Serializable;
14 |
15 | import android.os.Bundle;
16 | import com.google.gson.annotations.SerializedName;
17 |
18 | public class Item implements Serializable
19 | {
20 | public static final String NAME = "name";
21 | public static final String DESC = "desc";
22 | public static final String QUANTITY = "quantity";
23 | public static final String TAX_NAME = "taxName";
24 | public static final String TAX_RATE = "taxRate";
25 | public static final String PRICE = "price";
26 | @SerializedName("name")
27 | private final String _name;
28 | @SerializedName("description")
29 | private final String _description;
30 | @SerializedName("quantity")
31 | private final Double _quantity;
32 | @SerializedName("taxRate")
33 | private final String _taxRate;
34 | @SerializedName("taxName")
35 | private final String _taxName;
36 | @SerializedName("unitPrice")
37 | private final Double _unitPrice;
38 |
39 |
40 | public Item(String name, String description, Double quantity, String taxRate, String taxName, Double unitPrice)
41 | {
42 | _name = name;
43 | _description = description;
44 | _quantity = quantity;
45 | _taxRate = taxRate;
46 | _taxName = taxName;
47 | _unitPrice = unitPrice;
48 | }
49 |
50 |
51 | public Item(String name, String description, Double quantity, Double unitPrice)
52 | {
53 | _name = name;
54 | _description = description;
55 | _quantity = quantity;
56 | _taxRate = null;
57 | _taxName = null;
58 | _unitPrice = unitPrice;
59 | }
60 |
61 |
62 | public String getName()
63 | {
64 | return _name;
65 | }
66 |
67 |
68 | public String getDescription()
69 | {
70 | return _description;
71 | }
72 |
73 |
74 | public Double getQuantity()
75 | {
76 | return _quantity;
77 | }
78 |
79 |
80 | public String getTaxRate()
81 | {
82 | return _taxRate;
83 | }
84 |
85 |
86 | public String getTaxName()
87 | {
88 | return _taxName;
89 | }
90 |
91 |
92 | public Double getUnitPrice()
93 | {
94 | return _unitPrice;
95 | }
96 |
97 |
98 | public static final class Converter
99 | {
100 |
101 | public static Bundle toBundle(Item item)
102 | {
103 | Bundle bundle = new Bundle();
104 | bundle.putSerializable(Item.class.getName(), item);
105 | return bundle;
106 | }
107 |
108 |
109 | public static Item fromBundle(Bundle bundle)
110 | {
111 | Item item = (Item) bundle.getSerializable(Item.class.getName());
112 | return item;
113 | }
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/android/v2/android_pph_sample/src/main/java/com/paypal/here/sample/PayPalHereLauncher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * PayPalHereLauncher.java
3 | * PayPal_Here_Sample
4 | *
5 | * Created by mrakic on 6/16/13 11:28 PM.
6 | * Copyright (c) 2013 X.commerce Developer Tools.
7 | * Please see license.txt
8 | */
9 |
10 | package com.paypal.here.sample;
11 |
12 | import android.app.Activity;
13 | import android.app.AlertDialog;
14 | import android.content.DialogInterface;
15 | import android.content.Intent;
16 | import android.content.pm.PackageManager;
17 | import android.content.pm.ResolveInfo;
18 | import android.net.Uri;
19 | import android.os.Bundle;
20 | import android.view.View;
21 | import android.widget.EditText;
22 | import android.widget.TextView;
23 |
24 | import java.text.MessageFormat;
25 |
26 | public class PayPalHereLauncher extends Activity
27 | {
28 | public static final String MARKET_URL = "market://details?id=com.paypal.here";
29 | private static final String PPH_URL_STRING = "paypalhere://takePayment/v2?accepted={0}&returnUrl={1}&invoice={2}&step=choosePayment&payerPhone={3}";
30 | private static final String RETURN_URL = "pphsample://handleResponse/?Type={Type}&InvoiceId={InvoiceId}&Tip={Tip}&Email={Email}&TxId={TxId}&GrandTotal={GrandTotal}";
31 | private static final String ACCEPTED_PAYMENT_TYPES = "cash,card,paypal";
32 | private static final String RESPONSE_HOST = "handleResponse";
33 | private Invoice _invoice;
34 | private EditText _invoiceNumber;
35 | private EditText _paymentTerms;
36 | private EditText _payerEmail;
37 | private EditText _payerPhone;
38 | private EditText _merchantEmail;
39 | private TextView _itemCount;
40 | private EditText _discount;
41 | private EditText _currencyCode;
42 |
43 | private static final int ADD_ITEM_REQUEST_CODE = 100;
44 |
45 |
46 | /**
47 | * Called when the activity is first created.
48 | */
49 | @Override
50 | public void onCreate(Bundle savedInstanceState)
51 | {
52 | super.onCreate(savedInstanceState);
53 | setContentView(R.layout.paypal_here_launcher);
54 |
55 | _currencyCode = (EditText) findViewById(R.id.currency_code);
56 | _invoiceNumber = (EditText) findViewById(R.id.invoice_number);
57 | _discount = (EditText) findViewById(R.id.discount);
58 | _itemCount = (TextView) findViewById(R.id.item_count);
59 | _merchantEmail = (EditText) findViewById(R.id.merchant_email);
60 | _payerEmail = (EditText) findViewById(R.id.payer_email);
61 | _payerPhone = (EditText) findViewById(R.id.payer_phone);
62 | _paymentTerms = (EditText) findViewById(R.id.payment_terms);
63 |
64 | initializeDefaultDataList();
65 | }
66 |
67 |
68 | @Override
69 | protected void onNewIntent(Intent intent)
70 | {
71 | super.onNewIntent(intent);
72 | handleOpenURL(intent);
73 | }
74 |
75 |
76 | private void initializeDefaultDataList()
77 | {
78 | _invoice = new Invoice();
79 | _invoice.addItemWithName("T-Shirt", "I Love APIs shirt", "8.50", 9.99, "Sales Tax", 1.0);
80 | _itemCount.setText(String.valueOf(_invoice.getItemsCount()));
81 | }
82 |
83 |
84 | private void handleOpenURL(Intent intent)
85 | {
86 | Uri data = intent.getData();
87 | if (data == null)
88 | {
89 | return;
90 | }
91 |
92 | String host = data.getHost();
93 | if (RESPONSE_HOST.equals(host))
94 | {
95 | String response = data.toString();
96 | AlertDialog.Builder responseDialog = new AlertDialog.Builder(this);
97 | responseDialog.setMessage(response).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
98 | {
99 | @Override
100 | public void onClick(DialogInterface dialogInterface, int i)
101 | {
102 | dialogInterface.dismiss();
103 | }
104 | });
105 | responseDialog.show();
106 | }
107 | }
108 |
109 |
110 | public void addItem(View view)
111 | {
112 | Intent intent = new Intent(this, AddItem.class);
113 | startActivityForResult(intent, ADD_ITEM_REQUEST_CODE);
114 | }
115 |
116 |
117 | @Override
118 | protected void onActivityResult(int requestCode, int resultCode, Intent data)
119 | {
120 | super.onActivityResult(requestCode, resultCode, data);
121 |
122 | if (requestCode == ADD_ITEM_REQUEST_CODE && resultCode == Activity.RESULT_OK)
123 | {
124 | Bundle bundle = data.getBundleExtra(Item.class.getSimpleName());
125 | Item item = Item.Converter.fromBundle(bundle);
126 | _invoice.addItem(item);
127 | _itemCount.setText(String.valueOf(_invoice.getItemsCount()));
128 | }
129 | }
130 |
131 |
132 | public void launchPayPalHere(View view)
133 | {
134 | _invoice.setPayerEmail(_payerEmail.getText().toString());
135 | _invoice.setMerchantEmail(_merchantEmail.getText().toString());
136 | _invoice.setCurrencyCode(_currencyCode.getText().toString());
137 | _invoice.setDiscountPercentage(_discount.getText().toString());
138 | _invoice.setPaymentTerms(_paymentTerms.getText().toString());
139 | _invoice.setNumber(_invoiceNumber.getText().toString());
140 | String phone = _payerPhone.getText().toString();
141 |
142 | String urlEncodedReturnUrl = Uri.encode(RETURN_URL);
143 | String urlEncodedPaymentTypes = Uri.encode(ACCEPTED_PAYMENT_TYPES);
144 |
145 | String urlEncodedInvoice = Invoice.Converter.serializeToUrlEncodedJSonString(_invoice);
146 | String pphUrl = MessageFormat.format(PPH_URL_STRING, urlEncodedPaymentTypes, urlEncodedReturnUrl, urlEncodedInvoice, phone);
147 |
148 | Intent pphIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(pphUrl));
149 | PackageManager packageManager = getPackageManager();
150 | ResolveInfo resolveInfo = packageManager.resolveActivity(pphIntent, PackageManager.MATCH_DEFAULT_ONLY);
151 | if (resolveInfo == null)
152 | {
153 | AlertDialog.Builder pphNotFoundDialog = new AlertDialog.Builder(this);
154 | pphNotFoundDialog.setTitle("PayPal Here app Not Found!").setMessage("Install from Google Play");
155 | pphNotFoundDialog.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
156 | {
157 | @Override
158 | public void onClick(DialogInterface dialogInterface, int i)
159 | {
160 | startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(MARKET_URL)));
161 | dialogInterface.dismiss();
162 | }
163 | });
164 | pphNotFoundDialog.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener()
165 | {
166 | @Override
167 | public void onClick(DialogInterface dialogInterface, int i)
168 | {
169 | dialogInterface.dismiss();
170 | }
171 | });
172 | pphNotFoundDialog.show();
173 | }
174 | else
175 | {
176 | startActivity(pphIntent);
177 | }
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/android/v2/android_pph_sample/src/main/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v2/android_pph_sample/src/main/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/android/v2/android_pph_sample/src/main/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v2/android_pph_sample/src/main/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/v2/android_pph_sample/src/main/res/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v2/android_pph_sample/src/main/res/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/android/v2/android_pph_sample/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v2/android_pph_sample/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/v2/android_pph_sample/src/main/res/layout/add_item.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
15 |
16 |
23 |
24 |
27 |
28 |
31 |
32 |
35 |
36 |
37 |
40 |
41 |
44 |
45 |
48 |
49 |
50 |
53 |
54 |
57 |
58 |
62 |
63 |
64 |
67 |
68 |
71 |
72 |
75 |
76 |
77 |
80 |
81 |
84 |
85 |
89 |
90 |
91 |
94 |
95 |
98 |
99 |
103 |
104 |
105 |
108 |
109 |
116 |
117 |
118 |
--------------------------------------------------------------------------------
/android/v2/android_pph_sample/src/main/res/layout/paypal_here_launcher.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
15 |
16 |
23 |
24 |
27 |
28 |
31 |
32 |
36 |
37 |
38 |
41 |
42 |
45 |
46 |
50 |
51 |
52 |
55 |
56 |
59 |
60 |
64 |
65 |
66 |
69 |
70 |
73 |
74 |
78 |
79 |
80 |
83 |
84 |
87 |
88 |
91 |
92 |
93 |
96 |
97 |
100 |
101 |
104 |
105 |
108 |
109 |
112 |
113 |
116 |
117 |
118 |
122 |
123 |
126 |
127 |
131 |
132 |
137 |
138 |
139 |
142 |
143 |
150 |
151 |
152 |
--------------------------------------------------------------------------------
/android/v2/android_pph_sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | PayPal Here Sample
4 |
5 |
--------------------------------------------------------------------------------
/android/v2/android_pph_sample/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
15 |
--------------------------------------------------------------------------------
/android/v2/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | mavenCentral()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.0.0'
9 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | mavenCentral()
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/android/v2/build/intermediates/model_data.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v2/build/intermediates/model_data.bin
--------------------------------------------------------------------------------
/android/v2/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Settings specified in this file will override any Gradle settings
5 | # configured through the IDE.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/android/v2/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/android/v2/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/v2/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Jan 26 14:10:02 EST 2015
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.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/android/v2/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 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
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 |
--------------------------------------------------------------------------------
/android/v2/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 Windowz 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 |
--------------------------------------------------------------------------------
/android/v2/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':android_pph_sample'
2 |
--------------------------------------------------------------------------------
/docs/OrderPaymentStepCart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/docs/OrderPaymentStepCart.png
--------------------------------------------------------------------------------
/docs/OrderPaymentStepComplete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/docs/OrderPaymentStepComplete.png
--------------------------------------------------------------------------------
/docs/OrderPaymentStepSelectPayment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/docs/OrderPaymentStepSelectPayment.png
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # PayPal Here™ Mobile Apps API
2 |
3 | ## Getting Started Guide, version 1.3
4 |
5 | The functionality described in this document is subject to change.
6 |
7 |
8 | ### Overview
9 | Your order-entry mobile app can send an invoice to the PayPal Here app on iOS or Android. The invoice is sent as part of a URL that launches the PayPal Here app.
10 |
11 | For sample code, see _Appendix C: Sample Code in Objective-C_.
12 |
13 | For information about launching the PayPal Here app, see _Appendix D: Confirming the PayPal Here App Is Installed on a device_.
14 |
15 |
16 | ### Prerequisites
17 | * If your app is a native iOS app, the development of your app requires the Xcode 4.3 (or later) integrated development environment.
18 | * Testing your app requires that you already have a device that is set up with the [PayPal Here mobile app](https://www.paypal.com/webapps/mpp/credit-card-reader-faq) and the PayPal Here credit-card reader.
19 |
20 |
21 | ### Use Case
22 | A merchant installs your order-entry app, and the PayPal Here app, on a device. Then, a merchant can:
23 | * Use your app to assemble an order
24 | * Use your app to send the order, as an invoice, to launch the PayPal Here app
25 | * Use the PayPal Here app to adjust the amounts as necessary, or add items, and then accept payment with a credit card, PayPal, cash, an invoice or a check
26 |
27 | Thus, during the _Order and Payment Flow_:
28 | * Your app sends an order to the PayPal Here app (using the API)
29 | * The order details are pre-populated within the PayPal Here app
30 | * The merchant uses the PayPal Here app to accept a payment
31 | * After the payment is successful, the merchant is returned to your app
32 |
33 |
34 | ## Sending an Invoice to the PayPal Here Mobile App
35 | To send an invoice to the PayPal Here app, specify a URL. The URL root is the following:
36 |
37 | paypalhere://takePayment?
38 |
39 | For new Android integrations use:
40 |
41 | paypalhere://takePayment/v2?
42 |
43 | Android apps using `takePayment` will continue working as is, but `takePayment/v2` behavior is in sync with the API described in this document.
44 |
45 | When the URL root is used with the input fields discussed in this document, the PayPal Here mobile app
46 | is launched. **Most of the input values must be URL-encoded**, but the invoice data **may be** Base64-
47 | encoded instead (see below).
48 |
49 | **Note:** If the merchant has installed your app, but has **not** installed the PayPal Here app, your app should direct users to the app store: See _Appendix D: Confirming the PayPal Here App Is Installed on a Device_.
50 |
51 | The invoice data is sent in a JSON object. Before encoding, the full URL, with the required fields, will be in a format like the following:
52 |
53 | paypalhere://takePayment?
54 | accepted=cash,card,paypal
55 | &returnUrl=my_registered_location://takePayment/{result}?Type={Type}&InvoiceId={InvoiceId}&Tip={Tip}&TxId={TxId}
56 | &as=b64
57 | &step=choosePayment
58 | &payerPhone=4155551212
59 | &invoice=
60 | {
61 | "paymentTerms": "DueOnReceipt",
62 | "discountPercent": "0",
63 | "currencyCode": "USD",
64 | "number": "1457",
65 | "payerEmail": "foo@bar.com",
66 | "itemList": {
67 | "item": [
68 | {
69 | "taxRate": "8.5000",
70 | "name": "Curtains",
71 | "description": "Blue curtains",
72 | "unitPrice": "29.99",
73 | "taxName": "Tax",
74 | "quantity": "1"
75 | },
76 | {
77 | "taxRate": "0",
78 | "name": "Delivery Fee",
79 | "description": "Delivery Fee",
80 | "unitPrice": "5.0",
81 | "taxName": "Tax",
82 | "quantity": "1"
83 | }
84 | ]
85 | }
86 | }
87 |
88 |
89 | ### Invoice as a JSON object
90 | Put the invoice data (one or more items and amounts) into a JSON object.
91 |
92 | The JSON object’s format is largely the same as the invoice format in the PayPal Invoicing Service. For information about the available fields, see the descriptions in [CreateInvoice (a call in the Invoicing Service)](https://developer.paypal.com/webapps/developer/docs/classic/api/invoicing/CreateInvoice_API_Operation/). However, only certain fields are used; see the section "Call Reference" below for more details.
93 |
94 | Note that duplicate items are ignored in the `itemList`; instead, you should increment the quantity.
95 |
96 | **Note:** Sending an invoice field with no value (for example, sending `“payerEmail”: “”`) will cause unexpected behavior, so remove any fields that lack a value.
97 |
98 | For example, before encoding the values of each input field, the JSON object could be the following:
99 |
100 | ```json
101 |
102 | {
103 | "paymentTerms": "DueOnReceipt",
104 | "discountPercent": "0",
105 | "currencyCode": "USD",
106 | "number": "1457",
107 | "payerEmail": "foo@bar.com",
108 | "itemList": {
109 | "item": [
110 | {
111 | "taxRate": "8.5000",
112 | "name": "Curtains",
113 | "description": "Blue curtains",
114 | "unitPrice": "29.99",
115 | "taxName": "Tax",
116 | "quantity": "1"
117 | },
118 | {
119 | "taxRate": "0",
120 | "name": "Delivery Fee",
121 | "description": "Delivery Fee",
122 | "unitPrice": "5.0",
123 | "taxName": "Tax",
124 | "quantity": "1"
125 | }
126 | ]
127 | }
128 | }
129 |
130 | ```
131 |
132 | Note: In the JSON input object (containing the invoice data), you may provide a unique invoice ID (in the `number` field). It must be unique to the merchant. If you leave out the number field, an invoice ID will be assigned, but if you provide the number field with a repeated value, or no value, (for example, if you send `“number”: “”`, or send `“number”: “12345”` every time), unexpected behavior will result. This value will be passed back to you in the return URL as `Number`.
133 |
134 | To use this invoice to send Paypal Invoices, see [How to Send an Invoice Using the Invoicing Service](https://developer.paypal.com/webapps/developer/docs/classic/invoicing/ht_invoicing-send/). Also see _Appendix A: Sample HTML and Javascript Code_.
135 |
136 |
137 | ### Encoding the JSON invoice
138 | This JSON object with the contain the invoice data must be either Base64-encoded (recommended) or URL-encoded.
139 | Use the as input field to indicate whether you will Base64-encode the JSON invoice object. Note that the `as` input field only applies to the invoice data.
140 |
141 | If you plan to Base64-encode the JSON invoice object (recommended), set the `as` input field to `b64`:
142 |
143 | paypalhere://takePayment?as=b64
144 |
145 | Omit the `as` parameter if you plan to URL-encode the invoice instead.
146 |
147 |
148 | ### URL-Encoded Input Data
149 | Append (to the URL root) your input fields and their URL-encoded data. These input fields include the
150 | as input field, described above. For information in this document about the fields, see Call Reference.
151 | For example, the fields and values could be the following, before the values are encoded:
152 |
153 | accepted=cash,card,paypal,
154 | &returnUrl=my_registered_location://takePayment/{result}?Type={Type}&InvoiceId={InvoiceId}&Tip={Tip}&TxId={TxId}
155 | &as=b64
156 | &step=choosePayment
157 | &payerPhone=4155551212
158 | &invoice=[JSON object, which in this case is Base64-encoded]
159 |
160 |
161 | ### Response URL from the PayPal Here App
162 |
163 | After your order-entry app sends an invoice to the PayPal Here app, and the merchant completes the payment flow in the PayPal Here app, the PayPal Here app uses a response URL (`returnUrl`) to re- launch your app.
164 |
165 | For examples of the fields returned with this response URL, see Output Fields.
166 |
167 | If your app is written in Objective-C, see public tutorials such as [this tutorial](http://code.tutsplus.com/tutorials/ios-sdk-working-with-url-schemes--mobile-6629) for information about handling this event.
168 |
169 | For example, the response URL of the PayPal Here app could be similar to the following, which would correspond to the return URL specified in the original request:
170 |
171 | YourAppReturnURLRoot://takePayment?Type=CreditCard&InvoiceId=INV2-AHWG-SQHP-QMLT-1234&Tip=5.00&TxId=111-11-1111
172 |
173 | However, if a payment is canceled, the response of the PayPal Here app would be similar to the following:
174 |
175 | YourAppReturnURLRoot://takePayment?Type=UNKNOWN
176 |
177 | For sample code for working with the Paypal Here API in Objective C, see Appendix C below.
178 |
179 |
180 | ## Call Reference
181 |
182 | Your order-entry app can send an invoice to the PayPal Here app. For a description of this process, in this document, see Send an Invoice to the PayPal Here Mobile App.
183 |
184 | ### Input Fields
185 |
186 | | Input field name | Description | Comment |
187 | | ------------- | ----------- | ------- |
188 | | accepted | The payment methods to be offered in the PayPal Here app (i.e., the values that you specify will determine the payment methods offered). Acceptable values are `cash`, `card`, `invoice`, `check`, and `paypal`. | Individual countries may not allow certain payment methods. This field is optional. |
189 | | returnUrl | The URL of your app (or mobile web page, email, short URL, SMS, or anywhere a URL can be used). This value must be a well-formatted URL. The user is sent to this URL after the payment is completed (or the transaction is cancelled). **See _“Structuring the returnUrl Input Field,”_ below.** The URL can include placeholders (using curly braces), which will be replaced with desired transaction information. | This field is optional. |
190 | | as | Set the optional `as` input field to `b64` if you will Base64-encode the JSON invoice object. If you won’t Base64-encode the JSON invoice object, omit the as parameter. Base-64 encoding (used if you specify `as=b64`) is recommended for the JSON invoice object (as an alternative to URL-encoding) because Base-64 encoding is more likely to result in correct encoding. | For information about the JSON invoice object, see `invoice`, below. |
191 | | step | Where the merchant will begin after being taken to the PayPal Here app. Send nothing to start on the order entry page. Send `choosePayment` to cause the payment options screen to display automatically.| |
192 | | invoice | A JSON object that contains the invoice data. | See the following section of this document: _Invoice as a JSON object_ |
193 | | payerPhone | If the buyer email address is known ahead of time, this can be specified in the invoice directly. However, if the buyer's phone number is known and your app desires an SMS receipt to be offered to them, the `payerPhone` field will be used to pre-fill that field in US format. | |
194 |
195 |
196 | ### Structuring the `returnUrl` Input Field
197 |
198 | The data for the `returnUrl` input field is a URL that can include placeholders for the desired transaction information. That is, you can use curly braces in the URL for the PayPal Here app to return specific data about the transaction. The following table provides information about the keys you can use and the data they will get replaced with.
199 |
200 | As an example, if your return URL is:
201 | `myAppURLScheme://returnFromPPH?type={Type}&pph_inv_id={InvoiceId}`
202 |
203 | Then it will get changed into something like:
204 | `myAppURLScheme://returnFromPPH?type=CreditCard&pph_inv_id=12345`
205 |
206 | | Field of the `returnUrl` input field | Description |
207 | | ------------- | ----------- |
208 | | Root URL of your app, including the call that was invoked by your app. Example: `my_registered_location://takePayment` | The PayPal Here app uses this value to return the merchant to your app, after payment |
209 | | `Type` | The type of payment made, e.g. `SWIPE`. Specify `Type={Type}` See _Output Fields_ below for a comprehensive listing |
210 | | `InvoiceId` | The invoice ID. Specify `InvoiceId={InvoiceId}` |
211 | | `Tip` | The tip, if applicable. `Specify Tip={Tip}` |
212 | | `TxId` | The tax ID of the merchant. Specify `TxId={TxId}` |
213 | | `Number` | The merchant reference number for the invoice, which you can optionally pass in when opening PayPal Here with the `number` parameter. Mind the difference in capitalization. Specify `Number={Number}` |
214 | | `GrandTotal` | The final total amount of the invoice. `GrandTotal={GrandTotal}` **Available in builds > v2.5 on iOS, v2.5.2 on Android** |
215 |
216 |
217 | ### Output Fields
218 |
219 | | Input field name | Description |
220 | | ---------------- | ----------- |
221 | | `Type` | The payment method, for example `SWIPE`. Returned values are listed below, but your code should be able to handle new values as they get introduced.
If the transaction was interrupted, for example if a credit card was declined, the value is `UNKNOWN`. Note: If a credit card is declined, the merchant can enter an alternative payment method.
If the merchant cancels, the order-entry’s return URL is called, appended with `Type=UNKNOWN`.
Due to legacy issues, the values for "Type" currently differ based on the version being used. On PayPal Here versions 2.x on all platforms, these values can be: `UNKNOWN`, `KEY`, `SCAN`, `SWIPE`, `PAYPAL`, `CHECK`, `CASH`, `CHIP`, `EMV_SWIPE`. On iPad 1.x, these values can be: `Unknown`, `CreditCard`, `Check`, `Cash`, `PayPal`, `DebitCard`, `Other`, `ChipCard`.
You should code your integrations to handle new values being returned in this field.|
222 | | `InvoiceId` | The ID of the new invoice for which payment was accepted. |
223 | | `Tip` | The monetary value tip, if applicable. |
224 | | `Number` | The merchant reference number for the invoice, which you can optionally pass in when opening PayPal Here with the `number` parameter. Mind the difference in capitalization. For more information about the input value that corresponds to this ID, see __Invoice as a JSON object.__ |
225 | | `GrandTotal` | The final total amount of the invoice. |
226 |
227 |
228 | ## Order and Payment Flow
229 |
230 | This section uses an example of charging a credit card to outline steps for:
231 |
232 | * Using an order-entry app to send an invoice to the PayPal Here app
233 | * Accepting a payment in the PayPal Here app
234 |
235 | After the merchant accepts the payment, your order-entry app is re-launched so the merchant can
236 | confirm that the payment was successfully recorded in the order-entry app.
237 |
238 | The following steps describe a version of an order and payment flow.
239 |
240 | 1. Merchant starts the order-entry app and brings up an order.
241 | 2. Merchant chooses **Pay** in the order-entry app.
242 | 3. The order-entry app uses the following URL and fields to launch the PayPal Here app:
243 | `paypalhere://takePayment?[URL-encoded input fields]&invoice=[invoice as a base64-encoded JSON object]`
244 | 4. Merchant logs into Merchant’s PayPal account. On the Charge screen, the PayPal Here app displays the items and amounts of the order.
245 | *
246 | 5. In the PayPal Here app, Merchant chooses **Charge**.
247 | 6. . On the Payment Options screen, the Merchant can choose Card, or swipe the card. If the Merchant chooses a different option on the following screen, subsequent steps would differ from those below.
248 | *
249 | 7. On the Card Info screen, Merchant can swipe the credit card, as in this example. If Merchant keys in the card or uses a different payment method, the screens are different.
250 | 8. Merchant gives the phone to the customer so the customer can sign for the payment. The customer signs and hands back the phone.
251 | 9. Merchant asks the customer if the customer wants a receipt, and Merchant can choose to send the receipt.
252 | *
253 | 10. A confirmation is displayed, and when Merchant chooses **Done**, the following occurs: PayPal Here re-launches the order-entry app by calling the URL that was passed in as the return URL in the original call to the PayPal Here app. In that URL, PayPal Here includes the status of the transaction, so the order-entry app can display the status (see the Type output field in the _Call Reference_). If the payment was unsuccessful, the order-entry app records the lack of success and restarts at an appropriate step above.
254 |
255 |
256 | ## Appendix A: Sample HTML and Javascript Code
257 |
258 | The following code is an example of a call to the PayPal Here mobile app URL (`paypalhere://takePayment?`). The input fields include an invoice, as a Base64-encoded JSON object. **Note:** This code has references to standard javascript libraries.
259 |
260 | * [sample.html](./sample.html)
261 |
262 |
263 | ## Appendix B: Function for URL-Encoding in Objective-C
264 |
265 | For apps written in Objective-C, the following function shows how to URL-encode data (for the data of your input fields).
266 |
267 | ```Objective-c
268 |
269 | - (NSString *)urlEncode:(NSString *)rawStr {
270 | NSString *encodedStr = (NSString *)CFBridgingRelease(
271 | CFURLCreateStringByAddingPercentEscapes(
272 | NULL,
273 | (__bridge CFStringRef)rawStr,
274 | NULL,
275 | (CFStringRef)@"!*'();:@&=+$,/?%#[]",
276 | kCFStringEncodingUTF8));
277 | return encodedStr;
278 | }
279 |
280 |
281 | ```
282 |
283 | ## Appendix C: Sample Code in Objective-C
284 | The following is sample code in Objective-C that works with the PayPal Here mobile apps API.
285 |
286 | **Important:** Also see the complete sample app provided in this repository.
287 |
288 | For an example of how to do correct URL-encoding, see _Appendix B: Function for URL Encoding in Objective-C_.
289 |
290 | This sample code uses the JSONKit parser, but your app may use a different JSON parser instead.
291 |
292 | ```Objective-c
293 |
294 | // Step 1: Create Invoice JSON Object
295 | // Invoice contains an array of items
296 | NSMutableDictionary *itemListDictionary = [NSMutableDictionary dictionary];
297 | NSMutableArray *itemListArray = [NSMutableArray arrayWithCapacity:1];
298 | NSMutableDictionary *item = [NSMutableDictionary dictionary];
299 | // Create an item
300 | [item setObject:@"8.50" forKey:@"taxRate"];
301 | [item setObject:@"T-shirt" forKey:@"name"];
302 | [item setObject:@"Blue T-shirt" forKey:@"description"];
303 | [item setObject:@"15.99" forKey:@"unitPrice"];
304 | [item setObject:@"Tax" forKey:@"taxName"];
305 | [item setObject:@"1" forKey:@"quantity"];
306 | // Add the item to the dictionary
307 | [itemListArray addObject:item];
308 | // TODO: More items can be added as needed
309 | [itemListDictionary setObject:itemListArray forKey:@"item"];
310 | // Create invoice
311 | NSMutableDictionary *invoiceObj = [NSMutableDictionary dictionary];
312 | // Add invoice details including items from above
313 | [invoiceObj setObject:@"DueOnReceipt" forKey:@"paymentTerms"];
314 | [invoiceObj setObject:@"0" forKey:@"discountPercent"];
315 | [invoiceObj setObject:@"USD" forKey:@"currencyCode"];
316 | [invoiceObj setObject:@"9876" forKey:@"number"];
317 | [invoiceObj setObject:@"foo@bar.com" forKey:@"payerEmail"];
318 | [invoiceObj setObject:itemListDictionary forKey:@"itemList"];
319 |
320 | // Step 2:Prepare request data
321 | // Convert the Invoice object into JSON - this sample uses NSJSONSerialization but any JSON parser (JSONKit) can be used
322 | NSError *e = nil;
323 | NSData *jsonData = [NSJSONSerialization dataWithJSONObject:invoiceObj options:0 error:&e];
324 | NSString *jsonDataStr = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
325 | // url encode the invoice object
326 | NSString *encodedInvoiceJsonString = [self urlEncode:jsonDataStr];
327 | // urlencode the accepted payment types
328 | NSString *encodedAcceptedPaymentTypes = [self urlEncode:@"cash,card,paypal"];
329 | // TODO: Update URL below to match with your application URL Scheme
330 | // This is how PayPalHere will launch your application
331 | NSString *returnUrl = @"myapp://my-return-handler?{result}Type={Type}&InvoiceId={InvoiceId}&Tip={Tip}&Email={Email}&TxId={TxId}";
332 | NSString *encodedReturnUrl = [self urlEncode:returnUrl];
333 | // Create PayPal Here launch URL
334 | NSString *pphUrlString = [NSString stringWithFormat:@"paypalhere://takePayment?accepted=%@&returnUrl=%@&invoice=%@&step=choosePayment",
335 | encodedAcceptedPaymentTypes, encodedReturnUrl, encodedInvoiceJsonString];
336 | NSLog(@"PayPal Here URL = %@", pphUrlString);
337 | // Create URL object from string
338 | NSURL * pphUrl = [NSURL URLWithString:pphUrlString];
339 |
340 | // Step 3: Launch PayPal Here application
341 | UIApplication * ourApplication = [UIApplication sharedApplication];
342 | // Check if PayPal Here app is installed
343 | if ([ourApplication canOpenURL:pphUrl]){
344 | // Launch PayPal Here app
345 | [ourApplication openURL:pphUrl];
346 | } else {
347 | // Handle case when PayPal Here app is not installed
348 | // or launch PayPal Here app page in appstore:
349 | // http://itunes.apple.com/us/app/paypal-here/id505911015
350 | }
351 |
352 | ```
353 |
354 | ### Appendix D: Confirming the PayPal Here App Is Installed on a Device
355 |
356 | * If your app uses HTML and JavaScript, and the launch of the PayPal Here app fails, your app should direct users to the app store.
357 | * If your app is written for Android, and the Paypal Here app cannot be launched, your app should direct users to the Play Store.
358 |
359 | If your app is written in Objective-C or Swift, you can use the `canOpenURL` function in the [UIApplication class](https://developer.apple.com/library/ios/DOCUMENTATION/UIKit/Reference/UIApplication_Class/Reference/Reference.html) to confirm that the PayPal Here app is installed and then launch it, and if necessary direct users to the app store. For example:
360 |
361 | ```Objective-c
362 |
363 | UIApplication *ourApplication = [UIApplication sharedApplication];
364 | NSString *ourPath = [@"paypalhere://" stringByAppendingString:urlInfo];
365 | NSURL *ourURL = [NSURL URLWithString:ourPath];
366 | if ([ourApplication canOpenURL:ourURL]) {
367 | [ourApplication openURL:ourURL];
368 | } else {
369 | //Display error
370 | UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"PayPal Here Not Found"
371 | message:@"The PayPal Here App is not installed. It must be installed to take payment."
372 | delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
373 | [alertView show];
374 | [alertView release];
375 | }
376 | ```
377 |
378 |
379 | ## Order and Payment Flow
380 |
381 | **Important:** For a more detailed explanation of the order and payment flow, see the following user-experience document:
382 |
383 | * PayPal Here Mobile Apps API: Payment Flow Example (Filename: _PayPal Here Mobile Apps API - Payment flow Example.pdf_)
384 |
385 | This section uses an example of charging a credit card to outline steps for:
386 |
387 | * Using an order-entry app to send an invoice to the PayPal Here app
388 | * Accepting a payment in the PayPal Here app
389 |
390 | After the merchant accepts the payment, your order-entry app is re-launched so the merchant can
391 | confirm that the payment was successfully recorded in the order-entry app.
392 |
393 | The following steps describe a version of an order and payment flow.
394 |
395 | 1. Merchant starts the order-entry app and brings up an order.
396 | 2. Merchant chooses **Pay** in the order-entry app.
397 | 3. The order-entry app uses the following URL and fields to launch the PayPal Here app:
398 | `paypalhere://takePayment?[URL-encoded input fields]&invoice=[invoice as a base64-encoded JSON object]`
399 | 4. Merchant logs into Merchant’s PayPal account. On the Charge screen, the PayPal Here app displays the items and amounts of the order.
400 | *
401 | 5. In the PayPal Here app, Merchant chooses **Charge**.
402 | 6. . On the Payment Options screen, the Merchant can choose Card, or swipe the card. If the Merchant chooses a different option on the following screen, subsequent steps would differ from those below.
403 | *
404 | 7. On the Card Info screen, Merchant can swipe the credit card, as in this example. If Merchant keys in the card or uses a different payment method, the screens are different.
405 | 8. Merchant gives the phone to the customer so the customer can sign for the payment. The customer signs and hands back the phone.
406 | 9. Merchant asks the customer if the customer wants a receipt, and Merchant can choose to send the receipt.
407 | *
408 | 10. A confirmation is displayed, and when Merchant chooses **Done**, the following occurs: PayPal Here re-launches the order-entry app by calling the URL that was passed in as the return URL in the original call to the PayPal Here app. In that URL, PayPal Here includes the status of the transaction, so the order-entry app can display the status (see the Type output field in the _Call Reference_). If the payment was unsuccessful, the order-entry app records the lack of success and restarts at an appropriate step above.
409 |
410 |
411 |
412 | ## Call Reference
413 |
414 | Your order-entry app can send an invoice to the PayPal Here app. For a description of this process, in this document, see Send an Invoice to the PayPal Here Mobile App.
415 |
416 |
417 | ### Input Fields
418 |
419 | | Input field name | Description | Comment |
420 | | ------------- | ----------- | ------- |
421 | | accepted | The payment methods to be offered in the PayPal Here app (i.e., the values that you specify will determine the payment methods offered). Acceptable values are `cash`, `card`, `invoice`, `check`, and `paypal`. | Individual countries may not allow certain payment methods. This field is optional. |
422 | | returnUrl | The URL of your app (or mobile web page, email, short URL, SMS, or anywhere a URL can be used). This value must be a well-formatted URL. The user is sent to this URL after the payment is completed (or the transaction is cancelled). **See _“Structuring the returnUrl Input Field,”_ below.** The URL can include placeholders (using curly braces), which will be replaced with desired transaction information. | This field is optional. |
423 | | as | Set the optional `as` input field to `b64` if you will Base64-encode the JSON invoice object. If you won’t Base64-encode the JSON invoice object, omit the as parameter. Base-64 encoding (used if you specify `as=b64`) is recommended for the JSON invoice object (as an alternative to URL-encoding) because Base-64 encoding is more likely to result in correct encoding. | For information about the JSON invoice object, see `invoice`, below. |
424 | | step | Stage within the PayPal Here app at which the merchant will begin. Specify `step=choosePayment` | |
425 | | invoice | A JSON object that contains the invoice data. | See the following section of this document: _Invoice as a JSON object_ |
426 | | payerPhone | If the buyer email address is known ahead of time, this can be specified in the invoice directly. However, if the buyer's phone number is known and your app desires an SMS receipt to be offered to them, the `payerPhone` field will be used to pre-fill that field in US format. | |
427 |
428 |
429 | ### Structuring the `returnUrl` Input Field
430 |
431 | The data for the `returnUrl` input field is a URL that can include placeholders for the desired transaction information. That is, you can use curly braces in the URL for the PayPal Here app to return specific data about the transaction. The following table provides information about this data. For an example, see _URL-Encoded Input Fields_.
432 |
433 | | Field of the `returnUrl` input field | Description |
434 | | ------------- | ----------- |
435 | | Root URL of your app, including the call that was invoked by your app. Example: `my_registered_location://takePayment` | The PayPal Here app uses this value to return the merchant to your app, after payment |
436 | | `{result}?` | The fields whose values you want returned by the PayPal Here app |
437 | | `Type` | The type of payment made, e.g. `card`. Specify `Type={Type}` |
438 | | `InvoiceId` | The invoice ID. Specify `InvoiceId={InvoiceId}` |
439 | | `Tip` | The tip, if applicable. `Specify Tip={Tip}` |
440 | | `TxId` | The tax ID of the merchant. Specify `TxId={TxId}` |
441 | | `Email` | Email of buyer, if available. Specifiy `Email={Email}` |
442 |
443 |
444 | ### Output Fields
445 |
446 | | Input field name | Description |
447 | | ---------------- | ----------- |
448 | | `Type` | The payment method, for example `SWIPE`. Returned values are listed below, but your code should be able to handle new values as they get introduced.
If the transaction was interrupted, for example if a credit card was declined, the value is `UNKNOWN`. Note: If a credit card is declined, the merchant can enter an alternative payment method.
If the merchant cancels, the order-entry’s return URL is called, appended with `Type=Unknown`.
Due to legacy issues, the values for "Type" currently differ based on the version being used. On PayPal Here versions 2.x, these values can be: `UNKNOWN`, `KEY`, `SCAN`, `SWIPE`, `PAYPAL`, `CHECK`, `CASH`, `CHIP`, `EMV_SWIPE`. On iPad 1.x, these values can be: `Unknown`, `CreditCard`, `Check`, `Cash`, `PayPal`, `DebitCard`, `Other`, `ChipCard`.
For iPad versions 2.3 and later, the values are consistent with iPhone.
You should code your integrations to handle new values being returned in this field.|
449 | | `InvoiceId` | The ID of the new invoice for which payment was accepted. For information about the input value that corresponds to this ID, see __Invoice as a JSON object. |
450 | | `Tip` | The monetary value tip, if applicable. |
451 | | `Email` | Buyer email, if available. |
452 |
453 |
454 | ## Appendix A: Sample HTML and Javascript Code
455 |
456 | The following code is an example of a call to the PayPal Here mobile app URL (`paypalhere://takePayment?`). The input fields include an invoice, as a Base64-encoded JSON object. **Note:** This code has references to standard javascript libraries.
457 |
458 | * [sample.html](./sample.html)
459 |
460 |
461 |
462 | ## Appendix B: Function for URL-Encoding in Objective-C
463 |
464 | For apps written in Objective-C, the following function shows how to URL-encode data (for the data of your input fields).
465 |
466 | ```Objective-c
467 |
468 | - (NSString *)urlEncode:(NSString *)rawStr {
469 | NSString *encodedStr = (NSString *)CFBridgingRelease(
470 | CFURLCreateStringByAddingPercentEscapes(
471 | NULL,
472 | (__bridge CFStringRef)rawStr,
473 | NULL,
474 | (CFStringRef)@"!*'();:@&=+$,/?%#[]",
475 | kCFStringEncodingUTF8));
476 | return encodedStr;
477 | }
478 |
479 |
480 | ```
481 |
--------------------------------------------------------------------------------
/docs/sample.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Invoicing API example
4 |
6 |
7 |
8 |
60 |
61 |
62 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/ios/PPHere.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | B6538FD616CE4AC500413B7A /* JSONKit.m in Sources */ = {isa = PBXBuildFile; fileRef = B6538FD516CE4AC500413B7A /* JSONKit.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
11 | B6538FD916CE502900413B7A /* developer.png in Resources */ = {isa = PBXBuildFile; fileRef = B6538FD816CE502900413B7A /* developer.png */; };
12 | B6BF936716CD732700EAAADB /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6BF936616CD732700EAAADB /* UIKit.framework */; };
13 | B6BF936916CD732700EAAADB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6BF936816CD732700EAAADB /* Foundation.framework */; };
14 | B6BF936B16CD732700EAAADB /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6BF936A16CD732700EAAADB /* CoreGraphics.framework */; };
15 | B6BF937116CD732700EAAADB /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B6BF936F16CD732700EAAADB /* InfoPlist.strings */; };
16 | B6BF937316CD732700EAAADB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B6BF937216CD732700EAAADB /* main.m */; };
17 | B6BF937716CD732700EAAADB /* PPAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B6BF937616CD732700EAAADB /* PPAppDelegate.m */; };
18 | B6BF937916CD732700EAAADB /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = B6BF937816CD732700EAAADB /* Default.png */; };
19 | B6BF937B16CD732700EAAADB /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B6BF937A16CD732700EAAADB /* Default@2x.png */; };
20 | B6BF937D16CD732700EAAADB /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B6BF937C16CD732700EAAADB /* Default-568h@2x.png */; };
21 | B6BF938016CD732700EAAADB /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B6BF937E16CD732700EAAADB /* MainStoryboard.storyboard */; };
22 | B6BF938316CD732700EAAADB /* PPViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B6BF938216CD732700EAAADB /* PPViewController.m */; };
23 | /* End PBXBuildFile section */
24 |
25 | /* Begin PBXFileReference section */
26 | B6538FD416CE4AC500413B7A /* JSONKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONKit.h; sourceTree = ""; };
27 | B6538FD516CE4AC500413B7A /* JSONKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONKit.m; sourceTree = ""; };
28 | B6538FD816CE502900413B7A /* developer.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = developer.png; sourceTree = ""; };
29 | B6BF936316CD732700EAAADB /* PPHere.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PPHere.app; sourceTree = BUILT_PRODUCTS_DIR; };
30 | B6BF936616CD732700EAAADB /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
31 | B6BF936816CD732700EAAADB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
32 | B6BF936A16CD732700EAAADB /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
33 | B6BF936E16CD732700EAAADB /* PPHere-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "PPHere-Info.plist"; sourceTree = ""; };
34 | B6BF937016CD732700EAAADB /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
35 | B6BF937216CD732700EAAADB /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
36 | B6BF937416CD732700EAAADB /* PPHere-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PPHere-Prefix.pch"; sourceTree = ""; };
37 | B6BF937516CD732700EAAADB /* PPAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PPAppDelegate.h; sourceTree = ""; };
38 | B6BF937616CD732700EAAADB /* PPAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PPAppDelegate.m; sourceTree = ""; };
39 | B6BF937816CD732700EAAADB /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; };
40 | B6BF937A16CD732700EAAADB /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; };
41 | B6BF937C16CD732700EAAADB /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; };
42 | B6BF937F16CD732700EAAADB /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard.storyboard; sourceTree = ""; };
43 | B6BF938116CD732700EAAADB /* PPViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PPViewController.h; sourceTree = ""; };
44 | B6BF938216CD732700EAAADB /* PPViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PPViewController.m; sourceTree = ""; };
45 | /* End PBXFileReference section */
46 |
47 | /* Begin PBXFrameworksBuildPhase section */
48 | B6BF936016CD732700EAAADB /* Frameworks */ = {
49 | isa = PBXFrameworksBuildPhase;
50 | buildActionMask = 2147483647;
51 | files = (
52 | B6BF936716CD732700EAAADB /* UIKit.framework in Frameworks */,
53 | B6BF936916CD732700EAAADB /* Foundation.framework in Frameworks */,
54 | B6BF936B16CD732700EAAADB /* CoreGraphics.framework in Frameworks */,
55 | );
56 | runOnlyForDeploymentPostprocessing = 0;
57 | };
58 | /* End PBXFrameworksBuildPhase section */
59 |
60 | /* Begin PBXGroup section */
61 | B6538FD316CE4AA700413B7A /* External */ = {
62 | isa = PBXGroup;
63 | children = (
64 | B6538FD416CE4AC500413B7A /* JSONKit.h */,
65 | B6538FD516CE4AC500413B7A /* JSONKit.m */,
66 | );
67 | name = External;
68 | sourceTree = "";
69 | };
70 | B6538FD716CE501800413B7A /* Assets */ = {
71 | isa = PBXGroup;
72 | children = (
73 | B6538FD816CE502900413B7A /* developer.png */,
74 | );
75 | name = Assets;
76 | sourceTree = "";
77 | };
78 | B6BF935A16CD732700EAAADB = {
79 | isa = PBXGroup;
80 | children = (
81 | B6BF936C16CD732700EAAADB /* PPHere */,
82 | B6BF936516CD732700EAAADB /* Frameworks */,
83 | B6BF936416CD732700EAAADB /* Products */,
84 | );
85 | sourceTree = "";
86 | };
87 | B6BF936416CD732700EAAADB /* Products */ = {
88 | isa = PBXGroup;
89 | children = (
90 | B6BF936316CD732700EAAADB /* PPHere.app */,
91 | );
92 | name = Products;
93 | sourceTree = "";
94 | };
95 | B6BF936516CD732700EAAADB /* Frameworks */ = {
96 | isa = PBXGroup;
97 | children = (
98 | B6BF936616CD732700EAAADB /* UIKit.framework */,
99 | B6BF936816CD732700EAAADB /* Foundation.framework */,
100 | B6BF936A16CD732700EAAADB /* CoreGraphics.framework */,
101 | );
102 | name = Frameworks;
103 | sourceTree = "";
104 | };
105 | B6BF936C16CD732700EAAADB /* PPHere */ = {
106 | isa = PBXGroup;
107 | children = (
108 | B6538FD716CE501800413B7A /* Assets */,
109 | B6538FD316CE4AA700413B7A /* External */,
110 | B6BF937516CD732700EAAADB /* PPAppDelegate.h */,
111 | B6BF937616CD732700EAAADB /* PPAppDelegate.m */,
112 | B6BF937E16CD732700EAAADB /* MainStoryboard.storyboard */,
113 | B6BF938116CD732700EAAADB /* PPViewController.h */,
114 | B6BF938216CD732700EAAADB /* PPViewController.m */,
115 | B6BF936D16CD732700EAAADB /* Supporting Files */,
116 | );
117 | path = PPHere;
118 | sourceTree = "";
119 | };
120 | B6BF936D16CD732700EAAADB /* Supporting Files */ = {
121 | isa = PBXGroup;
122 | children = (
123 | B6BF936E16CD732700EAAADB /* PPHere-Info.plist */,
124 | B6BF936F16CD732700EAAADB /* InfoPlist.strings */,
125 | B6BF937216CD732700EAAADB /* main.m */,
126 | B6BF937416CD732700EAAADB /* PPHere-Prefix.pch */,
127 | B6BF937816CD732700EAAADB /* Default.png */,
128 | B6BF937A16CD732700EAAADB /* Default@2x.png */,
129 | B6BF937C16CD732700EAAADB /* Default-568h@2x.png */,
130 | );
131 | name = "Supporting Files";
132 | sourceTree = "";
133 | };
134 | /* End PBXGroup section */
135 |
136 | /* Begin PBXNativeTarget section */
137 | B6BF936216CD732700EAAADB /* PPHere */ = {
138 | isa = PBXNativeTarget;
139 | buildConfigurationList = B6BF938616CD732700EAAADB /* Build configuration list for PBXNativeTarget "PPHere" */;
140 | buildPhases = (
141 | B6BF935F16CD732700EAAADB /* Sources */,
142 | B6BF936016CD732700EAAADB /* Frameworks */,
143 | B6BF936116CD732700EAAADB /* Resources */,
144 | );
145 | buildRules = (
146 | );
147 | dependencies = (
148 | );
149 | name = PPHere;
150 | productName = PPHere;
151 | productReference = B6BF936316CD732700EAAADB /* PPHere.app */;
152 | productType = "com.apple.product-type.application";
153 | };
154 | /* End PBXNativeTarget section */
155 |
156 | /* Begin PBXProject section */
157 | B6BF935B16CD732700EAAADB /* Project object */ = {
158 | isa = PBXProject;
159 | attributes = {
160 | CLASSPREFIX = PP;
161 | LastUpgradeCheck = 0460;
162 | ORGANIZATIONNAME = "PayPal Developer";
163 | };
164 | buildConfigurationList = B6BF935E16CD732700EAAADB /* Build configuration list for PBXProject "PPHere" */;
165 | compatibilityVersion = "Xcode 3.2";
166 | developmentRegion = English;
167 | hasScannedForEncodings = 0;
168 | knownRegions = (
169 | en,
170 | );
171 | mainGroup = B6BF935A16CD732700EAAADB;
172 | productRefGroup = B6BF936416CD732700EAAADB /* Products */;
173 | projectDirPath = "";
174 | projectRoot = "";
175 | targets = (
176 | B6BF936216CD732700EAAADB /* PPHere */,
177 | );
178 | };
179 | /* End PBXProject section */
180 |
181 | /* Begin PBXResourcesBuildPhase section */
182 | B6BF936116CD732700EAAADB /* Resources */ = {
183 | isa = PBXResourcesBuildPhase;
184 | buildActionMask = 2147483647;
185 | files = (
186 | B6BF937116CD732700EAAADB /* InfoPlist.strings in Resources */,
187 | B6BF937916CD732700EAAADB /* Default.png in Resources */,
188 | B6BF937B16CD732700EAAADB /* Default@2x.png in Resources */,
189 | B6BF937D16CD732700EAAADB /* Default-568h@2x.png in Resources */,
190 | B6BF938016CD732700EAAADB /* MainStoryboard.storyboard in Resources */,
191 | B6538FD916CE502900413B7A /* developer.png in Resources */,
192 | );
193 | runOnlyForDeploymentPostprocessing = 0;
194 | };
195 | /* End PBXResourcesBuildPhase section */
196 |
197 | /* Begin PBXSourcesBuildPhase section */
198 | B6BF935F16CD732700EAAADB /* Sources */ = {
199 | isa = PBXSourcesBuildPhase;
200 | buildActionMask = 2147483647;
201 | files = (
202 | B6BF937316CD732700EAAADB /* main.m in Sources */,
203 | B6BF937716CD732700EAAADB /* PPAppDelegate.m in Sources */,
204 | B6BF938316CD732700EAAADB /* PPViewController.m in Sources */,
205 | B6538FD616CE4AC500413B7A /* JSONKit.m in Sources */,
206 | );
207 | runOnlyForDeploymentPostprocessing = 0;
208 | };
209 | /* End PBXSourcesBuildPhase section */
210 |
211 | /* Begin PBXVariantGroup section */
212 | B6BF936F16CD732700EAAADB /* InfoPlist.strings */ = {
213 | isa = PBXVariantGroup;
214 | children = (
215 | B6BF937016CD732700EAAADB /* en */,
216 | );
217 | name = InfoPlist.strings;
218 | sourceTree = "";
219 | };
220 | B6BF937E16CD732700EAAADB /* MainStoryboard.storyboard */ = {
221 | isa = PBXVariantGroup;
222 | children = (
223 | B6BF937F16CD732700EAAADB /* en */,
224 | );
225 | name = MainStoryboard.storyboard;
226 | sourceTree = "";
227 | };
228 | /* End PBXVariantGroup section */
229 |
230 | /* Begin XCBuildConfiguration section */
231 | B6BF938416CD732700EAAADB /* Debug */ = {
232 | isa = XCBuildConfiguration;
233 | buildSettings = {
234 | ALWAYS_SEARCH_USER_PATHS = NO;
235 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
236 | CLANG_CXX_LIBRARY = "libc++";
237 | CLANG_ENABLE_OBJC_ARC = YES;
238 | CLANG_WARN_CONSTANT_CONVERSION = YES;
239 | CLANG_WARN_EMPTY_BODY = YES;
240 | CLANG_WARN_ENUM_CONVERSION = YES;
241 | CLANG_WARN_INT_CONVERSION = YES;
242 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
243 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
244 | COPY_PHASE_STRIP = NO;
245 | GCC_C_LANGUAGE_STANDARD = gnu99;
246 | GCC_DYNAMIC_NO_PIC = NO;
247 | GCC_OPTIMIZATION_LEVEL = 0;
248 | GCC_PREPROCESSOR_DEFINITIONS = (
249 | "DEBUG=1",
250 | "$(inherited)",
251 | );
252 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
253 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
254 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
255 | GCC_WARN_UNUSED_VARIABLE = YES;
256 | IPHONEOS_DEPLOYMENT_TARGET = 6.1;
257 | ONLY_ACTIVE_ARCH = YES;
258 | SDKROOT = iphoneos;
259 | TARGETED_DEVICE_FAMILY = "1,2";
260 | };
261 | name = Debug;
262 | };
263 | B6BF938516CD732700EAAADB /* Release */ = {
264 | isa = XCBuildConfiguration;
265 | buildSettings = {
266 | ALWAYS_SEARCH_USER_PATHS = NO;
267 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
268 | CLANG_CXX_LIBRARY = "libc++";
269 | CLANG_ENABLE_OBJC_ARC = YES;
270 | CLANG_WARN_CONSTANT_CONVERSION = YES;
271 | CLANG_WARN_EMPTY_BODY = YES;
272 | CLANG_WARN_ENUM_CONVERSION = YES;
273 | CLANG_WARN_INT_CONVERSION = YES;
274 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
275 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
276 | COPY_PHASE_STRIP = YES;
277 | GCC_C_LANGUAGE_STANDARD = gnu99;
278 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
279 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
280 | GCC_WARN_UNUSED_VARIABLE = YES;
281 | IPHONEOS_DEPLOYMENT_TARGET = 6.1;
282 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
283 | SDKROOT = iphoneos;
284 | TARGETED_DEVICE_FAMILY = "1,2";
285 | VALIDATE_PRODUCT = YES;
286 | };
287 | name = Release;
288 | };
289 | B6BF938716CD732700EAAADB /* Debug */ = {
290 | isa = XCBuildConfiguration;
291 | buildSettings = {
292 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
293 | GCC_PREFIX_HEADER = "PPHere/PPHere-Prefix.pch";
294 | INFOPLIST_FILE = "PPHere/PPHere-Info.plist";
295 | PRODUCT_NAME = "$(TARGET_NAME)";
296 | WRAPPER_EXTENSION = app;
297 | };
298 | name = Debug;
299 | };
300 | B6BF938816CD732700EAAADB /* Release */ = {
301 | isa = XCBuildConfiguration;
302 | buildSettings = {
303 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
304 | GCC_PREFIX_HEADER = "PPHere/PPHere-Prefix.pch";
305 | INFOPLIST_FILE = "PPHere/PPHere-Info.plist";
306 | PRODUCT_NAME = "$(TARGET_NAME)";
307 | WRAPPER_EXTENSION = app;
308 | };
309 | name = Release;
310 | };
311 | /* End XCBuildConfiguration section */
312 |
313 | /* Begin XCConfigurationList section */
314 | B6BF935E16CD732700EAAADB /* Build configuration list for PBXProject "PPHere" */ = {
315 | isa = XCConfigurationList;
316 | buildConfigurations = (
317 | B6BF938416CD732700EAAADB /* Debug */,
318 | B6BF938516CD732700EAAADB /* Release */,
319 | );
320 | defaultConfigurationIsVisible = 0;
321 | defaultConfigurationName = Release;
322 | };
323 | B6BF938616CD732700EAAADB /* Build configuration list for PBXNativeTarget "PPHere" */ = {
324 | isa = XCConfigurationList;
325 | buildConfigurations = (
326 | B6BF938716CD732700EAAADB /* Debug */,
327 | B6BF938816CD732700EAAADB /* Release */,
328 | );
329 | defaultConfigurationIsVisible = 0;
330 | defaultConfigurationName = Release;
331 | };
332 | /* End XCConfigurationList section */
333 | };
334 | rootObject = B6BF935B16CD732700EAAADB /* Project object */;
335 | }
336 |
--------------------------------------------------------------------------------
/ios/PPHere/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/ios/PPHere/Default-568h@2x.png
--------------------------------------------------------------------------------
/ios/PPHere/Default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/ios/PPHere/Default.png
--------------------------------------------------------------------------------
/ios/PPHere/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/ios/PPHere/Default@2x.png
--------------------------------------------------------------------------------
/ios/PPHere/JSONKit.h:
--------------------------------------------------------------------------------
1 | //
2 | // JSONKit.h
3 | // http://github.com/johnezang/JSONKit
4 | // Dual licensed under either the terms of the BSD License, or alternatively
5 | // under the terms of the Apache License, Version 2.0, as specified below.
6 | //
7 |
8 | /*
9 | Copyright (c) 2011, John Engelhart
10 |
11 | All rights reserved.
12 |
13 | Redistribution and use in source and binary forms, with or without
14 | modification, are permitted provided that the following conditions are met:
15 |
16 | * Redistributions of source code must retain the above copyright
17 | notice, this list of conditions and the following disclaimer.
18 |
19 | * Redistributions in binary form must reproduce the above copyright
20 | notice, this list of conditions and the following disclaimer in the
21 | documentation and/or other materials provided with the distribution.
22 |
23 | * Neither the name of the Zang Industries nor the names of its
24 | contributors may be used to endorse or promote products derived from
25 | this software without specific prior written permission.
26 |
27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
33 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 | */
39 |
40 | /*
41 | Copyright 2011 John Engelhart
42 |
43 | Licensed under the Apache License, Version 2.0 (the "License");
44 | you may not use this file except in compliance with the License.
45 | You may obtain a copy of the License at
46 |
47 | http://www.apache.org/licenses/LICENSE-2.0
48 |
49 | Unless required by applicable law or agreed to in writing, software
50 | distributed under the License is distributed on an "AS IS" BASIS,
51 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
52 | See the License for the specific language governing permissions and
53 | limitations under the License.
54 | */
55 |
56 | #include
57 | #include
58 | #include
59 | #include
60 | #include
61 |
62 | #ifdef __OBJC__
63 | #import
64 | #import
65 | #import
66 | #import
67 | #import
68 | #import
69 | #endif // __OBJC__
70 |
71 | #ifdef __cplusplus
72 | extern "C" {
73 | #endif
74 |
75 |
76 | // For Mac OS X < 10.5.
77 | #ifndef NSINTEGER_DEFINED
78 | #define NSINTEGER_DEFINED
79 | #if defined(__LP64__) || defined(NS_BUILD_32_LIKE_64)
80 | typedef long NSInteger;
81 | typedef unsigned long NSUInteger;
82 | #define NSIntegerMin LONG_MIN
83 | #define NSIntegerMax LONG_MAX
84 | #define NSUIntegerMax ULONG_MAX
85 | #else // defined(__LP64__) || defined(NS_BUILD_32_LIKE_64)
86 | typedef int NSInteger;
87 | typedef unsigned int NSUInteger;
88 | #define NSIntegerMin INT_MIN
89 | #define NSIntegerMax INT_MAX
90 | #define NSUIntegerMax UINT_MAX
91 | #endif // defined(__LP64__) || defined(NS_BUILD_32_LIKE_64)
92 | #endif // NSINTEGER_DEFINED
93 |
94 |
95 | #ifndef _JSONKIT_H_
96 | #define _JSONKIT_H_
97 |
98 | #if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__APPLE_CC__) && (__APPLE_CC__ >= 5465)
99 | #define JK_DEPRECATED_ATTRIBUTE __attribute__((deprecated))
100 | #else
101 | #define JK_DEPRECATED_ATTRIBUTE
102 | #endif
103 |
104 | #define JSONKIT_VERSION_MAJOR 1
105 | #define JSONKIT_VERSION_MINOR 4
106 |
107 | typedef NSUInteger JKFlags;
108 |
109 | /*
110 | JKParseOptionComments : Allow C style // and /_* ... *_/ (without a _, obviously) comments in JSON.
111 | JKParseOptionUnicodeNewlines : Allow Unicode recommended (?:\r\n|[\n\v\f\r\x85\p{Zl}\p{Zp}]) newlines.
112 | JKParseOptionLooseUnicode : Normally the decoder will stop with an error at any malformed Unicode.
113 | This option allows JSON with malformed Unicode to be parsed without reporting an error.
114 | Any malformed Unicode is replaced with \uFFFD, or "REPLACEMENT CHARACTER".
115 | */
116 |
117 | enum {
118 | JKParseOptionNone = 0,
119 | JKParseOptionStrict = 0,
120 | JKParseOptionComments = (1 << 0),
121 | JKParseOptionUnicodeNewlines = (1 << 1),
122 | JKParseOptionLooseUnicode = (1 << 2),
123 | JKParseOptionPermitTextAfterValidJSON = (1 << 3),
124 | JKParseOptionValidFlags = (JKParseOptionComments | JKParseOptionUnicodeNewlines | JKParseOptionLooseUnicode | JKParseOptionPermitTextAfterValidJSON),
125 | };
126 | typedef JKFlags JKParseOptionFlags;
127 |
128 | enum {
129 | JKSerializeOptionNone = 0,
130 | JKSerializeOptionPretty = (1 << 0),
131 | JKSerializeOptionEscapeUnicode = (1 << 1),
132 | JKSerializeOptionEscapeForwardSlashes = (1 << 4),
133 | JKSerializeOptionValidFlags = (JKSerializeOptionPretty | JKSerializeOptionEscapeUnicode | JKSerializeOptionEscapeForwardSlashes),
134 | };
135 | typedef JKFlags JKSerializeOptionFlags;
136 |
137 | #ifdef __OBJC__
138 |
139 | typedef struct JKParseState JKParseState; // Opaque internal, private type.
140 |
141 | // As a general rule of thumb, if you use a method that doesn't accept a JKParseOptionFlags argument, it defaults to JKParseOptionStrict
142 |
143 | @interface JSONDecoder : NSObject {
144 | JKParseState *parseState;
145 | }
146 | + (id)decoder;
147 | + (id)decoderWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
148 | - (id)initWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
149 | - (void)clearCache;
150 |
151 | // The parse... methods were deprecated in v1.4 in favor of the v1.4 objectWith... methods.
152 | - (id)parseUTF8String:(const unsigned char *)string length:(size_t)length JK_DEPRECATED_ATTRIBUTE; // Deprecated in JSONKit v1.4. Use objectWithUTF8String:length: instead.
153 | - (id)parseUTF8String:(const unsigned char *)string length:(size_t)length error:(NSError **)error JK_DEPRECATED_ATTRIBUTE; // Deprecated in JSONKit v1.4. Use objectWithUTF8String:length:error: instead.
154 | // The NSData MUST be UTF8 encoded JSON.
155 | - (id)parseJSONData:(NSData *)jsonData JK_DEPRECATED_ATTRIBUTE; // Deprecated in JSONKit v1.4. Use objectWithData: instead.
156 | - (id)parseJSONData:(NSData *)jsonData error:(NSError **)error JK_DEPRECATED_ATTRIBUTE; // Deprecated in JSONKit v1.4. Use objectWithData:error: instead.
157 |
158 | // Methods that return immutable collection objects.
159 | - (id)objectWithUTF8String:(const unsigned char *)string length:(NSUInteger)length;
160 | - (id)objectWithUTF8String:(const unsigned char *)string length:(NSUInteger)length error:(NSError **)error;
161 | // The NSData MUST be UTF8 encoded JSON.
162 | - (id)objectWithData:(NSData *)jsonData;
163 | - (id)objectWithData:(NSData *)jsonData error:(NSError **)error;
164 |
165 | // Methods that return mutable collection objects.
166 | - (id)mutableObjectWithUTF8String:(const unsigned char *)string length:(NSUInteger)length;
167 | - (id)mutableObjectWithUTF8String:(const unsigned char *)string length:(NSUInteger)length error:(NSError **)error;
168 | // The NSData MUST be UTF8 encoded JSON.
169 | - (id)mutableObjectWithData:(NSData *)jsonData;
170 | - (id)mutableObjectWithData:(NSData *)jsonData error:(NSError **)error;
171 |
172 | @end
173 |
174 | ////////////
175 | #pragma mark Deserializing methods
176 | ////////////
177 |
178 | @interface NSString (JSONKitDeserializing)
179 | - (id)objectFromJSONString;
180 | - (id)objectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
181 | - (id)objectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;
182 | - (id)mutableObjectFromJSONString;
183 | - (id)mutableObjectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
184 | - (id)mutableObjectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;
185 | @end
186 |
187 | @interface NSData (JSONKitDeserializing)
188 | // The NSData MUST be UTF8 encoded JSON.
189 | - (id)objectFromJSONData;
190 | - (id)objectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
191 | - (id)objectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;
192 | - (id)mutableObjectFromJSONData;
193 | - (id)mutableObjectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
194 | - (id)mutableObjectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;
195 | @end
196 |
197 | ////////////
198 | #pragma mark Serializing methods
199 | ////////////
200 |
201 | @interface NSString (JSONKitSerializing)
202 | // Convenience methods for those that need to serialize the receiving NSString (i.e., instead of having to serialize a NSArray with a single NSString, you can "serialize to JSON" just the NSString).
203 | // Normally, a string that is serialized to JSON has quotation marks surrounding it, which you may or may not want when serializing a single string, and can be controlled with includeQuotes:
204 | // includeQuotes:YES `a "test"...` -> `"a \"test\"..."`
205 | // includeQuotes:NO `a "test"...` -> `a \"test\"...`
206 | - (NSData *)JSONData; // Invokes JSONDataWithOptions:JKSerializeOptionNone includeQuotes:YES
207 | - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions includeQuotes:(BOOL)includeQuotes error:(NSError **)error;
208 | - (NSString *)JSONString; // Invokes JSONStringWithOptions:JKSerializeOptionNone includeQuotes:YES
209 | - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions includeQuotes:(BOOL)includeQuotes error:(NSError **)error;
210 | @end
211 |
212 | @interface NSArray (JSONKitSerializing)
213 | - (NSData *)JSONData;
214 | - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
215 | - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error;
216 | - (NSString *)JSONString;
217 | - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
218 | - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error;
219 | @end
220 |
221 | @interface NSDictionary (JSONKitSerializing)
222 | - (NSData *)JSONData;
223 | - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
224 | - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error;
225 | - (NSString *)JSONString;
226 | - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
227 | - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error;
228 | @end
229 |
230 | #ifdef __BLOCKS__
231 |
232 | @interface NSArray (JSONKitSerializingBlockAdditions)
233 | - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingBlock:(id(^)(id object))block error:(NSError **)error;
234 | - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingBlock:(id(^)(id object))block error:(NSError **)error;
235 | @end
236 |
237 | @interface NSDictionary (JSONKitSerializingBlockAdditions)
238 | - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingBlock:(id(^)(id object))block error:(NSError **)error;
239 | - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingBlock:(id(^)(id object))block error:(NSError **)error;
240 | @end
241 |
242 | #endif
243 |
244 |
245 | #endif // __OBJC__
246 |
247 | #endif // _JSONKIT_H_
248 |
249 | #ifdef __cplusplus
250 | } // extern "C"
251 | #endif
252 |
--------------------------------------------------------------------------------
/ios/PPHere/PPAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // PPAppDelegate.h
3 | // PPHere
4 | //
5 | // Created by Messerschmidt, Tim on 14.02.13.
6 | // Copyright (c) 2013 PayPal Developer. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface PPAppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/ios/PPHere/PPAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // PPAppDelegate.m
3 | // PPHere
4 | //
5 | // Created by Messerschmidt, Tim on 14.02.13.
6 | // Copyright (c) 2013 PayPal Developer. All rights reserved.
7 | //
8 |
9 | #import "PPAppDelegate.h"
10 |
11 | @implementation PPAppDelegate
12 |
13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
14 | {
15 | // Override point for customization after application launch.
16 | return YES;
17 | }
18 |
19 | - (void)applicationWillResignActive:(UIApplication *)application
20 | {
21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
23 | }
24 |
25 | - (void)applicationDidEnterBackground:(UIApplication *)application
26 | {
27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
29 | }
30 |
31 | - (void)applicationWillEnterForeground:(UIApplication *)application
32 | {
33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | - (void)applicationDidBecomeActive:(UIApplication *)application
37 | {
38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
39 | }
40 |
41 | - (void)applicationWillTerminate:(UIApplication *)application
42 | {
43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
44 | }
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/ios/PPHere/PPHere-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | com.paypal.ios.dev.${PRODUCT_NAME:rfc1034identifier}
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0
25 | LSRequiresIPhoneOS
26 |
27 | UIMainStoryboardFile
28 | MainStoryboard
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | LSApplicationQueriesSchemes
34 |
35 | paypalhere
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ios/PPHere/PPHere-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header for all source files of the 'PPHere' target in the 'PPHere' project
3 | //
4 |
5 | #import
6 |
7 | #ifndef __IPHONE_5_0
8 | #warning "This project uses features only available in iOS SDK 5.0 and later."
9 | #endif
10 |
11 | #ifdef __OBJC__
12 | #import
13 | #import
14 | #endif
15 |
--------------------------------------------------------------------------------
/ios/PPHere/PPViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // PPViewController.h
3 | // PPHere
4 | //
5 | // Created by Messerschmidt, Tim on 14.02.13.
6 | // Copyright (c) 2013 PayPal Developer. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface PPViewController : UIViewController
12 |
13 | @property (weak, nonatomic) IBOutlet UITextField *priceField;
14 | @property (weak, nonatomic) IBOutlet UITextField *taxField;
15 | @property (weak, nonatomic) IBOutlet UITextField *nameField;
16 | @property (weak, nonatomic) IBOutlet UITextField *quantityField;
17 | @property (weak, nonatomic) IBOutlet UITextField *descriptionField;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/ios/PPHere/PPViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // PPViewController.m
3 | // PPHere
4 | //
5 | // Created by Messerschmidt, Tim on 14.02.13.
6 | // Copyright (c) 2013 PayPal Developer. All rights reserved.
7 | //
8 |
9 | #import "PPViewController.h"
10 | #import "JSONKit.h"
11 |
12 | @interface PPViewController ()
13 |
14 | @end
15 |
16 | @implementation PPViewController
17 |
18 | - (void)viewDidLoad
19 | {
20 | [super viewDidLoad];
21 | self.taxField.delegate = self;
22 | self.priceField.delegate = self;
23 | self.quantityField.delegate = self;
24 | self.nameField.delegate = self;
25 | self.descriptionField.delegate = self;
26 | }
27 |
28 | - (void)didReceiveMemoryWarning
29 | {
30 | [super didReceiveMemoryWarning];
31 | }
32 |
33 | - (BOOL)textFieldShouldReturn:(UITextField *)textField {
34 | [textField resignFirstResponder];
35 | return YES;
36 | }
37 |
38 |
39 | - (IBAction)onLaunchPayment:(id)sender {
40 | NSLog(@"Launching");
41 | NSMutableDictionary *shirt = [NSMutableDictionary dictionary];
42 | NSMutableDictionary *itemList = [NSMutableDictionary dictionary];
43 | NSMutableDictionary *invoice = [NSMutableDictionary dictionary];
44 |
45 | [shirt setObject:self.taxField.text forKey:@"taxRate"];
46 | [shirt setObject:self.priceField.text forKey:@"unitPrice"];
47 | [shirt setObject:self.quantityField.text forKey:@"quantity"];
48 | [shirt setObject:self.nameField.text forKey:@"name"];
49 | [shirt setObject:self.descriptionField.text forKey:@"description"];
50 | [shirt setObject:@"Tax" forKey:@"taxName"];
51 |
52 | NSMutableArray *items = [NSMutableArray arrayWithObject:shirt];
53 | [itemList setObject:items forKey:@"item"];
54 |
55 | [invoice setObject:@"DueOnReceipt" forKey:@"paymentTerms"];
56 | [invoice setObject:@"0" forKey:@"discountPercent"];
57 | [invoice setObject:@"USD" forKey:@"currencyCode"];
58 | [invoice setObject:@"merchant@ebay.com" forKey:@"merchantEmail"];
59 | [invoice setObject:@"foo@bar.com" forKey:@"payerEmail"];
60 | [invoice setObject:itemList forKey:@"itemList"];
61 |
62 | NSString *jsonInvoice = [invoice JSONString];
63 | NSString *encodedInvoice = [jsonInvoice stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
64 |
65 | NSString *encodedPaymentTypes = [@"cash,card,paypal" stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
66 |
67 | NSString *encodedReturnUrl = [@"myapp://handler?{result}?Type={Type}&InvoiceId={InvoiceId}&Tip={Tip}&Email={Email}&TxId={TxId}" stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
68 |
69 | NSString *pphUrlString = [NSString stringWithFormat:@"paypalhere://takePayment?accepted=%@&returnUrl=%@&invoice=%@&step=choosePayment",
70 | encodedPaymentTypes, encodedReturnUrl, encodedInvoice];
71 |
72 | NSURL *pphUrl = [NSURL URLWithString:pphUrlString];
73 |
74 | NSLog(@"%@", pphUrlString);
75 |
76 | UIApplication *application = [UIApplication sharedApplication];
77 | //iOS 9 -> Don't forget to add this schema to info.plist as a white schema (http://useyourloaf.com/blog/querying-url-schemes-with-canopenurl.html)
78 | if ([application canOpenURL:[NSURL URLWithString:@"paypalhere://"]]){
79 | [application openURL:pphUrl];
80 | } else {
81 | NSURL *url = [NSURL URLWithString:@"itms://itunes.apple.com/us/app/paypal-here/id505911015?mt=8"];
82 | [application openURL:url];
83 | }
84 |
85 | }
86 |
87 | @end
88 |
--------------------------------------------------------------------------------
/ios/PPHere/developer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/ios/PPHere/developer.png
--------------------------------------------------------------------------------
/ios/PPHere/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/ios/PPHere/en.lproj/MainStoryboard.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
63 |
71 |
79 |
84 |
85 |
86 |
87 |
88 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
--------------------------------------------------------------------------------
/ios/PPHere/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // PPHere
4 | //
5 | // Created by Messerschmidt, Tim on 14.02.13.
6 | // Copyright (c) 2013 PayPal Developer. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "PPAppDelegate.h"
12 |
13 | int main(int argc, char *argv[])
14 | {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([PPAppDelegate class]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/ios/README.md:
--------------------------------------------------------------------------------
1 | PayPal Here™ Sideloader API for iOS
2 | =======
3 | This sample allows to do a custom purchase by filling out the form.
4 |
5 | Tech used:
6 | ---
7 | The sample uses the following Open Source:
8 | - [JSONKit](https://github.com/johnezang/JSONKit) - for JSON (de-)serialization
--------------------------------------------------------------------------------
/web/README.md:
--------------------------------------------------------------------------------
1 | PayPal Here™ Sideloader API for Web Applications
2 | ======
3 | This sample shows a very simple intergration that allows to "buy" a cool [Sphero](http://www.gosphero.com/).
4 | This is just a **demo**: you really don't get anything ;)
5 |
6 | Tech used:
7 | ---
8 | The sample uses the following Open Source:
9 | - [AngularJS](http://angularjs.org/) - for data binding
10 | - [Twitter Bootstrap](http://twitter.github.com/bootstrap/) - for a good looking UI
--------------------------------------------------------------------------------
/web/css/bootstrap-responsive.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Responsive v2.3.0
3 | *
4 | * Copyright 2012 Twitter, Inc
5 | * Licensed under the Apache License v2.0
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Designed and built with all the love in the world @twitter by @mdo and @fat.
9 | */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@-ms-viewport{width:device-width}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:inherit!important}.hidden-print{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="offset"]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade{top:-100px}.modal.fade.in{top:20px}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.media .pull-left,.media .pull-right{display:block;float:none;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}}
10 |
--------------------------------------------------------------------------------
/web/css/main.css:
--------------------------------------------------------------------------------
1 | .table td {
2 | text-align: center;
3 | vertical-align: middle;
4 | }
5 |
6 | .centered {
7 | text-align: center;
8 | max-width: 700px;
9 | }
--------------------------------------------------------------------------------
/web/img/glyphicons-halflings-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/web/img/glyphicons-halflings-white.png
--------------------------------------------------------------------------------
/web/img/glyphicons-halflings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/web/img/glyphicons-halflings.png
--------------------------------------------------------------------------------
/web/img/sphero.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paypal/here-sideloader-api-samples/71fbd912e08461cc1a4f5ff3c7e7e954121f7355/web/img/sphero.jpg
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | PayPal
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |