Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge develop into main #5

Merged
merged 13 commits into from
Aug 12, 2024
8 changes: 6 additions & 2 deletions .github/workflows/lint_test_sonar.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Quality Check (Lint, Test, Sonarcloud)
name: Quality Check (Build, Lint, Format, Test, Sonarcloud)
on:
push:
branches:
Expand All @@ -24,10 +24,14 @@ jobs:
node-version: '20.x'
- name: Install dependencies
run: npm ci
- name: Run Build
run: npm run build
- name: Run Linting
run: npm run lint
- name: Run Format Check
run: npm run format:check
- name: Run Tests
run: npm run coverage
run: npm run test:coverage
- name: Run SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
name: Publish package to npm
on:
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
Expand All @@ -15,6 +16,7 @@ jobs:
registry-url: 'https://registry.npmjs.org'
scope: '@payone'
- run: npm ci
- run: npm run build
- run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
36 changes: 8 additions & 28 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,28 +1,8 @@
src
node_modules
coverage
example-app

temp
images

.github
.vscode
.idea
*.iml

.DS_Store
Thumbs.db

vitest.config.ts
tsconfig.json
sonar-project.properties
prepare_release.sh
lefthook.yml
eslint.config.mjs
.prettierrc
commitlint.config.js
.husky

*.tar.gz
*.tgz
# Exclude everything
*

