Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Changelog
All notable changes to this project will be documented in this file.

## [3.8.8]
- Extended Apple Pay support to include the MarketPay acquirer. For the updated payment methods settings please see [Configure the terminals for the checkout page](https://github.com/AltaPay/plugin-wordpress/wiki#configure-the-terminals-for-the-checkout-page)

## [3.8.7]
- Add support for MarketPay payment methods.
- Fix: Renewal/Recurring order status automatically changed to Processing.
Expand Down
6 changes: 3 additions & 3 deletions altapay.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
* Author URI: https://altapay.com
* Text Domain: altapay
* Domain Path: /languages
* Version: 3.8.7
* Version: 3.8.8
* Name: SDM_Altapay
* WC requires at least: 3.9.0
* WC tested up to: 10.7.0
* WC tested up to: 10.9.4
*
* @package Altapay
*/
Expand Down Expand Up @@ -41,7 +41,7 @@
}

if ( ! defined( 'ALTAPAY_PLUGIN_VERSION' ) ) {
define( 'ALTAPAY_PLUGIN_VERSION', '3.8.7' );
define( 'ALTAPAY_PLUGIN_VERSION', '3.8.8' );
}

// Include the autoloader, so we can dynamically include the rest of the classes.
Expand Down
5 changes: 4 additions & 1 deletion assets/js/applepay.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,9 @@ function onApplePayButtonClicked(applepay_obj, createSession, wc_checkout_form,
ajax_nonce: applepay_obj.nonce,
action: 'validate_merchant',
validation_url: event.validationURL,
terminal: applepay_obj.terminal
terminal: applepay_obj.terminal,
applepay_payment_method: applepay_obj.applepay_payment_method,
order_id: order_id
},
function (res) {
if (res.success === true) {
Expand Down Expand Up @@ -185,6 +187,7 @@ function onApplePayButtonClicked(applepay_obj, createSession, wc_checkout_form,
action: 'card_wallet_authorize',
provider_data: JSON.stringify( event.payment.token ),
terminal: applepay_obj.terminal,
applepay_payment_method: applepay_obj.applepay_payment_method,
order_id: order_id
},
function (res) {
Expand Down
196 changes: 155 additions & 41 deletions classes/core/ApplePay.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,27 @@ public function altapay_load_apple_pay_script() {
);
}

/**
* Whether the Apple Pay has the legacy flow enabled.
*
* @param string $payment_method.
* @return bool
*/
private function isLegacyApplePayFlow( $payment_method ) {

if ( ! $payment_method ) {
return true;
}

$settings = get_option( 'woocommerce_' . $payment_method . '_settings' );

if ( ! is_array( $settings ) ) {
return true;
}

return ( $settings['apple_pay_legacy_flow'] ?? 'yes' ) === 'yes';
}

/**
* Validate Apple Pay Session
*
Expand All @@ -94,32 +115,86 @@ public function altapay_load_apple_pay_script() {
public function applepay_validate_merchant() {

if ( ! wp_verify_nonce( wp_unslash( $_POST['ajax_nonce'] ), 'apple-pay' ) ) {
wc_add_notice( __( 'Payment failed. Please try again.', 'altapay' ), 'error' );
wp_send_json_error( array( 'redirect' => wc_get_cart_url() ) );
$this->sendPaymentFailedResponse();
}

$terminal = isset( $_POST['terminal'] ) ? sanitize_text_field( wp_unslash( $_POST['terminal'] ) ) : '';
$validation_url = isset( $_POST['validation_url'] ) ? sanitize_text_field( wp_unslash( $_POST['validation_url'] ) ) : '';
$applepay_payment_method = isset( $_POST['applepay_payment_method'] ) ? sanitize_text_field( wp_unslash( $_POST['applepay_payment_method'] ) ) : '';
$order_id = isset( $_POST['order_id'] ) ? absint( $_POST['order_id'] ) : 0;
$order = $order_id ? wc_get_order( $order_id ) : false;

$request = new CardWalletSession( $this->getAuth() );
$request->setTerminal( $terminal )
->setValidationUrl( $validation_url )
->setDomain( $_SERVER['HTTP_HOST'] );

if ( ! $this->isLegacyApplePayFlow( $applepay_payment_method ) ) {

if ( ! $order ) {
$this->sendPaymentFailedResponse();
}

$request->setShopOrderId( $order_id )
->setAmount( (float) $order->get_total() )
->setCurrency( $order->get_currency() )
->setApplePayRequestData( [
'validationUrl' => $validation_url,
'domain' => $_SERVER['HTTP_HOST']
] );
}

try {
$response = $request->call();
if ( $response->Result === 'Success' ) {
wp_send_json_success( $response->ApplePaySession, 200 );
} else {
wc_add_notice( __( 'Payment failed.', 'altapay' ), 'error' );
wp_send_json_error( array( 'redirect' => wc_get_cart_url() ) );
}
$this->sendValidateMerchantResponse( $response, $order );
} catch ( \Exception $e ) {
wc_add_notice( __( 'Payment failed:', 'altapay' ) . ' ' . $e->getMessage(), 'error' );
wp_send_json_error( array( 'redirect' => wc_get_cart_url() ) );
}
}

/**
* Add a generic payment-failed notice and redirect to the cart page.
*
* @return void
*/
private function sendPaymentFailedResponse() {
wc_add_notice( __( 'Payment failed. Please try again.', 'altapay' ), 'error' );
wp_send_json_error( array( 'redirect' => wc_get_cart_url() ) );
}

/**
* Send the AJAX response for a CardWalletSession result.
*
* @param object $response
* @param WC_Order|false $order
* @return void
*/
private function sendValidateMerchantResponse( $response, $order ) {

if ( $response->Result !== 'Success' ) {
wc_add_notice( __( 'Payment failed.', 'altapay' ), 'error' );
wp_send_json_error( array( 'redirect' => wc_get_cart_url() ) );
}

if ( isset( $response->ApplePaySession ) ) {
wp_send_json_success( $response->ApplePaySession, 200 );
}

if ( isset( $response->WalletData->Session ) ) {
$transaction = ! empty( $response->Transactions ) ? reset( $response->Transactions ) : null;

if ( $order && isset( $transaction->PaymentId ) ) {
$order->update_meta_data( 'altapay_payment_id', $transaction->PaymentId );
$order->save();
}
wp_send_json_success( $response->WalletData->Session, 200 );
}

wc_add_notice( __( 'Payment failed.', 'altapay' ), 'error' );
wp_send_json_error( array( 'redirect' => wc_get_cart_url() ) );
}

/**
* Call CardWalletAuthorize API
*
Expand All @@ -128,15 +203,21 @@ public function applepay_validate_merchant() {
public function applepay_card_wallet_authorize() {

if ( ! wp_verify_nonce( wp_unslash( $_POST['ajax_nonce'] ), 'apple-pay' ) ) {
wc_add_notice( __( 'Payment failed. Please try again.', 'altapay' ), 'error' );
wp_send_json_error( array( 'redirect' => wc_get_cart_url() ) );
$this->sendPaymentFailedResponse();
}

$provider_data = isset( $_POST['provider_data'] ) ? sanitize_text_field( wp_unslash( $_POST['provider_data'] ) ) : '';
$terminal = isset( $_POST['terminal'] ) ? sanitize_text_field( wp_unslash( $_POST['terminal'] ) ) : '';
$applepay_payment_method = isset( $_POST['applepay_payment_method'] ) ? sanitize_text_field( wp_unslash( $_POST['applepay_payment_method'] ) ) : '';
$order_id = isset( $_POST['order_id'] ) ? sanitize_text_field( wp_unslash( $_POST['order_id'] ) ) : '';
$order = wc_get_order( $order_id );

$legacy_flow = $this->isLegacyApplePayFlow( $applepay_payment_method );

if ( ! $legacy_flow ) {
$altapay_payment_id = $order->get_meta( 'altapay_payment_id' );
}

$payment_gateways = WC()->payment_gateways()->payment_gateways();
$payment_method = $order->get_payment_method();

Expand All @@ -162,6 +243,33 @@ public function applepay_card_wallet_authorize() {
->setOrderLines( $order_lines )
->setSaleReconciliationIdentifier( wp_generate_uuid4() );

if ( ! $legacy_flow ) {
$request->setPaymentId( $altapay_payment_id );
}

$payment_type = $this->determinePaymentType( $payment_gateways, $payment_method );

$request->setType( $payment_type );

try {
$response = $request->call();
$this->sendCardWalletAuthorizeResponse( $response, $order, $order_id, $payment_type );
} catch ( \Exception $e ) {
$order->add_order_note( __( 'Payment failed: ' . $e->getMessage() ) );
wc_add_notice( __( 'Payment failed:', 'altapay' ) . ' ' . $e->getMessage(), 'error' );
wp_send_json_error( array( 'redirect' => wc_get_cart_url() ) );
}
}

/**
* Whether the gateway used for this order is set to authorize-and-capture.
*
* @param array $payment_gateways
* @param string $payment_method
* @return string
*/
private function determinePaymentType( $payment_gateways, $payment_method ) {

$payment_type = 'payment';

foreach ( $payment_gateways as $key => $payment_gateway ) {
Expand All @@ -173,43 +281,48 @@ public function applepay_card_wallet_authorize() {
}
}

$request->setType( $payment_type );

try {
$response = $request->call();
return $payment_type;
}

$transactions = json_decode( wp_json_encode( $response->Transactions ), true );
$latest_transaction = $this->getLatestTransaction( $transactions, $payment_type );
$transaction = $transactions[ $latest_transaction ];
$txn_id = $transaction['TransactionId'];
/**
* Send the AJAX response for a CardWalletAuthorize result.
*
* @param object $response
* @param WC_Order $order
* @param string $order_id
* @param string $payment_type
* @return void
*/
private function sendCardWalletAuthorizeResponse( $response, $order, $order_id, $payment_type ) {

$order->add_order_note( __( "Gateway Order ID: $order_id", 'altapay' ) );
if ( $response->Result === 'Success' ) {
$order->set_transaction_id( $txn_id );
$order->add_order_note( __( 'Apple Pay payment completed', 'altapay' ) );
$order->payment_complete();
$transactions = json_decode( wp_json_encode( $response->Transactions ), true );
$latest_transaction = $this->getLatestTransaction( $transactions, $payment_type );
$transaction = $transactions[ $latest_transaction ];
$txn_id = $transaction['TransactionId'];

$reconciliation = new Core\AltapayReconciliation();
foreach ( $transaction['ReconciliationIdentifiers'] as $val ) {
$reconciliation->saveReconciliationIdentifier( $order_id, $txn_id, $val['Id'], $val['Type'] );
}
$order->add_order_note( __( "Gateway Order ID: $order_id", 'altapay' ) );

wp_send_json_success(
array(
'redirect' => $order->get_checkout_order_received_url(),
),
200
);
} else {
$order->add_order_note( __( 'Payment failed.' ) );
wc_add_notice( __( 'Payment failed.', 'altapay' ), 'error' );
wp_send_json_error( array( 'redirect' => wc_get_cart_url() ) );
}
} catch ( \Exception $e ) {
$order->add_order_note( __( 'Payment failed: ' . $e->getMessage() ) );
wc_add_notice( __( 'Payment failed:', 'altapay' ) . ' ' . $e->getMessage(), 'error' );
if ( $response->Result !== 'Success' ) {
$order->add_order_note( __( 'Payment failed.' ) );
wc_add_notice( __( 'Payment failed.', 'altapay' ), 'error' );
wp_send_json_error( array( 'redirect' => wc_get_cart_url() ) );
}

$order->set_transaction_id( $txn_id );
$order->add_order_note( __( 'Apple Pay payment completed', 'altapay' ) );
$order->payment_complete();

$reconciliation = new Core\AltapayReconciliation();
foreach ( $transaction['ReconciliationIdentifiers'] as $val ) {
$reconciliation->saveReconciliationIdentifier( $order_id, $txn_id, $val['Id'], $val['Type'] );
}

wp_send_json_success(
array(
'redirect' => $order->get_checkout_order_received_url(),
),
200
);
}

/**
Expand All @@ -233,6 +346,7 @@ public function applepay_woocommerce_after_checkout_form() {
'subtotal' => WC()->cart->get_total( 'edit' ),
'terminal' => $payment_gateway->terminal,
'apply_pay_label' => $payment_gateway->apple_pay_label,
'apple_pay_legacy_flow' => $payment_gateway->apple_pay_legacy_flow,
'apple_pay_supported_networks' => $payment_gateway->get_option('apple_pay_supported_networks'),
'applepay_payment_method' => $payment_gateway->id
);
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
},
"require": {
"php": "^7.4 || ^8.0",
"altapay/api-php":"^3.5.9",
"altapay/api-php":"^3.6.1",
"eftec/bladeone":"^4.4",
"humbug/php-scoper": "0.17.5"
},
Expand Down
Loading
Loading