背景
项目客户端是uniapp(app端),用户是海外微信支付宝肯定不行了,安卓苹果端都要,可选的支付方式有:1、苹果支付+谷歌支付。2、paypal。3、Stripe
我比较看好paypal,最后领导决定用braintree。我一看傻了,uniapp不支持braintree啊。只能自己对接了。
首先看下braintree是什么东西:
纯逆天,这种也有人用?
可行性分析
接下来看下对接文档,看看能不能搞
https://developer.paypal.com/braintree/docs/start/hello-client
在这里找到了js的sdk
下载下来一看
wdnmd,全是H5代码,这个再uniapp(app端)上是不能运行的
那只有两个方法:
1、原生插件
2、内嵌H5
原生插件不考虑,不会objectc和java。
看下内嵌H5是否能调用这个js
好像是可以的,那就可以搞。
再看下苹果上架能否上。看下苹果官网的协议https://ask.dcloud.net.cn/file/download/file_name-6Iu55p6c5pSv5LuYLnBkZg==__url-Ly9hc2suZGNsb3VkLm5ldC5jbi91cGxvYWRzL2FydGljbGUvMjAyMTA4MjMvMGMwNTBmMmQ4MDU3Njc1OTMyOTlmOTYzZWQ0YTQwOGU=
wdnmd全是英文,懒得看。以前上架过一个支付宝微信充值到钱包的,走的是免费app,很迷,所以先不管了,万一这个也能走免费app呢,不让走免费大不了不用内嵌打开支付了,跳转到Safari支付去。
所以先搞一个H5网页,内嵌进去不行就跳过去。没毛病,开搞。
调试过程
先看一波整体怎么做
步骤1
你的前端从你的服务器请求一个客户端令牌,并初始化客户端SDK。
第2步
你的服务器使用服务器SDK生成并向你的客户端发送一个客户端令牌。
第3步
客户提交支付信息,客户端SDK将该信息传达给Braintree并返回一个支付方式nonce。
第4步
你的前端发送支付方式nonce到你的服务器。
第5步
你的服务器代码收到支付方式nonce,然后使用服务器SDK来创建一个交易。
ojbk,很简单,开调
copy setup中的代码
这个就是调一下js,用这个js创建交易呗。那怎么知道交易是我们创的呢,需要个令牌,看后面的
这段说的是后端生成个令牌。你填进去,怎么填呢,要么写死,要么ajax过来。那当然是写死了,我们只对一个项目。接着往下看
下面是介绍沙箱环境,咋开始介绍沙箱环境呢,前面一步的token还没给我呢,又回去看了遍,这里是假设已经拿到了token,之后要去配环境了,ojbk,那就假装已经拿到了token,开始配沙箱环境。这里讲的是沙箱需要传的参,和重要信息“上线时候要把这几个换成正式环境的”。彳亍。看后面
后面讲的是客户端生成一个什么东西,要发给后端。按照尿性,应该是假设前面的都做完了。他应该是在后面后端要看的文档里说了怎么做这些。
这页看完了,接下来看后端的
后端的看不懂,主要讲了1、token生成以后要给前端。2、前端会给你一个东西,你用这个创交易记录。
都对起来了。
那就和后端试下呗。
遇到报错
是因为直接启动的html,要把html运行到端口再启动,可以用ngnix发一个也可以用vscode的live-sever,部署上去后再搞,不报这个错了。
但是与后端的传参报错networkError
跨域问题,同地址单端口号不一样,所以ngnix转发一下,解决跨域问题。
成功收到后端返回值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="https://js.braintreegateway.com/web/dropin/1.34.0/js/dropin.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="dropin-container"></div>
<button id="submit-button" class="button button--small button--green">Purchase</button>
<script type="text/javascript">
var token = 'sandbox_g42y39zw_348pk9cgf3bgyw2b'
// 信用卡
var button = document.querySelector('#submit-button');
braintree.dropin.create({
authorization: token,
container: '#dropin-container'
}, (error, instance) => {
if (error) return console.error(error);
button.addEventListener('click', function () {
instance.requestPaymentMethod(async function (err, payload) {
let res = await axios({
method: 'post',
url: 'xxxxxxxxxxxxxxxxxxxxxxxx',
params: {
'payment_method_nonce': payload.nonce||''
}
})
});
})
});
</script>
</body>
</html>
接下来对接paypal,https://developer.paypal.com/braintree/docs/guides/paypal/client-side
按照这里的填写完成后,加入paypal的代码。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="https://js.braintreegateway.com/web/dropin/1.34.0/js/dropin.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://www.paypal.com/sdk/js?client-id=sb"></script><!--沙盒client-id=sb,pro client-id取paypal的clientID-->
<script src="https://js.braintreegateway.com/web/3.91.0/js/client.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.91.0/js/paypal-checkout.min.js"></script>
</head>
<body>
<div id="dropin-container"></div>
<button id="submit-button" class="button button--small button--green">Purchase</button>
<script type="text/javascript">
var token = 'sandbox_g42y39zw_348pk9cgf3bgyw2b'
// 信用卡
var button = document.querySelector('#submit-button');
braintree.dropin.create({
authorization: token,
container: '#dropin-container'
}, (error, instance) => {
if (error) return console.error(error);
button.addEventListener('click', function () {
instance.requestPaymentMethod(async function (err, payload) {
let res = await axios({
method: 'post',
url: 'xxxxxxxxxxxxxxxxxxxxxxxx',
params: {
'payment_method_nonce': payload.nonce||''
}
})
});
})
});
// paypal
braintree.client.create({
authorization: token
}, (clientErr, clientInstance) => {
if (clientErr) return console.error('Error creating client:', clientErr);
braintree.paypalCheckout.create({
client: clientInstance
}, function (paypalCheckoutErr, paypalCheckoutInstance) {
if (paypalCheckoutErr) {
console.error('Error creating PayPal Checkout:', paypalCheckoutErr);
return;
}
});
});
</script>
</body>
</html>
加进去后报错Error creating client,提示说paypal和braintree没有link,让我参考https://developer.paypal.com/braintree/docs/guides/paypal/网址查看,我进去一看这不就是刚看的吗,一步步做下来的的啊。进入link的页面,发现其中说link已完成,paypal功能可用。怎么两边说的不一样。后来发现是paypal账号和braintree账号必须是同一个国家的,wdnmd,重新注册一波。不报错了。
在paypal沙箱环境中创个收款方再创个付款号,就用他给的号和密码就可以登进去了,号里余额5000绑了信用卡。
然后就完事了,付完钱后在onApprove中调后端接口创建交易(),然后过一会就会被结算了。
<!DOCTYPE html>
<!-- 禁止页面缩放 -->
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<html lang="en">
<head>
<meta charset="utf-8">
<script type="text/javascript" src="https://unpkg.com/@dcloudio/uni-webview-js@0.0.3/index.js"></script>
<script src="https://js.braintreegateway.com/web/dropin/1.23.0/js/dropin.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://www.paypal.com/sdk/js?client-id=sb"></script>
<!--沙盒client-id=sb,pro client-id取paypal的clientID-->
<script src="https://js.braintreegateway.com/web/3.91.0/js/client.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.91.0/js/paypal-checkout.min.js"></script>
</head>
<body>
<!-- <div id="dropin-container"></div>
<button id="submit-button" class="button button--small button--green">Purchase</button> -->
<div id="paypal-button"></div>
<div id="loading"></div>
<script type="text/javascript">
(async () => {
// 获取页面传值
let url = window.location.search
let trans = url.slice(url.indexOf('?') + 1)
let arr = trans.split('&')
let obj = {}
for (let i of arr) {
let a = i.split('=')
obj[a[0]] = a[1]
}
// 获取Token
let token = ‘sandbox_g42y39zw_348pk9cgf3bgyw2b’
// 信用卡
// braintree.dropin.create({
// authorization: token,
// container: '#dropin-container'
// }, (error, instance) => {
// if (error) return console.error(error);
// document.querySelector('#submit-button').addEventListener('click', function () {
// instance.requestPaymentMethod(async function (err, payload) {
// let res = await axios({
// method: 'post',
// url: 'xxxxxxxxxxx',
// params: {
// 'paymentMethodNonce': payload.nonce||''
// }
// })
// });
// })
// });
braintree.client.create({
authorization: token
}, function(clientErr, clientInstance) {
if (clientErr) {
console.error('Error creating client:', clientErr);
return;
}
braintree.paypalCheckout.create({
client: clientInstance
}, function(paypalCheckoutErr, paypalCheckoutInstance) {
if (paypalCheckoutErr) {
console.error('Error creating paypalCheckoutInstance:', paypalCheckoutErr);
}
paypalCheckoutInstance.loadPayPalSDK({
currency: 'USD',
intent: 'capture'
}, function() {
paypal.Buttons({
fundingSource: paypal.FUNDING.PAYPAL,
createOrder: function() {
//此处可以去服务端下订单,获取订单具体信息在放到createPayment里面
return paypalCheckoutInstance.createPayment({
flow: 'checkout', // Required
amount: obj.money, // Required
currency: 'USD', // Required, must match the currency passed in with loadPayPalSDK
intent: 'capture', // Must match the intent passed in with loadPayPalSDK
enableShippingAddress: false,
shippingAddressEditable: false,
shippingAddressOverride: {
recipientName: '',
line1: '',
line2: '',
city: '',
countryCode: '',
postalCode: '',
state: '',
phone: ''
}
});
},
onApprove: function(data, actions) {
//发送payload.nonce以及订单信息到服务端请求进行一次付款交易(transaction)
return paypalCheckoutInstance.tokenizePayment(
data, async (err, payload) => {
let res = await axios({
method: 'post',
url: 'xxxxxxxxxxxxxxx',
params: {
'paymentMethodNonce': payload.nonce || '',
'amount': obj.money,
}
})
let { success, message } = res.data
if (success) {
uni.reLaunch({ url: '/pages/device/index' })
}
});
},
onCancel: function(data) {
console.log('PayPal payment cancelled', JSON.stringify(data, 0, 2));
},
onError: function(err) {
console.error('PayPal error', err);
}
}).render('#paypal-button').then(function() {
console.log('paypal初始画完成');
});
});
});
});
})()
</script>
</body>
</html>