Hey,
I believe you could do it using a custom js function that pokes the API for orders with the correct parameters to check if the client has ordered that item before. The payment template could be a good place to put it. Add a v-if somewhere, maybe directly in the <snipcart-form…> that calls your custom function (must return truthy value if the customer can buy). It would add a bit of load time right before payment.
edit: I’ve tested a bit the above theory. You will need to create a backend call for the call to Snipcart’s api, due to the key needing to stay secret. The code below is a quick mockup :
Add the window.checkCustomer function wherever you might already have the listener. Otherwise add the snipcart.ready listener somewhere before your snipcart configs code.
The comment is where you’ll call your new backend GET request. It should take the items and customer name. You can also send it an array of item ids instead, taking all ids from items variable.
I added a category for all my products I want restricted, so we check the cart items with that category.
const category = 'OnePerCustomer';
document.addEventListener('snipcart.ready', () => {
window.checkCustomer = function () {
const items = Snipcart.store
.getState()
.cart.items.items.filter((e) => e.categories.includes(category));
const customer = Snipcart.store.getState().cart.billingAddress.fullname;
// Backend function that checks call orders API https://docs.snipcart.com/v3/api-reference/orders#get-orders
// with each items.id and customer.
// Check your response from your API and change valid to appropriate value
let valid = true;
return valid;
};
});
In my snipcart template overrides, I added a v-if with that function. Adding it there removes the whole payment part. It’s not really clean, but it’s just as an example. You might add a v-else after the form with an error message. Or do it some other way. I added it to payment due to the need of the customer’s name.
<div id="snipcart-templates">
<payment>
<snipcart-form
v-if="window.checkCustomer()"
@submit="confirmOrder"
class="snipcart-payment snipcart__box"
>
.....
Another way would be using webhooks. It’s far from optimal, but you could use a webhook on the order completed Webhooks: order events – Snipcart Documentation and just cancel the order automatically.
To update the order : API: orders – Snipcart Documentation
To add a comment to the order (for an email) : API: notifications – Snipcart Documentation
To issue a refund : API: refunds – Snipcart Documentation