You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

沙箱环境PayPal API弹窗点击后立即关闭问题(Django/Vue)

问题:Django+Vue结账系统集成PayPal沙箱弹窗立即关闭并报错

在Django与Vue构建的结账系统中集成PayPal API时,沙箱环境下点击PayPal结账按钮,弹窗会立即关闭,开发者工具出现报错。已排查到问题与购物车商品属性相关,但调整后仍未解决。


原实现代码

Template部分

<template>
    <div class="page-checkout">
        <div class="columns is-multiline">
            <div class="column is-12">
                <h1 class="title">Kasse</h1>
            </div>

            <div class="column is-12 box">
                <table class="table is-fullwidth">
                    <thead>
                        <tr>
                            <th>Artikel</th>
                            <th>Preis</th>
                            <th>Anzahl</th>
                            <th>Gesamt</th>
                        </tr>
                    </thead>
                    <!-- vue for loop for looping through items in cart and displaying them in a table -->
                    <tbody>
                        <tr
                            v-for="item in cart.items"
                            v-bind:key="item.product.id"
                        >
                            <td>{{ item.product.name }}</td>
                            <td>{{ item.product.price }}€</td>
                            <td>{{ item.quantity }}</td>
                            <td>{{ getItemTotal(item).toFixed(2) }}€</td>
                        </tr>
                    </tbody>

                    <tfoot>
                        <tr style="font-weight: bolder; font-size: larger;">
                            <td colspan="2">Insgesamt</td>
                            <td>{{ cartTotalLength }}</td>
                            <td>{{ cartTotalPrice.toFixed(2) }}€</td>
                        </tr>
                    </tfoot>
                </table>
            </div>

            <!-- Fields for user information -->
            <div class="column is-12 box">
                <h2 class="subtitle">Versanddetails</h2>

                <p class="has-text-grey mb-4">*Felder müssen ausgefüllt sein</p>

                <div class="columns is-multline">
                    <div class="column is-6">
                        <div class="field">
                            <label>*Vorname</label>
                            <div class="control">
                                <input type="text" class="input" v-model="first_name">
                            </div>
                        </div>

                        <div class="field">
                            <label>*Nachname</label>
                            <div class="control">
                                <input type="text" class="input" v-model="last_name">
                            </div>
                        </div>

                        <div class="field">
                            <label>*E-Mail</label>
                            <div class="control">
                                <input type="email" class="input" v-model="email">
                            </div>
                        </div>

                        <div class="field">
                            <label>*Telefonnummer</label>
                            <div class="control">
                                <input type="text" class="input" v-model="phone">
                            </div>
                        </div>

                        <div class="column is-6">
                        <div class="field">
                            <label>*Adresse</label>
                            <div class="control">
                                <input type="text" class="input" v-model="address">
                            </div>
                        </div>

                        <div class="field">
                            <label>*Postleitzahl</label>
                            <div class="control">
                                <input type="text" class="input" v-model="zipcode">
                            </div>
                        </div>

                        <div class="field">
                            <label>*Ort</label>
                            <div class="control">
                                <input type="text" class="input" v-model="place">
                            </div>
                        </div>
                    </div>
                    <!-- looping through errors for authorization -->
                    <div class="notification is-danger mt-4" v-if="errors.length">
                        <p v-for="error in errors" v-bind:key="error">{{ error }}</p>
                    </div>

                    <hr>

                    <div id="card-element" class="mb-5"></div>

                    <!-- Part for PayPal implementation -->
                    <template v-if="cartTotalLength">
                        <hr>

                        <!-- Set up a container element for the button -->
                        <div id="paypal-button-container"></div>

                        <!-- Include the PayPal JavaScript SDK -->
                        <div ref="paypal"></div>

                        <!-- <button class="button is-dark" @click="submitForm">Weiter mit PayPal</button> -->
                    </template>
                </div>
            </div>
        </div>
    </div>
</template>

Script部分

