2020-08-21 15:40:04 +00:00
import * as plugins from './paypal.plugins' ;
2020-08-24 01:55:50 +00:00
import { PayPalTransaction } from './paypal.classes.transaction' ;
2020-08-21 15:40:04 +00:00
export interface IPayPalOptions {
clientId : string ;
clientSecret : string ;
2020-08-25 11:57:03 +00:00
accountOwner : string ;
2020-08-21 15:40:04 +00:00
}
2020-08-23 15:35:28 +00:00
export class PayPalAccount {
2020-08-25 11:57:03 +00:00
public apiBaseUrl : string = 'https://api.paypal.com' ;
2020-08-21 15:40:04 +00:00
public options : IPayPalOptions ;
private apiToken : string ;
private apiTokenExpirationTime : number ;
constructor ( optionsArg : IPayPalOptions ) {
this . options = optionsArg ;
}
2020-08-25 11:57:03 +00:00
public async getTransactionsFromTo ( fromTimeMillisArg : number , toTimeMillisArg : number ) {
let allTransactions : PayPalTransaction [ ] = [ ] ;
// lets note the time from one month before. We need that for accurate transactions pools.
const monthBeforeStartMillis =
fromTimeMillisArg - plugins . smarttime . getMilliSecondsFromUnits ( { days : 30 } ) ;
2020-08-24 01:55:50 +00:00
do {
const transactions = await PayPalTransaction . getTransactionFor30days ( this , fromTimeMillisArg ) ;
2020-08-25 11:57:03 +00:00
allTransactions = allTransactions . concat ( transactions ) ;
fromTimeMillisArg =
fromTimeMillisArg + plugins . smarttime . getMilliSecondsFromUnits ( { days : 30 } ) ;
2020-08-24 01:55:50 +00:00
} while ( fromTimeMillisArg < toTimeMillisArg ) ;
2020-08-25 11:57:03 +00:00
const invoiceIds : string [ ] = [ ] ;
const transactionPools : PayPalTransaction [ ] [ ] = [ ] ;
// lets get all invoiceids
allTransactions . forEach ( ( transactionArg ) = > {
const invoiceId = transactionArg . data . originApiObject . transaction_info . invoice_id ;
if ( ! invoiceIds . includes ( invoiceId ) ) {
invoiceIds . push ( invoiceId ) ;
}
} ) ;
// lets get all transactions per invoiceId
invoiceIds . forEach ( ( invoiceIdArg ) = > {
const transactionPool : PayPalTransaction [ ] = [ ] ;
allTransactions . forEach ( ( transactionArg ) = > {
if ( transactionArg . data . originApiObject . transaction_info . invoice_id === invoiceIdArg ) {
transactionPool . push ( transactionArg ) ;
}
} ) ;
transactionPools . push ( transactionPool ) ;
} ) ;
const previousMonthTransactions = await PayPalTransaction . getTransactionFor30days (
this ,
monthBeforeStartMillis
) ;
transactionPools . forEach ( ( transactionPoolArg ) = > {
const poolInvoiceId = transactionPoolArg [ 0 ] . data . originApiObject . transaction_info . invoice_id ;
previousMonthTransactions . forEach ( ( transactionArg ) = > {
if ( transactionArg . data . originApiObject . transaction_info . invoice_id === poolInvoiceId ) {
transactionPoolArg . push ( transactionArg ) ;
}
} ) ;
} ) ;
let finalTransactions : PayPalTransaction [ ] = [ ] ;
// lets process all transactionPool
transactionPools . forEach ( ( transactionPoolArg ) = > {
// lets detect foreign transactions
let hasForeignTransactions = false ;
transactionPoolArg . forEach ( ( transactionArg ) = > {
if ( transactionArg . data . currency !== 'EUR' ) {
hasForeignTransactions = true ;
}
} ) ;
if ( hasForeignTransactions && transactionPoolArg . length < 4 ) {
console . log (
` Pool with invoiceId ${ transactionPoolArg [ 0 ] . data . originApiObject . transaction_info . invoice_id } is not completed yet. Omminiting ${ transactionPoolArg . length } transactions as a result. `
) ;
return ;
}
if ( hasForeignTransactions && transactionPoolArg . length === 4 ) {
const negativeNativeTransaction = transactionPoolArg . find ( transactionArg = > {
return transactionArg . data . amount < 0 && transactionArg . data . currency === 'EUR' ;
} ) ;
const negativeForeignTransaction = transactionPoolArg . find ( transactionArg = > {
return transactionArg . data . amount < 0 && transactionArg . data . currency !== 'EUR' ;
} ) ;
const positiveNativeTransaction = transactionPoolArg . find ( transactionArg = > {
return transactionArg . data . amount > 0 && transactionArg . data . currency === 'EUR' ;
} ) ;
const positiveForeignTransaction = transactionPoolArg . find ( transactionArg = > {
return transactionArg . data . amount > 0 && transactionArg . data . currency !== 'EUR' ;
} ) ;
negativeNativeTransaction . data . name = negativeForeignTransaction . data . name ;
negativeNativeTransaction . data . description = negativeForeignTransaction . data . description ;
positiveNativeTransaction . data . name = this . options . accountOwner ;
positiveNativeTransaction . data . description = 'account balance transfer' ;
transactionPoolArg = transactionPoolArg . filter ( transactionArg = > transactionArg . data . currency === 'EUR' ) ;
}
if ( ! hasForeignTransactions && transactionPoolArg . length === 2 ) {
const positiveNativeTransaction = transactionPoolArg . find ( transactionArg = > {
return transactionArg . data . amount > 0 && transactionArg . data . currency === 'EUR' ;
} ) ;
positiveNativeTransaction . data . name = this . options . accountOwner ;
positiveNativeTransaction . data . description = 'account balance transfer' ;
}
// pool is ready
finalTransactions = finalTransactions . concat ( transactionPoolArg ) ;
} ) ;
return finalTransactions ;
2020-08-24 01:55:50 +00:00
}
2020-08-23 13:33:19 +00:00
public async request ( methodArg : 'GET' | 'POST' , routeArg : string , payloadArg : any ) {
2020-08-21 15:40:04 +00:00
if ( ! this . apiToken || this . apiTokenExpirationTime < Date . now ( ) ) {
const authHeader = ` Basic ${ plugins . smartstring . base64 . encode (
` ${ this . options . clientId } : ${ this . options . clientSecret } `
) } ` ;
const response = await plugins . smartrequest . request (
` ${ this . apiBaseUrl } /v1/oauth2/token?grant_type=client_credentials ` ,
{
method : 'POST' ,
headers : {
Accept : 'application/json' ,
'Accept-Language' : 'en_US' ,
Authorization : authHeader ,
} ,
keepAlive : false ,
}
) ;
this . apiToken = response . body . access_token ;
this . apiTokenExpirationTime = Date . now ( ) + response . body . expires_in * 1000 - 600000 ;
}
// we have a token
2020-08-23 13:33:19 +00:00
const response = await plugins . smartrequest . request ( ` ${ this . apiBaseUrl } ${ routeArg } ` , {
2020-08-21 15:40:04 +00:00
method : 'GET' ,
headers : {
Accept : 'application/json' ,
'Accept-Language' : 'en_US' ,
Authorization : ` Bearer ${ this . apiToken } ` ,
} ,
} ) ;
2020-08-23 13:33:19 +00:00
return response . body ;
2020-08-21 15:40:04 +00:00
}
}