Professional Documents
Culture Documents
Credit Record Processing - v3
Credit Record Processing - v3
Credit Record Processing - v3
When dealing with System to Instructor payments there are two types of systems involved:
Database
External Payment Gateway
These two systems are not coordinated and they do not participate in distributed transaction. Under
such circumstances we can have situation where money were transferred to target Instructor account
(PayPal) but the database tracking records were not updated. For example, Instructor Course CREDIT
Transaction was not updated as completed due to intermittent database failure. In this unhappy
scenario, the same CREDIT Instructor Course Transaction will be reprocessed and the same amount will
be transferred to the Instructor account (which is not desirable at all).
In order to deal with such scenario we shall process CREDIT transactions by separating the logic into
multiple successive database transactions. Before trying to pay with PayPal (or another payment
gateway), we must set the Instructor Course Transaction status to PROCESSING. After PayPal payment
operation has been finished the Instructor Course Transaction’s status shall be updated accordingly.
However if something unexpected happens and Instructor Course transaction remains in PROCESSING
state, we must always check with PayPal, based on the Payment’s Reference Id if that payment
succeeded or not.
Before processing Instructor Course instructions in INITIALIZED state, the system must check and
sanitize ALL CREDIT Instructor Course Transactions left in PROCESSING state because of:
This is system undetermined state and we need to query the payment gateway and check the status of
the payment (by its reference id or additional tokens).
If the system finds some Instructor Course transactions as completed, the credit process for those
transactions will be completed (amount deduced from Instructor Course and the statuses will be set to
COMPLETED). If some Instructor Course transactions were not completed at Pay Pal side, they will be re-
initialized for repetition by setting their status to INITIALIZED.
Algorithm CHECK_CREDIT_RECORD
BOOLEAN FUNCTION CHECK_CREDIT_RECORD
INPUT:
PaymentGatewayUnavailableMap
BEGIN
BEGIN TRANSACTION
InstructorCourse=LOAD_INSTRUCTOR_COURSE
END TRANSACTION
IF PaymentGatewayUnavailableMap[Payment.PaymentGatewayType]=TRUE THEN
RETURN FALSE
END IF
PaymentTransaction=NULL
TRY
PaymentTransaction =CHECK_PAYMENT_STATUS(ReferenceId)
CATCH EXCEPTION
PaymentGatewayUnavailableMap[Payment.PaymentGatewayType]=TRUE
RETURN FALSE
END CATCH
IF PaymentTransaction.COMPLETED
BEGIN TRANSACTION
//use HQL
UPDATE InstructorCourse
SET Amount=Amount-TransferAmount
//use HQL
UPDATE Payment
SET Status=COMPLETED
SET ExternalPaymentGatewayId= PaymentTransaction.TransactionId
//use HQL
UPDATE InstructorCourseTransaction
SET Status=COMPLETED
END TRANSACTION
ELSE
PAYMENT_ERROR_LOG:
Payment Id
Payment Reference Id Type
Payment Reference Id
PaymentTransaction.Status
PaymentTransaction.TransactionId
PaymentTransaction.Message
Action=NOTIFICATION
BEGIN TRANSACTION
//use HQL
UPDATE InstructorCourseTransaction
SET Status=INITIALIZED
//use HQL
UPDATE Payment
SET Status=CANCELED
END TRANSACTION
END IF
RETURN TRUE
END FUNCTION
Note: All exceptions thrown from the CHECK_PAYMENT_STATUS function will mark the Payment
Gateway as temporary unavailable. The function in that case returns FALSE which is Boolean marker for
(pending) postponed processing.
Algorithm CREDIT_RECORD
BOOLEAN FUNCTION CREDIT_RECORD
INPUT:
InstructorCourseTransaction
PaymentGatewayUnavailableMap
BEGIN
InstructorCourse= NULL
PaymentGateway =NULL
BEGIN TRANSACTION
PaymentGateway=OBTAIN_PAYMENT_GATEWAY_FOR_THE_INSTRUCTOR
END TRANSACTION
IF PaymentGateway IS NULL
//this is the case when instructor does not have valid payment gateway account
BEGIN TRANSACTION
UPDATE InstructorCourseTransaction
END TRANSACTION
RETURN TRUE
END IF
IF PaymentGatewayUnavailableMap[PaymentGateway.Type]=TRUE THEN
RETURN FALSE;
END IF
InstructorCourse=LOAD_INSTRUCTOR_COURSE
Amount=InstructorCourse.AccruedAmmount
MaxAmount=PaymentGateway.maxTransferAmount
MinAmount=PaymentGateway.minTransferAmount
CurrentInstructorCourseTransaction=InstructorCourseTransaction
CurrentPayment=NULL
IF (Amount<=0) THEN
BEGIN TRANSACTION
UPDATE InstructorCourseTransaction
END TRANSACTION
RETURN TRUE
END IF
IF (Amount>MaxAmount)
TransferAmount=MaxAmount
ELSE
TransferAmount=Amount
END IF
Amount=Amount-TransferAmount
IF (TransferAmount <MinAmount)
BEGIN TRANSACTION
UPDATE CurrentInstructorCourseTransaction
SET Amount=TransferAmount
SET Status=CANCELED
END TRANSACTION
END IF
BREAK
END IF
BEGIN TRANSACTION
CurrentPayment= GENERATE_PAYMENT
SET Amount=TransferAmount
SET ReferenceIdType=’IC’
SET Status=PROCESSING
IF CurrentInstructorCourseTransaction IS NULL
CurrentInstructorCourseTransaction=GENERATE_INSTRUCTOR_COURSE_INSTRUCTION
ELSE
//use HQL
UPDATE CurrentInstructorCourseTransaction
SET Amount=TransferAmount
SET Payment=CurrentPayment
SET Status=PROCESSING
END IF
END TRANSACTION
//the payment reference id used must be proper concatenation of the current
//payment attributes: IC_REFERENCE_ID_TIMESTAMP
PaymentTransaction=NULL
TRY
PaymentTransaction =PAY_WITH_EXTERNAL_PAYMENT_GATEWAY
CATCH EXCEPTION
PaymentGatewayUnavailableMap[PaymentGateway.Type]=TRUE
RETURN FALSE
END CATCH
IF PaymentTransaction.COMPLETED
BEGIN TRANSACTION
//use HQL
UPDATE InstructorCourse
SET Amount=Amount-TransferAmount
//use HQL
UPDATE CurrentPayment
SET Status=COMPLETED
SET ExternalPaymentGatewayId= PaymentTransaction.TransactionId
//use HQL
UPDATE CurrentInstructorCourseTransaction
SET Status=COMPLETED
END TRANSACTION
ELSE
PAYMENT_ERROR_LOG:
Payment Id
Payment Reference Id
PaymentTransaction.Status
PaymentTransaction.TransactionId
PaymentTransaction.Message
Action=NOTIFICATION
BEGIN TRANSACTION
//use HQL
UPDATE CurrentInstructorCourseTransaction
SET Status=CANCELED
//use HQL
UPDATE CurrentPayment
SET Status=CANCELED
END TRANSACTION
END IF
CurrentInstructorCourseTransaction=NULL
END WHILE
RETURN TRUE
END FUNCTION
The scheduled procedure for processing Instructor Course Transaction is the following:
PROCEDURE PROCESS_INSTRUCTOR_COURSE_TRANSACTIONS
BEGIN
CommittedId=-1
TempId=CommitedId
PendingDate=NULL
PaymentGatewayUnavailableMap=[] //empty map
WHILE TRUE
IF (TempId=-1 OR
PendingDate=NULL
TempId=CommitedId
PaymentGatewayUnavailableMap=[]
Success=CHECK_CREDIT_RECORD(
InstructorCourseTransaction,
PaymentGatewayUnavailableMap)
PendingDate=CurrentDate
IF COUNT(PaymentGateways)=COUNT(PaymentGatewayUnavailableMap) THEN
RETURN
END IF
END IF
END FOR
END IF
InstructorCourseTransactions=
ORDER BY Id LIMIT N
RETURN
END IF
TempId=InstructorCourseTransaction.Id
DEBIT_RECORD (InstructorCourseTransaction)
ELSE
Success= CREDIT_RECORD(
InstructorCourseTransaction,
PaymentGatewayUnavailableMap)
PendingDate=CurrentDate
IF COUNT(PaymentGateways)=COUNT(PaymentGatewayUnavailableMap) THEN
RETURN
END IF
END IF
END
END FOR
IF PendingDate=NULL THEN
CommitedId=TempId
END IF
END WHILE
END PROCEDURE
The billing process is created once in a month. Its first state is INITIALIZED. Once all CREDIT Instructor
Course transaction are generated its state shall go into SUBMITTED.
The whole billing process shall follow the steps outlined below.
PROCEDURE BILL
IF
AND
//from this moment on, the system can generate another billing process
END IF
END IF
END IF
END IF
END PROCEDURE