Merx – Plugin to create online shops with Kirby 3

, ,

Hi @tobiasfabian I just moved to the server, configured production and added the license.
And when I try to continue to the payment in the checkout process (paypal) I got a json response with the following.
status: 201
redirect: “https://www.paypal.com/checkoutnow?token=8NA19628V…”

It works fine in localhost.

Any ideas!? Thanks!

Mmh that’s hard to tell without knowing your code. Which file do you think does not function as expected?

Hi Tobias, don’t worry I deleted the post becuase I managed to solve it, It was an issue with js.

1 Like

Hi! Is possible to customize Statement descriptors for Stripe Card payments?

Right now, in the credit card resume, it shows the compnay name and the phone, I want to remove the pone number.

Thanks!

I am curios to see how your shops turned out. Anyone willing to share a final shop? Thank you
Filip

@tobiasfabian I am working on a custom invoice number. It is easy to show it on the order page ($page->invoiceNumber()) but in the emails it is not visible because $orderPage->invoiceNumber() is empty and $page->invoiceNumber() is not possible of course because the confirmation mail is not the order page. I thought $orderPage->update (in config) would update $orderPage also for the email, but it seams not to be working. I followed the instructions on your website exactly. What do you think is the problem? Regards Bart

Thanks for your reply!

But where is the secrects folder located, that is used in the config files? For example by using

$stripeLivePublishableKey = file_get_contents('secrects/.stripeLivePublishableKey', FILE_USE_INCLUDE_PATH);
return [
  'ww.merx.stripe.test.publishable_key' => $stripeLivePublishableKey,
];

secrects folder is called. Currently I put it into the root of the project but calling

    option('ww.merx.stripe.test.publishable_key')

returns NULL.

Any hints where to put the keys and make them available by option()-method?

Solved it!
My mistake was wrong naming of the config file for localhost. Hence the file wasn’t called properly and the key wasn’t set. Filename is now changed to config.127.0.0.1.php (sounds kinda wrong, but works).
And I have set the secrects folder into the

site/config/

folder.

1 Like

I implemented a shop using Merx, after a lot of stress and trial & error!

4 Likes

I am having an issue with adding something to the cart. maybe someone knows where the issue could be:

I am creating the products as virtual pages from a spreadsheet.

there is a product page containing all the attribute fields and subpages for every variation of that product. both the product and the variation page have a price field with the same value.

in the frontend, the user is on the page of the overall product and with a select field chooses the variation he wants.

I copied the code from the babyreport example for adding the product to the cart, also checked that the variation has a price field with a value and that the id is valid.

it just throws me a message “Item … could not be added to cart.” without any details…

i thought that maybe it is because of the virtual pages but when i inserted the product as folders and textfiles in the content folder, nothing changed.

maybe from my description here someone sees a possible source of a mistake. any hint is much appreciated!

hey @sigi

It is good to hear that someone tries Merx with virtual pages from a spreadsheet. That’s an interesting usecase I always wanted to try out. I’m sure we will find a solution to your problem.

The code should throw the following exception.

'key' => 'merx.cart.add',
'data' => [
  'id' => $cartItem['id'] ?? '',
],
'details' => [
  'exception' => $ex,
],

https://github.com/wagnerwagner/merx/blob/43e9b8ddf195b1a6f540319dd49cda1de074a1b7/src/cart.php#L51-L57

Is data.id ($cartItem['id']) as expected. And what’s the response of details.exception?

Maybe it would help if you can show us the page model of the virtual page you want to add to the cart.

Hey @bartvandebiezen,

can you show us the code where you send the email and where you update the invoice number.

We have build a shop for disinfections :man_shrugging:

1 Like

Would you please create a ticket at Github. I can’t tell you at the moment how difficult it would be to implement this.

hey @tobiasfabian,

thank you for your reply!

yes, this is the exception i get. but the details.exception is empty.

actually, i am nesting virtual pages, these are my models:

there are different pages for different “seasons”. from a spreadsheet, virtual pages for the fabrics the products are made of are created. the model season.php is:

  <?php

  class SeasonPage extends Page
  {

    public function children()
    {
        $csv      = csv($this->kirby()->root() . '/products.csv', ';');

        $children = [];

        foreach ($csv as $product) {

            if ($this->slug() === $product['hauptsaison']) {
                $children[] = [
                    'slug'     => Str::slug($product['vkfarb']),
                    'template' => 'fabric',
                    'model'    => 'fabric',
                    'children' => [],
                    'num'      => 0,
                    'content'  => [
                        'title'        => $product['vkfarb'],
                    ]
                ];
            }
        }

        return Pages::factory($children, $this);
    }

}

inside the fabrics pages, the product pages are generated. the model fabric.php is:

<?php

class FabricPage extends Page
{

    public function subpages()
    {
        return Pages::factory($this->inventory()['children'], $this);
    }

