在 Vue.js 组件中放置 PayPal 按钮
Posted
技术标签:
【中文标题】在 Vue.js 组件中放置 PayPal 按钮【英文标题】:Placing PayPal buttons inside Vue.js component 【发布时间】:2021-02-26 07:50:45 【问题描述】:我正在尝试在我的 Vue.js 组件中放置 PayPal 订单按钮。
我正在关注official documentation,它基本上说要做三件事:
-
导入 PayPal SDK 脚本
定义将呈现按钮的
<div>
元素
添加一些javascript tode来配置回调并使用变量paypal
呈现按钮
这是我在纯 html 文件中执行此操作时的外观:
<!-- 1 -->
<script src="https://www.paypal.com/sdk/js?&client-id=xxx"></script>
<!-- 2 -->
<div id="paypal-button-container"></div>
<!-- 3 -->
<script>
paypal.Buttons(
createOrder: function (data, actions)
return fetch('http://localhost:8081/api/v1/pay-pal/create-order',
method: 'POST'
).then(function(res)
return res.json();
).then(function(data)
return data.id;
);
,
onApprove: function (data, actions)
return fetch('http://localhost:8081/api/v1/pay-pal/capture-order/' + data.orderID,
method: 'POST'
).then(function(res)
if (!res.ok)
alert('Something went wrong');
);
).render('#paypal-button-container');
</script>
上面的代码可以找到。我的问题是如何在 Vue.js 组件中执行此操作。
对于第 1 步,我使用了这样的 mounted()
钩子:
mounted()
let payPalSdk = document.createElement('script')
payPalSdk.setAttribute('src', 'https://www.paypal.com/sdk/js?&client-id=xxx')
document.head.appendChild(payPalSdk)
第 2 步很简单,我只是在模板中添加了 div
元素。
但是我应该把 javascript 代码放在哪里来执行第 3 步?
我尝试将它放在一个外部 js 文件中,并在 mounted()
方法中加载它,如下所示:
mounted()
let payPalSdk = document.createElement('script')
payPalSdk.setAttribute('src', 'https://www.paypal.com/sdk/js?&client-id=xxx')
document.head.appendChild(payPalSdk)
let payPalScript = document.createElement('script')
payPalScript.setAttribute('src', '/js/paypal.js')
document.head.appendChild(payPalScript)
paypal.js:
paypal.Buttons(
createOrder: function (data, actions)
return fetch('http://localhost:8081/api/v1/pay-pal/create-order',
method: 'POST'
).then(function(res)
return res.json();
).then(function(data)
return data.id;
);
,
onApprove: function (data, actions)
return fetch('http://localhost:8081/api/v1/pay-pal/capture-order/' + data.orderID,
method: 'POST'
).then(function(res)
if (!res.ok)
alert('Something went wrong');
);
).render('#paypal-button-container');
按钮确实被渲染,但控制台显示以下错误:
buttons?style.layout…re&commit=true:1182 unhandled_error
err: "Error: Invalid json: .↵ at XMLHttpRequest.<anon…rrency=USD&intent=capture&commit=true:1182:22901)", timestamp: "1605367583366", referer: "www.sandbox.paypal.com", sdkCorrelationID: "7d650f42fd450", sessionID: "09b33213cd_mtu6mjy6mja", …
buttonCorrelationID: "72135879fd67d"
buttonSessionID: "473d7ab57f_mtu6mjy6mja"
env: "sandbox"
err: "Error: Invalid json: .↵ at XMLHttpRequest.<anonymous> (https://www.sandbox.paypal.com/smart/buttons?style.layout=vertical&style.color=gold&style.shape=rect&style.tagline=false&components.0=buttons&locale.country=US&locale.lang=en&sdkMeta=eyJ1cmwiOiJodHRwczovL3d3dy5wYXlwYWwuY29tL3Nkay9qcz8mY2xpZW50LWlkPUFUX1hyMUl3ekZpM2ItRmhFd0RMQ0VndEM2Y2F4MHgwaWR1VF9yeEprQUhycFRlUXpkbHZRRDhKWFUxZmlNQ01vclN3T1hSWWU1eVVPaENBIiwiYXR0cnMiOnsiZGF0YS11aWQiOiJlOGQyMGY4MzBlX210dTZtank2bWphIn19&clientID=xxx&sessionID=09b33213cd_mtu6mjy6mja&buttonSessionID=473d7ab57f_mtu6mjy6mja&enableBNPL=true&env=sandbox&fundingEligibility=eyJwYXlwYWwiOnsiZWxpZ2libGUiOnRydWUsInZhdWx0YWJsZSI6dHJ1ZX0sInBheWxhdGVyIjp7ImVsaWdpYmxlIjpmYWxzZSwicHJvZHVjdHMiOnsiZmxleCI6eyJlbGlnaWJsZSI6ZmFsc2V9LCJwYXlJbjQiOnsiZWxpZ2libGUiOmZhbHNlfX19LCJjYXJkIjp7ImVsaWdpYmxlIjp0cnVlLCJicmFuZGVkIjp0cnVlLCJpbnN0YWxsbWVudHMiOmZhbHNlLCJ2ZW5kb3JzIjp7InZpc2EiOnsiZWxpZ2libGUiOnRydWUsInZhdWx0YWJsZSI6dHJ1ZX0sIm1hc3RlcmNhcmQiOnsiZWxpZ2libGUiOnRydWUsInZhdWx0YWJsZSI6dHJ1ZX0sImFtZXgiOnsiZWxpZ2libGUiOnRydWUsInZhdWx0YWJsZSI6dHJ1ZX0sImRpc2NvdmVyIjp7ImVsaWdpYmxlIjpmYWxzZSwidmF1bHRhYmxlIjp0cnVlfSwiaGlwZXIiOnsiZWxpZ2libGUiOmZhbHNlLCJ2YXVsdGFibGUiOmZhbHNlfSwiZWxvIjp7ImVsaWdpYmxlIjpmYWxzZSwidmF1bHRhYmxlIjp0cnVlfSwiamNiIjp7ImVsaWdpYmxlIjpmYWxzZSwidmF1bHRhYmxlIjp0cnVlfX19LCJ2ZW5tbyI6eyJlbGlnaWJsZSI6ZmFsc2V9LCJpdGF1Ijp7ImVsaWdpYmxlIjpmYWxzZX0sImNyZWRpdCI6eyJlbGlnaWJsZSI6ZmFsc2V9LCJzZXBhIjp7ImVsaWdpYmxlIjpmYWxzZX0sImlkZWFsIjp7ImVsaWdpYmxlIjpmYWxzZX0sImJhbmNvbnRhY3QiOnsiZWxpZ2libGUiOmZhbHNlfSwiZ2lyb3BheSI6eyJlbGlnaWJsZSI6ZmFsc2V9LCJlcHMiOnsiZWxpZ2libGUiOmZhbHNlfSwic29mb3J0Ijp7ImVsaWdpYmxlIjpmYWxzZX0sIm15YmFuayI6eyJlbGlnaWJsZSI6ZmFsc2V9LCJwMjQiOnsiZWxpZ2libGUiOmZhbHNlfSwiemltcGxlciI6eyJlbGlnaWJsZSI6ZmFsc2V9LCJ3ZWNoYXRwYXkiOnsiZWxpZ2libGUiOmZhbHNlfSwicGF5dSI6eyJlbGlnaWJsZSI6ZmFsc2V9LCJibGlrIjp7ImVsaWdpYmxlIjpmYWxzZX0sInRydXN0bHkiOnsiZWxpZ2libGUiOmZhbHNlfSwib3h4byI6eyJlbGlnaWJsZSI6ZmFsc2V9LCJtYXhpbWEiOnsiZWxpZ2libGUiOmZhbHNlfSwiYm9sZXRvIjp7ImVsaWdpYmxlIjpmYWxzZX0sIm1lcmNhZG9wYWdvIjp7ImVsaWdpYmxlIjpmYWxzZX19&platform=desktop&flow=purchase¤cy=USD&intent=capture&commit=true:1182:22901)"
referer: "www.sandbox.paypal.com"
sdkCorrelationID: "7d650f42fd450"
sessionID: "09b33213cd_mtu6mjy6mja"
timestamp: "1605367583366"
__proto__: Object
y @ buttons?style.layout…re&commit=true:1182
S @ buttons?style.layout…re&commit=true:1182
error @ buttons?style.layout…re&commit=true:1182
(anonymous) @ buttons?style.layout…re&commit=true:1182
(anonymous) @ buttons?style.layout…re&commit=true:1182
(anonymous) @ buttons?style.layout…re&commit=true:1182
setTimeout (async)
n.reject @ buttons?style.layout…re&commit=true:1182
(anonymous) @ buttons?style.layout…re&commit=true:1182
n.dispatch @ buttons?style.layout…re&commit=true:1182
n.reject @ buttons?style.layout…re&commit=true:1182
n.dispatch @ buttons?style.layout…re&commit=true:1182
n.reject @ buttons?style.layout…re&commit=true:1182
n.dispatch @ buttons?style.layout…re&commit=true:1182
n.reject @ buttons?style.layout…re&commit=true:1182
(anonymous) @ buttons?style.layout…re&commit=true:1182
(anonymous) @ buttons?style.layout…re&commit=true:1182
load (async)
(anonymous) @ buttons?style.layout…re&commit=true:1182
e @ buttons?style.layout…re&commit=true:1182
ke @ buttons?style.layout…re&commit=true:1182
Oe @ buttons?style.layout…re&commit=true:1182
(anonymous) @ buttons?style.layout…re&commit=true:1182
e.try @ buttons?style.layout…re&commit=true:1182
w @ buttons?style.layout…re&commit=true:1182
e.try @ buttons?style.layout…re&commit=true:1182
(anonymous) @ buttons?style.layout…re&commit=true:1182
setTimeout (async)
w::promiseDebounced @ buttons?style.layout…re&commit=true:1182
G.then.intent @ buttons?style.layout…re&commit=true:1182
(anonymous) @ buttons?style.layout…re&commit=true:1182
n.dispatch @ buttons?style.layout…re&commit=true:1182
n.resolve @ buttons?style.layout…re&commit=true:1182
n.dispatch @ buttons?style.layout…re&commit=true:1182
n.resolve @ buttons?style.layout…re&commit=true:1182
n.dispatch @ buttons?style.layout…re&commit=true:1182
n.resolve @ buttons?style.layout…re&commit=true:1182
(anonymous) @ buttons?style.layout…re&commit=true:1182
n.dispatch @ buttons?style.layout…re&commit=true:1182
n.resolve @ buttons?style.layout…re&commit=true:1182
n.dispatch @ buttons?style.layout…re&commit=true:1182
n.resolve @ buttons?style.layout…re&commit=true:1182
n.dispatch @ buttons?style.layout…re&commit=true:1182
n.resolve @ buttons?style.layout…re&commit=true:1182
(anonymous) @ buttons?style.layout…re&commit=true:1182
(anonymous) @ buttons?style.layout…re&commit=true:1182
setInterval (async)
(anonymous) @ buttons?style.layout…re&commit=true:1182
e @ buttons?style.layout…re&commit=true:1182
(anonymous) @ buttons?style.layout…re&commit=true:1182
anonymous::memoized @ buttons?style.layout…re&commit=true:1182
G.style @ buttons?style.layout…re&commit=true:1182
ht @ buttons?style.layout…re&commit=true:1182
(anonymous) @ buttons?style.layout…re&commit=true:1183
我也尝试将代码放入 mounted()
钩子中,但这不起作用,因为变量 paypal
在那里未定义。
【问题讨论】:
@tao 该 URL 实际上返回 HTML,而不是 JSON。这不是问题,因为当我在工作示例中尝试它时它返回相同的 HTML。 【参考方案1】:从mounted() 试试这个,看看是否在加载PayPal JS 后使用回调或客户端createOrder/onApprove 产生影响
function loadAsync(url, callback)
var s = document.createElement('script');
s.setAttribute('src', url); s.onload = callback;
document.head.insertBefore(s, document.head.firstElementChild);
loadAsync('https://www.paypal.com/sdk/js?client-id=sb¤cy=USD', function()
paypal.Buttons(
// Set up the transaction
createOrder: function(data, actions)
return actions.order.create(
purchase_units: [
amount:
value: '0.01'
]
);
,
// Finalize the transaction
onApprove: function(data, actions)
return actions.order.capture().then(function(details)
// Show a success message to the buyer
alert('Transaction completed by ' + details.payer.name.given_name);
);
).render('#paypal-button-container');
);
至于实际的客户端批准代码继续与您的服务器后端配对,我推荐https://developer.paypal.com/demo/checkout/#/pattern/server的错误处理
【讨论】:
谢谢,我试过这种方式,但我得到了完全相同的错误。 你的 vue 环境中的某些东西正在干扰或阻止 XHR 请求。检查网络选项卡和跨站点标题。 在网络选项卡中对 paypal.com 的所有调用都返回 200。“检查跨站点标题”是什么意思? 如果是200,那么响应体不是JSON怎么办? 我没有看到任何返回 JSON 的请求。甚至在工作示例中也没有。以上是关于在 Vue.js 组件中放置 PayPal 按钮的主要内容,如果未能解决你的问题,请参考以下文章
从 PayPal 检索 PayKey 时出现错误 580022(无效的 AccountID)。应该在接收者的 AccountID 中放置啥以及在哪里可以找到该信息?
Vuetify.js:如何在左右两侧的 v-card 中放置按钮操作?