braintree支付,包含paypal、card、apple支付
官网:https://developer.paypal.com
前端代码
<!-- SDK -->
<script src="https://js.braintreegateway.com/web/3.85.3/js/client.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.85.3/js/apple-pay.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.85.3/js/hosted-fields.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.85.3/js/data-collector.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.85.3/js/paypal.min.js"></script>
<script>
new Vue({
el: "#app",
data() {
return {
tokenUrl: '',
clientInstance: null,
hostedFieldsInstance: null,
applePayInstance: null,
deviceData: null
}
},
methods: {
createClient() {
// init client
var $this = this;
tip.ajax(this.tokenUrl, {}, (ret) => {
if (ret.code != 0) {
console.error(ret.msg);
tip.err("We're sorry. An error has occurred.");
return;
}
braintree.client.create({
authorization: ret.data
}, function (err, clientInstance) {
if (err) {
console.error('Error creating client:', err);
tip.err("We're sorry. An error has occurred.");
return;
}
console.log('client instance success')
$this.clientInstance = clientInstance;
braintree.dataCollector.create({
client: $this.clientInstance,
paypal: true,
kount: true
}, function (err, dataCollectorInstance) {
if (err) {
console.error(err);
alert(err)
return;
}
dataCollectorInstance.getDeviceData().then(function (deviceData) {
// pass onto your server with the payment method nonce
if (typeof deviceData === 'string') {
$this.deviceData = deviceData;
$('#device_data').val(deviceData)
}
});
});
braintree.hostedFields.create({
container: '#creditCard',
client: $this.clientInstance,
styles: {
'input': {
'font-size': '14px',
'font-family': 'courier, monospace',
'font-weight': 'lighter',
'color': '#ccc',
},
':focus': {
'color': 'black'
},
'.valid': {
'color': '#8bdda8'
}
},
fields: {
number: {
selector: '#card-number',
placeholder: ''
},
cvv: {
selector: '#cvv',
placeholder: 'CVV'
},
expirationDate: {
selector: '#expiration-date',
placeholder: 'MM/YY'
},
postalCode: {
selector: '#postal-code',
placeholder: 'No More Than 9 Characters'
}
}
}, function (err, hostedFieldsInstance) {
if (err) {
console.error(err);
return;
}
$this.hostedFieldsInstance = hostedFieldsInstance;
$this.enablePay();
hostedFieldsInstance.on('focus', function (event) {
var field = event.fields[event.emittedBy];
});
hostedFieldsInstance.on('blur', function (event) {
var field = event.fields[event.emittedBy];
});
hostedFieldsInstance.on('empty', function (event) {
var field = event.fields[event.emittedBy];
});
hostedFieldsInstance.on('validityChange', function (event) {
var field = event.fields[event.emittedBy];
});
hostedFieldsInstance.on('cardTypeChange', function (event) {
var field = event.fields[event.emittedBy];
// Change card bg depending on card type
if (event.cards.length === 1) {
//$(form).removeClass().addClass(event.cards[0].type);
$('#card-image').removeClass().addClass(event.cards[0].type);
//$('header').addClass('header-slide');
// Change the CVV length for AmericanExpress cards
if (event.cards[0].code.size === 4) {
hostedFieldsInstance.setAttribute({
field: 'cvv',
attribute: 'placeholder',
value: 'xxxx'
});
}
} else {
hostedFieldsInstance.setAttribute({
field: 'cvv',
attribute: 'placeholder',
value: 'xxx'
});
}
});
});
// Create a Apple Pay Checkout component.
if (window.ApplePaySession && window.ApplePaySession.supportsVersion(3) && window.ApplePaySession.canMakePayments()) {
if (!window.ApplePaySession) {
console.error('This device does not support Apple Pay');
}
if (!ApplePaySession.canMakePayments()) {
console.error('This device is not capable of making Apple Pay payments');
}
// This device supports version 3 of Apple Pay.
braintree.applePay.create({
client: $this.clientInstance
}, function (applePayErr, applePayInstance) {
if (applePayErr) {
console.error('Error creating applePayInstance:', applePayErr);
return;
}
$this.applePayInstance = applePayInstance;
// Set up your Apple Pay button here
// var promise = window.ApplePaySession.canMakePaymentsWithActiveCard(applePayInstance.merchantIdentifier);
// promise.then(function (canMakePaymentsWithActiveCard) {
// if (canMakePaymentsWithActiveCard) {
// // Set up Apple Pay buttons
// } else {
// // $("#apple-pay-msg").html('Your devices has not been opened Apple Pay ')
// }
// });
});
}
});
});
},
paypalPay(button) {
var $this = this;
// Create a PayPal component.
braintree.paypal.create({
client: $this.clientInstance
}, function (paypalErr, paypalInstance) {
if (paypalErr) {
button.removeAttribute('disabled');
console.error('Error creating PayPal:', paypalErr);
tip.err("We're sorry. An error has occurred. Please return to your cart .");
return;
}
// When the button is clicked, attempt to tokenize.
paypalInstance.tokenize({
flow: 'vault',
amount: $this.actual_price, // Required
currency: p.currency_code, // Required
// enableShippingAddress: true,
// shippingAddressEditable: false,
// shippingAddressOverride: {
// recipientName: $this.address.name + $this.address.lastname,
// line1: $this.address.address,
// line2: '',
// city: $this.address.city,
// state: $this.address.state_name || $this.state_val,
// postalCode: $this.address.zip_code,
// countryCode: '',
// phone: $this.address.tel,
// }
// For more tokenization options, see the full PayPal tokenization documentation
// https://braintree.github.io/braintree-web/current/PayPal.html#tokenize
}, function (tokenizeErr, payload) {
button.removeAttribute('disabled');
if (tokenizeErr) {
switch (tokenizeErr.code) {
case 'PAYPAL_POPUP_CLOSED':
console.error('Customer closed PayPal popup.');
break;
case 'PAYPAL_ACCOUNT_TOKENIZATION_FAILED':
console.error('PayPal tokenization failed. See details:', tokenizeErr.details);
break;
case 'PAYPAL_FLOW_FAILED':
console.error('Unable to initialize PayPal flow. Are your options correct?', tokenizeErr.details);
break;
default:
console.error('Error!', tokenizeErr);
}
if (tokenizeErr.type !== 'CUSTOMER') {
console.error('Error tokenizing:', tokenizeErr);
}
return;
}
// Tokenization succeeded
console.log('Got a nonce! You should submit this to your server.');
$this.pay(payload.nonce, button);
});
});
},
cartsPay(button) {
var $this = this;
// Check if all fields are valid
var state = $this.hostedFieldsInstance.getState();
var formValid = Object.keys(state.fields).every(function (key) {
return state.fields[key].isValid;
});
if (formValid === false) {
$this.hostedFieldsInstance.focus('number', function (focusErr) {
if (focusErr) {
console.error(focusErr);
}
});
button.removeAttribute('disabled');
tip.err('Something went wrong. Check your card details and try again.');
return;
}
$this.hostedFieldsInstance.tokenize(function (err, payload) {
if (err) {
if (err.type === 'CUSTOMER') {
$this.hostedFieldsInstance.focus('number', function (focusErr) {
if (focusErr) {
console.error(focusErr);
}
});
}
console.error(err)
tip.err(' BraintreeError ' + err.message);
var state = hostedFieldsInstance.getState();
Object.keys(state.fields).forEach(function (field) {
if (!state.fields[field].isValid) {
$('.hosted-field').addClass(
'braintree-hosted-fields-invalid');
}
});
button.removeAttribute('disabled');
return;
}
$this.pay(payload.nonce, button);
// instance threeDSecure
// braintree.threeDSecure.create({
// client: $this.clientInstance,
// version: '2'
// }, function (createError, threeDSecure) {
// if (createError) {
// console.error(createError);
// button.removeAttribute('disabled');
// return;
// }
// // set up lookup-complete listener
// threeDSecure.on('lookup-complete', function (data, next) {
// // check lookup data
// console.log(data, next)
// next();
// });
//
// // using Hosted Fields, use `tokenize` to get back a credit card nonce
//
// threeDSecure.verifyCard({
// nonce: payload.nonce,
// bin: payload.details.bin,
// amount: $this.actual_price
// }, function (verifyError, payload) {
// // inspect payload
// // send payload.nonce to your server
// button.removeAttribute('disabled');
// if (verifyError) {
// console.log(verifyError);
// return;
// }
// if (!payload.liabilityShifted) {
// console.log('Liability did not shift', payload);
// return;
// }
//
// console.log('verification success:', payload);
//
// $this.pay(payload.nonce, button);
// });
// });
});
},
applePay(button) {
var $this = this;
// Create a Apple Pay Checkout component.
if (window.ApplePaySession && window.ApplePaySession.supportsVersion(3) && window.ApplePaySession.canMakePayments()) {
var applePayInstance = $this.applePayInstance;
var paymentRequest = applePayInstance.createPaymentRequest({
total: {
label: 'My Store',
amount: $this.actual_price
},
});
console.log(paymentRequest.countryCode);
console.log(paymentRequest.currencyCode);
console.log(paymentRequest.merchantCapabilities);
console.log(paymentRequest.supportedNetworks);
var session = new ApplePaySession(3, paymentRequest);
session.onvalidatemerchant = function (event) {
applePayInstance.performValidation({
validationURL: event.validationURL,
displayName: 'My Great Store'
}, function (validationErr, validationData) {
if (validationErr) {
console.error(validationErr);
session.abort();
return;
}
session.completeMerchantValidation(validationData);
});
};
session.onpaymentauthorized = function (event) {
console.log('Your shipping address is:', event.payment.shippingContact);
applePayInstance.tokenize({
token: event.payment.token
}, function (tokenizeErr, payload) {
if (tokenizeErr) {
console.error('Error tokenizing Apple Pay:', tokenizeErr);
session.completePayment(ApplePaySession.STATUS_FAILURE);
return;
}
// Send payload.nonce to your server.
console.log('nonce:', payload.nonce);
// If requested, address information is accessible in event.payment
// and may also be sent to your server.
console.log('billingPostalCode:', event.payment.billingContact.postalCode);
// After you have transacted with the payload.nonce,
// call `completePayment` to dismiss the Apple Pay sheet.
session.completePayment(ApplePaySession.STATUS_SUCCESS);
});
};
session.begin();
// var paymentRequest = $this.applePayInstance.createPaymentRequest({
// total: {
// label: 'Eonon.com',
// amount: $this.actual_price,
// },
// merchantCapabilities: [
// "supports3DS",
// "supportsEMV"
// ],
// // We recommend collecting billing address information, at minimum
// // billing postal code, and passing that billing postal code with
// // all Apple Pay transactions as a best practice.
// // requiredBillingContactFields: ["postalAddress"]
// });
//
// console.log(paymentRequest.countryCode);
// console.log(paymentRequest.currencyCode);
// console.log(paymentRequest.merchantCapabilities);
// console.log(paymentRequest.supportedNetworks);
//
// var session = new ApplePaySession(3, paymentRequest);
// session.onvalidatemerchant = function (event) {
// $this.applePayInstance.performValidation({
// validationURL: event.validationURL,
// displayName: 'Eonon.com'
// }, function (err, merchantSession) {
// if (err) {
// // You should show an error to the user, e.g. 'Apple Pay failed to load.'
// alert("merchantSession err" + err)
// return;
// }
// session.completeMerchantValidation(merchantSession);
// });
// };
//
// session.onpaymentauthorized = function (
// event) {
// console.log('Your shipping address is:',event.payment.shippingContact);
// // alert('Your shipping address is:', event.payment.shippingContact)
// $this.applePayInstance.tokenize({
// token: event.payment.token
// }, function (tokenizeErr, payload) {
// if (tokenizeErr) {
// console.error('Error tokenizing Apple Pay:', tokenizeErr);
// alert('Error tokenizing Apple Pay:' + tokenizeErr)
// session.completePayment(ApplePaySession.STATUS_FAILURE);
// return;
// }
// // Send payload.nonce to your server.
// console.log('nonce:', payload.nonce);
//
// // If requested, address information is accessible in event.payment
// // and may also be sent to your server.
// console.log('billingPostalCode:', event.payment.billingContact.postalCode);
// //alert('billingPostalCode:' + event.payment.billingContact.postalCode)
// // After you have transacted with the payload.nonce,
// // call `completePayment` to dismiss the Apple Pay sheet.
// session.completePayment(ApplePaySession.STATUS_SUCCESS);
//
// $this.pay(payload.nonce, button);
// });
// };
// session.begin();
}
},
pay(nonce, button) {
$('#payment_method_nonce').val(nonce);
if (this.log_id) {
let data = {
payment_type: this.payment_type,
payment_method_nonce: nonce,
device_data: this.deviceData
};
tip.ajax('pay nonce url', data, (ret) => {
if (ret.code == 0) {
location.href = ret.data.jump_url;
// tip.suc(ret.msg, () => {
// });
} else {
button.removeAttribute('disabled');
tip.err(ret.msg);
}
}, 'post', true);
}
}
}
});
</script>