1. Einführung
Zuletzt aktualisiert: 13.09.2021
Erheben von Zahlungen
Das Erfassen von Zahlungen in Business Messages eröffnet Ihnen ganz neue Geschäftsmöglichkeiten auf der Plattform für Unterhaltungen. Stellen Sie sich einen potenziellen Kunden vor, der Ihnen eine Anfrage zu einem Produkt sendet, über das er mehr erfahren möchte. Nachdem die Fragen beantwortet wurden, können Sie den Deal abschließen, indem Sie direkt in der Unterhaltung ein Zahlungsportal bereitstellen.
Was ist eine gute Zahlungserfahrung?
Eine gute Zahlungsabwicklung ist eine, bei der Nutzer wie gewohnt bezahlen.
Nutzer haben in Bezug auf Zahlungsmethoden Präferenzen und verschiedene Zahlungsmethoden sind in anderen Teilen der Welt üblicher als andere. Mit Business Messages können Sie mehr als einen Zahlungsabwickler einbinden, um Nutzern den größtmöglichen Komfort zu bieten.
Wenn ein Nutzer einen Zahlungsvorgang abschließt, möchten Sie ihn darüber informieren, dass Sie seine Zahlung erfolgreich erhalten haben. Die meisten Zahlungsabwickler haben einen Callback für Erfolg oder Fehler, der nach Abschluss des Zahlungsvorgangs eine HTTP-Anfrage an eine URL Ihrer Wahl sendet.
Inhalt
Im vorherigen Abschnitt der Codelab-Reihe haben Sie den Bonjour-Mahlzeit-Agent um einen Katalog von Artikeln erweitert, einen Warenkorb erstellt, in dem Nutzer Artikel hinzufügen und entfernen können, und den Gesamtpreis des Warenkorbs berechnet. In diesem Abschnitt erweitern Sie den Agent so, dass er Zahlungen basierend auf dem Inhalt des Einkaufswagens verarbeiten kann.
In diesem Codelab wird deine App
- In das Stripe-Zahlungsgateway einbinden
- Nutzern erlauben, den Zahlungsvorgang basierend auf dem Preis des Einkaufswagens abzuschließen
- Eine Benachrichtigung an die Unterhaltungsoberfläche senden, um den Nutzer über den Zahlungsstatus zu informieren
Aufgabe
- Integrieren Sie den Stripe-Zahlungsabwickler.
- Senden Sie eine Anfrage an Stripe, um eine Zahlungssitzung zu initiieren.
- Umgang mit Zahlungserfolgen oder Fehlantworten von Stripe.
Voraussetzungen
- Ein GCP-Projekt, das registriert und für die Verwendung mit Business Messages genehmigt wurde
- Eine Anleitung dazu finden Sie auf unserer Entwicklerwebsite.
- Ein Android-Gerät mit Version 5 oder höher ODER ein iOS-Gerät mit der Google Maps App
- Erfahrung mit Programmen für Webanwendungen
- Eine Internetverbindung
2. Abhängigkeiten hinzufügen
Die Datei „requirements.txt“ wird aktualisiert
Bei der Einbindung des Stripe-Zahlungsabwicklers können wir die Python-Clientbibliothek von Streifen verwenden. Fügen Sie stripe
zu „requirements.txt“ ohne Version hinzu, um die neueste Version der Abhängigkeit zu erhalten.
Dies ist erforderlich, damit die Python-Laufzeit von Google Cloud App Engine das Stripe-Python-Modul enthält.
requirements.txt
...
stripe
...
bopis/views.py wird vorbereitet
Importieren Sie oben aus bopis/views.py render
aus django.shortcuts
und JsonResponse
aus django.http
. Außerdem müssen Sie stripe
importieren, um Aufrufe an die Stripe Python-Clientbibliothek zu unterstützen.
...
from django.shortcuts import render
from django.http import JsonResponse
import stripe
...
3. Mit Stripe arbeiten
Konto bei Stripe.com erstellen
In diesem Codelab nutzen wir gerade Stripe. Du kannst aber beliebige Prozessoren verwenden, die Webintegration unterstützen. Erstellen Sie auf stripe.com ein Konto. Wir verwenden dieses Profil zu Testzwecken und zu Bildungszwecken, um zu erfahren, wie Sie es direkt in einen externen Zahlungsabwickler einbinden können.
Sobald Sie ein Konto erstellt und sich angemeldet haben, sollte ein Dashboard wie dieses angezeigt werden.
Achten Sie darauf, dass Sie im Modus „Testen“ arbeiten und klicken Sie auf die Schaltfläche Entwickler, wie im Screenshot oben beschrieben, um nach Ihren API-Schlüsseln zu suchen. Sie sollten zwei verschiedene API-Schlüsselsätze sehen: einen veröffentlichbaren Schlüssel und einen geheimen Schlüssel. Sie benötigen beide Schlüssel, um Zahlungstransaktionen mit Stripe zu ermöglichen.
bopis/views.py aktualisieren
Ihre Anwendung benötigt beide Schlüsselsätze. Aktualisieren Sie sie daher unter views.py.
Sie können den geheimen Schlüssel direkt für die Eigenschaft Stripe.api_key festlegen und ihm den Wert des geheimen Schlüssels aus dem Stripe-Entwickler-Dashboard zuweisen. Erstellen Sie dann eine globale Variable mit dem Namen STRIPE_PUBLIC_KEY
und legen Sie sie auf den veröffentlichten Schlüssel fest.
Außerdem muss Stripe den Nutzer zu einer von Ihnen verwalteten Webseite weiterleiten. Erstellen Sie daher eine zusätzliche globale Variable, die die öffentlich erreichbare Domain Ihrer Anwendung enthält.
Am Ende dieser Änderungen sehen Sie in etwa Folgendes:
stripe.api_key = 'sk_test_abcde-12345'
STRIPE_PUBLIC_KEY = 'pk_test_edcba-54321'
YOUR_DOMAIN = 'https://<GCP_PROJECT_ID>.appspot.com'
Das wars für die Einrichtung von Stripe.
4. Bezahlvorgang
„Gesamtpreis des Einkaufswagens“ aktualisieren
Derzeit sendet die Funktion send_shopping_cart_total_price
nur eine Nachricht, die den Preis des Einkaufswagens angibt. Fügen Sie eine vorgeschlagene Aktion hinzu, um eine URL zur Zahlungsseite zu öffnen.
def send_shopping_cart_total_price(conversation_id):
"""Sends shopping cart price to the user through Business Messages.
Args:
conversation_id (str): The unique id for this user and agent.
"""
cart_price = get_cart_price(conversation_id)
message_obj = BusinessMessagesMessage(
messageId=str(uuid.uuid4().int),
representative=BOT_REPRESENTATIVE,
text=f'Your cart\'s total price is ${cart_price}.',
suggestions=[
BusinessMessagesSuggestion(
action=BusinessMessagesSuggestedAction(
text='Checkout',
postbackData='checkout',
openUrlAction=BusinessMessagesOpenUrlAction(
url=f'{YOUR_DOMAIN}/checkout/{conversation_id}'))),
]
)
send_message(message_obj, conversation_id)
Wenn der Nutzer auf diese vorgeschlagene Aktion tippt, wird er zu einer Webseite weitergeleitet, auf der sein Gesamtpreis sowie eine Schaltfläche zum Bezahlen mit Stripe angezeigt werden.
Lassen Sie uns eine einfache Webseite erstellen, die diesen Vorgang unterstützt.
Suchen Sie im Quellcode des Projekts nach dem Verzeichnis bopis
. Erstellen Sie in bopis ein neues Verzeichnis namens templates
und in Vorlagen ein weiteres Verzeichnis namens bopis
. Dies ist ein GCR-Designmuster, das den Anwendungsnamen im Vorlagenverzeichnis angibt. Sie verringern die Verwechslung von Vorlagen zwischen GCR-Apps.
Sie sollten jetzt ein Verzeichnis mit einem Pfad unter bopis/templates/bopis/
haben. Sie können in diesem Verzeichnis HTML-Dateien erstellen, um Webseiten bereitzustellen. In GCR werden diese Vorlagen als Vorlagen bezeichnet, die im Browser gerendert werden. Fangen wir mit checkout.html
an.
Erstellen Sie in diesem Verzeichnis checkout.html
. Im folgenden Code-Snippet werden eine Zahlungsschaltfläche und der Preis des Einkaufswagens angezeigt. Sie umfasst auch JavaScript, um den Stripe-Kauf zu starten.
{% load static %}
<!DOCTYPE html>
<html>
<head>
<title>Purchase from Bonjour Meal</title>
<script src="https://js.stripe.com/v3/"></script>
<style>
.description{
font-size: 4em;
}
button {
color: red;
padding: 40px;
font-size: 4em;
}
</style>
</head>
<body>
<section>
<img
src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"
alt="Bonjour Meal Restaurant"
/>
<div class="product">
<div class="description">
<h3>Your Bonjour Meal Total</h3>
<h5>${{cart_price}}</h5>
</div>
</div>
<button type="button" id="checkout-button">Checkout</button>
</section>
</body>
<script type="text/javascript">
// Create an instance of the Stripe object with your publishable API key
var stripe = Stripe("{{stripe_public_key}}");
var checkoutButton = document.getElementById("checkout-button");
checkoutButton.addEventListener("click", function () {
fetch("/create-checkout-session/{{conversation_id}}", {
method: "POST",
})
.then(function (response) {
return response.json();
})
.then(function (session) {
return stripe.redirectToCheckout({ sessionId: session.id });
})
.then(function (result) {
// If redirectToCheckout fails due to a browser or network
// error, you should display the localized error message to your
// customer using error.message.
if (result.error) {
alert(result.error.message);
}
})
.catch(function (error) {
console.error("Error:", error);
});
});
</script>
</html>
Wir benötigen eine Route zu dieser Webseite, wenn die URL angefordert wird. Der Wert „suggestedAction“ an der Kasse hat den Wert „openUrlAction“ auf {YOUR_DOMAIN}/checkout/{conversation_id}
festgelegt. Dies entspricht in etwa https://<GCP-Project-ID>.appspot.com/checkout/abc123-cba321-abc123-cba321
. Bevor wir diese Route erstellen, sollten Sie sich den JavaScript-Code aus der HTML-Vorlage ansehen.
...
<script type="text/javascript">
// Create an instance of the Stripe object with your publishable API key
var stripe = Stripe("{{stripe_public_key}}");
var checkoutButton = document.getElementById("checkout-button");
checkoutButton.addEventListener("click", function () {
fetch("/create-checkout-session/{{conversation_id}}", {
method: "POST",
})
.then(function (response) {
return response.json();
})
.then(function (session) {
return stripe.redirectToCheckout({ sessionId: session.id });
})
.then(function (result) {
// If redirectToCheckout fails due to a browser or network
// error, you should display the localized error message to your
// customer using error.message.
if (result.error) {
alert(result.error.message);
}
})
.catch(function (error) {
console.error("Error:", error);
});
});
</script>
...
Gehen wir das Code-Snippet oben gemeinsam durch.
- Zuerst wird eine Stripe-Entität mit dem öffentlichen Schlüssel erstellt, der durch den Kontext aus der Ansichtsfunktion übergeben wird, einem weiteren GCR-Modell.
- Dann wird nach einem Element auf der Seite mit der ID
checkout-button
gesucht. - Diesem Element wird ein Ereignis-Listener hinzugefügt.
Dieser Ereignis-Listener wird ausgelöst, wenn ein Nutzer auf diese Schaltfläche klickt oder tippt. Dadurch wird eine POST-Anfrage an den Webserver initiiert, den Sie über die URL {YOUR_DOMAIN}/create-checkout-session/{conversation_id}.
angeben.
Die Webserverlogik wird in den Snippets unten angezeigt. Wenn der Nutzer auf die Schaltfläche mit der ID checkout-button
tippt, sollte eine Stripe-Sitzungs-ID zurückgegeben werden, die mit der Stripe API erstellt wurde und den Preis des Einkaufswagens angibt.
Wenn Ihr Server eine gültige Sitzungs-ID erzeugen konnte, leitet die Anwendungslogik den Nutzer zu einer Stripe Checkout-Seite weiter. Andernfalls wird der Nutzer mit einer standardmäßigen JavaScript-Nachricht darauf hingewiesen, dass ein Fehler aufgetreten ist.
Fügen Sie dem URL-Muster neue Pfade hinzu, um die Zahlungsseite zu unterstützen und die Sitzungs-ID zu generieren. Fügen Sie dem urlpatterns-Array in urls.py Folgendes hinzu:
...
path('checkout/<str:conversation_id>', bopis_views.payment_checkout),
path('create-checkout-session/<str:conversation_id>', bopis_views.create_checkout_session),
...
Anschließend erstellen Sie die Ansichtsfunktionen in views.py, um die Vorlage checkout.html zurückzugeben und den Stripe-Kaufvorgang zu generieren.
...
def payment_checkout(request, conversation_id):
"""Sends the user to a payment confirmation page before the payment portal.
Args:
request (HttpRequest): Incoming Django request object
conversation_id (str): The unique id for this user and agent.
Returns:
Obj (HttpResponse): Returns an HTTPResponse to the browser
"""
cart_price = get_cart_price(conversation_id)
context = {'conversation_id': conversation_id,
'stripe_public_key': STRIPE_PUBLIC_KEY,
'cart_price': cart_price
}
return render(request, 'bopis/checkout.html', context)
@csrf_exempt
def create_checkout_session(request, conversation_id):
"""Creates a Stripe session to start a payment from the conversation.
Args:
request (HttpRequest): Incoming Django request object
conversation_id (str): The unique id for this user and agent.
Returns:
Obj (HttpResponse): Returns an HTTPResponse to the browser
"""
cart_price = get_cart_price(conversation_id)
try:
checkout_session = stripe.checkout.Session.create(
payment_method_types=['card'],
line_items=[
{
'price_data': {
'currency': 'usd',
'unit_amount': int(cart_price*100),
'product_data': {
'name': 'Bonjour Meal Checkout',
'images': ['https://storage.googleapis.com/bonjour-rail.appspot.com/apple-walnut-salad.png'],
},
},
'quantity': 1,
},
],
mode='payment',
success_url=YOUR_DOMAIN + '/success/' + conversation_id,
cancel_url=YOUR_DOMAIN + '/cancel/' + conversation_id,
)
return JsonResponse({
'id': checkout_session.id
})
except Exception as e:
# Handle exceptions according to your payment processor's documentation
# https://stripe.com/docs/api/errors/handling?lang=python
return HttpResponse(e)
...
Bei beiden Funktionen wird die „conversation_id“ verwendet, um dem Nutzer den Einkaufswagen zuzuordnen und anschließend den Preis zu bestimmen, dem Stripe den Nutzer in Rechnung stellen soll.
Diese beiden Methoden bilden die erste Hälfte des Zahlungsvorgangs. Wenn Sie die Bereitstellung durchführen und die Websitevariante testen, sehen Sie ein Stripe-Bezahlformular. Dort können Sie die Zahlung mit einer Testkreditkarte abschließen, wie in der Stripe-Entwicklerdokumentation für den Test von Visa-Bezahl empfohlen.
Die zweite Hälfte des Ablaufs besteht darin, wie wir den Nutzer wieder in die Unterhaltung einbringen, nachdem wir die Antwort von Stripe zur Zahlung des Nutzers erhalten haben.
5. Stripe-Antworten
Wenn ein Nutzer Ihren Zahlungsvorgang abwickelt, konnte er die Zahlung entweder erfolgreich oder nicht abschließen. In der Funktion create_checkout_session
haben wir success_url
und cancel_url
definiert. Stripe leitet den Nutzer je nach Status der Zahlung an eine dieser beiden URLs weiter. Definieren Sie diese beiden Routen in urls.py und fügen Sie dann bopis/views.py zwei Ansichtsfunktionen hinzu, um diese beiden möglichen Abläufe zu unterstützen.
Fügen Sie diese Zeilen der Datei urls.py hinzu.
...
path('success/<str:conversation_id>', bopis_views.payment_success),
path('cancel/<str:conversation_id>', bopis_views.payment_cancel),
...
Die entsprechenden Ansichten sehen dann so aus:
...
def payment_success(request, conversation_id):
"""Sends a notification to the user prompting them back into the conversation.
Args:
request (HttpRequest): Incoming Django request object
conversation_id (str): The unique id for this user and agent.
Returns:
Obj (HttpResponse): Returns an HTTPResponse to the browser
"""
message_obj = BusinessMessagesMessage(
messageId=str(uuid.uuid4().int),
representative=BOT_REPRESENTATIVE,
suggestions=[
BusinessMessagesSuggestion(
reply=BusinessMessagesSuggestedReply(
text='Check on order', postbackData='check-order')),
],
text='Awesome it looks like we\'ve received your payment.')
send_message(message_obj, conversation_id)
return render(request, 'bopis/success.html')
def payment_cancel(request, conversation_id):
"""Sends a notification to the user prompting them back into the conversation.
Args:
request (HttpRequest): Incoming Django request object
conversation_id (str): The unique id for this user and agent.
Returns:
Obj (HttpResponse): Returns an HTTPResponse to the browser
"""
message_obj = BusinessMessagesMessage(
messageId=str(uuid.uuid4().int),
representative=BOT_REPRESENTATIVE,
suggestions=[
BusinessMessagesSuggestion(
action=BusinessMessagesSuggestedAction(
text='Checkout',
postbackData='checkout',
openUrlAction=BusinessMessagesOpenUrlAction(
url=f'{YOUR_DOMAIN}/checkout/{conversation_id}'))),
],
text='It looks like there was a problem with checkout. Try again?')
send_message(message_obj, conversation_id)
return render(request, 'bopis/cancel.html')
...
Stripe leitet die Nutzer wieder zur Domain zurück, wie Sie in der Konstante DOMAIN
angegeben haben. Das bedeutet, dass Sie eine HTML-Antwort über eine Vorlage rendern müssen oder die Website sehr minimalistisch aussieht. Erstellen Sie im Verzeichnis „bopis/template/bopis/“ zusammen mit „checkout.html“ zwei einfache HTML-Dateien.
bm-django-echo-bot/bopis/ Vorlagen/bopis/success.html
{% load static %}
<html>
<head>
<title>Business Messages Payment Integration Sample!</title>
<style>
p{
font-size: 4em;
}
</style>
</head>
<body>
<section>
<p>
Checkout succeeded - We appreciate your business!
<br/><br/>
For support related questions, please email
<a href="mailto:bm-support@google.com">bm-support@google.com</a>.
</p>
</section>
</body>
</html>
bm-django-echo-bot/bopis/ vorlagen/bopis/cancel.html
{% load static %}
<html>
<head>
<title>Checkout canceled</title>
<style>
p{
font-size: 4em;
}
</style>
</head>
<body>
<section>
<p>Checkout canceled - Forgot to add something to your cart? Shop around then come back to pay!</p>
</section>
</body>
</html>
Mit diesen beiden Vorlagen wird ein Nutzer, der einen Zahlungsvorgang mit der Stripe-Integration durchführt, an die entsprechenden URLs weitergeleitet und mit den entsprechenden Vorlagen dargestellt. Sie erhalten auch eine Nachricht über Business Messages, sodass sie zur Unterhaltung zurückkehren können.
6. Zahlungen erhalten
Glückwunsch, Sie haben einen Zahlungsabwickler erfolgreich in Ihren Business Messages-Agent eingebunden.
In dieser Reihe haben Sie eine Webanwendung in Google Cloud App Engine bereitgestellt, Ihren Webhook in der Business Communications Developer Console eingerichtet, die Anwendung zur Unterstützung der Inventarsuche über eine statische Datenbank erweitert und einen Einkaufswagen mit Google Datastore erstellt. Im letzten Teil der Reihe haben Sie Stripe integriert, einen Zahlungsabwickler, der Webintegrationen und diese Erfahrung unterstützt. Sie können jetzt mit anderen Zahlungsabwicklern zusammenarbeiten.
Was liegt als Nächstes an?
Wenn Sie so weit sind, sehen Sie sich die folgenden Themen an, um mehr über komplexere Interaktionen mit Business Messages zu erfahren:
- Funktionsweise von Business Messages
- Best Practices
- Richtlinien für Logos
- Übergabe an Kundenservicemitarbeiter
- Codelabs für Business Messages
Referenzdokumente
- Vorgeschlagene Antwort
- Dokument für Business Messages-Nachrichten
- JSON-Definition für RichCard