Skip to content

Commit

Permalink
Merge pull request #39 from xendit/bugfix/multishipping
Browse files Browse the repository at this point in the history
Bugfix/multishipping
  • Loading branch information
IreneGohtami authored Jun 11, 2020
2 parents a3968d2 + aa6ddcd commit b2eafce
Show file tree
Hide file tree
Showing 13 changed files with 132 additions and 64 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# CHANGELOG

## 2.0.1 (2020-06-11)

Bugfix:

- Support order ID with prefix (single and multishipping)
- Fix OVO callback for single checkout

## 2.0.0 (2020-06-01)

Features:
Expand Down
33 changes: 18 additions & 15 deletions Xendit/M2Invoice/Controller/Checkout/CCMultishipping.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public function execute()
$orderIds = explode("-", $rawOrderIds);

$transactionAmount = 0;
$incrementIds = [];
$tokenId = '';
$orders = [];

Expand All @@ -41,42 +40,40 @@ public function execute()
}

$transactionAmount += (int)$order->getTotalDue();
$incrementIds[] = $order->getIncrementId();
}

if ($method === 'cc') {
$externalIdSuffix = implode("-", $incrementIds);
$requestData = array(
'token_id' => $tokenId,
'card_cvn' => $cvn,
'amount' => $transactionAmount,
'external_id' => $this->getDataHelper()->getExternalId($externalIdSuffix),
'return_url' => $this->getDataHelper()->getThreeDSResultUrl($externalIdSuffix)
'external_id' => $this->getDataHelper()->getExternalId($rawOrderIds),
'return_url' => $this->getDataHelper()->getThreeDSResultUrl($rawOrderIds, true)
);

$charge = $this->requestCharge($requestData);

$chargeError = isset($charge['error_code']) ? $charge['error_code'] : null;
if ($chargeError == 'EXTERNAL_ID_ALREADY_USED_ERROR') {
$newRequestData = array_replace($requestData, array(
'external_id' => $this->getDataHelper()->getExternalId($externalIdSuffix, true)
'external_id' => $this->getDataHelper()->getExternalId($rawOrderIds, true)
));
$charge = $this->requestCharge($newRequestData);
}

$chargeError = isset($charge['error_code']) ? $charge['error_code'] : null;
if ($chargeError == 'AUTHENTICATION_ID_MISSING_ERROR') {
return $this->handle3DSFlow($requestData, $payment, $incrementIds, $orders);
return $this->handle3DSFlow($requestData, $payment, $orderIds, $orders);
}

if ($chargeError !== null) {
return $this->processFailedPayment($incrementIds, $chargeError);
return $this->processFailedPayment($orderIds, $chargeError);
}

if ($charge['status'] === 'CAPTURED') {
return $this->processSuccessfulPayment($orders, $payment, $charge);
} else {
return $this->processFailedPayment($incrementIds, $charge['failure_reason']);
return $this->processFailedPayment($orderIds, $charge['failure_reason']);
}
}
else if ($method === 'cchosted') {
Expand All @@ -87,7 +84,7 @@ public function execute()
'store_name' => $this->getStoreManager()->getStore()->getName(),
'platform_name' => 'MAGENTO2',
'success_redirect_url' => $this->getDataHelper()->getSuccessUrl(true),
'failure_redirect_url' => $this->getDataHelper()->getFailureUrl($rawOrderIds),
'failure_redirect_url' => $this->getDataHelper()->getFailureUrl($rawOrderIds, true),
'platform_callback_url' => $this->_url->getUrl('xendit/checkout/cccallback') . '?order_ids=' . $rawOrderIds
];

