The debug option did not expand the error we recieve with the reponse.
To give you the full picture we are trying to create a stripe plugin, to confirm the payment request we send an AJAX call to a custom component which includes stripe and hikashop helpers. The stripe end of things successfully completes, but we then need to create and then confirm the order with hikashop.
However when trying to create an order from cart it falls over with the error, even thought getFullCart() and cart_id works.
/plugins/hikashoppayment/example/example.php: This sends the AJAX
<?php
/*
* A payment plugin called "example". This is the main file of the plugin.
*/
defined('_JEXEC') or die('Restricted access');
require $_SERVER['DOCUMENT_ROOT'] . '/vendor/autoload.php';
// You need to extend from the hikashopPaymentPlugin class which already define lots of functions in order to simplify your work
class plgHikashoppaymentExample extends hikashopPaymentPlugin
{
//Payment plugin name (the name of the PHP file)
var $accepted_currencies = array('USD', 'GBP', 'EUR', 'JPY', 'CAD', 'AUD');
var $multiple = true;
var $name = 'example';
var $pluginConfig = array(
'login' => array('HIKA_USERNAME', 'input'),
'password' => array('HIKA_PASSWORD', 'input'),
'signature' => array('SIGNATURE', 'input'),
'environnement' => array('ENVIRONNEMENT', 'list', array(
'production' => 'HIKA_PRODUCTION',
'sandbox' => 'HIKA_SANDBOX',
'beta-sandbox' => 'Beta-Sandbox'
)),
'instant_capture' => array('Instant Capture', 'boolean', '0'),
'ask_ccv' => array('Ask CCV', 'boolean', '1'),
'details' => array('SEND_DETAILS_OF_ORDER', 'boolean', '1'),
'send_order_id' => array('Send order id', 'boolean', '0'),
'send_notification' => array('ORDER_NOTIFICATION', 'boolean', '0'),
'debug' => array('DEBUG', 'boolean', '0'),
'cancel_url' => array('CANCEL_URL', 'input'),
'return_url' => array('RETURN_URL', 'input'),
'verified_status' => array('VERIFIED_STATUS', 'orderstatus')
);
function needCC(&$method)
{
$method->custom_html = '
<script src="https://js.stripe.com/v3/"></script>
<input type="hidden" id="hiddencontainer" name="hiddencontainer"/>
<div id="payment-request-button">
<!-- A Stripe Element will be inserted here. -->
</div>
<script>
const stripe = Stripe("secretkeygoeshere", {
apiVersion: "2020-08-27",
});
console.log("amount in basket: ", document.getElementsByClassName("hikashop-count")[0].innerHTML);
let amount = 3495 * document.getElementsByClassName("hikashop-count")[0].innerHTML;
let label = "ellaOne x" + document.getElementsByClassName("hikashop-count")[0].innerHTML + "tablet";
const paymentRequest = stripe.paymentRequest({
country: "GB",
currency: "gbp",
total: {
label: label,
amount:amount,
},
});
const elements = stripe.elements();
const prButton = elements.create("paymentRequestButton", {
paymentRequest,
});
(async () => {
// Check the availability of the Payment Request API first.
const result = await paymentRequest.canMakePayment();
if (result) {
prButton.mount("#payment-request-button");
} else {
document.getElementById("payment-request-button").style.display = "none";
}
})();
async function handleServerResponse(response, complete) {
if (response.error) {
complete("fail");
} else if (response.requires_action) {
complete("success");
await handleAction(response);
} else {
complete("success");
console.log("MISHA");
let myhidden = document.getElementById("hiddencontainer");
myhidden.value = 1;
}
}
async function handleAction(response) {
const {
error: errorAction,
paymentIntent
} = await stripe.handleCardAction(
response.payment_intent_client_secret
);
if (errorAction) {
// Show error from Stripe.js in payment form
} else {
const response = await fetch(
"/plugins/hikashoppayment/example/confirm_payment.php", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
payment_intent_id: paymentIntent.id
})
}
);
// Step 3: handle server response
handleServerResponse(await response.json());
}
}
paymentRequest.on("paymentmethod",
async ({paymentMethod, complete}) => {
// Send paymentMethod to server
const response = await fetch(
"index.php?option=com_helloworld&format=ajax&lang=en&view=helloworld&task=getArticles&tmpl=component", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
payment_method_id: paymentMethod.id
})
}
)
// Step 3: handle server response
await handleServerResponse(await response.json(), complete);
});
</script>
';
return true;
}
}
?>
/components/com_helloworld/views/helloworld: This recieves the ajax and fails on createFromCart()
<?php
# vendor using composer
require $_SERVER['DOCUMENT_ROOT'] . '/vendor/autoload.php';
defined('_JEXEC') or die;
//ini_set('display_errors', 1);
//ini_set('display_startup_errors', 1);
//error_reporting(E_ALL);
\Stripe\Stripe::setApiKey('secretkeygoeshere');
header('Content-Type: application/json');
class HelloWorldViewHelloWorld extends JViewLegacy
{
function display($tpl = null)
{
$app = JFactory::getApplication();
$user = JFactory::getUser();
$userId = $user->get('id');
$task = JRequest::getString('task');
switch ($task) {
case "getArticles":
$this->_getArticles();
break;
}
parent::display($tpl);
jexit();
}
public function _getArticles()
{
# retrieve json from POST body
$json_str = file_get_contents('php://input');
$json_obj = json_decode($json_str);
$intent = null;
try {
if (isset($json_obj->payment_method_id)) {
# Create the PaymentIntent
$intent = \Stripe\PaymentIntent::create([
'payment_method' => $json_obj->payment_method_id,
'amount' => 3495,
'currency' => 'gbp',
'confirmation_method' => 'manual',
'confirm' => true,
]);
}
if (isset($json_obj->payment_intent_id)) {
$intent = \Stripe\PaymentIntent::retrieve(
$json_obj->payment_intent_id
);
$intent->confirm();
}
$this->generateResponse($intent);
} catch (\Stripe\Exception\ApiErrorException $e) {
# Display error on client
echo json_encode([
'error' => $e->getMessage()
]);
}
}
function generateResponse($intent)
{
# Note that if your API version is before 2019-02-11, 'requires_action'
# appears as 'requires_source_action'.
if ($intent->status == 'requires_action' &&
$intent->next_action->type == 'use_stripe_sdk') {
# Tell the client to handle the action
echo json_encode([
'requires_action' => true,
'payment_intent_client_secret' => $intent->client_secret
]);
} else if ($intent->status == 'succeeded') {
# The payment didn’t need any additional actions and completed!
# Handle post-payment fulfillment
echo json_encode([
"success" => true,
]);
$hikashopHelper = rtrim(JPATH_ADMINISTRATOR, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'components' . DIRECTORY_SEPARATOR . 'com_hikashop' . DIRECTORY_SEPARATOR . 'helpers' . DIRECTORY_SEPARATOR . 'helper.php';
if (!file_exists($hikashopHelper) || !include_once($hikashopHelper)) {
echo "HIKA NOT WORKING";
return;
}
$cartClass = hikashop_get('class.cart');
$orderClass = hikashop_get('class.order');
$cart = $cartClass->getFullCart();
$cart_id = $cart->cart_id;
//Error here
$order = $orderClass->createFromCart($cart_id);
// $orderClass = hikashop_get('class.cart');
// $orderClass->createFromCart(0);
} else {
# Invalid status
http_response_code(500);
echo json_encode(['error' => 'Invalid PaymentIntent status']);
}
}
}
We have been stuck on this for days and at least a nudge in the right direction would be appreciated. Many thanks for your time.