连接 plaid.io 与 django

Connect plaid.io with django

我只是想连接 plaid.ioDjango。 为此,我正在使用示例。

https://github.com/plaid/quickstart/tree/master/python

server.py

import os
import datetime
import plaid
from flask import Flask
from flask import render_template
from flask import request
from flask import jsonify

app = Flask(__name__)


# Fill in your Plaid API keys - https://dashboard.plaid.com/account/keys
PLAID_CLIENT_ID = 'xxxxxxxxxxxxxx'
PLAID_SECRET = 'xxxxxxxxxxxxxx'
PLAID_PUBLIC_KEY = 'xxxxxxxxxxxxxx'
# Use 'sandbox' to test with Plaid's Sandbox environment (username: user_good,
# password: pass_good)
# Use `development` to test with live users and credentials and `production`
# to go live
PLAID_ENV='sandbox'


client = plaid.Client(client_id = PLAID_CLIENT_ID, secret=PLAID_SECRET,
                  public_key=PLAID_PUBLIC_KEY, environment=PLAID_ENV)

@app.route("/")
def index():
   return render_template('index.ejs', plaid_public_key=PLAID_PUBLIC_KEY, plaid_environment=PLAID_ENV)


access_token = None
public_token = None

@app.route("/get_access_token", methods=['POST'])
def get_access_token():
  global access_token
  public_token = request.form['public_token']
  exchange_response = client.Item.public_token.exchange(public_token)
  # print 'access token: ' + exchange_response['access_token']

  access_token = exchange_response['access_token']

  return jsonify(exchange_response)

@app.route("/set_access_token", methods=['POST'])
def set_access_token():
  global access_token
  access_token = request.form['access_token']
  # print 'access token: ' + access_token
  return jsonify({'error': False})

@app.route("/accounts", methods=['GET'])
def accounts():
  global access_token
  accounts = client.Auth.get(access_token)
  return jsonify(accounts)

@app.route("/item", methods=['GET', 'POST'])
def item():
  global access_token
  item_response = client.Item.get(access_token)
  institution_response = client.Institutions.get_by_id(item_response['item']['institution_id'])
  return jsonify({'item': item_response['item'], 'institution': institution_response['institution']})

@app.route("/transactions", methods=['GET', 'POST'])
def transactions():
  global access_token
  # Pull transactions for the last 30 days
  start_date = "{:%Y-%m-%d}".format(datetime.datetime.now() + datetime.timedelta(-30))
  end_date = "{:%Y-%m-%d}".format(datetime.datetime.now())

  response = client.Transactions.get(access_token, start_date, end_date)
  return jsonify(response)

@app.route("/create_public_token", methods=['GET'])
def create_public_token():
  global access_token
  # Create a one-time use public_token for the Item. This public_token can be used to
  # initialize Link in update mode for the user.
  response = client.Item.public_token.create(access_token)
  return jsonify(response)

if __name__ == "__main__":
    app.run()

