de tintalimon: pague lo que pueda
This commit is contained in:
parent
a1fd00908b
commit
bba8bfa9aa
3 changed files with 344 additions and 0 deletions
125
_includes/donacion.html
Normal file
125
_includes/donacion.html
Normal file
|
@ -0,0 +1,125 @@
|
|||
{% comment %}
|
||||
Traer la donación pasada como parámetro o la que se haya establecido por
|
||||
defecto para el layout correspondiente.
|
||||
|
||||
product = producto
|
||||
page = post que incluye esta donación
|
||||
icon = ícono del botón
|
||||
class = clases extra para el botón
|
||||
boton = texto opcional para el botón
|
||||
{% endcomment %}
|
||||
{%- assign product = include.product | default: include.page -%}
|
||||
{%- assign donacion = include.page.donacion | default: product.donacion -%}
|
||||
|
||||
<input data-controller="open" data-action="donacion" type="checkbox" id="donacion" class="d_toggler sr-only">
|
||||
<label class="btn-block" for="donacion">
|
||||
<span class="btn {{ include.class }} btn-block">
|
||||
{{ include.boton | default: donacion.boton }}
|
||||
|
||||
{% if include.icon %}
|
||||
<i class="{{ include.icon }}"></i>
|
||||
{% endif %}
|
||||
</span>
|
||||
|
||||
<div class="telon d_share-box"></div>
|
||||
</label>
|
||||
|
||||
<form
|
||||
data-pay-what-you-can-target="form"
|
||||
{% include_cached pay_what_you_can_controller.html product=product url=include.page.pdf.path %}
|
||||
style="z-index: 1011"
|
||||
class="d_share-box pointer-event-none d_toggled d-flex align-items-center justify-content-center"
|
||||
itemscope
|
||||
itemtype="https://schema.org/Offer">
|
||||
<meta itemprop="sku" content="{{ product.sku }}" />
|
||||
<meta itemprop="availableDeliveryMethod" content="http://purl.org/goodrelations/v1#DirectDownload" />
|
||||
<meta itemprop="acceptedPaymentMethod" content="http://purl.org/goodrelations/v1#PayPal" />
|
||||
|
||||
<div class="box inside background-white pointer-event-auto row no-gutters align-items-center justify-content-center p-5">
|
||||
<div class="row">
|
||||
<div class="col-md-9 black font-weight-light lead text-md-justify hyphens-md e-content">
|
||||
{{ donacion.content | markdownify }}
|
||||
</div>
|
||||
|
||||
<div class="col-md-3 d-flex justify-content-center">
|
||||
{% if include.page.image.path %}
|
||||
<picture>
|
||||
<source srcset="{{ include.page.image.path | thumbnail: nil, 370 }}" media="(max-width: 767px)" />
|
||||
<img class="cover shadow w-200px" src="{{ include.page.image.path | thumbnail: nil, 300 }}" loading="lazy" />
|
||||
</picture>
|
||||
{% else %}
|
||||
{% include_cached logo_horizontal.svg %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="col-md-3 mb-3 mb-md-0">
|
||||
<h2>{{ site.i18n.donacion.monto }}</h2>
|
||||
|
||||
<label class="sr-only" for="price">{{ site.i18n.donacion.monto }}</label>
|
||||
<input id="price" name="price" type="number" class="form-control" min="1" value="1" data-name="price" data-action="pay-what-you-can#store" required/>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3 mb-3 mb-md-0">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<input id="currency-ars" type="radio" class="sr-only" name="currency" value="ARS" data-name="currency" data-action="pay-what-you-can#store" required/>
|
||||
<label for="currency-ars" itemprop="priceCurrency" class="d-flex flex-column justify-content-center">
|
||||
<span class="btn border mb-3">ARS</span>
|
||||
|
||||
{% include mp-logo.svg %}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<input id="currency-usd" type="radio" class="sr-only" name="currency" value="USD" data-name="currency" data-action="pay-what-you-can#store" required/>
|
||||
<label for="currency-usd" itemprop="priceCurrency" class="d-flex flex-column justify-content-center">
|
||||
<span class="btn border mb-3">USD</span>
|
||||
|
||||
{% include pp-logo.svg %}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="col-12 text-center">
|
||||
{% comment %}
|
||||
Este input invisible es para que Bootstrap pueda mostrar el
|
||||
error si querés mandar el formulario sin elegir una moneda.
|
||||
{% endcomment %}
|
||||
<input type="radio" class="d-none" name="currency" value="" />
|
||||
<div class="invalid-feedback">
|
||||
{{ site.i18n.donacion.currency }}
|
||||
</div>
|
||||
|
||||
<p data-controller="cart-paypal-confirmation"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<button class="btn btn-primary btn-block mb-2" data-action="pay-what-you-can#pay">
|
||||
<span class="hide-when-disabled">{{ donacion.boton }}</span>
|
||||
<span class="show-when-disabled">
|
||||
<span class="sr-only">{{ site.i18n.donacion.espera }}</span>
|
||||
<i class="fa fa-fw fa-spinner fa-spin"></i>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
{% if include.page.pdf.path %}
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<a
|
||||
download
|
||||
href="{{ include.page.pdf.path | uri_escape }}"
|
||||
class="btn btn-transparent border black btn-block">
|
||||
{{ site.i18n.libro.download }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="col-md-3"></div>
|
||||
|
||||
<div class="col-12">
|
||||
{{ site.i18n.donacion.medios | markdownify | replace: '<p>', '<p class="mb-0 mt-3"><small>' | replace: '</p>', '</small></p>' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
13
_includes/pay_what_you_can_controller.html
Normal file
13
_includes/pay_what_you_can_controller.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
data-controller="pay-what-you-can"
|
||||
data-pay-what-you-can-download-value="{{ include.product.url | present }}"
|
||||
data-pay-what-you-can-url-value="{{ include.url | default: include.product.url }}"
|
||||
data-pay-what-you-can-variant-id-value="{{ include.product.variant_id }}"
|
||||
data-pay-what-you-can-firstname-value="{{ include.product.title }}"
|
||||
data-pay-what-you-can-currency-value="ARS"
|
||||
data-pay-what-you-can-price-value="1"
|
||||
data-image="{{ include.product.image.path | thumbnail: 300 }}"
|
||||
data-title="{{ include.product.title }}"
|
||||
data-price="{{ include.product.price }}"
|
||||
data-in-stock="{{ include.product.in_stock }}"
|
||||
data-stock="{{ include.product.stock }}"
|
||||
data-extra="{{ include.extra | join: '|' }}"
|
206
_packs/controllers/pay_what_you_can_controller.js
Normal file
206
_packs/controllers/pay_what_you_can_controller.js
Normal file
|
@ -0,0 +1,206 @@
|
|||
import { CartBaseController } from './cart_base_controller'
|
||||
|
||||
/*
|
||||
* Al pagar lo que podamos, primero hay que crear una orden y luego
|
||||
* contactarse con la APIv2 para generar la variante con el precio que
|
||||
* queramos agregar. Agregamos la variante al carrito y lanzamos el
|
||||
* proceso de pago.
|
||||
*/
|
||||
export default class extends CartBaseController {
|
||||
static targets = [ 'form' ]
|
||||
static values = {
|
||||
variantId: Number,
|
||||
currency: String,
|
||||
price: Number,
|
||||
firstname: String
|
||||
}
|
||||
|
||||
connect () {
|
||||
this.paymentMethodByCurrency = {
|
||||
ARS: 'Spree::PaymentMethod::MercadoPago',
|
||||
USD: 'Spree::PaymentMethod::Paypal'
|
||||
}
|
||||
}
|
||||
|
||||
store (event) {
|
||||
const target = event.currentTarget || event.target
|
||||
|
||||
this[`${target.dataset.name}Value`] = target.value
|
||||
}
|
||||
|
||||
set formDisable (disable) {
|
||||
this.formTarget.elements.forEach(x => x.disabled = disable)
|
||||
}
|
||||
|
||||
/*
|
||||
* Realiza todos los pasos:
|
||||
*
|
||||
* * Crear pedido
|
||||
* * Crear variante con el monto y moneda
|
||||
* * Agregar al pedido
|
||||
* * Agregar dirección al pedido
|
||||
* * Obtener métodos de envío
|
||||
* * Obtener métodos de pago
|
||||
* * Pagar
|
||||
* * Reenviar a confirmación
|
||||
* * Ejecutar el pago (si aplica)
|
||||
*/
|
||||
async pay (event = undefined) {
|
||||
if (event) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
if (!this.formTarget.checkValidity()) {
|
||||
this.formTarget.classList.add('was-validated')
|
||||
return
|
||||
}
|
||||
|
||||
this.formDisable = true
|
||||
|
||||
// Crear pedido. Todos los pedidos van a ser hechos desde
|
||||
// Argentina, no hay forma de cambiar esto.
|
||||
const orderToken = await this.tempCartCreate()
|
||||
const quantity = 1
|
||||
const include = 'line_items'
|
||||
const currency = this.currencyValue
|
||||
const price = this.priceValue
|
||||
const email = 'noreply@sutty.nl'
|
||||
const firstname = this.firstnameValue
|
||||
const lastname = '-'
|
||||
const address1 = '-'
|
||||
const country_id = 250 // XXX: Internet
|
||||
const city = '-'
|
||||
const phone = '11111111'
|
||||
const zipcode = '1111'
|
||||
const ship_address_attributes = { firstname, lastname, address1, city, country_id, zipcode, phone }
|
||||
const bill_address_attributes = ship_address_attributes
|
||||
const confirmation_delivered = true
|
||||
const custom_return_url = this.customReturnUrl()
|
||||
|
||||
let variant_id = this.variantIdValue
|
||||
|
||||
// Crear la variante
|
||||
const payWhatYouCanResponse = await this.spree.sutty.payWhatYouCan({ orderToken }, { variant_id, price, currency, quantity })
|
||||
|
||||
variant_id = payWhatYouCanResponse.data.id
|
||||
|
||||
if (!variant_id) {
|
||||
this.formDisable = false
|
||||
console.error('No se pudo generar la variante', { variant_id, price, currency, quantity })
|
||||
return
|
||||
}
|
||||
|
||||
// Configurar la moneda del pedido
|
||||
let response = await this.spree.sutty.updateOrder({ orderToken }, { currency, confirmation_delivered, custom_return_url })
|
||||
|
||||
if (response.status > 299) {
|
||||
console.error(response)
|
||||
this.formDisable = false
|
||||
return
|
||||
}
|
||||
|
||||
// Agregar al carrito
|
||||
response = await this.spree.cart.addItem({ orderToken }, { variant_id, quantity, include })
|
||||
|
||||
if (response.isFail()) {
|
||||
this.handleFailure(response)
|
||||
this.formDisable = false
|
||||
return
|
||||
}
|
||||
|
||||
// Actualizar la dirección
|
||||
response = await this.spree.checkout.orderUpdate({ orderToken }, { order: { email, ship_address_attributes, bill_address_attributes }})
|
||||
|
||||
if (response.isFail()) {
|
||||
this.handleFailure(response)
|
||||
this.formDisable = false
|
||||
return
|
||||
}
|
||||
|
||||
// Obtener los medios de envío
|
||||
response = await this.spree.checkout.shippingMethods({ orderToken }, { include: 'shipping_rates' })
|
||||
|
||||
if (response.isFail()) {
|
||||
this.handleFailure(response)
|
||||
this.formDisable = false
|
||||
return
|
||||
}
|
||||
|
||||
// Elegir medio de envío
|
||||
response = await this.spree.checkout.orderUpdate({ orderToken }, {
|
||||
order: {
|
||||
shipments_attributes: [{
|
||||
id: response.success().data[0].id,
|
||||
selected_shipping_rate_id: response.success().included.filter(x => x.type == 'shipping_rate')[0].id
|
||||
}]
|
||||
}
|
||||
})
|
||||
|
||||
// Elegir medio de pago
|
||||
response = await this.spree.checkout.paymentMethods({ orderToken })
|
||||
|
||||
if (response.isFail()) {
|
||||
this.handleFailure(response)
|
||||
this.formDisable = false
|
||||
return
|
||||
}
|
||||
|
||||
const payment_method_id = response.success().data.find(x => this.paymentMethodByCurrency[this.currencyValue] == x.attributes.type).id
|
||||
|
||||
response = await this.spree.checkout.orderUpdate({ orderToken },
|
||||
{
|
||||
order: { payments_attributes: [{ payment_method_id }] },
|
||||
payment_source: {
|
||||
[payment_method_id]: {
|
||||
name: 'Pepitx',
|
||||
month: 12,
|
||||
year: 2021
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (response.isFail()) {
|
||||
this.handleFailure(response)
|
||||
this.formDisable = false
|
||||
return
|
||||
}
|
||||
|
||||
response = await this.spree.checkout.complete({ orderToken })
|
||||
|
||||
if (response.isFail()) {
|
||||
this.handleFailure(response)
|
||||
this.formDisable = false
|
||||
return
|
||||
}
|
||||
|
||||
// Reenviar al medio de pago
|
||||
const checkoutUrls = await this.spree.sutty.getCheckoutURL({ orderToken })
|
||||
const redirectUrl = checkoutUrls.data[0]
|
||||
|
||||
Turbolinks.visit(redirectUrl)
|
||||
|
||||
// Volver
|
||||
}
|
||||
|
||||
async tempCartCreate () {
|
||||
const response = await this.spree.cart.create()
|
||||
|
||||
// If we fail here it's probably a server error, so we inform the
|
||||
// user.
|
||||
if (response.isFail()) {
|
||||
this.handleFailure(response)
|
||||
return
|
||||
}
|
||||
|
||||
return response.success().data.attributes.token
|
||||
}
|
||||
|
||||
// @return [String]
|
||||
customReturnUrl () {
|
||||
const url = new URL(window.location.href)
|
||||
url.searchParams.set('open', '')
|
||||
|
||||
return url.toString()
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue