import paypal from '@paypal/checkout-server-sdk' ;
import assert from "assert" ;
import { paypal _private } from "../lib/config.js" ;
import { Product , Payment } from "../lib/models.js" ;
import { product _id } from "../client/config.js" ;
import logging from "../lib/logging.js" ;
import { developer _admin } from "../lib/api.js" ;
const log = logging . create ( "queue/paypal.js" ) ;
const create _paypal = ( ) => {
if ( developer _admin ) {
log . warn ( "Running in DANGER_ADMIN mode so using the Sandbox for Paypal." ) ;
const environment = new paypal . core . SandboxEnvironment ( paypal _private . client _id , paypal _private . secret ) ;
const client = new paypal . core . PayPalHttpClient ( environment ) ;
return [ environment , client ] ;
} else {
const environment = new paypal . core . LiveEnvironment ( paypal _private . client _id , paypal _private . secret ) ;
const client = new paypal . core . PayPalHttpClient ( environment ) ;
return [ environment , client ] ;
}
}
const [ environment , client ] = create _paypal ( ) ;
const order _is _valid = ( course , response , payment ) => {
let order = response . result . purchase _units [ 0 ] ;
assert ( course . id , "Product is invalid in order_is_valid check." ) ;
assert ( payment . id , "Payment is invalid in order_is_valid check." ) ;
if ( ! order ) {
log . error ( ` Invalid response payment ${ payment . id } , no order in the purchase_units. ` ) ;
return [ false , "invalid_purchase_units" ] ;
} else if ( parseInt ( order . amount . value , 10 ) !== course . price ) {
// BUG: this will fail if you use a float for the price
log . error ( ` Wrong price ${ order . amount . value } ` ) ;
return [ false , "invalid_order_amount" ] ;
} else if ( order . payments . captures . length < 1 ) {
log . error ( "Not enough captures, only 0." ) ;
return [ false , "invalid_capture_count" ] ;
} else if ( order . payments . captures [ 0 ] . status !== "COMPLETED" ) {
log . error ( ` Capture not completed: ${ order . payments . captures . status } ` ) ;
return [ false , "capture_not_completed" ] ;
} else if ( parseInt ( order . payments . captures [ 0 ] . amount . value , 10 ) !== course . price ) {
console . error ( ` Capture amount ${ order . payments . captures [ 0 ] . amount . value } doesn't match course price ${ course . price } ` ) ;
return [ false , "capture_price_mismatch" ] ;
} else {
return [ true , "validated" ] ;
}
}
export const validate _order = async ( job ) => {
try {
assert ( job . data . payment _id , ` Invalid order ID: ${ JSON . stringify ( job ) } ` ) ;
const course = await Product . first ( { id : product _id } ) ;
assert ( course , ` No course for ID ${ product _id } from client/config.js:product_id ` ) ;
const payment = await Payment . first ( { id : job . data . payment _id } ) ;
assert ( payment , ` No payment for ID ${ job . payment _id } ` ) ;
let request = new paypal . orders . OrdersGetRequest ( payment . sys _primary _id ) ;
// Call API with your client and get a response for your call
let response = await client . execute ( request ) ;
log . debug ( ` Validating Paypal ID ${ response . result . id } ` ) ;
const [ valid , status _reason ] = order _is _valid ( course , response , payment ) ;
if ( valid ) {
log . info ( ` Order for payment ${ payment . id } is validated. ` ) ;
await Payment . update ( { id : payment . id } , { status : "complete" , status _reason } ) ;
} else {
log . error ( ` Invalid Order for payment ${ payment . id } . ` ) ;
await Payment . update ( { id : payment . id } , { status : "failed" , status _reason } ) ;
}
} catch ( error ) {
log . error ( error , ` Processing payment paypal verification for ${ job . data . payment _id } ` ) ;
try {
await Payment . update ( { id : job . data . payment _id } , { status : "failed" , status _reason : "check_logs" } ) ;
} catch ( e ) {
log . error ( error , ` Failed to update the database with failure on payment id ${ job . data . payment _id } ` ) ;
}
}
}