Last active
July 20, 2023 19:03
-
-
Save Frank-Magmodules/ef3cb88ecbcd58b55ebe6769331583ed to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdn.tailwindcss.com"></script> | |
<script src="https://unpkg.com/vue@3"></script> | |
<script src="https://js.mollie.com/v1/mollie.js"></script> | |
<div class="mx-auto container mb-20"> | |
<div id="app"> | |
<div v-if="hasError" class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert"> | |
<span class="block sm:inline" v-text="errorMessage"></span> | |
</div> | |
<div class="border bg-gray-200 p-2 mb-4 mt-4"> | |
<dl class="grid grid-cols-1 gap-x-4 gap-y-8 sm:grid-cols-2"> | |
<div class="sm:col-span-1"> | |
<dt class="text-sm font-medium text-gray-500">Profile ID (required)</dt> | |
<dd class="mt-1 text-sm text-gray-900"><input class="border px-2" type="text" v-model="profileId"></dd> | |
</div> | |
<div class="sm:col-span-1"> | |
<dt class="text-sm font-medium text-gray-500"> | |
Mode | |
<span class="text-xs">(Must match <code>payment/mollie_general/type</code>)</span> | |
</dt> | |
<dd class="mt-1 text-sm text-gray-900"> | |
<label><input type="radio" value="live" name="mode" v-model="mode"> Live</label><br> | |
<label><input type="radio" value="test" name="mode" v-model="mode"> Test</label> | |
</dd> | |
</div> | |
<div class="sm:col-span-1"> | |
<dt class="text-sm font-medium text-gray-500">CurrentStep</dt> | |
<dd class="mt-1 text-sm text-gray-900">{{ currentStep }}</dd> | |
</div> | |
<div class="sm:col-span-1"> | |
<dt class="text-sm font-medium text-gray-500">CartId</dt> | |
<dd class="mt-1 text-sm text-gray-900">{{ cartId }}</dd> | |
</div> | |
</dl> | |
</div> | |
<ul> | |
<li> | |
<svg v-if="!paused && !hasError && currentStep == 1" class="animate-spin h-5 w-5 text-black inline-block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg> | |
<svg v-if="!hasError && currentStep > 1" class="h-5 w-5 text-black inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"></path></svg> | |
Create cart | |
<span v-if="cartIdFromStorage"> | |
(from storage) | |
</span> | |
</li> | |
<li> | |
<svg v-if="!paused && !hasError && currentStep == 2" class="animate-spin h-5 w-5 text-black inline-block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg> | |
<svg v-if="!hasError && currentStep > 2" class="h-5 w-5 text-black inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"></path></svg> | |
Add product to cart | |
</li> | |
<li> | |
<svg v-if="!paused && !hasError && currentStep == 3" class="animate-spin h-5 w-5 text-black inline-block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg> | |
<svg v-if="!hasError && currentStep > 3" class="h-5 w-5 text-black inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"></path></svg> | |
Add shipping & billing address | |
</li> | |
<li> | |
<svg v-if="!paused && !hasError && currentStep == 4" class="animate-spin h-5 w-5 text-black inline-block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg> | |
<svg v-if="!hasError && currentStep > 4" class="h-5 w-5 text-black inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"></path></svg> | |
Get shippings methods <span v-if="shippingMethod">({{ shippingMethod }})</span> | |
</li> | |
<li> | |
<svg v-if="!paused && !hasError && currentStep == 5" class="animate-spin h-5 w-5 text-black inline-block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg> | |
<svg v-if="!hasError && currentStep > 5" class="h-5 w-5 text-black inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"></path></svg> | |
Set shipping method | |
</li> | |
<li> | |
<svg v-if="!paused && !hasError && currentStep == 6" class="animate-spin h-5 w-5 text-black inline-block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg> | |
<svg v-if="!hasError && currentStep > 6" class="h-5 w-5 text-black inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"></path></svg> | |
Get payment methods | |
</li> | |
<li> | |
<svg v-if="!paused && !hasError && currentStep == 7" class="animate-spin h-5 w-5 text-black inline-block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg> | |
<svg v-if="!hasError && currentStep > 7" class="h-5 w-5 text-black inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"></path></svg> | |
Set the payment method | |
</li> | |
<li> | |
<svg v-if="!paused && !hasError && currentStep == 8" class="animate-spin h-5 w-5 text-black inline-block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg> | |
<svg v-if="!hasError && currentStep > 8" class="h-5 w-5 text-black inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"></path></svg> | |
Place order | |
</li> | |
<li> | |
<svg v-if="!paused && !hasError && currentStep == 9" class="animate-spin h-5 w-5 text-black inline-block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg> | |
<svg v-if="!hasError && currentStep > 9" class="h-5 w-5 text-black inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"></path></svg> | |
Check transaction | |
</li> | |
</ul> | |
<div v-if="orderId"> | |
<div class="rounded-md bg-green-50 p-4"> | |
<div class="flex"> | |
<div class="flex-shrink-0"> | |
<!-- Heroicon name: solid/check-circle --> | |
<svg class="h-5 w-5 text-green-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> | |
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" /> | |
</svg> | |
</div> | |
<div class="ml-3"> | |
<h3 class="text-sm font-medium text-green-800">Order done!</h3> | |
<div class="mt-2 text-sm text-green-700"> | |
<p><strong>Order ID:</strong> {{ orderId }}</p> | |
<p class="mt-4 font-bold">1. Please open this url and select a payment status (or not):</p> | |
<a v-bind:href="redirectUrl" target="_blank">{{ redirectUrl }}</a><br> | |
<p class="mt-4 font-bold">2. When you have opened the url, click here to get the payment status:</p> | |
<button @click="currentStep === 9 && checkTransactionStatus()" type="button" class="mt-4 inline-flex items-center px-2.5 py-1.5 border border-transparent text-xs font-medium rounded shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"> | |
Process Transaction | |
<svg v-if="checkingPaymentStatus" class="ml-2 animate-spin h-4 w-4 text-white inline-block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg> | |
</button> | |
<div class="mt-4" v-if="paymentStatus"> | |
<span class="font-bold">PaymentStatus</span>: {{ paymentStatus }}<br> | |
<span class="font-bold">redirect_to_cart</span>: {{ redirectToCart ? 'true' : 'false' }}<br> | |
<span class="font-bold">redirect_to_success_page</span>: {{ redirectToSuccessPage ? 'true' : 'false' }}<br> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div v-if="mollieMethods && currentStep === 6" class="grid gap-x-8 gap-y-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 mt-8"> | |
<div | |
v-for="method in mollieMethods" | |
@click="setMethod(method.code)" | |
v-bind:class="{'bg-gray-300': selectedMethod === method.code}" | |
class="bg-gray-200 hover:bg-gray-300 cursor-pointer p-2" | |
> | |
<img v-bind:src="method.mollie_meta.image" /> | |
{{ method.title }} | |
<span v-if="selectedMethod === method.code && method.mollie_available_issuers"> | |
<ul> | |
<li v-for="issuer in method.mollie_available_issuers"> | |
<label @click="setIssuer(issuer.code)"> | |
<input type="radio" :checked="selectedIssuer === issuer.code" /> | |
{{ issuer.name }} | |
</label> | |
</li> | |
</ul> | |
</span> | |
<div | |
v-if="method.code === 'mollie_methods_creditcard'" | |
v-show="selectedMethod === method.code" | |
class="pt-4" | |
> | |
<div class="mb-4"> | |
<div class="text-small text-gray-600">Card Number</div> | |
<div class="bg-white py-2 px-2" ref="cardNumber"></div> | |
<div | |
class="p-2 mt-2 bg-red-300 border border-red-400 text-red-800" | |
ref="cardNumberError" | |
v-show="cardNumberError" | |
></div> | |
</div> | |
<div class="mb-4"> | |
<div class="text-small text-gray-600">Card Holder</div> | |
<div class="bg-white py-2 px-2" ref="cardHolder"></div> | |
<div | |
class="p-2 mt-2 bg-red-300 border border-red-400 text-red-800" | |
ref="cardHolderError" | |
v-show="cardHolderError" | |
></div> | |
</div> | |
<div class="mb-4"> | |
<div class="text-small text-gray-600">Expiry Date</div> | |
<div class="bg-white py-2 px-2" ref="expiryDate"></div> | |
<div | |
class="p-2 mt-2 bg-red-300 border border-red-400 text-red-800" | |
ref="expiryDateError" | |
v-show="expiryDateError" | |
></div> | |
</div> | |
<div class="mb-4"> | |
<div class="text-small text-gray-600">CVV</div> | |
<div class="bg-white py-2 px-2" ref="verificationCode"></div> | |
<div | |
class="p-2 mt-2 bg-red-300 border border-red-400 text-red-800" | |
ref="verificationCodeError" | |
v-show="verificationCodeError" | |
></div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div v-if="paused && currentStep === 6 && selectedMethod" class="mt-8"> | |
<div> | |
<button @click="callPlaceOrder()" type="button" class="inline-flex items-center px-2.5 py-1.5 border border-transparent text-xs font-medium rounded shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">Place order</button> | |
</div> | |
</div> | |
<div v-if="paused && !hasError && currentStep === 8" class="mt-8"> | |
<div> | |
<button @click="currentStep === 8 && callNextStep()" type="button" class="inline-flex items-center px-2.5 py-1.5 border border-transparent text-xs font-medium rounded shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">Place order</button> | |
</div> | |
Continue!? | |
</div> | |
</div> | |
</div> | |
<script> | |
async function graphql(query, variables) { | |
const data = JSON.stringify({ | |
query, | |
variables, | |
}); | |
const response = await fetch( | |
'/graphql', | |
{ | |
credentials: "same-origin", | |
method: 'post', | |
body: data, | |
headers: { | |
'Content-Type': 'application/json', | |
'Content-Length': data.length, | |
}, | |
} | |
); | |
return await response.json(); | |
} | |
</script> | |
<script> | |
const { createApp } = Vue | |
createApp({ | |
data() { | |
return { | |
mode: 'test', | |
cartId: null, | |
cartIdFromStorage: false, | |
currentStep: 0, | |
orderId: null, | |
paused: false, | |
hasError: false, | |
errorMessage: '', | |
shippingMethod: '', | |
mollieMethods: [], | |
selectedMethod: null, | |
selectedIssuer: null, | |
redirectUrl: null, | |
paymentToken: null, | |
mollie: null, | |
fieldsMounted: false, | |
cardNumberError: false, | |
cardHolderError: false, | |
expiryDateError: false, | |
verificationCodeError: false, | |
componentsToken: null, | |
profileId: null, | |
checkingPaymentStatus: false, | |
paymentStatus: null, | |
redirectToCart: null, | |
redirectToSuccessPage: null, | |
} | |
}, | |
async mounted() { | |
this.getProfileIdFromLocalStorage(); | |
}, | |
watch: { | |
selectedMethod(method) { | |
if (method !== 'mollie_methods_creditcard' || this.fieldsMounted) { | |
return; | |
} | |
this.addComponentField('cardNumber'); | |
this.addComponentField('cardHolder'); | |
this.addComponentField('expiryDate'); | |
this.addComponentField('verificationCode'); | |
this.fieldsMounted = true; | |
console.info('Mollie Component fields mounted'); | |
}, | |
profileId(profileId) { | |
if (!profileId) { | |
return; | |
} | |
localStorage.setItem('mollie_profile_id', profileId); | |
this.loadMollieComponents(); | |
this.callNextStep(); | |
} | |
}, | |
methods: { | |
loadMollieComponents() { | |
this.mollie = Mollie(this.profileId, { locale: 'nl_NL', testmode: this.mode == 'test' }); | |
}, | |
getProfileIdFromLocalStorage() { | |
const profileId = localStorage.getItem('mollie_profile_id'); | |
if (profileId) { | |
this.profileId = profileId; | |
this.loadMollieComponents(); | |
} | |
}, | |
async callPlaceOrder() { | |
if (this.selectedMethod !== 'mollie_methods_creditcard') { | |
this.currentStep === 6; | |
this.callNextStep(); | |
return; | |
} | |
var { token, error } = await this.mollie.createToken(); | |
if (error) { | |
// Something wrong happened while creating the token. Handle this situation gracefully. | |
this.hasError = 'One or more fields are invalid.'; | |
this.errorMessage = error.message; | |
this.componentsToken = null; | |
return; | |
} | |
this.componentsToken = token; | |
this.currentStep === 6; | |
this.callNextStep(); | |
}, | |
addComponentField(name) { | |
const field = this.mollie.createComponent(name); | |
field.mount(this.$refs[name][0]); | |
field.addEventListener('change', event => { | |
if (event.error && event.touched) { | |
this.$refs[`${name}Error`][0].textContent = event.error; | |
this[`${name}Error`] = true | |
} else { | |
this.$refs[`${name}Error`][0].textContent = ''; | |
this[`${name}Error`] = false | |
} | |
}); | |
}, | |
setMethod(method) { | |
this.selectedMethod = method; | |
}, | |
setIssuer(issuer) { | |
this.selectedIssuer = issuer; | |
}, | |
async callNextStep() { | |
if (this.hasError) { | |
return; | |
} | |
this.paused = false; | |
if (this.currentStep === 0) { | |
await this.getCart(); | |
} | |
if (this.currentStep === 1) { | |
await this.addProductToCart(); | |
} | |
if (this.currentStep === 2) { | |
await this.setShippingAndBillingAddress(); | |
} | |
if (this.currentStep === 3) { | |
await this.getShippingMethods(); | |
} | |
if (this.currentStep === 4) { | |
await this.setShippingMethodOnCart(); | |
} | |
if (this.currentStep === 5) { | |
await this.getPaymentMethods(); | |
} | |
if (this.currentStep === 6) { | |
await this.setPaymentMethodOnCart(); | |
} | |
if (this.currentStep === 7) { | |
await this.setGuestEmailOnCart(); | |
} | |
if (this.currentStep === 8) { | |
await this.placeOrder(); | |
} | |
// 0. Create cart | |
// 1. Add product to cart | |
// 2. Add shipping & billing address | |
// 3. Get shippings methods | |
// 4. Set shipping method | |
// 5. Get payment methods | |
// 6. Set the payment method | |
// 7. Set guest email | |
// 8. Place order | |
// 9. Check transaction | |
if (this.currentStep === 9) { | |
await this.checkTransactionStatus(); | |
} | |
this.currentStep++; | |
}, | |
async getCart() { | |
const cartId = localStorage.getItem('cartId'); | |
if (!cartId) { | |
this.createEmptyCart(); | |
return; | |
} | |
graphql( | |
` | |
query getCart($cartId: String!) { | |
cart(cart_id: $cartId) { | |
id | |
} | |
} | |
`, | |
{ | |
cartId, | |
} | |
).then(response => { | |
if (!response.data.cart) { | |
this.createEmptyCart(); | |
return; | |
} | |
this.cartId = cartId; | |
this.cartIdFromStorage = true; | |
this.currentStep++; | |
this.callNextStep(); | |
}); | |
}, | |
async createEmptyCart() { | |
graphql(` | |
mutation { | |
createEmptyCart | |
} | |
`).then(response => { | |
this.cartId = response.data.createEmptyCart; | |
this.callNextStep(); | |
localStorage.setItem('cartId', this.cartId); | |
}); | |
}, | |
async addProductToCart() { | |
if (this.cartIdFromStorage) { | |
this.currentStep++; | |
this.callNextStep(); | |
return; | |
} | |
graphql(` | |
mutation addSimpleProductsToCart($cartId: String!, $sku: String!) { | |
addSimpleProductsToCart( | |
input: { | |
cart_id: $cartId, | |
cart_items: [ | |
{ | |
data: { | |
quantity: 1 | |
sku: $sku | |
} | |
} | |
] | |
} | |
) { | |
cart { | |
items { | |
id | |
product { | |
sku | |
stock_status | |
} | |
quantity | |
} | |
} | |
} | |
} | |
`, | |
{ | |
cartId: this.cartId, | |
sku: '24-WB02', | |
} | |
).then(response => { | |
if (response.errors) { | |
this.hasError = true; | |
this.errorMessage = response.errors[0].debugMessage || response.errors[0].message; | |
throw new Error(response.errors[0].debugMessage || response.errors[0].message); | |
} | |
this.callNextStep(); | |
}); | |
}, | |
async setShippingAndBillingAddress() { | |
graphql(` | |
mutation setBillingAddressOnCart($cartId: String!) { | |
setBillingAddressOnCart( | |
input: { | |
cart_id: $cartId | |
billing_address: { | |
address: { | |
firstname: "Michiel" | |
lastname: "Gerritsen" | |
company: "Control Alt Delete" | |
street: ["Hoofdweg", "95A"] | |
city: "De Cocksdorp" | |
postcode: "1795JC" | |
country_code: "NL" | |
telephone: "123-456-0000" | |
save_in_address_book: false | |
} | |
use_for_shipping: true | |
} | |
} | |
) { | |
cart { | |
billing_address { | |
firstname | |
lastname | |
company | |
street | |
city | |
postcode | |
telephone | |
country { | |
code | |
label | |
} | |
} | |
shipping_addresses { | |
firstname | |
lastname | |
company | |
street | |
city | |
postcode | |
telephone | |
country { | |
code | |
label | |
} | |
} | |
} | |
} | |
} | |
`, | |
{ | |
cartId: this.cartId, | |
} | |
).then(response => { | |
if (response.errors) { | |
this.hasError = true; | |
this.errorMessage = response.errors[0].debugMessage; | |
throw new Error(response.errors[0].debugMessage); | |
} | |
this.callNextStep(); | |
}); | |
}, | |
async getShippingMethods() { | |
graphql(` | |
query($cartId: String!) { | |
cart(cart_id: $cartId) { | |
shipping_addresses { | |
available_shipping_methods { | |
error_message | |
method_code | |
method_title | |
} | |
} | |
} | |
} | |
`, | |
{ | |
cartId: this.cartId | |
}).then(response => { | |
if (response.errors) { | |
this.hasError = true; | |
this.errorMessage = response.errors[0].debugMessage; | |
throw new Error(response.errors[0].debugMessage); | |
} | |
const method = response.data.cart.shipping_addresses[0].available_shipping_methods[0]; | |
this.shippingMethod = method.method_code; | |
this.callNextStep(); | |
}); | |
}, | |
async setShippingMethodOnCart() { | |
graphql(` | |
mutation setShippingMethodsOnCart($cartId: String! $method: String!) { | |
setShippingMethodsOnCart(input: { | |
cart_id: $cartId | |
shipping_methods: [ | |
{ | |
carrier_code: $method | |
method_code: $method | |
} | |
] | |
}) { | |
cart { | |
shipping_addresses { | |
selected_shipping_method { | |
carrier_code | |
method_code | |
carrier_title | |
method_title | |
} | |
} | |
} | |
} | |
} | |
`, | |
{ | |
cartId: this.cartId, | |
method: this.shippingMethod, | |
} | |
).then(response => { | |
if (response.errors) { | |
this.hasError = true; | |
this.errorMessage = response.errors[0].debugMessage || response.errors[0].message; | |
throw new Error(response.errors[0].debugMessage); | |
} | |
this.callNextStep(); | |
}); | |
}, | |
async setGuestEmailOnCart() { | |
graphql(` | |
mutation setGuestEmailOnCart($cartId: String!) { | |
setGuestEmailOnCart(input: { | |
cart_id: $cartId | |
email: "guest@example.com" | |
}) { | |
cart { | |
} | |
} | |
} | |
`, | |
{ | |
cartId: this.cartId, | |
} | |
).then(response => { | |
if (response.errors) { | |
this.hasError = true; | |
this.errorMessage = response.errors[0].debugMessage; | |
throw new Error(response.errors[0].debugMessage); | |
} | |
this.callNextStep(); | |
}); | |
}, | |
async getPaymentMethods() { | |
graphql(` | |
query($cartId: String!) { | |
cart(cart_id: $cartId) { | |
available_payment_methods { | |
code | |
title | |
mollie_meta { | |
image | |
} | |
mollie_available_issuers { | |
name | |
code | |
image | |
svg | |
} | |
} | |
} | |
} | |
`, { | |
cartId: this.cartId, | |
}).then(response => { | |
if (response.errors) { | |
this.hasError = true; | |
this.errorMessage = response.errors[0].debugMessage; | |
throw new Error(response.errors[0].debugMessage); | |
} | |
this.paused = true; | |
const methods = response.data.cart.available_payment_methods; | |
this.mollieMethods = methods.filter(element => element.code.indexOf('mollie_methods_') === 0); | |
if (!this.mollieMethods) { | |
alert('No Mollie payment method found. Please check if they are activated'); | |
return; | |
} | |
}); | |
}, | |
async setPaymentMethodOnCart() { | |
graphql(` | |
mutation setPaymentMethodOnCart( | |
$cartId: String! | |
$method: String! | |
$issuer: String | |
$componentsToken: String | |
) { | |
setPaymentMethodOnCart(input: { | |
cart_id: $cartId | |
payment_method: { | |
code: $method | |
mollie_card_token: $componentsToken | |
mollie_selected_issuer: $issuer | |
} | |
}) { | |
cart { | |
selected_payment_method { | |
code | |
} | |
} | |
} | |
} | |
`, | |
{ | |
cartId: this.cartId, | |
method: this.selectedMethod, | |
issuer: this.selectedIssuer, | |
componentsToken: this.componentsToken, | |
} | |
).then(response => { | |
console.log('setPaymentMethodOnCart', response); | |
if (response.errors) { | |
this.hasError = true; | |
this.errorMessage = response.errors[0].debugMessage || response.errors[0].message; | |
throw new Error(response.errors[0].debugMessage); | |
} | |
this.callNextStep(); | |
}); | |
}, | |
async placeOrder() { | |
graphql(` | |
mutation placeOrder($cartId: String!) { | |
placeOrder(input: { | |
cart_id: $cartId | |
}) { | |
order { | |
order_id | |
mollie_redirect_url | |
mollie_payment_token | |
} | |
} | |
} | |
`, | |
{ | |
cartId: this.cartId, | |
} | |
).then(response => { | |
if (response.errors) { | |
this.hasError = true; | |
this.errorMessage = response.errors[0].debugMessage; | |
throw new Error(response.errors[0].debugMessage); | |
} | |
this.orderId = response.data.placeOrder.order.order_id; | |
this.redirectUrl = response.data.placeOrder.order.mollie_redirect_url | |
this.paymentToken = response.data.placeOrder.order.mollie_payment_token | |
this.paused = true; | |
}) | |
}, | |
async checkTransactionStatus() { | |
this.checkingPaymentStatus = true; | |
graphql(` | |
mutation($paymentToken: String!) { | |
mollieProcessTransaction(input: { | |
payment_token: $paymentToken | |
}) { | |
paymentStatus | |
redirect_to_cart | |
redirect_to_success_page | |
} | |
} | |
`, { | |
paymentToken: this.paymentToken | |
}).then(response => { | |
this.checkingPaymentStatus = false; | |
if (response.errors) { | |
this.hasError = true; | |
this.errorMessage = response.errors[0].debugMessage; | |
throw new Error(response.errors[0].debugMessage); | |
} | |
const data = response.data.mollieProcessTransaction; | |
this.paymentStatus = data.paymentStatus; | |
this.redirectToCart = data.redirect_to_cart; | |
this.redirectToSuccessPage = data.redirect_to_success_page; | |
this.paused = true; | |
}) | |
} | |
} | |
}).mount('#app') | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment