2015-12-16 15 views
8

Sono leggermente frainteso dall'evento di flusso Paypal dopo aver letto https://developer.paypal.com/docs/api/. Mi piacerebbe integrare il pagamento express e i pagamenti con carta di credito sul mio sito. Sto usando Flask e paypalrestsdk senza alcuna estensione Flask.Integrazione Paypal all'applicazione Flask

Ecco estratti dalla mia app:

@app.route('/', methods=['GET']) 
def index(): 
    # Page with but form, price/quantity/name values 
    # are stored in hidden fields, "Buy now" acts as submit 
    return render_template('index.html') 

@app.route('/payment/paypal', methods=['POST']) 
def payment_paypal(): 
    # Here I am creating dict with required params 
    payment_template = { 
     'intent': 'sale', 
     'payer': {'payment_method': 'paypal'}, 
     'redirect_urls': { 
      'return_url': url_for('payment_paypal_execute'), 
      'cancel_url': url_for('payment_paypal_error') 
     }, 
     ...... 
    } 

    payment = paypalrestsdk.Payment(payment) 

    if payment.create(): 
     print('Payment "{}" created successfully'.format(payment.id)) 

     for link in payment.links: 
      if link.method == "REDIRECT": 
       redirect_url = str(link.href) 
       print('Redirect for approval: {}'.format(redirect_url)) 
       return redirect(redirect_urls) 

@app.route('/payment/paypal/execute', methods=['GET']) 
def payment_paypal_execute(): 
    payer_id = request.args.get('payerId') 
    payment_id = request.args.get('paymentId') 
    token = request.args.get('token') 

    pending_payment = PayPalPayment.query.filter_by(token=token).filter_by(state='created').first_or_404() 

    try: 
     payment = paypalrestsdk.Payment.find(pending_payment.payment_id) 
    except paypalrestsdk.exceptions.ResourceNotFound as ex: 
     print('Paypal resource not found: {}'.format(ex)) 
     abort(404) 

    if payment.execute({"payer_id": payer_id}): 
     pending_payment.state = payment.state 
     pending_payment.updated_at = datetime.strptime(payment.update_time, "%Y-%m-%dT%H:%M:%SZ") 
     db.session.commit() 
     return render_template('payment/success.html', payment_id=payment.id, state=payment.state) 

    return render_template('payment/error.html', payment_error=payment.error, step='Finallizing payment') 

E 'funziona bene, dopo aver fatto clic sul pulsante payment creato con successo (con lo stato created) utente reindirizzati alla pagina di approvazione. Lì fa clic su "Conferma" ... E non sono mai tornato alla mia domanda, evento quando ho specificato return_url! Cioè l'applicazione non può mai essere informata del fatto che l'acquirente ha approvato il pagamento e dovrebbe essere aggiornato nel mio database e la nuova licenza dovrebbe essere inviata a quella persona.

Problemi:

  1. non riesco a trovare modo per definire alcuni callback utilizzando pyhtonrestsdk. Come farlo?

  2. Anche se aggiungo la richiamata (ho provato a incorporare Express Checkout utilizzando puro codice pulsante Javascript) con data-callback la mia applicazione non è stata chiamata. Sospetto che il server remoto non possa chiamare http://127.0.0.1/payment/paypal/success

  3. L'utente potrebbe chiudere la finestra con conferma PayPal immediatamente dopo aver fatto clic su "Conferma", quindi non potevo fidarmi del reindirizzamento del browser in seguito.

Infine, ho il sospetto che io non capisco il flusso di lavoro PayPal chiaro, ma non sono riuscito a trovare ulteriori informazioni su di esso evento sul portale sviluppatori.

+0

Errore di CORS durante il tentativo di reindirizzamento. "Impossibile caricare paypal.sandbox.com nessuna intestazione 'Access-Control-Allow-Origin-Allow-Origin' presente sulla risorsa richiesta." – shell

risposta

2

Come al solito, il diavolo si nasconde nei dettagli. Il mio problema principale era il seguente: paypal non mi reindirizza alla mia applicazione, ma ho scoperto che mi reindirizza (dopo la conferma) a URL che assomiglia a https://sandbox.paypal.com/ con stringa di query contiene i parametri desiderati. Cioè redirect_urls funziona come previsto, semplicemente mi reindirizza a un host sbagliato.

Successivamente ho ricordato che url_for genera relativi collegamenti. Quindi ho appena aggiunto la parola chiave _external=True Sono stato reindirizzato alla mia applicazione con tutti gli argomenti richiesti e il pagamento è stato confermato ed eseguito con successo.

I.e. corretta redirect_urls blocco volontà assomiglia:

'redirect_urls': { 
    'return_url': url_for('payment_paypal_execute', _external=True), 
    'cancel_url': url_for('payment_paypal_error', _external=True) 
} 

Infine ho seguente flusso di lavoro:

  1. Aperto / (index) quale pulsante Pay with PayPal ha È pulsante immagine all'interno modulo. Accanto a questo pulsante il modulo contiene campi nascosti con quantità, nome del prodotto e quantità (in realtà se non è una buona idea perché non possiamo fidarci degli utenti, quindi memorizzo solo product_license_type_id che è memorizzato nel DB e contiene tutte le informazioni necessarie sul prodotto).

  2. Una volta fatto clic su POST modulo su '/ payment/paypal' (paypal_create) dove creare l'oggetto Payment con il riempimento di tutti i campi.Se la chiamata payment.create viene completata correttamente, crea anche record nel mio database con payment_id e state (questi campi sono relativi al flusso di lavoro paypal, ovviamente in realtà sto memorizzando un paio di altri campi relativi alla mia app).

  3. Una volta creato il pagamento sul lato PayPal, l'aspetto dell'applicazione è pronto per l'elenco payment.links. Vogliamo uno con rel == 'approval_url' e method == 'REDIRECT' e tornare flask.redirect(found_link)

  4. Sul acquirenti PayPal sito dovrebbe fare clic su 'Approva', indirizzo di revisione di spedizione e dopo che sarà immediatamente reindirizzato a redirect_urls.return_url con i seguenti parametri nella stringa di query: PayerID, paymentId, token .

  5. volta reindirizzato si dovrebbe ottenere questo parametri dalla query string (tenere a mente - che è case-sensitive), trovare il pagamento tramite PayPal API (payment = paypalrestsdk.Payment.find(payment_id)) e finalizzarlo (payment.execute({"payer_id": payer_id}):).

  6. Quando il pagamento finalizzato cambia stato a approved.

  7. ....

  8. UTILE!

UPD: Non è necessario attivare "AutoRedirect" in voi vendere preferenze dell'account e questo approccio adatto per l'integrazione di un account in più siti.

+0

Ci scusiamo per il secondo commento, ma nel passaggio 3 quando provo a reindirizzare ottengo "Impossibile caricare paypal.sandbox.com no" Access-Control-Allow-Origin ". Sto eseguendo il flask localmente. – shell