<script>
    import axios from 'axios'

    export default {
        name: 'Checkout',
        data() {
            return {
                loaded: false,
                paidFor: false,
                cart: {
                    items: []
                },
                stripe: {},
                card: {},
                first_name: '',
                last_name: '',
                email: '',
                phone: '',
                address: '',
                zipcode: '',
                place: '',
                errors: []
            }
        },
        mounted() {
            document.title = 'Kasse | RELOAD'

            this.cart = this.$store.state.cart
            
            // Imported PayPal functionality
            const script = document.createElement("script");
            script.src = "https://www.paypal.com/sdk/js?client-id=AeAKmRDX7HTesdUvfqYqCQz3fZHIkjAoQ5-BG6K-7xnL5GBMVvwQba53v-I8Fx1p9wurUtoBuk7D6bV1";
            script.addEventListener("load", this.setLoaded);
            document.body.appendChild(script);
        },
        watch: {
            $route(to, from,) {
                if (to.name === 'Category') {
                    this.getCategory()
                }
            }
        },
        methods: {
            getItemTotal(item) {
                return item.quantity * item.product.price
            },
            // Authorization methods
            submitForm() {
                this.errors = []

                if (this.first_name === '') {
                    this.errors.push('Bitte Vornamen angeben')
                }

                if (this.last_name === '') {
                    this.errors.push('Bitte Nachnamen angeben')
                }

                if (this.email === '') {
                    this.errors.push('Bitte E-Mail angeben')
                }

                if (this.phone === '') {
                    this.errors.push('Bitte Telefonnummer angeben')
                }

                if (this.adress === '') {
                    this.errors.push('Bitte Adresse angeben')
                }

                if (this.zipcode === '') {
                    this.errors.push('Bitte Postleitzahl angeben')
                }

                if (this.place === '') {
                    this.errors.push('Bitte Ort angeben')
                }

            },
            // PayPal functionality
            setLoaded() {
                this.loaded = true;
                window.paypal
                    .Buttons({
                    createOrder: (data, actions) => {
                        return actions.order.create({
                            "purchase_units": [{
                                "amount": {
                                    "currency_code": "EUR",
                                    "value": item.product.price,
                                "breakdown": {
                                    "item_total": {  /* Required when including the items array */
                                    "currency_code": "EUR",
                                    "value": item.quantity * product.price
                                    }
                                }
                                },
                                "items": [
                                {
                                    "name": item.product.name,
                                    "description": item.product.description,
                                    "unit_amount": {
                                    "currency_code": "EUR",
                                    "value": item.product.price
                                    },
                                    "quantity": item.product.quantity
                                },
                                ]
                            }]
                        });
                    },
                    onApprove: async (data, actions) => {
                        const order = await actions.order.capture();
                        this.paidFor = true;
                        console.log(order);
                    },
                    onError: err => {
                        console.log(err);
                    }
                    })
                    .render(this.$refs.paypal);
                }
        },
        computed: {
            // Computing total price and total amount of all items 
            cartTotalPrice() {
                return this.cart.items.reduce((acc, curVal) => {
                    return acc += curVal.product.price * curVal.quantity
                }, 0)
            },
            cartTotalLength() {
                return this.cart.items.reduce((acc, curVal) => {
                    return acc += curVal.quantity
                }, 0)
            }
        }
    }
</script>

修复方案

1. 修正createOrder函数的变量与金额计算

原代码中createOrder直接使用未定义的item/product变量,且金额逻辑错误。修改为遍历购物车构建合法订单数据:

createOrder: (data, actions) => {
    // 构建PayPal格式的商品列表
    const paypalItems = this.cart.items.map(item => ({
        name: item.product.name,
        description: item.product.description || '',
        unit_amount: {
            currency_code: "EUR",
            value: item.product.price.toString()
        },
        quantity: item.quantity.toString()
    }));

    // 计算商品总价(与购物车合计保持一致)
    const itemTotal = this.cart.items.reduce((sum, item) => {
        return sum + (item.product.price * item.quantity);
    }, 0);

    return actions.order.create({
        purchase_units: [{
            amount: {
                currency_code: "EUR",
                value: itemTotal.toFixed(2),
                breakdown: {
                    item_total: {
                        currency_code: "EUR",
                        value: itemTotal.toFixed(2)
                    }
                }
            },
            items: paypalItems
        }]
    });
},

2. 修复表单验证的拼写错误

submitForm中地址判断变量名拼写错误,将this.adress改为this.address:

if (this.address === '') {
    this.errors.push('Bitte Adresse angeben')
}

3. 统一PayPal按钮渲染容器

模板中保留一个容器即可,比如删除id="paypal-button-container",确保render方法指向正确的this.$refs.paypal。

4. 增强错误调试信息

在onError中补充详细错误输出:

onError: err => {
    console.error('PayPal错误详情:', err);
    alert('Beim Verarbeiten der PayPal-Zahlung ist ein Fehler aufgetreten.');
}

内容的提问来源于stack exchange,提问作者Julius Buller

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 12:55:25