    public function children()
    {
        $csv      = csv($this->kirby()->root() . '/products.csv', ';');

        $children = [];

        foreach ($csv as $product) {

            $slug = Str::slug($product['product_name']);
            $page = $this->subpages()->find($slug);

            if ($this->parent()->slug() === $product['hauptsaison'] && $this->title()->toString() === $product['vkfarb']) {
                $children[] = [
                    'slug'     => Str::slug($product['product_name']),
                    'template' => 'variable',
                    'model'    => 'variable',
                    'children' => $page ? $page->children()->toArray() : null,
                    'files'    => $page ? $page->files()->toArray() : null,
                    'num'      => 0,
                    'content'  => [
                        'title'        => $product['product_name'],
                        'sku'          => $product['sku'],
                        'simples_skus' => $product['simples_skus'],
                        'body'         => $product['materialzusammensetzung'],
                        'lining'       => $product['futter'],
                        'price'        => $product['price'],
                        'style'        => $product['artikelgruppe'],
                        'isinstock'    => $product['is_in_stock'],
                        'cover'   => $page ? $page->cover()->toArray() : null,
                        'gallery'   => $page ? $page->gallery()->toArray() : null,
                        'saleprice'   => $page ? $page->saleprice()->value() : null,
                        'goeswellwith'   => $page ? $page->goeswellwith()->value() : null,
                        'hidden'   => $page ? $page->hidden()->value() : null,
                        'description'   => $page ? $page->description()->value() : null,
                    ]
                ];
            }
        }

        return Pages::factory($children, $this);
    }

}

and inside the product pages, the variations are generated. the model for variable.php is:

<?php

class VariablePage extends Page
{

    public function subpages()
    {
        return Pages::factory($this->inventory()['children'], $this);
    }

    public function zip()
    {
        return F::unzip($this->kirby()->root() . '/lagerbestand.zip', $this->kirby()->root());
    }

    public function children()
    {
        
        $this->zip();
        $csv      = csv($this->kirby()->root() . '/lagerbestand.csv', ';');
        $children = [];

        foreach ($csv as $variation) {

            $slug = Str::slug($variation['_grkbez']);
            $page = $this->subpages()->find($slug);

            if (strpos($this->simples_skus(), $variation['sku']) !== false) {
                $children[] = [
                    'slug'     => Str::slug($variation['_grkbez']),
                    'template' => 'product',
                    'model'    => 'product',
                    'num'      => 0,
                    'content'  => [
                        'title'       => $this->title() . ' - ' . str_replace('.', '', $variation['_grkbez']),
                        'sku'         => $variation['sku'],
                        'price'       => $this->price(),
                        'size'        => $variation['_grkbez'],
                        'stock'       => ($page && $page->stock()->value() != $variation['qty']) ? $page->stock()->value() : $variation['qty'],
                    ],
                ];
            }
        }

        return Pages::factory($children, $this);
    }

}

so the id of a product variation in the end will be: {season}/{fabric}/{product name}/{size}.

i hope this makes sense haha. thank you in advance for any help!

Hi @tobiasfabian I placed this in the config file:

<?php
	return [
		'hooks' => [
			'ww.merx.completePayment:after' => function ($orderPage) {
				$invoiceNumber = 0;
				if ($prevOrder = $orderPage->prevListed()) {
					$invoiceNumber = (int)$prevOrder->invoiceNumber();
				}
				$invoiceNumber = $invoiceNumber + 1;
				$orderPage->update([
					'invoiceNumber' => $invoiceNumber,
				]);
				sendConfirmationMail($orderPage);
				sendNewOrderToAdmin($orderPage);
			}
		]
	]
?>

@tobiasfabian update:

I removed the last model variable.php and now add the variations to a structure field from the csv. this works!

I used the solution you suggested here: https://github.com/wagnerwagner/merx/issues/18

thanks a lot!

1 Like

Can anybody give some advice or tips about the paypal implementation?

I just created a sandbox app on the PayPal developer page and simply added the clientID and secret into the according files. Credit-card is already working and I didn’t change anything on the methods or routes (formCheckout.js, and config-files are the same as the ones from babyreport), so I kinda expected to get everything working but the error I am getting is:

code: 500
details: {message: "{"error":"invalid_client","error_description":"Client Authentication failed"}"}
exception: "Kirby\Exception\Exception"
file: "site/plugins/merx/src/merx.php"
key: "error.merx.initializePayment"
line: 258
message: "Die Bezahlung konnte nicht initialisiert werden."

The app on paypal is a sandbox app for REST APIs. Are there some key aspects I am probably missing?
Thanks in advance!

Hi there @nurcihandem ,

Did you already added sandbox accounts to try the transaction ?

see here: https://developer.paypal.com/docs/api/overview/#create-sandbox-accounts

Once you create the accounts, you need to test the payment using the fake buyer account.

Or you did that already ?

EDIT I assume you have 'ww.merx.production' => false, on your config, do you ?

The following should work.

You’ve sent the ”old“ $oderPage to your mail function. You have to use the return value of $page->update() (the updated $orderPage) for your mail functions.

<?php
	return [
		'hooks' => [
			'ww.merx.completePayment:after' => function ($orderPage) {
				$invoiceNumber = 0;
				if ($prevOrder = $orderPage->prevListed()) {
					$invoiceNumber = (int)$prevOrder->invoiceNumber();
				}
				$invoiceNumber = $invoiceNumber + 1;
				$orderPage = $orderPage->update([
					'invoiceNumber' => $invoiceNumber,
				]);
				sendConfirmationMail($orderPage);
				sendNewOrderToAdmin($orderPage);
			}
		]
	]
?>