# Northstar Server SDK for PHP Innersource Guide [Overview](#Overview) [Prerequisites](#Prerequisites) [Coding Style](#Coding-Style) [Getting Started](#Getting-Started) [Generating Models](#Generating-Models) [Authorization](#Authorization) [Adding a New PayPal REST API Endpoint](#Adding-a-New-PayPal-REST-API-Endpoint-to-SDK) [Modifying Existing PayPal REST API Endpoint](#Modifying-Existing-PayPal-REST-API-Endpoint-in-SDK) [Testing](#Testing) ## Overview This document covers how to contribute to the [Northstar Server SDKs](https://github.paypal.com/Braintree/northstar-server-sdks). ## Prerequisites [Docker](https://engineering.paypalcorp.com/confluence/display/DockerDesktop/Docker+Desktop+Getting+Started) is required to run the tool that generates the SDKs. Please ensure you have this before proceeding. | Language | Version | Tools | | -------- | --------| ------| | PHP | 8+ | [Composer](https://getcomposer.org/) | | Java* | 8 | Maven* | *These can be easily installed through the Self Service app 1. PayPal Sandbox account for testing. * [Create account](https://developer.paypal.com/tools/sandbox/accounts/#create-and-manage-sandbox-accounts) in [PayPal Sandbox Dashboard](https://developer.paypal.com/dashboard/accounts) if you do not have one or want to use a different one. 2. Create app and retrieve client ID and secret pair for PayPal REST API access. * Navigate to **Dashboard** > **My Apps & Credentials** in [PayPal Sandbox Dashboard](https://developer.paypal.com/dashboard/applications/sandbox). * Create new app by clicking on **Create App** button and selecting Merchant as App Type. Or choose an existing app from the list under **REST API apps**. * Once created or selected, [enable your app to accept Advanced Credit and Debit Card Payments](https://developer.paypal.com/docs/checkout/advanced/integrate/#link-enableyouraccounttoacceptcardpayments) within the Accept Payments advanced options * Client ID and Client Secret are shown on the app details screen under **Sandbox API Credentials** ## Coding Style For each language, please see below for specific coding conventions: <details> <summary>PHP</summary> * [PSR-1: Basic Coding Standard](https://www.php-fig.org/psr/psr-1/) and [PSR-12: Extended Coding Style](https://www.php-fig.org/psr/psr-12/) as guidelines. * [PHPDoc](https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc-tags.md) for commenting interfaces, classes, methods, functions, etc. </details> <details> <summary>Java</summary> * Content TBD </details> ## Getting Started * Clone the [northstar-server-sdks](https://github.paypal.com/Braintree/northstar-server-sdks) repository on your local machine. For each language, please see below for environment setup instructions below: <details> <summary>PHP</summary> 1. Go to php subdirectory of northstar-server-sdks. 2. Install dependencies by running the following command: ```bash composer install ``` </details> <details> <summary>Java</summary> 1. Go to java subdirectory of northstar-server-sdks. 2. Install dependencies and run baseline tests by running the following command: ```CLIENT_ID=your_client_id CLIENT_SECRET=your_client_secret mvn verify``` </details> ## Generating Models 1. Run this command to download the PayPal public API schema: ```bash curl -L0 --output paypal-public-api-schema-1.0.5.tgz "https://artifactory.g.devqa.gcp.dev.paypalinc.com/ui/api/v1/download?repoKey=npm-paypal&path=%2540paypalcorp%252Fpaypal-public-api-schema%252F-%252F%2540paypalcorp%252Fpaypal-public-api-schema-1.0.5.tgz" && tar zxvf paypal-public-api-schema-1.0.5.tgz ``` * Alternatively, download [paypal-public-api-schema-1.0.5.tgz](https://artifactory.g.devqa.gcp.dev.paypalinc.com/ui/api/v1/download?repoKey=npm-paypal&path=%254[…]aypalcorp%252Fpaypal-public-api-schema-1.0.5.tgz) from https://go/api-pkg. 2. Unzip and extract files. 3. Locate the PayPal public api schema which corresponds to the feature you want to add to Northstar Server SDK. For example, Orders V2 is checkout.ordersspecification-v2.json. 4. Generate models using the command for the language you are working with below. > IMPORTANT: Each command below assumes the schema files have been extracted to `/home/admin/shared` and directory is unmodified after being unzipped. If you extract the schema to a different location or move files in the unzipped directory, you will need to adjust the commands accordingly. <details> <summary>PHP</summary> ```bash= docker run --rm -v "${PWD}:/generated" -v "/home/admin/shared:/shared" openapitools/openapi-generator-cli generate -i shared/package/swagger-2.0/{PAYPAL_PUBLIC_API_SCHEMA} -g php -o generated/php_generated --global-property models,modelDocs=false,modelTests=false,supportingFiles="ObjectSerializer.php:composer.json" --additional-properties=modelPackage="Model",srcBasePath="lib",invokerPackage="PayPalSdk" ``` There is currently a bug wherein generated classes that reference other generated classes in their `$openApiTypes` properties do not use the correct `PayPalSdk\Model` namespace. Until we have a more permanent fix, Any Model classes you use when implementing your API classes will need to be modified to correctly include the namespace. As an example of this property, [OrderJson.php](https://github.paypal.com/Braintree/northstar-server-sdks/blob/main/php/lib/Model/OrderJson.php#L64) references various models. In your newly used generated model, you will need to ensure the namespace is properly generated. </details> <details> <summary>Java</summary> ```bash docker run --rm -v "${PWD}:/generated" -v "/home/admin/shared:/shared" openapitools/openapi-generator-cli generate -i shared/package/swagger-2.0/{PAYPAL_PUBLIC_API_SCHEMA} -g java -o generated/java_generated --global-property models,modelDocs=false,modelTests=false,supportingFiles="JSON.java:StringUtil.java",serializableModel=true,serializationLibrary=gson --additional-properties=modelPackage=com.paypal.sdk.paypalsdk.model ``` </details> ## Authorization PayPal REST API requests require client id and secret for authorization. Add environment variables named PP_SANDBOX_CLIENT_ID and PP_SANDBOX_CLIENT_SECRET using the client id/secret pair from [Prerequisites](#Prerequisites) for values on server. Environment variables can be set for either your shell session or only for a given command.eg: For a shell session: ```bash export PP_SANDBOX_CLIENT_ID=your_client_id export PP_SANDBOX_CLIENT_SECRET=your_client_secret ./vendor/bin/phpunit tests ``` Per Command: ```bash PP_SANDBOX_CLIENT_ID=your_client_id PP_SANDBOX_CLIENT_SECRET=your_client_secret mvn verify ``` ## Adding a New PayPal REST API Endpoint to SDK <details> <summary>PHP</summary> 1. Create a class with the name of your PayPal REST API in singular form. For example, [Orders API](https://ppaas/api/3719176155271664#apiReference) class name is [Order](https://github.braintreeps.com/braintree/northstar-server-sdks/blob/main/php/lib/Order.php). Extend from [Base class](https://github.braintreeps.com/braintree/northstar-server-sdks/blob/main/php/lib/Base.php). ```php= class Order extends Base { } ``` - Your new class should implement a method for each action supported. You can refer to the [Order](https://github.braintreeps.com/braintree/northstar-server-sdks/blob/main/php/lib/Order.php) class as a reference. 2. Add a public method to [PayPalClient class](https://github.braintreeps.com/braintree/northstar-server-sdks/blob/main/php/lib/PayPalClient.php) to instantiate an object of the class created in step 1. ```php= class PayPalClient { private Configuration $_config; private Order $_order; public function order(): Order { if (!isset($this->_order)) { $this->_order = new Order($this->_config); } return $this->_order; } } ``` </details> <details> <summary>Java</summary> 1. Create a class with the name of your PayPal REST API in singular form. For example, [Orders API](https://ppaas/api/3719176155271664#apiReference) class name is [Order](#TBD). Extend from [Base class](#TBD). ```java= public class Order extends Base { { } ``` - Your new class should implement a method for each action supported. You can refer to the [Order](#TBD) class as a reference. 2. Add a public method to [Client class](#TBD) to instantiate an object of the class created in step 1. ```Java= public class Client { ... public Order order() { return new Order(configuration, http); } } ``` </details> ## Modifying Existing PayPal REST API Endpoint in SDK ## Testing The testing approach in use avoids unit testing the generated models. Unit tests should be used to test functionality unique to the non generated SDK API classes or Utility classes sparingly. This will prevent re-testing functionality from the API layer which is used to generate the schema itself, as it's tested upstream. Integration testing isn't quite as light as unit testing will be as we do want to ideally test a happy path and sad path for each method on a class representing a unique API (eg The Order class's methods). <details> <summary>PHP</summary> [PHPUnit](https://phpunit.de/) is used for testing. 1. [Configure](https://www.php.net/manual/en/errorfunc.configuration.php) php.ini. ```ini # By default, it is 1024 bytes, so long messages are truncated. # Setting to 0 removes maximum length restriction. log_errors_max_len=0 ``` 2. Add integration tests for the PayPal REST API in [php/tests/integration directory](https://github.paypal.com/Braintree/northstar-server-sdks/tree/main/php/tests/integration). 3. Run the test suite: ```bash PP_SANDBOX_CLIENT_ID=<your-client-id> PP_SANDBOX_CLIENT_SECRET=<your-client-secret> ./vendor/bin/phpunit tests ``` </details> <details> <summary>Java</summary> </details>