1

I have been trying to hide checkout process of my saleor site, because I think the process choosing payment gateway before payment could make people confused.

I have searched a lot of documents and tried to understand and modified codes related to payment process for almost a week. It was not successful because of my poor understanding of django framework.

Please, help me and let me know some hints about where and what should I look into. If it is possible, teach me how to set default payment gateway and hide options for choosing payment gateway.

I think it is related to three files.

  1. saleor/templates/order/pavement.html By modifying pavement template, I succeed in making default payment gateway and hiding radio buttons but whenever it was hidden, payment processing was also not proceed( In successful payment, the url should be changed from 'http://127.0.0.1:8000/ko/order/[ order token ]/payment/' to 'http://127.0.0.1:8000/ko/order/[ order token ]/payment/[ payment gateway name ]/' but when I hided radio button, the url was not changed. )

  2. saleor/saleor/order/views.py

  3. saleor/saleor/order/forms.py

    I guessed the payment gateway information is transferring from payment.html to start_payment function of views.py and somewhat related to PaymentsForms class in forms.py. I have been trying to analysis and understand these codes but I got stuck.

some part of code in 'saleor/templates/order/pavement.html'

            <h3>
              <b>{% trans "Choose payment method" %}</b>
            </h3>
            <div class="checkout__payment-form">
              <form method="post" action="{% url "order:payment" token=order.token %}" class="payment-form radio">
                {% csrf_token %}
                {% for choice in payment_form.gateway %}
                  <div class="radio checkout__payment-form__choice">
                    <label>
                      <div class="card card-default">
                        <div class="card-body">
                          <strong>
                            {{choice}}
                          </strong>
                        </div>
                      </div>
                    </label>
                  </div>
                {% endfor %}
                {% block form_submit %}
                  <button type="submit" class="btn btn-primary">
                    {% trans "Proceed to payment" context "Payment details primary action" %}
                  </button>
                {% endblock %}
              </form>
            </div>

'start_payment' function in 'saleor/saleor/order/views.py'

@check_order_status
def start_payment(request, order, gateway):
    payment_gateway, connection_params = get_payment_gateway(gateway)
    #payment_gateway, connection_params = get_payment_gateway('Dummy gateway')
    extra_data = {'customer_user_agent': request.META.get('HTTP_USER_AGENT')}
    with transaction.atomic():
        payment = create_payment(
            gateway=gateway,
            currency=order.total.gross.currency,
            email=order.user_email,
            billing_address=order.billing_address,
            customer_ip_address=get_client_ip(request),
            total=order.total.gross.amount,
            order=order,
            extra_data=extra_data)

        if (order.is_fully_paid()
                or payment.charge_status == ChargeStatus.FULLY_REFUNDED):
            return redirect(order.get_absolute_url())

        payment_info = create_payment_information(payment)
        form = payment_gateway.create_form(
            data=request.POST or None,
            payment_information=payment_info,
            connection_params=connection_params)
        if form.is_valid():
            try:
                gateway_process_payment(
                    payment=payment, payment_token=form.get_payment_token())
            except Exception as exc:
                form.add_error(None, str(exc))
            else:
                if order.is_fully_paid():
                    return redirect('order:payment-success', token=order.token)
                return redirect(order.get_absolute_url())

    client_token = payment_gateway.get_client_token(
        connection_params=connection_params)
    ctx = {
        'form': form,
        'payment': payment,
        'client_token': client_token,
        'order': order}
    return TemplateResponse(request, payment_gateway.TEMPLATE_PATH, ctx)

'PaymentsForms' class in 'saleor/saleor/order/forms.py'

PAYMENT_CHOICES = [
    (k, v) for k, v in settings.CHECKOUT_PAYMENT_GATEWAYS.items()]


class PaymentsForm(forms.Form):
    gateway = forms.ChoiceField(
        label=pgettext_lazy('Payments form label', 'Payment Method'),
        choices=PAYMENT_CHOICES,
        initial=PAYMENT_CHOICES[0][0],
        widget=forms.RadioSelect)

I tried to set default payment gateway and hide radio box for choosing payment gateways, but failed.

  • See [my answer here](https://stackoverflow.com/a/49628788/2689986). Particularly the `PaymentMethodView.get` method. It checks if there is only one method (you can put your own logic here to set the default method) & if there is only one method, it just redirects (& sets default method) to the next step in the checkout process, else, renders the payment method form (with choice / radio button). You don't need to hide anything in your form or template, just modify the logic inside that view class's `get` method. – shad0w_wa1k3r Apr 27 '19 at 13:36

1 Answers1

0

I resolved your issue by modifying only few lines of code.

I started choosing only one payment gateway (for me: BrainTree), to do so you have to insert only the payment gateway that you want to allow in you e-commerce. Modify the dict CHECKOUT_PAYMENT_GATEWAYS in the file saleor/settings.py.

CHECKOUT_PAYMENT_GATEWAYS = {
  BRAINTREE: pgettext_lazy('Payment method name', 'Brain tree')
}

Then you have to redirect users from the page where are present radio buttons to the only one payment option page. Modify the function payment in the file saleor/order/views.py and add a second function that I called exist_one_gateway.

def payment(request, token):
    [...]
    if not order.is_pre_authorized():
        payment_form = PaymentsForm(form_data)
        if payment_form.is_valid():
            payment = payment_form.cleaned_data['gateway']
            return redirect(
                'order:payment', token=order.token, gateway=payment)
        elif exist_one_gateway():
            payment = list(settings.CHECKOUT_PAYMENT_GATEWAYS.items())[0][0]
            return redirect(
                'order:payment', token=order.token, gateway=payment)
    [...]
    return TemplateResponse(request, 'order/payment.html', ctx)


    def exist_one_gateway():
        gateway = list(settings.CHECKOUT_PAYMENT_GATEWAYS.items())
    return len(gateway) == 1

The payment function works for two different pages, the first one for the page where you have to click on the radio button of the payment gateway that you want to choose (the one that we want to skip) and for the specific payment option page.

For this reason I added a condition where if the payment_form is not valid (that means no one has submitted a payment), it is verified if exist only one payment option. If True, the user is redirected to the specific payment page chose in the previous file.

I hope I was helpful.