# But include these files and directories
!package.json
!README.md
!dist/
!dist/**
80 changes: 60 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@

Welcome to the Node SDK for the PAYONE Commerce Platform! This repository contains a powerful, easy-to-use software development kit (SDK) designed to simplify the integration of online payment processing into your applications.

### TODOS

- [ ] Write more tests

## Table of Contents

- [Features](#features)
- [Installation](#installation)
- [Usage](#usage)
- [Configuration](#configuration)
- [Error Handling](#error-handling)
- [Client Side](#client-side)
- [Apple Pay](#apple-pay)
- [Contributing](#contributing)
- [Build the library](#build-the-library)
- [Run tests](#run-tests)
Expand All @@ -37,29 +35,71 @@ Welcome to the Node SDK for the PAYONE Commerce Platform! This repository contai

## Installation

```sh
# npm
npm i pcp-server-nodejs-sdk
# yarn
yarn add pcp-server-nodejs-sdk
```

## Usage

### Configuration
To use this SDK you need to construct a `CommunicatorConfiguration` which encapsulate everything needed to connect to the PAYONE Commerce Platform.

```ts
const apiKey = process.env.API_KEY;
const apiSecret = process.env.API_SECRET;

const config = new CommunicatorConfiguration(apiKey, apiSecret, "preprod.commerce-api.payone.com");
```

With the configuration you can create an API client for each reource you want to interact with. For example to create a commerce case you can use the `CommerceCaseApiClient`.


```ts
const commerceCaseClient = new CommerceCaseApiClient(config);
```

All payloads and reponses are availabe as ts interfaces exported from this library.
For example, to create an empty commerce case you can pass an object with the `CreateCommerceCaseRequest` interface:


```ts
const createCommerceCaseRequest: CreateCommerceCaseRequest = {};

const createCommerceCaseResponse: CreateCommerceCaseResponse = commerceCaseClient.createCommerceCaseRequest('merchant_id', createCommerceCaseRequest);
```

The models directly map to the API as described in [PAYONE Commerce Platform API Reference](https://docs.payone.com/pcp/commerce-platform-api).


### Error Handling

When making a request any client may throw a `ApiException`. There two subtypes of this exception:

- `ApiErrorReponseException`: This exception is thrown when the API returns an well-formed error response. The given errors are deserialized into `APIError` objects which are availble via the `getErrors()` method on the exception. They usually contain useful information about what is wrong in your request or the state of the resource.
- `ApiResponseRetrievalException`: This exception is a catch-all exception for any error that cannot be turned into a helpful error response. This includes malformed responses or unknown responses.


### Client Side

For most [payment methods](https://docs.payone.com/pcp/commerce-platform-payment-methods) some information from the client is needed, e.g. payment information given by Apple when a payment via ApplePay suceeds. PAYONE provides client side SDKs which helps you interact the third party payment providers. You can find the SDKs under the [PAYONE GitHub organization](https://github.com/PAYONE-GmbH). Either way ensure to never store or even send credit card information to your server. The PAYONE Commerce Platform never needs access to the credit card information. The client side is responsible for safely retrieving a credit card token. This token must be used with this SDK.

### Apple Pay

When a client is successfully made a payment via ApplePay it receives a [ApplePayPayment](https://developer.apple.com/documentation/apple_pay_on_the_web/applepaypayment). This structure is accessible as the `ApplePayPayment` class. You can use the `ApplePayTransformer` to map an `ApplePayPayment` to a `MobilePaymentMethodSpecificInput` which can be used for payment executions or order requests. The transformer has a static method `transformApplePayPaymentToMobilePaymentMethodSpecificInput()` which takes an `ApplePayPayment` and returns a `MobilePaymentMethodSpecificInput`. The transformer does not check if the response is complete, if anything is missing the field will be set to `undefined`.

### Run the example app

```sh
cd example-app
yarn
API_KEY=api_key API_SECRET=api_secret MERCHANT_ID=123 COMMERCE_CASE_ID=234 CHECKOUT_ID=345 yarn dev
npm i
API_KEY=api_key API_SECRET=api_secret MERCHANT_ID=123 COMMERCE_CASE_ID=234 CHECKOUT_ID=345 npm run dev
```

## Contributing

We welcome contributions from the community. If you want to contribute, please follow these steps:

Fork the repository.
Create a new branch (`git checkout -b feature-branch`).
Make your changes.
Commit your changes (`git commit -am 'Add new feature'`).
Push to the branch (`git push origin feature-branch`).
Create a new Pull Request.
Please make sure to follow the coding standards and write appropriate tests for your changes.
See [Contributing](./CONTRIBUTING.md)

### Build the library

Expand All @@ -86,15 +126,15 @@ npm run coverage
git checkout -b release/0.1.0
```

- Run prepare-release.sh script to set correct version
- Apply versioning

```sh
./prepare-release.sh
npm version major|minor|patch
```

#### Changelog Generation with Conventional Changelog

After calling the `prepare_release.sh` script, it is recommended to manually trigger the changelog generation script (which uses [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog)).
After versioning, it is recommended to manually trigger the changelog generation script (which uses [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog)).

1. **Conventional Commit Messages**:

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pcp-server-nodejs-sdk",
"version": "0.0.1",
"version": "0.0.2",
"description": "",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand All @@ -17,7 +17,8 @@
"format:write": "prettier --write \"src/**/!(*.d).ts\"",
"test": "vitest",
"test:coverage": "vitest run --coverage",
"changelog": "conventional-changelog -i CHANGELOG.md -s -r 0 --config ./changelog.config.cjs"
"changelog": "conventional-changelog -i CHANGELOG.md -s -r 0 --config ./changelog.config.cjs",
"version": "./version.sh"
},
"keywords": [
"payone",
Expand Down
2 changes: 1 addition & 1 deletion src/endpoints/CheckoutApiClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ describe('CheckoutApiClient', () => {
merchantCustomerId: 'cust-1234',
references: { merchantReference: 'com-12345' },
amountOfMoney: { currencyCode: 'YEN', amount: 1000 },
checkoutStatus: StatusCheckout.Open,
checkoutStatus: StatusCheckout.OPEN,
};

mockedFetch.mockResolvedValueOnce(createResponseMock<CheckoutResponse>(200, expectedResponse));
Expand Down
4 changes: 2 additions & 2 deletions src/endpoints/PaymentInformationApiClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ describe('PaymentInformationApiClient', () => {
},
type: PaymentType.Sale,
paymentProductId: 1331,
paymentChannel: PaymentChannel.Ecommerce,
paymentChannel: PaymentChannel.ECOMMERCE,
};

test('given request was successful, should return response', async () => {
const expectedResponse: PaymentInformationResponse = {
paymentChannel: PaymentChannel.Pos,
paymentChannel: PaymentChannel.POS,
terminalId: 'terminalId',
cardPaymentDetails: {
maskedCardNumber: '672559XXXXXX1108',
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export * from './endpoints/index.js';
export * from './errors/index.js';
export * from './queries/index.js';
export * from './models/index.js';
export * from './transformer/index.js';
export { CommunicatorConfiguration } from './CommunicatorConfiguration.js';
6 changes: 3 additions & 3 deletions src/transformer/applepay.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import type { ApplePayPayment } from '../models/applepay/ApplePayPayment.js';
import type { MobilePaymentMethodSpecificInput } from '../models/MobilePaymentMethodSpecificInput.js';
import { ApplePayPaymentMethodType } from '../models/applepay/ApplePayPaymentMethodType.js';
import { Network } from '../models/Network.js';
import { applePayPaymentToMobilePaymentMethodSpecificInput } from '../transformer/applepay.js';
import { transformApplePayPaymentToMobilePaymentMethodSpecificInput } from '../transformer/applepay.js';

describe('applepay transformer', () => {
describe('applePayPaymentToMobilePaymentMethodSpecificInput', () => {
describe('transformApplePayPaymentToMobilePaymentMethodSpecificInput', () => {
test('converts a full ApplePayPayment correctly', () => {
const payment: ApplePayPayment = {
token: {
Expand Down Expand Up @@ -60,7 +60,7 @@ describe('applepay transformer', () => {
},
};

expect(applePayPaymentToMobilePaymentMethodSpecificInput(payment)).toEqual(expected);
expect(transformApplePayPaymentToMobilePaymentMethodSpecificInput(payment)).toEqual(expected);
});
});
});
2 changes: 1 addition & 1 deletion src/transformer/applepay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function versionFromString(value: string): ApplePaymentTokenVersion {
}
}

export function applePayPaymentToMobilePaymentMethodSpecificInput(
export function transformApplePayPaymentToMobilePaymentMethodSpecificInput(
payment: ApplePayPayment,
): MobilePaymentMethodSpecificInput {
return {
Expand Down
1 change: 1 addition & 0 deletions src/transformer/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { transformApplePayPaymentToMobilePaymentMethodSpecificInput } from './applepay.js';
2 changes: 1 addition & 1 deletion src/utils/ServerMetaInfo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe('ServerMetaInfo', () => {
test('initializes with correct values', () => {
const serverMetaInfo = new ServerMetaInfo();
expect(serverMetaInfo.platformIdentifier).toBe(`${os.platform()}, node version is: ${process.version}`);
expect(serverMetaInfo.sdkIdentifier).toBe('JavaServerSDK/v0.0.2');
expect(serverMetaInfo.sdkIdentifier).toBe('NodeServerSDK/v0.0.2');
expect(serverMetaInfo.sdkCreator).toBe('PAYONE GmbH');
});
});
2 changes: 1 addition & 1 deletion src/utils/ServerMetaInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export class ServerMetaInfo {

constructor(integrator?: string) {
this.platformIdentifier = `${os.platform()}, node version is: ${process.version}`;
this.sdkIdentifier = 'JavaServerSDK/v0.0.2'; // version gets updated with the prepare-release.sh script
this.sdkIdentifier = 'NodeServerSDK/v0.0.2'; // version gets updated with the prepare-release.sh script
this.sdkCreator = 'PAYONE GmbH';
this.integrator = integrator || '';
}
Expand Down
18 changes: 18 additions & 0 deletions version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
SERVER_META_INFO_PATH='./src/utils/ServerMetaInfo.ts'
SERVER_META_INFO_TEST_PATH='./src/utils/ServerMetaInfo.test.ts'
NEW_VERSION=$npm_package_version

if [ -n "$NEW_VERSION" ]; then
if [ -f $SERVER_META_INFO_PATH ]; then
sed -i '' "s/NodeServerSDK\/v[0-9]*\.[0-9]*\.[0-9]*/NodeServerSDK\/v$NEW_VERSION/g" ${SERVER_META_INFO_PATH}
sed -i '' "s/NodeServerSDK\/v[0-9]*\.[0-9]*\.[0-9]*/NodeServerSDK\/v$NEW_VERSION/g" ${SERVER_META_INFO_TEST_PATH}
git add $SERVER_META_INFO_PATH
echo "Updated $SERVER_META_INFO_PATH with version $NEW_VERSION"
else
echo "Could not find $SERVER_META_INFO_PATH"
exit 1
fi

else
echo "Script can only be run as npm version hook"
fi