Expand All @@ -96,7 +93,7 @@ public function execute()
if (isset($hostedPayment['error_code'])) {
$message = isset($hostedPayment['message']) ? $hostedPayment['message'] : $hostedPayment['error_code'];

return $this->processFailedPayment($incrementIds, $message);
return $this->processFailedPayment($orderIds, $message);
} else if (isset($hostedPayment['id'])) {
$hostedPaymentId = $hostedPayment['id'];
$hostedPaymentToken = $hostedPayment['hp_token'];
Expand All @@ -112,7 +109,7 @@ public function execute()
} else {
$message = 'Error connecting to Xendit. Please check your API key.';

return $this->processFailedPayment($incrementIds, $message);
return $this->processFailedPayment($orderIds, $message);
}
}
} catch (\Exception $e) {
Expand Down Expand Up @@ -163,6 +160,9 @@ private function addCCHostedData($orders, $data)
}
}

/**
* $orderIds = prefixless order IDs
*/
private function handle3DSFlow($requestData, $payment, $orderIds, $orders)
{
unset($requestData['card_cvn']);
Expand All @@ -183,9 +183,9 @@ private function handle3DSFlow($requestData, $payment, $orderIds, $orders)
$payment->setAdditionalInformation('xendit_hosted_3ds_id', $hostedId);

foreach ($orderIds as $key => $value) {
$order = $this->getOrderById($value);

$order->addStatusHistoryComment("Xendit payment waiting for authentication. 3DS id: $hostedId");
$order = $this->getOrderFactory()->create();
$order->load($value);
$order->addStatusHistoryComment("Xendit payment waiting for authentication. 3DS ID: $hostedId");
$order->save();
}

Expand All @@ -210,6 +210,9 @@ private function handle3DSFlow($requestData, $payment, $orderIds, $orders)
return $this->processFailedPayment($orderIds);
}

