doutangshuan6473 2015-09-18 15:32
浏览 48
已采纳

在使用jQuery / ajax提交付款到条目时,如何发布多个表单?

I have a checkout page for a site I am building and because of the way it is setup, I have multiple forms going to different actions. I am using the cakephp 3.x framework and I am using the stripe api to allow someone pay for a membership as well as having the person sign up as a member on the site. Depending on the membership, the client will be able to either sign up 1 or 2 people to the site. The following code is the only way I have gotten all the forms to submit after clicking pay. I am fairly new to jQuery and Ajax calls and coding in general so my code could be better I am sure. Any suggestions on making this simpler, better, or more dynamic? I got it to work, but I am using the .submit() function multiple times and I am worried that it will cause problems in the future.

HTML/PHP:

<div class="page-wrap">
    <div class="checkout-form">
        <h3>Membership Level</h3>
        <p>You have selected the <span class="bold"><?= $membershipLevel->name ?></span> membership level.</p>
        <p><?= $membershipLevel->description ?></p>
        <p>The price for this membership is <span class="bold">$<?= $membershipLevel->billing_amount ?> per <?= $membershipLevel->cycle_period ?>.</span></p>
        <p>Membership expires after <?= $membershipLevel->expiration_number ?> <?= $membershipLevel->expiration_period ?>.</p>
        <?php if (isset($logged_in)): ?>
            <p>You are logged in as <span class="bold"><?= $current_user['username']; ?></span>. If you would like to use a different account for this membership, <?= $this->Html->link('log out now', ['controller' => 'users', 'action' => 'logout']); ?>.</p>
        <?php //else: ?>
            <?= $this->Form->create('user', ['url' => ['controller' => 'users', 'action' => 'add'], 'id' => 'userForm']) ?>
                <?= $this->Form->input('full_name') ?>
                <?= $this->Form->input('username') ?>
                <?= $this->Form->input('email', ['data-stripe' => 'email']) ?>
                <?= $this->Form->input('password') ?>
                <?= $this->Form->input('password_confirmation', array('type' => 'password')) ?>

                <?php if ($current_user['role'] === 1 && isset($logged_in)) {
                    echo $this->Form->input('role', ['type' => 'select', 'options' => ['1' => 'Admin', '2' => 'Editor', '3' => 'Author', '4' => 'Reader'], 'default' => '4']);
                } ?>
            <?= $this->Form->end() ?>
            <?php if (in_array($membershipLevel->id, [2,4,5])) { ?>
                <?= $this->Form->create(null) ?>
                    <p>You are entitled to add another user with this membership level.</p>
                    <p><?= $this->Form->input('Add Second User Now', ['type' => 'checkbox', 'class' => 'second_user_checkbox']) ?> (If you do not add a second user now you will receive an email to add a second user at a later time).</p>
                <?= $this->Form->end() ?>
                <div class="second_user_form" style="display:none;">
                    <?= $this->Form->create('user', ['url' => ['controller' => 'users', 'action' => 'add'], 'id' => 'secondUserForm']) ?>
                        <?= $this->Form->input('full_name') ?>
                        <?= $this->Form->input('username') ?>
                        <?= $this->Form->input('email', ['data-stripe' => 'email']) ?>
                        <?= $this->Form->input('password') ?>
                        <?= $this->Form->input('password_confirmation', array('type' => 'password')) ?>

                        <?php if ($current_user['role'] === 1 && isset($logged_in)) {
                            echo $this->Form->input('role', ['type' => 'select', 'options' => ['1' => 'Admin', '2' => 'Editor', '3' => 'Author', '4' => 'Reader'], 'default' => '4']);
                        } ?>
                    <?= $this->Form->end() ?>
                </div>
            <?php } ?>
        <?php endif; ?>
        <?= $this->Form->create(null, ['controller' => 'membershipLevels', 'action' => 'charge', 'id' => 'payment-form']) ?>
            <div class="payment-errors" style="color:red;font-size:12px;"></div>
            <fieldset>
                <legend><?= __('Billing Address') ?></legend>
                <?= $this->Form->input('billing_name', ['label' => 'Name', 'name' => false, 'data-stripe' => 'name'] ) ?>
                <?= $this->Form->input('billing_street', ['label' => 'Address 1', 'name' => false, 'data-stripe' => 'address_line1'] ) ?>
                <?= $this->Form->input('billing_street_2', ['label' => 'Address 2', 'name' => false, 'data-stripe' => 'address_line2'] ) ?>
                <?= $this->Form->input('billing_city', ['label' => 'City', 'name' => false, 'data-stripe' => 'address_city'] ) ?>
                <?= $this->Form->input('billing_state', ['label' => 'State', 'type' => 'select', 'options' => $this->CustomFormOptions->states(), 'default' => 'UT', 'name' => false, 'data-stripe' => 'address_state'] ) ?>
                <?= $this->Form->input('billing_zip', ['label' => 'Zip', 'data-stripe' => 'address_zip'] ) ?>
                <?= $this->Form->input('billing_country', ['label' => 'Country', 'type' => 'select', 'options' => $this->CustomFormOptions->countries(), 'default' => 'US', 'name' => false, 'data-stripe' => 'address_country'] ) ?>
                <?= $this->Form->input('billing_phone', ['label' => 'Phone', 'data-stripe' => 'address_phone'] ) ?>
                <legend><?= __('Payment Information') ?></legend>
                <?= $this->Form->input('billing_amount', ['type' => 'hidden', 'data-stripe' => 'amount', 'value' => $membershipLevel->billing_amount] ) ?>
                <?= $this->Form->input('Card Number', ['name' => false, 'data-stripe' => 'number'] ) ?>
                <?= $this->Form->input('CVC', ['name' => false, 'data-stripe' => 'cvc'] ) ?>
                <?= $this->Form->input('Month', ['type' => 'select', 'options' => ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'], 'empty' => '(choose one)', 'name' => false, 'label' => 'Expiration (MM/YYYY)', 'size' => '1', 'data-stripe' => 'exp-month'] ) ?> / 
                <?= $this->Form->input('Year', ['name' => false, 'label' => false, 'size' => '4', 'data-stripe' => 'exp-year'] ) ?>
            </fieldset>
            <?= $this->Form->button(__('Pay'), ['id' => 'submitBtn']) ?>
        <?= $this->Form->end() ?>
    </div>
</div>

jQuery / Ajax:

<?php $this->Html->script('//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js', ['block' => true]); ?>
<?php $this->Html->script('https://js.stripe.com/v2/', ['block' => true]); ?>
<?php $this->Html->scriptStart(['safe' => false, 'block' => true]); ?>
$(function() {
    $('.second_user_checkbox').click(function() {
        $('.second_user_form').toggle();
    });
});
$(function() {
    var submitAllForms = function() {
        $('#userForm, #secondUserForm').submit(function(e) {
            e.preventDefault();
            var formID = $(this).attr('id');
            var formDetails = $('#'+formID);
            $.ajax({
                type: formDetails.attr('method'),
                url: formDetails.attr('action'),
                data: formDetails.serialize(),
                success: function() {
                    console.log('user\(s\) have been added');
                },
                error: function(e) {
                    console.log(e);
                }
            });
            return false;
        });
        $('#userForm, #secondUserForm').submit();
        $('#payment-form').get(0).submit();
    }
    Stripe.setPublishableKey('<?= $keys[0]['publishable_key'] ?>');
    $('#payment-form').submit(function(e) {
        $form = $(this);
        $form.find('button').prop('disabled', true);
        //async
        Stripe.card.createToken($form, function(status, response){
            console.log(status);
            console.log(response);
            if(response.error) {
                $form.find('.payment-errors').text(response.error.message);
                $form.find('button').prop('disabled', false);
            } else {
                var token = response.id;
                $form.append($('<input type="hidden" name="stripeToken"/>').val(token));
                submitAllForms();               
            }
        });
        return false;
    });
});
<?php $this->Html->scriptEnd(); ?>
  • 写回答

1条回答 默认 最新

  • duanmei2459 2015-09-18 15:51
    关注

    You're re-submitting the payment-form before your other two forms have finished submitting data, which will result in a race condition where one or both of those forms may or may not be aborted before they're complete. To solve this, you'll need to use a promise chain to keep track of when those requests complete so that you can wait until after they are complete to submit the payment-form.

    $(function() {
        var submitAllForms = function() {
            var promiseArr = $('#userForm, #secondUserForm').map(function() {
                var formDetails = $(this);
                return $.ajax({
                    type: formDetails.attr('method'),
                    url: formDetails.attr('action'),
                    data: formDetails.serialize(),
                    success: function() {
                        console.log('user\(s\) have been added');
                    },
                    error: function(e) {
                        console.log(e);
                    }
                });
            }).get();
            // wait until both of the other forms' data are submitted
            $.when.apply(null, promiseArr).then(function () {
                $('#payment-form').get(0).submit();
            });            
        }
        Stripe.setPublishableKey('<?= $keys[0]['publishable_key'] ?>');
        $('#payment-form').submit(function(e) {
            $form = $(this);
            $form.find('button').prop('disabled', true);
            //async
            Stripe.card.createToken($form, function(status, response){
                console.log(status);
                console.log(response);
                if(response.error) {
                    $form.find('.payment-errors').text(response.error.message);
                    $form.find('button').prop('disabled', false);
                } else {
                    var token = response.id;
                    $form.append($('<input type="hidden" name="stripeToken"/>').val(token));
                    submitAllForms();               
                }
            });
            return false;
        });
    });
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?