2015-12-16 20 views
8

Jestem trochę źle zrozumiany Paypal flow event po przeczytaniu https://developer.paypal.com/docs/api/. Chciałbym zintegrować płatności ekspresowe i płatności kartą kredytową z moją witryną. Używam Flask i paypalrestsdk bez żadnych rozszerzeń Flask.Integracja Paypal z aplikacją Flask

Oto fragmenty z mojej aplikacji:

@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') 

Jest działa dobrze, po kliknięciu na przycisk payment stworzonej pomyślnie (z państwowej created) użytkownik przekierowany do strony zatwierdzania. Tam kliknij "Potwierdź" ... I nigdy nie wróciłem do mojej aplikacji, zdarzenia, gdy określam return_url! To znaczy. wniosek nigdy nie może zostać poinformowany, że kupujący zatwierdził płatność i powinien zostać zaktualizowany we własnej bazie danych, a nowa licencja powinna zostać wysłana do tej osoby.

Problemy:

  1. nie mogę znaleźć sposób, aby zdefiniować kilka zwrotnego używając pyhtonrestsdk. Jak to zrobić?

  2. Nawet jeśli dodałem funkcję oddzwaniania (próbowałem umieścić Express Checkout przy użyciu czystego kodu przycisku Javascript) z data-callback, moja aplikacja nie została wywołana. Podejrzewam, że serwer zdalny nie mógł zadzwonić pod numer http://127.0.0.1/payment/paypal/success

  3. Użytkownik może zamknąć okno z potwierdzeniem PayPal natychmiast po kliknięciu "Potwierdź", więc nie mogłem ufać przekierowaniu przeglądarki, które wykonał później.

Wreszcie, podejrzewam, że nie rozumiem przepływu pracy PayPal jest jasne, ale nie mogłem znaleźć więcej informacji o tym zdarzeniu na portalu deweloperów.

+0

Dostaję jakiś dziwny błąd CORS, gdy próbuję przekierować. "Nie można załadować strony paypal.sandbox.com. Żądany zasób nie zawiera nagłówka" Access-Control-Allow-Origin "." – shell

Odpowiedz

2

Jak zwykle diabeł kryje się w szczegółach. Mój główny problem to: paypal nie przekierowuje mnie do mojej aplikacji, ale odkryłem, że przekierowuje mnie (po potwierdzeniu) na adres URL, który wygląda jak https://sandbox.paypal.com/, a ciąg zapytania zawiera pożądane parametry. To znaczy. redirect_urls działa zgodnie z oczekiwaniami, przekierowuje mnie do niewłaściwego hosta.

Po tym przypomniałem sobie, że url_for generuje względne linki. Tak właśnie dodano słowo kluczowe _external=True Zostałem przekierowany do mojej aplikacji z wszystkimi wymaganymi argumentami i płatności pomyślnie potwierdzone i wykonane.

tj. poprawne redirect_urls blok wygląda następująco:

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

Wreszcie mam następujący workflow:

  1. Otwarty / (index), który ma przycisk Pay with PayPal Jest przycisk obraz wewnątrz formy. Obok tego przycisku znajdują się ukryte pola z kwotą, nazwą produktu i ilością (w rzeczywistości, jeśli nie jest to dobry pomysł, ponieważ nie możemy ufać użytkownikowi, więc przechowuję tylko product_license_type_id, który jest przechowywany w DB i zawiera wszystkie wymagane informacje o produkcie).

  2. Po kliknięciu formularza POST do "/ payment/paypal" (paypal_create), gdzie należy utworzyć obiekt Payment z wypełnieniem wszystkich pól.Jeśli wywołanie payment.create zakończyło się pomyślnie, to również tworzy rekord we własnej bazie danych z payment_id i state (te pola związane z workflow Paypal, oczywiście faktycznie przechowuję kilka innych pól związanych z moją aplikacją).

  3. Po dokonaniu płatności po stronie PayPal, aplikacja sprawdza odpowiedź na listę payment.links. Chcemy jeden z rel == 'approval_url' i method == 'REDIRECT' i powrócić flask.redirect(found_link)

  4. na paypal stronie kupującego należy kliknąć przycisk „Zatwierdź”, adres ocena transportową, a potem zostanie on natychmiast przekierowany do redirect_urls.return_url z następujących parametrów w ciągu zapytania: PayerID, paymentId, token .

  5. Po przekierowaniu z powrotem powinieneś pobrać te parametry z ciągu zapytania (pamiętaj - wielkość liter ma znaczenie!), Znajdź płatność za pomocą interfejsu API PayPal (payment = paypalrestsdk.Payment.find(payment_id)) i sfinalizuj (payment.execute({"payer_id": payer_id}):).

  6. Po sfinalizowaniu płatności zmienia status na approved.

  7. ....

  8. PROFIT!

UPD: Nie trzeba włączyć „AutoRedirect” w was sprzedaje preferencje konta i to podejście odpowiednie dla integracji jedno konto w wielu miejscach.

+0

Przepraszamy za drugi komentarz, ale w kroku 3, gdy próbuję przekierować, otrzymuję komunikat "Nie można załadować strony paypal.sandbox.com no" Access-Control-Allow-Origin. "Używam lokalnej lokacji. Czy to się zdarzyło? – shell