/**
* $orderIds = prefixless order IDs
*/
private function processFailedPayment($orderIds, $failureReason = 'Unexpected Error with empty charge')
{
$this->getCheckoutHelper()->processOrdersFailedPayment($orderIds, $failureReason);
Expand Down
5 changes: 3 additions & 2 deletions Xendit/M2Invoice/Controller/Checkout/Failure.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ class Failure extends AbstractAction {
public function execute()
{
$orderIds = explode('-', $this->getRequest()->get('order_id'));
$type = $this->getRequest()->get('type');

if (count($orderIds) > 1) { //multishipping
if ($type == 'multishipping') {
foreach ($orderIds as $orderId) {
$order = $this->getOrderFactory()->create();
$order ->load($orderId);
Expand All @@ -23,7 +24,7 @@ public function execute()
}
}
} else { //onepage
$order = $this->getOrderById($orderIds[0]);
$order = $this->getOrderById($this->getRequest()->get('order_id'));

if ($order) {
$this->getLogger()->debug('Requested order cancelled by customer. OrderId: ' . $order->getIncrementId());
Expand Down
2 changes: 1 addition & 1 deletion Xendit/M2Invoice/Controller/Checkout/Invoice.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ private function getApiRequestData($order)
return;
}

$orderId = $order->getRealOrderId();
$orderId = $order->getEntityId();
$preferredMethod = $this->getRequest()->getParam('preferred_method');

$requestData = [
Expand Down
9 changes: 3 additions & 6 deletions Xendit/M2Invoice/Controller/Checkout/InvoiceMultishipping.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ public function execute()
$orderIds = explode("-", $rawOrderIds);

$transactionAmount = 0;
$incrementIds = [];

$orders = [];
foreach ($orderIds as $key => $value) {
Expand All @@ -33,17 +32,15 @@ public function execute()
$order->save();

$transactionAmount += (int)$order->getTotalDue();
$incrementIds[] = $order->getIncrementId();
}

$externalIdSuffix = implode("-", $incrementIds);
$preferredMethod = $this->getRequest()->getParam('preferred_method');
$requestData = [
'success_redirect_url' => $this->getDataHelper()->getSuccessUrl(true),
'failure_redirect_url' => $this->getDataHelper()->getFailureUrl($rawOrderIds),
'failure_redirect_url' => $this->getDataHelper()->getFailureUrl($rawOrderIds, true),
'amount' => $transactionAmount,
'external_id' => $this->getDataHelper()->getExternalId($externalIdSuffix),
'description' => $externalIdSuffix,
'external_id' => $this->getDataHelper()->getExternalId($rawOrderIds),
'description' => $rawOrderIds,
'payer_email' => $billingEmail,
'preferred_method' => $preferredMethod,
'should_send_email' => "true",
Expand Down
22 changes: 16 additions & 6 deletions Xendit/M2Invoice/Controller/Checkout/Notification.m22.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,26 @@ public function execute()
return $result;
}

$orderId = $decodedPost['description'];
$transactionId = $decodedPost['id'];
$orderIds = explode("-", $orderId);

$isMultishipping = (count($orderIds) > 1) ? true : false;
if ($isEwallet) {
// default code if API doesn't send failure_code
$failureCode = 'UNKNOWN_ERROR';
if (isset($decodedPost['failure_code'])) {
$failureCode = $decodedPost['failure_code'];
}

$extIdPrefix = $this->dataHelper->getExternalIdPrefix();
$orderId = ltrim($decodedPost['external_id'], $extIdPrefix);

// standalone OVO can only be single checkout
$orderIds = [$orderId];
} else {
$orderId = $decodedPost['description'];
$orderIds = explode("-", $orderId);
}

$transactionId = $decodedPost['id'];
$isMultishipping = (count($orderIds) > 1) ? true : false;

if (!empty($callbackToken)) {
$result = $this->jsonResultFactory->create();
/** You may introduce your own constants for this custom REST API */
Expand Down Expand Up @@ -136,7 +143,8 @@ public function execute()
}

private function checkOrder($orderId, $isEwallet, $decodedPost, $invoice, $callbackDescription) {
$order = $this->getOrderById($orderId);
$order = $this->orderFactory->create();
$order->load($orderId);
$transactionId = $decodedPost['id'];

if (!$order) {
Expand All @@ -152,6 +160,8 @@ private function checkOrder($orderId, $isEwallet, $decodedPost, $invoice, $callb
}

if ($isEwallet) {
$order = $this->getOrderById($orderId);

if ($order->getState() === Order::STATE_PENDING_PAYMENT || $order->getState() === Order::STATE_PAYMENT_REVIEW) {
//get ewallet payment status
$paymentStatus = $this->getEwalletStatus($decodedPost['ewallet_type'], $decodedPost['external_id']);
Expand Down
24 changes: 17 additions & 7 deletions Xendit/M2Invoice/Controller/Checkout/Notification.m23.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,20 +93,27 @@ public function execute()

return $result;
}

$orderId = $decodedPost['description'];
$transactionId = $decodedPost['id'];
$orderIds = explode("-", $orderId);

$isMultishipping = (count($orderIds) > 1) ? true : false;

if ($isEwallet) {
// default code if API doesn't send failure_code
$failureCode = 'UNKNOWN_ERROR';
if (isset($decodedPost['failure_code'])) {
$failureCode = $decodedPost['failure_code'];
}

$extIdPrefix = $this->dataHelper->getExternalIdPrefix();
$orderId = ltrim($decodedPost['external_id'], $extIdPrefix);

// standalone OVO can only be single checkout
$orderIds = [$orderId];
} else {
$orderId = $decodedPost['description'];
$orderIds = explode("-", $orderId);
}

$transactionId = $decodedPost['id'];
$isMultishipping = (count($orderIds) > 1) ? true : false;

if (!empty($callbackToken)) {
$result = $this->jsonResultFactory->create();
/** You may introduce your own constants for this custom REST API */
Expand Down Expand Up @@ -147,7 +154,8 @@ public function execute()
}

private function checkOrder($orderId, $isEwallet, $decodedPost, $invoice, $callbackDescription) {
$order = $this->getOrderById($orderId);
$order = $this->orderFactory->create();
$order->load($orderId);
$transactionId = $decodedPost['id'];

if (!$order) {
Expand All @@ -163,6 +171,8 @@ private function checkOrder($orderId, $isEwallet, $decodedPost, $invoice, $callb
}

if ($isEwallet) {
$order = $this->getOrderById($orderId);

if ($order->getState() === Order::STATE_PENDING_PAYMENT || $order->getState() === Order::STATE_PAYMENT_REVIEW) {
//get ewallet payment status
$paymentStatus = $this->getEwalletStatus($decodedPost['ewallet_type'], $decodedPost['external_id']);
Expand Down
43 changes: 32 additions & 11 deletions Xendit/M2Invoice/Controller/Checkout/ThreeDSResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,32 @@ public function execute()
{
$orderId = $this->getRequest()->get('order_id');
$hosted3DSId = $this->getRequest()->get('hosted_3ds_id');
$isMultishipping = ($this->getRequest()->get('type') == 'multishipping' ? true : false);

$orderIds = explode('-', $orderId);
$orders = [];

foreach ($orderIds as $key => $value) {
$order = $this->getOrderById($value);
$orderIds = [];

if ($isMultishipping) {
$orderIds = explode('-', $orderId);

foreach ($orderIds as $key => $value) {
$order = $this->getOrderFactory()->create();
$order->load($value);

if (!is_object($order)) {
return;
}

if ($order->getState() !== Order::STATE_PENDING_PAYMENT) {
return;
}

$orders[] = $order;
}
} else {
$order = $this->getOrderFactory()->create()->loadByIncrementId($orderId);
$orderId = $order->getId(); //replace increment $orderId with prefixless order ID
$orderIds[] = $orderId;

if (!is_object($order)) {
return;
Expand All @@ -43,18 +63,18 @@ public function execute()
$charge = $this->createCharge($hosted3DS, $orderId, true);
}

return $this->processXenditPayment($charge, $orders, $orderIds);
return $this->processXenditPayment($charge, $orders, $orderIds, $isMultishipping);
} catch (\Magento\Framework\Exception\LocalizedException $e) {
$message = 'Exception caught on xendit/checkout/threedsresult: ' . $e->getMessage();
$this->getLogDNA()->log(LogDNALevel::ERROR, $message);

return $this->processFailedPayment($orderIds);
}
}

private function getThreeDSResult($hosted3DSId)
{
$hosted3DSUrl = $this->getDataHelper()->getCheckoutUrl()
. "/payment/xendit/credit-card/hosted-3ds/$hosted3DSId";
$hosted3DSUrl = $this->getDataHelper()->getCheckoutUrl() . "/payment/xendit/credit-card/hosted-3ds/$hosted3DSId";
$hosted3DSMethod = \Zend\Http\Request::METHOD_GET;

try {
Expand Down Expand Up @@ -92,7 +112,7 @@ private function createCharge($hosted3DS, $orderId, $duplicate = false)
return $charge;
}

private function processXenditPayment($charge, $orders, $orderIds)
private function processXenditPayment($charge, $orders, $orderIds, $isMultishipping = false)
{
if ($charge['status'] === 'CAPTURED') {
$transactionId = $charge['id'];
Expand All @@ -112,14 +132,15 @@ private function processXenditPayment($charge, $orders, $orderIds)
$this->invoiceOrder($order, $transactionId);
}

$isMultishipping = (count($orderIds) > 1);

$this->_redirect($this->getDataHelper()->getSuccessUrl(true));
$this->_redirect($this->getDataHelper()->getSuccessUrl($isMultishipping));
} else {
$this->processFailedPayment($orderIds, $charge['failure_reason']);
}
}

/**
* $orderIds = prefixless order IDs
*/
private function processFailedPayment($orderIds, $failureReason = 'Unexpected Error')
{
$this->getCheckoutHelper()->processOrdersFailedPayment($orderIds, $failureReason);
Expand Down
Loading

0 comments on commit b2eafce

Please sign in to comment.