uniapp对接braintree支付

463 阅读1分钟

公司要求在uniapp上对接braintree支付,自己研究了一下

这是braintree官网 Braintree Developer Documentation (paypal.com)

话不多说,直接上代码

<template>
  <view class="content">
    <view class="top">
      <view class="input-amount">
        <view class="">
          金额:
        </view>
        <input type="number" v-model="amount" id="amount" value="" placeholder="付款金额" />
      </view>

      <view class="card">
        <view class="card-Number" id="cc-number"></view>
        <view class="card-cvv" id="cc-cvv"></view>
        <view class="card-date" id="cc-expiration-date"></view>
      </view>

      <view class="card-pay" id="card-pay">

      </view>


    </view>

    <view class="bottom">
      <view class="buttom-Card" @click="payCard()">
        使用信用卡支付
      </view>
      <view class="buttom-PayPay" @click="payPaypal()">
        使用paypal支付
      </view>
    </view>
  </view>
</template>
<script>
  export default {
    data() {
      return {

        amount: 1.1,
        cardNumberPlaceholder: "请输入你的信用卡号",
        cardCVVPlaceholder: "请输入信用卡号背面3位号码",
        cardDatePlaceholder: "请输入信用卡有效期",

        client: null,
        hostedFields: null,
        threeDSecure: null,
        paypal: null,


        clientErr: null,
        clientInstance: null,
        hostedFieldsInstance: null

      }
    },
    onLoad() {
      this.client = require('@/lib/client.min.js');
      this.hostedFields = require('@/lib/hosted-fields.min.js');
      this.threeDSecure = require('@/lib/three-d-secure.min.js');
      this.paypal = require('@/lib/paypal.min.js');


      this.client.create({
        authorization: "eyJ2ZXJzaW9uIjoyLCJhdXRob3JpemF0aW9uRmluZ2VycHJpbnQiOiJleUowZVhBaU9pSktWMVFpTENKaGJHY2lPaUpGVXpJMU5pSXNJbXRwWkNJNklqSXdNVGd3TkRJMk1UWXRjMkZ1WkdKdmVDSXNJbWx6Y3lJNkltaDBkSEJ6T2k4dllYQnBMbk5oYm1SaWIzZ3VZbkpoYVc1MGNtVmxaMkYwWlhkaGVTNWpiMjBpZlEuZXlKbGVIQWlPakUyTVRnME5UYzFPVFlzSW1wMGFTSTZJbU5pTW1Rek9UTXlMV0pqTW1VdE5ESTBOaTA1TjJaa0xUazJaVFprTmprMU16azVPU0lzSW5OMVlpSTZJbmgwZVRZek4yTnlhbXBpTm1jNVpEWWlMQ0pwYzNNaU9pSm9kSFJ3Y3pvdkwyRndhUzV6WVc1a1ltOTRMbUp5WVdsdWRISmxaV2RoZEdWM1lYa3VZMjl0SWl3aWJXVnlZMmhoYm5RaU9uc2ljSFZpYkdsalgybGtJam9pZUhSNU5qTTNZM0pxYW1JMlp6bGtOaUlzSW5abGNtbG1lVjlqWVhKa1gySjVYMlJsWm1GMWJIUWlPblJ5ZFdWOUxDSnlhV2RvZEhNaU9sc2liV0Z1WVdkbFgzWmhkV3gwSWwwc0luTmpiM0JsSWpwYklrSnlZV2x1ZEhKbFpUcFdZWFZzZENKZExDSnZjSFJwYjI1eklqcDdmWDAuX2xyWmh3VU95b01aTDEwdzJ1SkFtYlFYLXFVRzhUN3VqYWh4OEdaWFZRVFRfT0gzVlZZSkw4WldxVkFjLWJhN2R0VE93VGxrc3RVTE1MSmZuSWoxbEEiLCJjb25maWdVcmwiOiJodHRwczovL2FwaS5zYW5kYm94LmJyYWludHJlZWdhdGV3YXkuY29tOjQ0My9tZXJjaGFudHMveHR5NjM3Y3JqamI2ZzlkNi9jbGllbnRfYXBpL3YxL2NvbmZpZ3VyYXRpb24iLCJncmFwaFFMIjp7InVybCI6Imh0dHBzOi8vcGF5bWVudHMuc2FuZGJveC5icmFpbnRyZWUtYXBpLmNvbS9ncmFwaHFsIiwiZGF0ZSI6IjIwMTgtMDUtMDgiLCJmZWF0dXJlcyI6WyJ0b2tlbml6ZV9jcmVkaXRfY2FyZHMiXX0sImNsaWVudEFwaVVybCI6Imh0dHBzOi8vYXBpLnNhbmRib3guYnJhaW50cmVlZ2F0ZXdheS5jb206NDQzL21lcmNoYW50cy94dHk2MzdjcmpqYjZnOWQ2L2NsaWVudF9hcGkiLCJlbnZpcm9ubWVudCI6InNhbmRib3giLCJtZXJjaGFudElkIjoieHR5NjM3Y3JqamI2ZzlkNiIsImFzc2V0c1VybCI6Imh0dHBzOi8vYXNzZXRzLmJyYWludHJlZWdhdGV3YXkuY29tIiwiYXV0aFVybCI6Imh0dHBzOi8vYXV0aC52ZW5tby5zYW5kYm94LmJyYWludHJlZWdhdGV3YXkuY29tIiwidmVubW8iOiJvZmYiLCJjaGFsbGVuZ2VzIjpbXSwidGhyZWVEU2VjdXJlRW5hYmxlZCI6dHJ1ZSwiYW5hbHl0aWNzIjp7InVybCI6Imh0dHBzOi8vb3JpZ2luLWFuYWx5dGljcy1zYW5kLnNhbmRib3guYnJhaW50cmVlLWFwaS5jb20veHR5NjM3Y3JqamI2ZzlkNiJ9LCJwYXlwYWxFbmFibGVkIjp0cnVlLCJwYXlwYWwiOnsiYmlsbGluZ0FncmVlbWVudHNFbmFibGVkIjp0cnVlLCJlbnZpcm9ubWVudE5vTmV0d29yayI6ZmFsc2UsInVudmV0dGVkTWVyY2hhbnQiOmZhbHNlLCJhbGxvd0h0dHAiOnRydWUsImRpc3BsYXlOYW1lIjoiY2hpbmEiLCJjbGllbnRJZCI6IkFXbjY0WnNIVTk2Q3dGY2VfSTlVUXFfTDdjUzZ1dlM0ei1QUTVSWWJjZmRkSFUxbnh2RDVrZjljNDJqS2xnQ25IMTBfRllSRDFPcGE5UFV3IiwicHJpdmFjeVVybCI6Imh0dHA6Ly9leGFtcGxlLmNvbS9wcCIsInVzZXJBZ3JlZW1lbnRVcmwiOiJodHRwOi8vZXhhbXBsZS5jb20vdG9zIiwiYmFzZVVybCI6Imh0dHBzOi8vYXNzZXRzLmJyYWludHJlZWdhdGV3YXkuY29tIiwiYXNzZXRzVXJsIjoiaHR0cHM6Ly9jaGVja291dC5wYXlwYWwuY29tIiwiZGlyZWN0QmFzZVVybCI6bnVsbCwiZW52aXJvbm1lbnQiOiJvZmZsaW5lIiwiYnJhaW50cmVlQ2xpZW50SWQiOiJtYXN0ZXJjbGllbnQzIiwibWVyY2hhbnRBY2NvdW50SWQiOiJjaGluYSIsImN1cnJlbmN5SXNvQ29kZSI6IlVTRCJ9fQ=="
      }, (clientErr, clientInstance) => {
        // console.log("clientErr:", clientErr)
        // console.log("clientInstance:", clientInstance)

        this.clientErr = clientErr
        this.clientInstance = clientInstance
        if (this.clientErr) {
          console.error('Error creating client:', clientErr);
          return;
        }
        this.showView()
        console.warn("braintree init scuess!")
      })
    },
    methods: {

      showView() {
        this.hostedFields.create({
          client: this.clientInstance,
          fields: {
            number: {
              selector: '#cc-number',
              placeholder: this.cardNumberPlaceholder
            },
            cvv: {
              selector: '#cc-cvv',
              placeholder: this.cardCVVPlaceholder
            },
            expirationDate: {
              selector: '#cc-expiration-date',
              placeholder: this.cardDatePlaceholder
            }
          }
        }, function(err, hostedFieldsInstance) {
          if (err) {
            console.error("this.hostedFields.create:", err);
            return;
          }
          this.hostedFieldsInstance = hostedFieldsInstance

        }.bind(this))
      },
      payCard() {
        console.log("payCard")
        this.hostedFieldsInstance.tokenize(function(err, payload) {
          if (err) {
            console.error(err);
            return;
          }
          console.log("payload:", payload)
          let cardType = payload.details.cardType;
          let lastFour = payload.details.lastFour;
          console.warn("payload.nonce :", payload.nonce);
          let my3DSContainer;
          this.threeDSecure.create({
            client: this.clientInstance
          }, function(threeDSecureErr, threeDSecure) {
            if (threeDSecureErr) {
              console.error("Error creating 3DSecure" + threeDSecureErr);
              return;
            }
            console.log("threeDSecure:", threeDSecure)
            threeDSecure.verifyCard({
              nonce: payload.nonce,
              amount: this.amount,
              // bin: payload.details.bin,
              addFrame: function(err, iframe) {
                // Set up your UI and add the iframe.
                my3DSContainer = document.createElement('div');
                my3DSContainer.appendChild(iframe);
                //document.body.appendChild(my3DSContainer);

                document.querySelector("#card-pay").appendChild(my3DSContainer);
              },
              removeFrame: function() {
                //Remove UI that you added in addFrame.
                //document.body.removeChild(my3DSContainer);
                document.querySelector("#card-pay").removeChild(my3DSContainer);
              }

            }, function(err, thpayload) {
              if (err) {
                console.error("verifyCard:", err);
                return;
              }
              if (thpayload.liabilityShiftPossible) {
                if (thpayload.liabilityShifted) {
                  //Liablity has shifted
                  //submitNonceToServer(payload.nonce);
                  //document.querySelector('#nonce').value = thpayload.nonce;
                  console.log('Card Got nonce:', thpayload.nonce);
                  console.log("payCard ->payload:支付成功 去服务端验证", payload.nonce)
                } else {
                  console.log("Invalid Card!");
                }
              } else {
                document.querySelector('#nonce').value = thpayload.nonce;
                console.log('No3D nonce:', thpayload.nonce);
                console.log("payCard ->payload:支付成功 去服务端验证", payload.nonce)
              }

            })
          }.bind(this))

        }.bind(this))

      },
      payPaypal() {
        console.log("payPaypal")

        console.log(" this.client:", this.client)
        this.paypal.create({
          client: this.clientInstance
        }, function(paypalErr, paypalInstance) {
          if (paypalErr) {
            console.error('Error creating PayPal:', paypalErr);
            return;
          }

          paypalInstance.tokenize({
            flow: 'checkout',
            amount: this.amount,
            currency: 'USD'
          }, function(tokenizeErr, payload) {
            if (tokenizeErr) {
              if (tokenizeErr.type !== 'CUSTOMER') {
                console.log('Error tokenizing:', tokenizeErr);
              }
              return;
            }
            console.log("payPaypal ->payload:支付成功 去服务端验证", payload.nonce)

          })


        }.bind(this))

      }
    }
  }
