【问题标题】:Braintree JSv3 payment_method_nonce Value Bad With HostedFieldsBraintree JSv3 payment_method_nonce Value Bad With HostedFields
【发布时间】:2017-05-15 23:12:50
【问题描述】:

我在这里查看了一些关于相同问题但在不同情况下无法为我的特定问题提供答案的帖子...

我在我的 Django 项目中使用 Braintree JSv2,一切正常。由于我已经迁移到 Braintree 的 v3,我现在似乎唯一的问题是输入到“payment_method_nonce”的值不存在......

这是应该转储 payment_method_nonce 值的代码:

document.querySelector('input[name="payment_method_nonce"]').value = payload.nonce;

这是应该在 python 端抓取它的代码:

client_payment_nonce = request.POST['payment_method_nonce']

在我的开发环境中提交此文件时,我收到一个错误 (MultiValueDictKeyError) for "payment_method_nonce"

我正在使用 Django 1.9 和 Python 2.7。我还在使用 Braintree 提供的 example 进行使用 HostedFields 的简单集成...

小测试

所以我在我的表单中手动添加了一个名为“payment_method_nonce”的输入字段,只是为了看看没有字段是否会导致一些问题。我知道它是由 Braintree 注入的,但只是测试一个想法。似乎虽然payment_method_nonce 的值应该是我的nonce,但我没有在输入框中输入任何内容,它仍然返回为null。

Form 和 HostedFields 的完整片段

<form action="/booking/" method="post" id="checkout_form">
                    {% csrf_token %}
                <div class="payment">
                    <span>Payment</span>
                        <!--input elements for user card data-->
                        <div class="hosted-fields" id="card-number"></div>

                        <div class="hosted-fields" id="postal-code"></div>

                        <div class="hosted-fields" id="expiration-date"></div>

                        <div class="hosted-fields" id="cvv"></div>

                        <div class="btns">
                            <input type="hidden" name="payment_method_nonce">
                            <input type="submit" value="Complete Booking" id="pay-button">
                        </div>
                </div>
            </form>

注意:我刚刚将payment_method_nonce 字段更改为type="hidden" 而不是type="text",但仍然具有相同的效果...

<!-- load the required client component -->
    <script src="https://js.braintreegateway.com/web/3.15.0/js/client.min.js"></script>
    <!-- load the hosted fields component -->
    <script src="https://js.braintreegateway.com/web/3.15.0/js/hosted-fields.min.js"></script>
    <!-- Braintree setup -->
    <script>
        var client_token = "{{ request.session.braintree_client_token }}"
        var form = document.querySelector('#checkout-form');
        var submit = document.querySelector('input[type="submit"]');

        braintree.client.create({
            authorization: client_token
        }, function (clientErr, clientInstance) {
            if (clientErr) {
                // Handle error in client creation
                return;
            }
            braintree.hostedFields.create({
                client: clientInstance,
                styles: {
                    'input': {
                        'font-size': '14px'
                    },
                    'input.invalid': {
                        'color': 'red'
                    },
                    'input.valid': {
                        'color': 'green'
                    }
                },
                fields: {
                    number: {
                        selector: '#card-number',
                        placeholder: 'Credit Card Number'
                    },
                    cvv: {
                        selector: '#cvv',
                        placeholder: '123'
                    },
                    expirationDate: {
                        selector: '#expiration-date',
                        placeholder: '10/2019'
                    },
                    postalCode: {
                        selector: '#postal-code',
                        placeholder: '10014'
                    }
                }
            }, function (hostedFieldsErr, hostedFieldsInstance) {
                if (hostedFieldsErr) {
                    // handle error in Hosted Fields creation
                    return;
                }

                submit.removeAttribute('disabled');

                form.addEventListener('submit', function (event) {
                    event.preventDefault();

                    hostedFieldsInstance.tokenize(function (tokenizeErr, payload) {
                        if (tokenizeErr) {
                            // handle error in Hosted Fields tokenization
                            return;
                        }
                        // Put `payload.nonce` into the `payment_method_nonce`
                        document.querySelector('input[name="payment_method_nonce"]').value = payload.nonce;
                        document.querySelector('input[id="pay-button"]').value = "Please wait...";
                        form.submit();
                    });
                }, false);
            });
        });
    </script>

注意document.querySelector('input[id="pay-button"]').value = "Please wait..."; 行不会触发(我知道这一点是因为按钮不会更改值)。也许这些 querySelector 行不起作用?

新发现

我只是回到我的页面并点击提交按钮,甚至没有输入任何信息。在 Braintree 的 v2 中,在填写所有字段之前,我无法单击提交按钮......也许我的表单中的值甚至没有被发送到 Braintree 接收随机数,这就是为什么有一个空字符串被退回..?

【问题讨论】:

  • Braintree 的 JavaScript SDK 从 v2 到 v3 之间存在设计差异。在 v3 中,in the documentation 它表明您确实需要将其添加到您的表单中:,因此payment_method_nonce 是一个输入字段,而在 v2 中 Braintree 会自动注入该字段.您说,在您的小测试中,您尝试进行自己的测试——您能否提供托管字段表单的完整代码 sn-p?
  • 这是我的疏忽,但当我回顾文档时才发现。我用同样的问题改变了我放在 type="hidden" 的行。我用 sn-ps 更新了我的帖子。
  • 看起来您的表单操作正在引用 id="checkout_form" 但您使用 var form = document.querySelector('#checkout-form'); 查找表单,因此 ID 不匹配。您可以尝试更改它以使 ID 匹配,看看是否能解决您的问题?
  • 说实话我觉得有点傻,这就是导致我问题的原因...谢谢你的第二眼!

标签: javascript python django braintree


【解决方案1】:

故事的寓意

检查您的代码...多次。正如C Joseph 所指出的,我的form ID 与我的var form 所引用的不同......

&lt;form action="/booking/" method="post" id="checkout_form"&gt;

var form = document.querySelector('#checkout-form');

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-07
    • 2020-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-02
    相关资源
    最近更新 更多