Skip to content
Open
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
18 changes: 17 additions & 1 deletion spiff-connect/spiff-connect.php
Original file line number Diff line number Diff line change
Expand Up @@ -610,10 +610,26 @@ function spiff_post_order($application_key, $items, $woo_order_id, $paid, $exter
$response_body = wp_remote_retrieve_body($response);
$decoded = json_decode($response_body);
if ($response_status !== 200 || !empty($decoded->errors) || empty($decoded->data->orderCreate->id)) {
error_log('Failed to create Spiff order for WooCommerce order ' . $woo_order_id . ': ' . $response_body);
$error = is_wp_error($response) ? $response->get_error_message() : $response_body;
spiff_report_order_failure($woo_order_id, $response_status, $error, $external_data);
}
}

// Surface a failed order sync in the WooCommerce logs and on the order itself, so it isn't silently lost.
function spiff_report_order_failure($woo_order_id, $response_status, $error, $external_data) {
$message = 'Failed to create Spiff order for WooCommerce order ' . $woo_order_id . ' (HTTP ' . $response_status . '): ' . $error;
wc_get_logger()->error($message, array('source' => 'spiff-connect'));

// The ID may have been customised via spiff_order_external_id, so only annotate the order if it is the one we sent.
$order = wc_get_order($woo_order_id);
if (!$order || (string) $order->get_order_number() !== $external_data['orderNumber']) {
return;
}
$order->add_order_note('Failed to send this order to Spiff. See the spiff-connect log under WooCommerce > Status > Logs.');
$order->update_meta_data('_spiff_sync_failed', 'yes');
$order->save();
}

/**
* Shortcodes.
*/
Expand Down
65 changes: 58 additions & 7 deletions tests/CreateOrderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,18 +149,69 @@ public function testSendsOrderToUnitedStatesWhenConfigured() {
public function testFailedRequestDoesNotStopCheckout() {
spiff_test_queue_response(array('errors' => array(array('message' => 'Unauthorised'))), 401);
$this->addOrder(123, 'VEG-1042', array($this->spiffItem('transaction-1')));
$log = ini_get('error_log');
ini_set('error_log', '/dev/null');

try {
spiff_create_order(123);
} finally {
ini_set('error_log', $log);
}
spiff_create_order(123);

$this->assertCount(1, $GLOBALS['spiff_test_requests']);
}

public function testFailedRequestIsLoggedWithStatusAndResponse() {
spiff_test_queue_response(array('errors' => array(array('message' => 'Unauthorised'))), 401);
$this->addOrder(123, 'VEG-1042', array($this->spiffItem('transaction-1')));

spiff_create_order(123);

$this->assertCount(1, $GLOBALS['spiff_test_logs']);
$log = $GLOBALS['spiff_test_logs'][0];
$this->assertSame('spiff-connect', $log['context']['source']);
$this->assertStringContainsString('WooCommerce order 123 (HTTP 401)', $log['message']);
$this->assertStringContainsString('Unauthorised', $log['message']);
}

public function testFailedRequestAnnotatesAndFlagsOrder() {
spiff_test_queue_response(array('errors' => array(array('message' => 'Unauthorised'))), 401);
$this->addOrder(123, 'VEG-1042', array($this->spiffItem('transaction-1')));

spiff_create_order(123);

$order = $GLOBALS['spiff_test_orders'][123];
$this->assertCount(1, $order->notes);
$this->assertSame('yes', $order->meta['_spiff_sync_failed']);
}

public function testTransportErrorMessageIsLogged() {
$GLOBALS['spiff_test_responses'][] = new WP_Error('http_request_failed', 'cURL error 28: timeout');
$this->addOrder(123, 'VEG-1042', array($this->spiffItem('transaction-1')));

spiff_create_order(123);

$this->assertStringContainsString('cURL error 28: timeout', $GLOBALS['spiff_test_logs'][0]['message']);
}

public function testFailureWithCustomExternalIdDoesNotAnnotateUnrelatedOrder() {
spiff_test_queue_response(array('errors' => array(array('message' => 'Unauthorised'))), 401);
$this->addOrder(123, 'VEG-1042', array($this->spiffItem('transaction-1')));
$this->addOrder(5000, 'VEG-2000', array());
add_filter('spiff_order_external_id', function () {
return 5000;
}, 10, 2);

spiff_create_order(123);

$this->assertCount(1, $GLOBALS['spiff_test_logs']);
$this->assertSame(array(), $GLOBALS['spiff_test_orders'][5000]->notes);
$this->assertSame(array(), $GLOBALS['spiff_test_orders'][123]->notes);
}

public function testSuccessfulRequestIsNotLoggedOrFlagged() {
$this->addOrder(123, 'VEG-1042', array($this->spiffItem('transaction-1')));

spiff_create_order(123);

$this->assertSame(array(), $GLOBALS['spiff_test_logs']);
$this->assertSame(array(), $GLOBALS['spiff_test_orders'][123]->meta);
}

public function testSendsPaidFlagAndApplicationKey() {
$this->addOrder(123, 'VEG-1042', array($this->spiffItem('transaction-1')), false);

Expand Down
43 changes: 41 additions & 2 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function spiff_test_reset() {
$GLOBALS['spiff_test_requests'] = array();
$GLOBALS['spiff_test_responses'] = array();
$GLOBALS['spiff_test_orders'] = array();
$GLOBALS['spiff_test_logs'] = array();
$GLOBALS['spiff_test_products'] = array();
$GLOBALS['spiff_test_users'] = array();
$GLOBALS['spiff_test_user_meta'] = array();
Expand Down Expand Up @@ -190,16 +191,42 @@ function wp_remote_post($url, $args) {
);
}

function is_wp_error($thing) {
return $thing instanceof WP_Error;
}

class WP_Error {
private $message;

public function __construct($code = '', $message = '') {
$this->message = $message;
}

public function get_error_message() {
return $this->message;
}
}

function wp_remote_retrieve_response_code($response) {
return $response['response']['code'];
return is_wp_error($response) ? '' : $response['response']['code'];
}

function wp_remote_retrieve_body($response) {
return $response['body'];
return is_wp_error($response) ? '' : $response['body'];
}

// WooCommerce.

class Spiff_Test_Logger {
public function error($message, $context = array()) {
$GLOBALS['spiff_test_logs'][] = array('message' => $message, 'context' => $context);
}
}

function wc_get_logger() {
return new Spiff_Test_Logger();
}

function wc_get_order($order_id) {
return $GLOBALS['spiff_test_orders'][$order_id] ?? false;
}
Expand Down Expand Up @@ -321,6 +348,8 @@ class Spiff_Test_Order {
private $items;
private $paid;
private $fields;
public $notes = array();
public $meta = array();

public function __construct($id, $order_number, $items, $paid = true, $fields = array()) {
$this->id = $id;
Expand Down Expand Up @@ -350,6 +379,16 @@ public function get_coupon_codes() {
return $this->fields['coupon_codes'] ?? array();
}

public function add_order_note($note) {
$this->notes[] = $note;
}

public function update_meta_data($key, $value) {
$this->meta[$key] = $value;
}

public function save() {}

// Remaining getters (addresses, email, phone, note) read from $fields, e.g. get_billing_city => 'billing_city'.
public function __call($name, $arguments) {
return $this->fields[substr($name, strlen('get_'))] ?? '';
Expand Down
Loading