index.ejs

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Plaid Walkthrough Example</title>
    <link rel="stylesheet" type="text/css" href="static/style.css">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
    <div id="banner">
        <h1>Plaid Example Walkthrough</h1>
        <p id="intro">
            This is an example application that walks through integrating Plaid Link using the API to retrieve Auth and Transaction data.
        </p>
        <p id="steps">
            Great - you just created an Item! The server was successfully able to exchange the public_token for an access_token.
            Below are a few options - you can get account data, retrieve information about the Item itself, or pull transaction data.
        </p>
    </div>

    <div id="container">
        <p>
            Click the button below to open a list of Institutions - after you select one,
            you'll be guided through an authentication process. The public_token will be passed
            back to the example server, which will then exchange it for an access_token and log it
            to your console.
        </p>

        <button id="link-btn">Open Link</button>
    </div>

    <div id="app">
        <div class="box">
            <button id="get-accounts-btn">Get Accounts</button>
            <div id="get-accounts-data"></div>
        </div>

        <div class="box">
            <button id="get-item-btn">Get Item</button>
            <div id="upgrade-to-connect-data" class="inner"></div>
        </div>

        <div class="box" id="txnBox">
            <button id="get-transaction-data">Get Transactions</button>
            <div id="get-transactions-data"></div>
        </div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.3/jquery.min.js"></script>
    <script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js"></script>
    <script>
    function getParameterByName(name, url) {
        if (!url) url = window.location.href;
        name = name.replace(/[\[\]]/g, "\$&");
        var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
            results = regex.exec(url);
        if (!results) return null;
        if (!results[2]) return '';
        return decodeURIComponent(results[2].replace(/\+/g, " "));
    }
    ;(function($) {
        var handler = Plaid.create({
            apiVersion: 'v2',
            clientName: 'Plaid Walkthrough Demo',
            env: '{{ plaid_environment }}',
            product: ['transactions'],
            key: '{{ plaid_public_key }}',
            onSuccess: function(public_token) {
                $.post('/get_access_token', {public_token: public_token}, function() {
                    $('#container').fadeOut('fast', function() {
                        $('#intro').hide();
                        $('#app, #steps').fadeIn('slow');
                    });
                });
            },
        });

        $('#link-btn').on('click', function(e) {
            handler.open();
        });

        var accessToken =  getParameterByName('access_token');
        if (accessToken != null) {
            $.post('/set_access_token', {access_token: accessToken}, function() {
                $('#container').fadeOut('fast', function() {
                    $('#intro').hide();
                    $('#app, #steps').fadeIn('slow');
                });
            });
        }

        $('#get-accounts-btn').on('click', function(e) {
            $.get('/accounts', function(data) {
                $('#get-accounts-data').slideUp(function() {
                    var html = '';
                    data.accounts.forEach(function(account, idx) {
                        html += '<div class="inner">';
                        html += '<strong>' + account.name +
                                ' $' + (account.balances.available != null ? account.balances.available : account.balances.current) + '</strong><br>';
                        html += account.subtype + ' ' + account.mask;
                        html += '</div>';
                    });

                    $(this).html(html).slideDown();
                });
            });
        });

        $('#get-item-btn').on('click', function(e) {
            $.post('/item', function(data) {
                $('#upgrade-to-connect-data').slideUp(function() {
                    if(data.error)
                        $(this).html('<p>' + data.error + '</p>').slideDown();
                    else {
                        var html = '';
                        html += '<p>Here\'s some basic information about your Item:</p>';
                        html += '<p>Institution name:' + data.institution.name +'</p>';
                        html += '<p>Billed products: ' + data.item.billed_products.join(', ') + '</p>';
                        html += '<p>Available products: ' + data.item.available_products.join(', ') + '</p>';


                        $(this).html(html).slideDown();
                        $('#txnBox').slideDown();
                    }
                });
            });
        });

        $('#get-transaction-data').on('click', function(e) {
            $.post('/transactions', function(data) {
                if (data.error) {
                    $(this).html('<p>' + data.error + '</p>').slideDown();
                } else {
                $('#get-transactions-data').slideUp(function() {
                    var html = '<p>Pulled ' + data.transactions.length + ' transaction(s).</p>';
                    data.transactions.forEach(function(txn, idx) {
                        html += '<div class="inner">';
                        html += '<strong>' + txn.name + '</strong><br>';
                        html += '$' + txn.amount;
                        html += '<br><em>' + txn.date + '</em>';
                        html += '</div>';
                    });

                    $(this).slideUp(function() {
                        $(this).html(html).slideDown();
                    });
                });
                }
            });
        });
    })(jQuery);
    </script>
</body>
</html>

这与我的令牌完全相同。

但是在终端中出现了下一条消息:

sandbox.plaid.com/link/client/get Failed to load resource: the server responded with a status of 400 (Bad Request) link.js:125 Error: Error retrieving info for public key. Make sure that the entered key is correct. If the error persists, contact support@plaid.com. at link.js:125 (anonymous) @ link.js:125 cdn.plaid.com/authenticate Failed to load resource: the server responded with a status of 403 (Forbidden)

为什么我得到 400 Bad Request Message

终于找到问题所在了。 plaid.io 的当前版本不适用于 python 3.x。当前版本适用于 python 2.7。 一旦获得指定版本的 python 就可以正常工作