New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

line-pay-merchant

Package Overview
Dependencies
Maintainers
1
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

line-pay-merchant - npm Package Compare versions

Comparing version 0.2.0-alpha.1 to 0.2.0

dist/handler/payment-details-recovery.d.ts

13

CHANGELOG.md

@@ -0,1 +1,14 @@

# [0.2.0](https://github.com/enylin/line-pay-merchant/compare/v0.1.1...v0.2.0) (2021-12-14)
### Features
* **error:** add basic error types ([8c0c8b7](https://github.com/enylin/line-pay-merchant/commit/8c0c8b70d24099f6f454ea83d4f97cb445ac60d7))
* **handler:** add duplicate request handler ([0708066](https://github.com/enylin/line-pay-merchant/commit/0708066c4ea6b75d149a420b1a0ea3a5ca88e920))
* **handler:** add retry handler ([a96f2d3](https://github.com/enylin/line-pay-merchant/commit/a96f2d371f1db6f5185e098f4edd440f5d6aebf3))
* **handler:** export built-in handlers ([41be390](https://github.com/enylin/line-pay-merchant/commit/41be3904811b6c78f1b39344da8f6859a1409932))
* **handler:** rename duplicate-request handler and allow customized predicate ([28c552c](https://github.com/enylin/line-pay-merchant/commit/28c552c191ca66eac0d615bfb2ddd881a79ef5c0))
## [0.1.1](https://github.com/enylin/line-pay-merchant/compare/v0.1.0...v0.1.1) (2021-12-13)

@@ -2,0 +15,0 @@

14

dist/handler/timeout-retry.d.ts

@@ -1,10 +0,16 @@

import { GeneralResponseBody } from '@/line-pay-api/type';
import { ApiHandler, ApiResponse } from '../payment-api/type';
import { ApiHandler, LinePayApiClients } from '../payment-api/type';
/**
* Create a handler that retries the request if it fails with a timeout error.
*
* Example:
* ```ts
* const maxRetry = 10 // will send maximum 11 times (10 retry + 1 initial request)
* const retryTimeout = 5000 // retry after 5 seconds (after request failed)
* handlers.createTimeoutRetryHandler(maxRetry, retryTimeout)
* ```
*
* @param maxRetry maximum number of retries
* @param timeout milliseconds to wait before retrying
* @param retryTimeout milliseconds to wait before retrying
* @returns a handler that retries the request if it fails with a timeout error
*/
export declare const createTimeoutRetryHandler: <Req, Res extends GeneralResponseBody>(maxRetry?: number, timeout?: number) => ApiHandler<Req, ApiResponse<Res>>;
export declare const createTimeoutRetryHandler: <T extends keyof LinePayApiClients>(maxRetry?: number, retryTimeout?: number) => ApiHandler<T>;

@@ -17,11 +17,23 @@ "use strict";

*
* Example:
* ```ts
* const maxRetry = 10 // will send maximum 11 times (10 retry + 1 initial request)
* const retryTimeout = 5000 // retry after 5 seconds (after request failed)
* handlers.createTimeoutRetryHandler(maxRetry, retryTimeout)
* ```
*
* @param maxRetry maximum number of retries
* @param timeout milliseconds to wait before retrying
* @param retryTimeout milliseconds to wait before retrying
* @returns a handler that retries the request if it fails with a timeout error
*/
const createTimeoutRetryHandler = (maxRetry = 10, timeout = 5000) => (req, next) => __awaiter(void 0, void 0, void 0, function* () {
const createTimeoutRetryHandler = (maxRetry = 10, retryTimeout = 5000) => ({ req, next }) => __awaiter(void 0, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
const f = (count, originalError) => __awaiter(void 0, void 0, void 0, function* () {
try {
resolve(yield next(req));
const res = yield next(req);
if (originalError !== null &&
res.comments.originalLinePayApiError !== undefined) {
res.comments.originalLinePayApiError = originalError;
}
resolve(res);
}

@@ -31,3 +43,3 @@ catch (e) {

if (count < maxRetry)
setTimeout(() => f(count + 1, e), timeout);
setTimeout(() => f(count + 1, e), retryTimeout);
else

@@ -39,3 +51,3 @@ reject(originalError);

});
f(0, new Error());
f(0, null);
});

@@ -42,0 +54,0 @@ });

import { LineMerchantConfig } from './line-pay-api/type';
import { LinePayClient } from './type';
import { toConfirmResponse, toRefundResponse } from './handler/payment-details-recovery';
/**

@@ -10,1 +11,7 @@ * Create a client for LINE Pay API.

export declare function createLinePayClient(config: LineMerchantConfig): LinePayClient;
export declare const handler: {
createPaymentDetailsRecoveryHandler: <T extends "confirm" | "refund">(converter: import("./handler/payment-details-recovery").PaymentDetailsConverter<T>, predicate?: (error: unknown) => boolean) => import("./payment-api/type").ApiHandler<T>;
createTimeoutRetryHandler: <T_1 extends keyof import("./payment-api/type").LinePayApiClients>(maxRetry?: number, retryTimeout?: number) => import("./payment-api/type").ApiHandler<T_1>;
toConfirmResponse: typeof toConfirmResponse;
toRefundResponse: typeof toRefundResponse;
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createLinePayClient = void 0;
exports.handler = exports.createLinePayClient = void 0;
const auth_http_client_1 = require("./line-pay-api/auth-http-client");

@@ -10,2 +10,4 @@ const confirm_1 = require("./line-pay-api/confirm");

const payment_details_1 = require("./line-pay-api/payment-details");
const payment_details_recovery_1 = require("./handler/payment-details-recovery");
const timeout_retry_1 = require("./handler/timeout-retry");
/**

@@ -20,9 +22,15 @@ * Create a client for LINE Pay API.

return {
request: (0, create_1.createPaymentApi)(request_1.requestWithClient, httpClient),
confirm: (0, create_1.createPaymentApi)(confirm_1.confirmWithClient, httpClient),
refund: (0, create_1.createPaymentApi)(refund_1.refundWithClient, httpClient),
paymentDetails: (0, create_1.createPaymentApi)(payment_details_1.paymentDetailsWithClient, httpClient)
request: (0, create_1.createPaymentApi)('request', request_1.requestWithClient, httpClient),
confirm: (0, create_1.createPaymentApi)('confirm', confirm_1.confirmWithClient, httpClient),
refund: (0, create_1.createPaymentApi)('refund', refund_1.refundWithClient, httpClient),
paymentDetails: (0, create_1.createPaymentApi)('paymentDetails', payment_details_1.paymentDetailsWithClient, httpClient)
};
}
exports.createLinePayClient = createLinePayClient;
exports.handler = {
createPaymentDetailsRecoveryHandler: payment_details_recovery_1.createPaymentDetailsRecoveryHandler,
createTimeoutRetryHandler: timeout_retry_1.createTimeoutRetryHandler,
toConfirmResponse: payment_details_recovery_1.toConfirmResponse,
toRefundResponse: payment_details_recovery_1.toRefundResponse
};
//# sourceMappingURL=index.js.map

@@ -0,3 +1,4 @@

import { LinePayApiClients } from '@/payment-api/type';
import { GeneralResponseBody } from './type';
import { Currency, Address, HttpClient } from './type';
import { Currency, Address } from './type';
export declare type ConfirmRequestBody = {

@@ -132,2 +133,2 @@ /**

};
export declare const confirmWithClient: (httpClient: HttpClient) => ({ transactionId, body }: ConfirmRequestConfig) => Promise<ConfirmResponseBody>;
export declare const confirmWithClient: LinePayApiClients['confirm'];

@@ -13,3 +13,3 @@ "use strict";

exports.confirmWithClient = void 0;
const confirmWithClient = (httpClient) => ({ transactionId, body }) => __awaiter(void 0, void 0, void 0, function* () {
const confirmWithClient = httpClient => ({ transactionId, body }) => __awaiter(void 0, void 0, void 0, function* () {
const { data } = yield httpClient.post(`/v3/payments/${transactionId}/confirm`, body);

@@ -16,0 +16,0 @@ return data;

@@ -0,3 +1,4 @@

import { LinePayApiClients } from '@/payment-api/type';
import { GeneralResponseBody } from './type';
import { Product, HttpClient, Address } from './type';
import { Product, Address } from './type';
export declare type Fields = 'ALL' | 'TRANSACTION' | 'ORDER';

@@ -191,2 +192,2 @@ export declare type PaymentDetailsRequestParams = {

};
export declare const paymentDetailsWithClient: (httpClient: HttpClient) => (config: PaymentDetailsRequestConfig) => Promise<PaymentDetailsResponseBody>;
export declare const paymentDetailsWithClient: LinePayApiClients['paymentDetails'];

@@ -13,3 +13,3 @@ "use strict";

exports.paymentDetailsWithClient = void 0;
const paymentDetailsWithClient = (httpClient) => (config) => __awaiter(void 0, void 0, void 0, function* () {
const paymentDetailsWithClient = httpClient => (config) => __awaiter(void 0, void 0, void 0, function* () {
const { data } = yield httpClient.get('/v3/payments', config);

@@ -16,0 +16,0 @@ return data;

@@ -0,3 +1,3 @@

import { LinePayApiClients } from '@/payment-api/type';
import { GeneralResponseBody } from './type';
import { HttpClient } from './type';
export declare type RefundRequestBody = {

@@ -36,2 +36,2 @@ /**

};
export declare const refundWithClient: (httpClient: HttpClient) => ({ transactionId, body }: RefundRequestConfig) => Promise<RefundResponseBody>;
export declare const refundWithClient: LinePayApiClients['refund'];

@@ -13,3 +13,3 @@ "use strict";

exports.refundWithClient = void 0;
const refundWithClient = (httpClient) => ({ transactionId, body }) => __awaiter(void 0, void 0, void 0, function* () {
const refundWithClient = httpClient => ({ transactionId, body }) => __awaiter(void 0, void 0, void 0, function* () {
const { data } = yield httpClient.post(`/v3/payments/${transactionId}/refund`, body);

@@ -16,0 +16,0 @@ return data;

@@ -0,3 +1,4 @@

import { LinePayApiClients } from '@/payment-api/type';
import { GeneralResponseBody } from './type';
import { Currency, Address, Product, HttpClient } from './type';
import { Currency, Address, Product } from './type';
export declare type Package = {

@@ -219,2 +220,2 @@ /**

};
export declare const requestWithClient: (httpClient: HttpClient) => ({ body }: RequestRequestConfig) => Promise<RequestResponseBody>;
export declare const requestWithClient: LinePayApiClients['request'];

@@ -13,3 +13,3 @@ "use strict";

exports.requestWithClient = void 0;
const requestWithClient = (httpClient) => ({ body }) => __awaiter(void 0, void 0, void 0, function* () {
const requestWithClient = httpClient => ({ body }) => __awaiter(void 0, void 0, void 0, function* () {
const { data } = yield httpClient.post('/v3/payments/request', body);

@@ -16,0 +16,0 @@ return data;

@@ -6,2 +6,9 @@ /**

/**
* LINE Pay API client builder
*
* @param httpClient http client communicate with LINE Pay API
* @returns LINE Pay API request function
*/
export declare type ApiClientBuilder<Req, Res> = (httpClient: HttpClient) => (req: Req) => Promise<Res>;
/**
* Payment currency (ISO 4217)

@@ -8,0 +15,0 @@ */

import { HttpClient } from '@/line-pay-api/type';
import { ApiResponse, ApiHandler, PaymentApi } from './type';
import { GeneralResponseBody } from '@/line-pay-api/type';
export declare function createPaymentApi<Req, Res extends GeneralResponseBody>(createSender: (httpClient: HttpClient) => (req: Req) => Promise<Res>, httpClient: HttpClient, handlers?: ApiHandler<Req, ApiResponse<Res>>[]): PaymentApi<Req, ApiResponse<Res>>;
import { ApiHandler, PaymentApi, LinePayApiClients, RequestConfig, ResponseBody } from './type';
export declare function createPaymentApi<T extends keyof LinePayApiClients>(type: T, createSender: (httpClient: HttpClient) => (req: RequestConfig<T>) => Promise<ResponseBody<T>>, httpClient: HttpClient, handlers?: ApiHandler<T>[]): PaymentApi<T>;

@@ -13,6 +13,6 @@ "use strict";

exports.createPaymentApi = void 0;
function createPaymentApi(createSender, httpClient, handlers = []) {
function createPaymentApi(type, createSender, httpClient, handlers = []) {
const addHandlers = (...fs) => {
handlers.push(...fs);
return createPaymentApi(createSender, httpClient, handlers);
return createPaymentApi(type, createSender, httpClient, handlers);
};

@@ -25,3 +25,12 @@ const sender = (req) => __awaiter(this, void 0, void 0, function* () {

});
const getHandler = (i) => (req) => __awaiter(this, void 0, void 0, function* () { return i < 0 ? sender(req) : handlers[i](req, getHandler(i - 1), httpClient); });
const getHandler = (i) => (req) => __awaiter(this, void 0, void 0, function* () {
return i < 0
? sender(req)
: handlers[i]({
type,
req,
next: getHandler(i - 1),
httpClient
});
});
const send = (req) => __awaiter(this, void 0, void 0, function* () { return getHandler(handlers.length - 1)(req); });

@@ -28,0 +37,0 @@ return {

@@ -1,15 +0,43 @@

import { GeneralResponseBody, HttpClient } from '@/line-pay-api/type';
export declare type ApiHandler<Req, Res> = (
import { ConfirmRequestConfig, ConfirmResponseBody } from '@/line-pay-api/confirm';
import { PaymentDetailsRequestConfig, PaymentDetailsResponseBody } from '@/line-pay-api/payment-details';
import { RefundRequestConfig, RefundResponseBody } from '@/line-pay-api/refund';
import { RequestRequestConfig, RequestResponseBody } from '@/line-pay-api/request';
import { ApiClientBuilder, GeneralResponseBody, HttpClient } from '@/line-pay-api/type';
/**
* The request object
* All LINE Pay API Clients supported by this library.
*/
req: Req,
export declare type LinePayApiClients = {
request: ApiClientBuilder<RequestRequestConfig, RequestResponseBody>;
confirm: ApiClientBuilder<ConfirmRequestConfig, ConfirmResponseBody>;
refund: ApiClientBuilder<RefundRequestConfig, RefundResponseBody>;
paymentDetails: ApiClientBuilder<PaymentDetailsRequestConfig, PaymentDetailsResponseBody>;
};
declare type Awaited<T> = T extends PromiseLike<infer U> ? Awaited<U> : T;
/**
* The next handler or the request sending function
* Request config of LinePayApiClients
*/
next: (req: Req) => Promise<Res>,
export declare type RequestConfig<T extends keyof LinePayApiClients> = Parameters<ReturnType<LinePayApiClients[T]>>[0];
/**
* The HTTP client
* Response body of LinePayApiClients
*/
httpClient: HttpClient) => Promise<Res>;
export declare type ResponseBody<T extends keyof LinePayApiClients> = Awaited<ReturnType<ReturnType<LinePayApiClients[T]>>>;
export declare type ApiHandlerParams<T extends keyof LinePayApiClients> = {
/**
* LINE Pay API type
*/
type: keyof LinePayApiClients;
/**
* The request object
*/
req: RequestConfig<T>;
/**
* The next handler or the request sending function
*/
next: (req: RequestConfig<T>) => Promise<ApiResponse<ResponseBody<T>>>;
/**
* The HTTP client
*/
httpClient: HttpClient;
};
export declare type ApiHandler<T extends keyof LinePayApiClients> = (params: ApiHandlerParams<T>) => Promise<ApiResponse<ResponseBody<T>>>;
export declare type ApiResponse<Body extends GeneralResponseBody> = {

@@ -25,3 +53,3 @@ /**

};
export interface PaymentApi<Req, Res> {
export interface PaymentApi<T extends keyof LinePayApiClients> {
/**

@@ -32,3 +60,3 @@ * Add request/response handler to the API

*/
addHandler(handler: ApiHandler<Req, Res>): PaymentApi<Req, Res>;
addHandler(handler: ApiHandler<T>): PaymentApi<T>;
/**

@@ -39,3 +67,3 @@ * Add request/response handlers to the API

*/
addHandlers(...handlers: ApiHandler<Req, Res>[]): PaymentApi<Req, Res>;
addHandlers(...handlers: ApiHandler<T>[]): PaymentApi<T>;
/**

@@ -46,3 +74,4 @@ * Send request to the API

*/
send(request: Req): Promise<Res>;
send(request: RequestConfig<T>): Promise<ApiResponse<ResponseBody<T>>>;
}
export {};

@@ -1,23 +0,82 @@

import { ConfirmRequestConfig, ConfirmResponseBody } from './line-pay-api/confirm';
import { PaymentDetailsRequestConfig, PaymentDetailsResponseBody } from './line-pay-api/payment-details';
import { RefundRequestConfig, RefundResponseBody } from './line-pay-api/refund';
import { RequestRequestConfig, RequestResponseBody } from './line-pay-api/request';
import { ApiResponse, PaymentApi } from './payment-api/type';
import { PaymentApi } from './payment-api/type';
export declare type LinePayClient = {
/**
* An API to request payment information to LINE Pay. User can change settings such as order information or various payment methods. Once the request is successful, a transaction ID is generated and with the ID, you can complete the payment or process refund.
*
* Example:
* ```ts
* const order: RequestRequestBody = {
* amount: 1000,
* currency: 'TWD',
* orderId: '20211209003',
* packages: [
* {
* id: 'c99abc79-3b29-4f40-8851-bc618ca57857',
* amount: 1000,
* products: [
* {
* name: 'Demo Product',
* quantity: 2,
* price: 500
* }
* ]
* }
* ],
* redirectUrls: {
* confirmUrl: 'https://example.com/confirmUrl',
* cancelUrl: 'https://example.com/cancelUrl'
* }
* }
* const res = await linePayClient.request.send({
* body: order
* })
* ```
*/
request: PaymentApi<RequestRequestConfig, ApiResponse<RequestResponseBody>>;
request: PaymentApi<'request'>;
/**
* An API for the merchant to complete the payment when the user approves with the [ConfirmURL](https://pay.line.me/documents/online_v3_en.html?shell#confirmurl-spec) or [Check Payment Status API](https://pay.line.me/documents/online_v3_en.html?shell#check-payment-status-api). Status of a payment where authorization and purchase are separated because 'options.payment.capture' of the Request API is set as `false` will be in purchase standby (Authentication) even after it is completed. To complete the purchase, an additional purchase process is required through the [Capture API](https://pay.line.me/documents/online_v3_en.html?shell#capture-api).
*
* Example:
* ```ts
* const res = await linePayClient.confirm
* .send({
* transactionId: '2021121300698360310',
* body: {
* currency: 'TWD',
* amount: 1000
* }
* })
* ```
*/
confirm: PaymentApi<ConfirmRequestConfig, ApiResponse<ConfirmResponseBody>>;
confirm: PaymentApi<'confirm'>;
/**
* An API to refund transactions that has been completed the payment (purchase). The transaction ID of LINE Pay user must be passed when refunded and partial refund is also possible.
*
* Example:
* ```ts
* const res = await linePayClient.refund
* .send({
* transactionId: '2021121300698360310',
* body: {
* refundAmount: 20
* }
* })
* ```
*/
refund: PaymentApi<RefundRequestConfig, ApiResponse<RefundResponseBody>>;
refund: PaymentApi<'refund'>;
/**
* An API to check transaction history in LINE Pay. You can check histories of authorizations and payment completions. With fields setting, you can selectively check transaction information or order information as needed.
*
* Example:
* ```ts
* const res = await linePayClient.paymentDetails
* .send({
* params: {
* transactionId: ['2021113000697335210'],
* orderId: ['20211209003'],
* }
* })
* ```
*/
paymentDetails: PaymentApi<PaymentDetailsRequestConfig, ApiResponse<PaymentDetailsResponseBody>>;
paymentDetails: PaymentApi<'paymentDetails'>;
};
{
"name": "line-pay-merchant",
"version": "0.2.0-alpha.1",
"version": "0.2.0",
"description": "LINE Pay Merchant API V3",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -79,6 +79,35 @@ # line-pay-merchant

### Handler
### Built-in handler
Request:
```ts
import { createLinePayClient, handler } from 'line-pay-merchant'
const linePayClient = createLinePayClient(config)
try {
const res = await linePayClient.confirm
.addHandlers(
handler.createTimeoutRetryHandler(),
handler.createPaymentDetailsRecoveryHandler(handler.toConfirmResponse)
)
.send({
transactionId: '2021121300698360310',
body: {
currency: 'TWD',
amount: 1000
}
})
console.log('res = ', JSON.stringify(res, null, 2))
} catch (e) {
console.log('e = ', e)
}
```
### Custom handler
Request:
```ts
const res = await linePayClient.refund

@@ -136,6 +165,35 @@ .addHandler(async (req, next) => {

See type definitions:
- [RequestRequestConfig](src/line-pay-api/request.ts#L227)
- [RequestResponseBody](src/line-pay-api/request.ts#L133)
Definitions:
- [RequestRequestConfig](src/line-pay-api/request.ts#L228)
- [RequestResponseBody](src/line-pay-api/request.ts#L221)
Example:
```ts
const order: RequestRequestBody = {
amount: 1000,
currency: 'TWD',
orderId: '20211209003',
packages: [
{
id: 'c99abc79-3b29-4f40-8851-bc618ca57857',
amount: 1000,
products: [
{
name: 'Demo Product',
quantity: 2,
price: 500
}
]
}
],
redirectUrls: {
confirmUrl: 'https://example.com/confirmUrl',
cancelUrl: 'https://example.com/cancelUrl'
}
}
const res = await linePayClient.request.send({
body: order
})
```
### Confirm

@@ -149,6 +207,18 @@

See type definitions:
- [ConfirmRequestConfig](src/line-pay-api/confirm.ts#L20)
- [ConfirmResponseBody](src/line-pay-api/confirm.ts#L220)
Definitions:
- [ConfirmRequestConfig](src/line-pay-api/confirm.ts#L21)
- [ConfirmResponseBody](src/line-pay-api/confirm.ts#L134)
Example:
```ts
const res = await linePayClient.confirm
.send({
transactionId: '2021121300698360310',
body: {
currency: 'TWD',
amount: 1000
}
})
```
### Refund

@@ -162,6 +232,17 @@

See type definitions:
Definitions:
- [RefundRequestConfig](src/line-pay-api/refund.ts#L12)
- [RefundResponseBody](src/line-pay-api/refund.ts#L34)
Example:
```ts
const res = await linePayClient.refund
.send({
transactionId: '2021121300698360310',
body: {
refundAmount: 20
}
})
```
### Payment Details

@@ -175,6 +256,17 @@

See type definitions:
- [PaymentDetailsRequestConfig](src/line-pay-api/payment-details.ts#L26)
- [PaymentDetailsResponseBody](src/line-pay-api/payment-details.ts#L195)
Definitions:
- [PaymentDetailsRequestConfig](src/line-pay-api/payment-details.ts#L27)
- [PaymentDetailsResponseBody](src/line-pay-api/payment-details.ts#L196)
Example:
```ts
const res = await linePayClient.paymentDetails
.send({
params: {
transactionId: ['2021113000697335210'],
orderId: ['20211209003'],
}
})
```
## Further details

@@ -189,4 +281,4 @@

JavaScript numbers are double-precision floating-point numbers.
LINE Pay Transaction ID is a number larger than the largest integer JavaScript can be precisely stored (which is `2^53`, `9007199254740992`).
This may cause the transaction ID received from LINE Pay APIs to be recognized incorrectly. For example, the transaction ID number `2021121300698360310` may be converted to `2021121300698360300` by default parser.
LINE Pay Transaction ID is a number larger than the largest integer JavaScript can be precisely stored (which is 2^53, 9007199254740992).
This may cause the transaction ID received from LINE Pay APIs to be recognized incorrectly. For example, the transaction ID number 2021121300698360310 may be converted to 2021121300698360300 by default parser.
This library handles the behavior by converting the transaction ID number to string format before the default parser (`JSON.parse`) parses the response received from LINE Pay APIs.

@@ -197,13 +289,1 @@

- [LINE Pay Online APIs](https://pay.line.me/tw/developers/apis/onlineApis?locale=en_US)
## Roadmap
TODOs:
- Implement Capture API and add unit tests
- Implement Void API and add unit tests
- Implement Check Payment Status API and add unit tests
- Implement Check RegKey API and add unit tests
- Implement Pay Preapproved API and add unit tests
- Implement Expire RegKey API and add unit tests
- Provide handlers
- Add more examples to README.md

@@ -1,4 +0,3 @@

import { GeneralResponseBody } from '@/line-pay-api/type'
import { isTimeoutError } from '../line-pay-api/error/timeout'
import { ApiHandler, ApiResponse } from '../payment-api/type'
import { ApiHandler, LinePayApiClients } from '../payment-api/type'

@@ -8,19 +7,36 @@ /**

*
* Example:
* ```ts
* const maxRetry = 10 // will send maximum 11 times (10 retry + 1 initial request)
* const retryTimeout = 5000 // retry after 5 seconds (after request failed)
* handlers.createTimeoutRetryHandler(maxRetry, retryTimeout)
* ```
*
* @param maxRetry maximum number of retries
* @param timeout milliseconds to wait before retrying
* @param retryTimeout milliseconds to wait before retrying
* @returns a handler that retries the request if it fails with a timeout error
*/
export const createTimeoutRetryHandler =
<Req, Res extends GeneralResponseBody>(
<T extends keyof LinePayApiClients>(
maxRetry = 10,
timeout = 5000
): ApiHandler<Req, ApiResponse<Res>> =>
async (req, next) =>
retryTimeout = 5000
): ApiHandler<T> =>
async ({ req, next }) =>
new Promise((resolve, reject) => {
const f = async (count: number, originalError: unknown) => {
try {
resolve(await next(req))
const res = await next(req)
if (
originalError !== null &&
res.comments.originalLinePayApiError !== undefined
) {
res.comments.originalLinePayApiError = originalError
}
resolve(res)
} catch (e) {
if (isTimeoutError(e)) {
if (count < maxRetry) setTimeout(() => f(count + 1, e), timeout)
if (count < maxRetry)
setTimeout(() => f(count + 1, e), retryTimeout)
else reject(originalError)

@@ -31,3 +47,4 @@ }

}
f(0, new Error())
f(0, null)
})

@@ -9,2 +9,8 @@ import { createAuthHttpClient } from './line-pay-api/auth-http-client'

import { paymentDetailsWithClient } from './line-pay-api/payment-details'
import {
createPaymentDetailsRecoveryHandler,
toConfirmResponse,
toRefundResponse
} from './handler/payment-details-recovery'
import { createTimeoutRetryHandler } from './handler/timeout-retry'

@@ -21,7 +27,18 @@ /**

return {
request: createPaymentApi(requestWithClient, httpClient),
confirm: createPaymentApi(confirmWithClient, httpClient),
refund: createPaymentApi(refundWithClient, httpClient),
paymentDetails: createPaymentApi(paymentDetailsWithClient, httpClient)
request: createPaymentApi('request', requestWithClient, httpClient),
confirm: createPaymentApi('confirm', confirmWithClient, httpClient),
refund: createPaymentApi('refund', refundWithClient, httpClient),
paymentDetails: createPaymentApi(
'paymentDetails',
paymentDetailsWithClient,
httpClient
)
}
}
export const handler = {
createPaymentDetailsRecoveryHandler,
createTimeoutRetryHandler,
toConfirmResponse,
toRefundResponse
}

@@ -0,3 +1,4 @@

import { LinePayApiClients } from '@/payment-api/type'
import { GeneralResponseBody } from './type'
import { Currency, Address, HttpClient } from './type'
import { Currency, Address } from './type'

@@ -140,5 +141,5 @@ export type ConfirmRequestBody = {

export const confirmWithClient =
(httpClient: HttpClient) =>
async ({ transactionId, body }: ConfirmRequestConfig) => {
export const confirmWithClient: LinePayApiClients['confirm'] =
httpClient =>
async ({ transactionId, body }) => {
const { data } = await httpClient.post<

@@ -145,0 +146,0 @@ ConfirmRequestBody,

@@ -0,3 +1,4 @@

import { LinePayApiClients } from '@/payment-api/type'
import { GeneralResponseBody } from './type'
import { Product, HttpClient, Address } from './type'
import { Product, Address } from './type'

@@ -202,4 +203,4 @@ export type Fields = 'ALL' | 'TRANSACTION' | 'ORDER'

export const paymentDetailsWithClient =
(httpClient: HttpClient) => async (config: PaymentDetailsRequestConfig) => {
export const paymentDetailsWithClient: LinePayApiClients['paymentDetails'] =
httpClient => async config => {
const { data } = await httpClient.get<

@@ -206,0 +207,0 @@ PaymentDetailsRequestParams,

@@ -0,3 +1,3 @@

import { LinePayApiClients } from '@/payment-api/type'
import { GeneralResponseBody } from './type'
import { HttpClient } from './type'

@@ -41,5 +41,5 @@ export type RefundRequestBody = {

export const refundWithClient =
(httpClient: HttpClient) =>
async ({ transactionId, body }: RefundRequestConfig) => {
export const refundWithClient: LinePayApiClients['refund'] =
httpClient =>
async ({ transactionId, body }) => {
const { data } = await httpClient.post<

@@ -46,0 +46,0 @@ RefundRequestBody,

@@ -0,3 +1,4 @@

import { LinePayApiClients } from '@/payment-api/type'
import { GeneralResponseBody } from './type'
import { Currency, Address, Product, HttpClient } from './type'
import { Currency, Address, Product } from './type'

@@ -234,5 +235,5 @@ export type Package = {

export const requestWithClient =
(httpClient: HttpClient) =>
async ({ body }: RequestRequestConfig) => {
export const requestWithClient: LinePayApiClients['request'] =
httpClient =>
async ({ body }) => {
const { data } = await httpClient.post<

@@ -239,0 +240,0 @@ RequestRequestBody,

@@ -7,2 +7,12 @@ /**

/**
* LINE Pay API client builder
*
* @param httpClient http client communicate with LINE Pay API
* @returns LINE Pay API request function
*/
export type ApiClientBuilder<Req, Res> = (
httpClient: HttpClient
) => (req: Req) => Promise<Res>
/**
* Payment currency (ISO 4217)

@@ -9,0 +19,0 @@ */

import { HttpClient } from '@/line-pay-api/type'
import { ApiResponse, ApiHandler, PaymentApi } from './type'
import { GeneralResponseBody } from '@/line-pay-api/type'
import {
ApiResponse,
ApiHandler,
PaymentApi,
LinePayApiClients,
RequestConfig,
ResponseBody
} from './type'
export function createPaymentApi<Req, Res extends GeneralResponseBody>(
createSender: (httpClient: HttpClient) => (req: Req) => Promise<Res>,
export function createPaymentApi<T extends keyof LinePayApiClients>(
type: T,
createSender: (
httpClient: HttpClient
) => (req: RequestConfig<T>) => Promise<ResponseBody<T>>,
httpClient: HttpClient,
handlers: ApiHandler<Req, ApiResponse<Res>>[] = []
): PaymentApi<Req, ApiResponse<Res>> {
const addHandlers = (...fs: ApiHandler<Req, ApiResponse<Res>>[]) => {
handlers: ApiHandler<T>[] = []
): PaymentApi<T> {
const addHandlers = (...fs: ApiHandler<T>[]) => {
handlers.push(...fs)
return createPaymentApi(createSender, httpClient, handlers)
return createPaymentApi(type, createSender, httpClient, handlers)
}
const sender = async (req: Req): Promise<ApiResponse<Res>> => ({
const sender = async (
req: RequestConfig<T>
): Promise<ApiResponse<ResponseBody<T>>> => ({
body: await createSender(httpClient)(req),

@@ -20,6 +31,14 @@ comments: {}

const getHandler = (i: number) => async (req: Req) =>
i < 0 ? sender(req) : handlers[i](req, getHandler(i - 1), httpClient)
const getHandler = (i: number) => async (req: RequestConfig<T>) =>
i < 0
? sender(req)
: handlers[i]({
type,
req,
next: getHandler(i - 1),
httpClient
})
const send = async (req: Req) => getHandler(handlers.length - 1)(req)
const send = async (req: RequestConfig<T>) =>
getHandler(handlers.length - 1)(req)

@@ -26,0 +45,0 @@ return {

@@ -1,12 +0,62 @@

import { GeneralResponseBody, HttpClient } from '@/line-pay-api/type'
import {
ConfirmRequestConfig,
ConfirmResponseBody
} from '@/line-pay-api/confirm'
import {
PaymentDetailsRequestConfig,
PaymentDetailsResponseBody
} from '@/line-pay-api/payment-details'
import { RefundRequestConfig, RefundResponseBody } from '@/line-pay-api/refund'
import {
RequestRequestConfig,
RequestResponseBody
} from '@/line-pay-api/request'
import {
ApiClientBuilder,
GeneralResponseBody,
HttpClient
} from '@/line-pay-api/type'
export type ApiHandler<Req, Res> = (
/**
* All LINE Pay API Clients supported by this library.
*/
export type LinePayApiClients = {
request: ApiClientBuilder<RequestRequestConfig, RequestResponseBody>
confirm: ApiClientBuilder<ConfirmRequestConfig, ConfirmResponseBody>
refund: ApiClientBuilder<RefundRequestConfig, RefundResponseBody>
paymentDetails: ApiClientBuilder<
PaymentDetailsRequestConfig,
PaymentDetailsResponseBody
>
}
type Awaited<T> = T extends PromiseLike<infer U> ? Awaited<U> : T
/**
* Request config of LinePayApiClients
*/
export type RequestConfig<T extends keyof LinePayApiClients> = Parameters<
ReturnType<LinePayApiClients[T]>
>[0]
/**
* Response body of LinePayApiClients
*/
export type ResponseBody<T extends keyof LinePayApiClients> = Awaited<
ReturnType<ReturnType<LinePayApiClients[T]>>
>
export type ApiHandlerParams<T extends keyof LinePayApiClients> = {
/**
* LINE Pay API type
*/
type: keyof LinePayApiClients
/**
* The request object
*/
req: Req,
req: RequestConfig<T>
/**
* The next handler or the request sending function
*/
next: (req: Req) => Promise<Res>,
next: (req: RequestConfig<T>) => Promise<ApiResponse<ResponseBody<T>>>
/**

@@ -16,4 +66,8 @@ * The HTTP client

httpClient: HttpClient
) => Promise<Res>
}
export type ApiHandler<T extends keyof LinePayApiClients> = (
params: ApiHandlerParams<T>
) => Promise<ApiResponse<ResponseBody<T>>>
export type ApiResponse<Body extends GeneralResponseBody> = {

@@ -30,3 +84,3 @@ /**

export interface PaymentApi<Req, Res> {
export interface PaymentApi<T extends keyof LinePayApiClients> {
/**

@@ -37,3 +91,3 @@ * Add request/response handler to the API

*/
addHandler(handler: ApiHandler<Req, Res>): PaymentApi<Req, Res>
addHandler(handler: ApiHandler<T>): PaymentApi<T>
/**

@@ -44,3 +98,3 @@ * Add request/response handlers to the API

*/
addHandlers(...handlers: ApiHandler<Req, Res>[]): PaymentApi<Req, Res>
addHandlers(...handlers: ApiHandler<T>[]): PaymentApi<T>
/**

@@ -51,3 +105,3 @@ * Send request to the API

*/
send(request: Req): Promise<Res>
send(request: RequestConfig<T>): Promise<ApiResponse<ResponseBody<T>>>
}

@@ -1,15 +0,2 @@

import {
ConfirmRequestConfig,
ConfirmResponseBody
} from './line-pay-api/confirm'
import {
PaymentDetailsRequestConfig,
PaymentDetailsResponseBody
} from './line-pay-api/payment-details'
import { RefundRequestConfig, RefundResponseBody } from './line-pay-api/refund'
import {
RequestRequestConfig,
RequestResponseBody
} from './line-pay-api/request'
import { ApiResponse, PaymentApi } from './payment-api/type'
import { PaymentApi } from './payment-api/type'

@@ -19,20 +6,79 @@ export type LinePayClient = {

* An API to request payment information to LINE Pay. User can change settings such as order information or various payment methods. Once the request is successful, a transaction ID is generated and with the ID, you can complete the payment or process refund.
*
* Example:
* ```ts
* const order: RequestRequestBody = {
* amount: 1000,
* currency: 'TWD',
* orderId: '20211209003',
* packages: [
* {
* id: 'c99abc79-3b29-4f40-8851-bc618ca57857',
* amount: 1000,
* products: [
* {
* name: 'Demo Product',
* quantity: 2,
* price: 500
* }
* ]
* }
* ],
* redirectUrls: {
* confirmUrl: 'https://example.com/confirmUrl',
* cancelUrl: 'https://example.com/cancelUrl'
* }
* }
* const res = await linePayClient.request.send({
* body: order
* })
* ```
*/
request: PaymentApi<RequestRequestConfig, ApiResponse<RequestResponseBody>>
request: PaymentApi<'request'>
/**
* An API for the merchant to complete the payment when the user approves with the [ConfirmURL](https://pay.line.me/documents/online_v3_en.html?shell#confirmurl-spec) or [Check Payment Status API](https://pay.line.me/documents/online_v3_en.html?shell#check-payment-status-api). Status of a payment where authorization and purchase are separated because 'options.payment.capture' of the Request API is set as `false` will be in purchase standby (Authentication) even after it is completed. To complete the purchase, an additional purchase process is required through the [Capture API](https://pay.line.me/documents/online_v3_en.html?shell#capture-api).
*
* Example:
* ```ts
* const res = await linePayClient.confirm
* .send({
* transactionId: '2021121300698360310',
* body: {
* currency: 'TWD',
* amount: 1000
* }
* })
* ```
*/
confirm: PaymentApi<ConfirmRequestConfig, ApiResponse<ConfirmResponseBody>>
confirm: PaymentApi<'confirm'>
/**
* An API to refund transactions that has been completed the payment (purchase). The transaction ID of LINE Pay user must be passed when refunded and partial refund is also possible.
*
* Example:
* ```ts
* const res = await linePayClient.refund
* .send({
* transactionId: '2021121300698360310',
* body: {
* refundAmount: 20
* }
* })
* ```
*/
refund: PaymentApi<RefundRequestConfig, ApiResponse<RefundResponseBody>>
refund: PaymentApi<'refund'>
/**
* An API to check transaction history in LINE Pay. You can check histories of authorizations and payment completions. With fields setting, you can selectively check transaction information or order information as needed.
*
* Example:
* ```ts
* const res = await linePayClient.paymentDetails
* .send({
* params: {
* transactionId: ['2021113000697335210'],
* orderId: ['20211209003'],
* }
* })
* ```
*/
paymentDetails: PaymentApi<
PaymentDetailsRequestConfig,
ApiResponse<PaymentDetailsResponseBody>
>
paymentDetails: PaymentApi<'paymentDetails'>
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc