Skip to content

Commit

Permalink
Merge pull request #28 from xendit/TPI-7930/whcms-delayed-to-update-w…
Browse files Browse the repository at this point in the history
…ebhook-status

Update WHMCS order status when customer redirected to success_redirect_url
  • Loading branch information
andykim authored Aug 24, 2022
2 parents 669e6c0 + f5e6206 commit b38dcfe
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 161 deletions.
14 changes: 7 additions & 7 deletions modules/gateways/callback/xendit.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
require_once __DIR__ . '/../../../includes/invoicefunctions.php';
require_once __DIR__ . '/../xendit/autoload.php';

use Xendit\Lib\Callback;
use Xendit\Lib\Webhook;
use Xendit\Lib\CreditCard;
use Xendit\Lib\XenditRequest;

$callback = new Callback();
$webhook = new Webhook();
$creditCard = new CreditCard();
$xenditRequest = new XenditRequest();

Expand Down Expand Up @@ -106,25 +106,25 @@
);
}
} else {
// use for callback
// use for webhook
$arrRequestInput = json_decode(file_get_contents("php://input"), true);
if (!empty($arrRequestInput) && isset($arrRequestInput['external_id']) && !empty($arrRequestInput['external_id'])) {
$invoiceId = $callback->getInvoiceIdFromExternalId($arrRequestInput['external_id']);
$transactions = $callback->getTransactionFromInvoiceId($invoiceId);
$invoiceId = $webhook->getInvoiceIdFromExternalId($arrRequestInput['external_id']);
$transactions = $webhook->getTransactionFromInvoiceId($invoiceId);

try {
// Get invoice from Xendit
$xenditInvoice = $xenditRequest->getInvoiceById($arrRequestInput['id']);
if (isset($arrRequestInput['credit_card_token'])) {
$xenditInvoice['credit_card_token'] = $arrRequestInput['credit_card_token'];
}
$result = $callback->confirmInvoice(
$result = $webhook->confirmInvoice(
$invoiceId,
$xenditInvoice,
$xenditInvoice["status"] == "PAID" || $xenditInvoice["status"] == "SETTLED"
);
if ($result) {
$callback->updateTransactions($transactions);
$webhook->updateTransactions($transactions);
echo 'Success';
exit;
}
Expand Down
12 changes: 6 additions & 6 deletions modules/gateways/xendit.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@

require __DIR__ . '/xendit/autoload.php';

// defines
define('XENDIT_PAYMENT_GATEWAY_VERSION', '1.0.9');
// Module version
const XENDIT_PAYMENT_GATEWAY_VERSION = '1.1.0';

use WHMCS\Billing\Invoice;
use Xendit\Lib\ActionBase;
use Xendit\Lib\CreditCard;
use Xendit\Lib\Link;
use Xendit\Lib\PaymentLink;
use Xendit\Lib\Model\XenditTransaction;
use Xendit\Lib\Recurring;
use Xendit\Lib\XenditRequest;
Expand Down Expand Up @@ -73,11 +73,11 @@ function xendit_deactivate()
*/
function xendit_link($params)
{
$link = new Link();
$paymentLink = new PaymentLink();
try {
return $link->generatePaymentLink($params);
return $paymentLink->generatePaymentLink($params);
} catch (\Exception $e) {
return $link->errorMessage($e->getMessage());
return $paymentLink->errorMessage($e->getMessage());
}
}

Expand Down
90 changes: 0 additions & 90 deletions modules/gateways/xendit/lib/ActionBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,83 +219,6 @@ public function extractPaidAmount($xenditTotal, $whmcsTotal): float
return $decimalAmount > 0 && $decimalAmount < 1 ? (float)$whmcsTotal : (float)$xenditTotal;
}

/**
* @param int $invoiceId
* @param array $xenditInvoiceData
* @param bool $success
* @return bool
* @throws \Exception
*/
public function confirmInvoice(int $invoiceId, array $xenditInvoiceData, bool $success = true): bool
{
try {
if (!$success) {
return false;
}

/*
* Verify the invoice need to update is correct
* Avoid update wrong WHMCS invoice
*/
if ($invoiceId != $this->getInvoiceIdFromExternalId($xenditInvoiceData['external_id'])) {
throw new \Exception('Invoice id is incorrect!');
}

// Load WHMCS invoice
$invoice = $this->getInvoice($invoiceId);

$transactionId = $xenditInvoiceData['id'];
$paymentAmount = $this->extractPaidAmount($xenditInvoiceData['paid_amount'], $invoice->total);
$paymentFee = $xenditInvoiceData['fees'][0]["value"];
$transactionStatus = 'Success';

// Save credit card token
if (isset($xenditInvoiceData['credit_card_charge_id']) && isset($xenditInvoiceData['credit_card_token'])) {
$cardInfo = $this->xenditRequest->getCardInfo($xenditInvoiceData['credit_card_charge_id']);
$cardExpired = $this->xenditRequest->getCardTokenInfo($xenditInvoiceData['credit_card_token']);

if (!empty($cardInfo) && !empty($cardExpired)) {
$lastDigit = substr($cardInfo["masked_card_number"], -4);
invoiceSaveRemoteCard(
$invoiceId,
$lastDigit,
$cardInfo["card_brand"],
sprintf("%s/%s", $cardExpired["card_expiration_month"], $cardExpired["card_expiration_year"]),
$xenditInvoiceData['credit_card_token']
);
}
}

$invoiceId = checkCbInvoiceID($invoiceId, $this->getDomainName());
checkCbTransID($transactionId);

addInvoicePayment(
$invoiceId,
$transactionId,
$paymentAmount,
$paymentFee,
$this->getDomainName()
);

// Save payment method
$transactions = $this->getTransactionFromInvoiceId($invoiceId);
if (!empty($transactions)) {
$this->updateTransactions(
$transactions,
[
"status" => XenditTransaction::STATUS_PAID,
"payment_method" => $xenditInvoiceData["payment_method"]
]
);
}

logTransaction($this->getDomainName(), $_POST, $transactionStatus);
return true;
} catch (\Exception $exception) {
throw new \Exception($exception->getMessage());
}
}

/**
* @param int $invoiceId
* @return mixed
Expand All @@ -305,19 +228,6 @@ public function getRecurringBillingInfo(int $invoiceId)
return getRecurringBillingValues($invoiceId);
}

/**
* @param int $invoiceId
* @return bool
*/
public function isRecurring(int $invoiceId): bool
{
$recurringData = $this->getRecurringBillingInfo($invoiceId);
if (!isset($recurringData["firstpaymentamount"]) && !isset($recurringData['firstcycleperiod'])) {
return true;
}
return false;
}

/**
* @param float $total
* @return float
Expand Down
15 changes: 0 additions & 15 deletions modules/gateways/xendit/lib/Callback.php

This file was deleted.

2 changes: 1 addition & 1 deletion modules/gateways/xendit/lib/CreditCard.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public function generateCCPaymentRequest(array $params = [], int $auth_id = null
"should_charge_multiple_use_token" => true
];

if(!empty($billingDetailObject)){
if (!empty($billingDetailObject)) {
$payload['billing_details'] = $billingDetailObject;
}
if (!empty($auth_id)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Xendit\Lib\Model\XenditTransaction;

class Link extends ActionBase
class PaymentLink extends ActionBase
{
/** @var string $callbackUrl */
protected $callbackUrl = 'modules/gateways/callback/xendit.php';
Expand Down Expand Up @@ -32,7 +32,7 @@ protected function generateInvoicePayload(array $params, bool $retry = false): a
'should_charge_multiple_use_token' => true
];

if(!empty($customerObject)){
if (!empty($customerObject)) {
$payload['customer'] = $customerObject;
}

Expand Down Expand Up @@ -136,6 +136,69 @@ protected function generateFormParam(array $params, string $invoiceUrl): string
return $htmlOutput;
}

/**
* @param array $params
* @param $transactions
* @param bool $isForced
* @return false|string
* @throws \Exception
*/
protected function createXenditInvoice(array $params, $transactions, bool $isForced = false)
{
try {
$payload = $this->generateInvoicePayload($params, $isForced);
$xenditInvoice = $this->xenditRequest->createInvoice($payload);
$this->updateTransactions(
$transactions,
[
'transactionid' => $xenditInvoice["id"],
'status' => XenditTransaction::STATUS_PENDING,
'external_id' => $payload["external_id"]
]
);
return $xenditInvoice;
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}

/**
* @param array $params
* @param array $xenditInvoice
* @param $transactions
* @return string|null
* @throws \Exception
*/
protected function updateInvoiceStatus(array $params, array $xenditInvoice, $transactions)
{
if (empty($xenditInvoice)) {
throw new \Exception('Xendit invoice not found.');
}

try {
$xenditInvoiceStatus = $xenditInvoice['status'] ?? '';
switch ($xenditInvoiceStatus) {
case 'PAID':
case 'SETTLED':
$webhook = new \Xendit\Lib\Webhook();
$confirmed = $webhook->confirmInvoice($params['invoiceid'], $xenditInvoice);
if (!$confirmed) {
throw new \Exception('Cannot update invoice status.');
}
return $this->redirectUrl($xenditInvoice['success_redirect_url']);

case 'EXPIRED':
$this->updateTransactions($transactions, ['status' => XenditTransaction::STATUS_EXPIRED]);
return $this->generatePaymentLink($params, true);

default:
return $this->generateFormParam($params, $xenditInvoice['invoice_url']);
}
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}

/**
* @param array $params
* @param bool $force
Expand All @@ -149,24 +212,13 @@ public function generatePaymentLink(array $params, bool $force = false): string
return false;
}

// Get transaction
// Get transactions by WHMCS invoice
$transactions = $this->getTransactionFromInvoiceId($params["invoiceid"]);

// If force create new invoice
// Create a new Xendit invoice in case the previous invoice is EXPIRED
if ($force) {
$payload = $this->generateInvoicePayload($params, true);
$createInvoice = $this->xenditRequest->createInvoice($payload);
$url = $createInvoice['invoice_url'];

$this->updateTransactions(
$transactions,
[
'transactionid' => $createInvoice["id"],
'status' => XenditTransaction::STATUS_PENDING,
'external_id' => $payload["external_id"]
]
);
return $this->generateFormParam($params, $url);
$xenditInvoice = $this->createXenditInvoice($params, $transactions, true);
return $this->generateFormParam($params, $xenditInvoice['invoice_url']);
}

// Get Xendit Invoice by transaction (Xendit invoice_id)
Expand All @@ -175,28 +227,16 @@ public function generatePaymentLink(array $params, bool $force = false): string
$xenditInvoice = $this->xenditRequest->getInvoiceById($transactions[0]->transactionid);
}

// Check xendit invoice status
/*
* Check if Xendit invoice exists then update WHMCS invoice status
*/
if (!empty($xenditInvoice)) {
if ($xenditInvoice['status'] == "EXPIRED") {
$this->updateTransactions($transactions, ['status' => XenditTransaction::STATUS_EXPIRED]);
return $this->generatePaymentLink($params, true);
} else {
$url = $xenditInvoice['invoice_url'];
}
} else {
$createInvoice = $this->xenditRequest->createInvoice(
$this->generateInvoicePayload($params)
);
$url = $createInvoice['invoice_url'];
$this->updateTransactions(
$transactions,
[
'transactionid' => $createInvoice["id"],
'status' => XenditTransaction::STATUS_PENDING
]
);
return $this->updateInvoiceStatus($params, $xenditInvoice, $transactions);
}
return $this->generateFormParam($params, $url);

// If Xendit invoice does not exist, create a new Xendit invoice
$xenditInvoice = $this->createXenditInvoice($params, $transactions);
return $this->generateFormParam($params, $xenditInvoice['invoice_url']);
} catch (\Exception $e) {
/*
* If currency is error
Expand Down
Loading

0 comments on commit b38dcfe

Please sign in to comment.