沙箱环境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
相关产品推荐
相关产品推荐