</script>
<style lang="scss">
  .content {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;

  }

  .logo {
    height: 200rpx;
    width: 200rpx;
    margin-top: 200rpx;
    margin-left: auto;
    margin-right: auto;
    margin-bottom: 50rpx;
  }

  .text-area {
    display: flex;
    justify-content: center;
  }

  .title {
    font-size: 36rpx;
    color: #8f8f94;
  }

  .top {
    display: flex;
    flex-direction: column;
    align-items: center;
    background-color: #677a6e;
    width: 100%;
    height: 500rpx;
    // justify-content: space-around;

    .input-amount {
      margin-top: 35rpx;
      display: flex;
      flex-direction: row;
      align-items: center;
      justify-content: center;
      width: 80%;
      color: #FFFFFF;

      input {
        padding-left: 20rpx;
        color: #000000;
        margin-left: 20rpx;
        width: 80%;
        background-color: #c0beb0;
      }

    }

    .card {
      margin-top: 35rpx;
      width: 80%;
      height: 300rpx;
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      justify-content: space-around;


      .card-Number {
        width: 100%;
        border-radius: 15rpx;
        padding-left: 20rpx;
        height: 88rpx;
        background-color: #dddddd;
      }

      .card-cvv {
        width: 100%;
        border-radius: 15rpx;
        padding-left: 20rpx;
        height: 88rpx;
        background-color: #dddddd;

      }

      .card-date {
        width: 100%;
        border-radius: 15rpx;
        padding-left: 20rpx;
        height: 88rpx;
        background-color: #dddddd;
      }

    }
  }

  .bottom {
    position: absolute;
    bottom: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-around;
    width: 100%;
    height: 200rpx;
    background-color: #b7d9a7;

    .buttom-Card {
      width: 80%;
      height: 88rpx;
      background-color: #007AFF;
      border-radius: 30rpx;
      text-align: center;
      line-height: 88rpx;
      color: #FFFFFF;
    }

    .buttom-PayPay {

      width: 80%;
      height: 88rpx;
      background-color: #ff7139;
      border-radius: 30rpx;
      text-align: center;
      line-height: 88rpx;
      color: #FFFFFF;
    }
  }
</style>

lib目录

2.png

使用官网的测试卡号去支付 Testing and Go Live | Ruby - Braintree Developer Documentation (paypal.com)

最后把 authorization 换成自己的就可以了 (必须)

最终效果 (作者这边 authorization 是过期的,只有 authorization 有效的时候输入框才能输入,会显示请输入,authorization 无效则输入框则空白,就像作者一样)

1.png

觉得还可以的话点赞评论下