Last active
November 17, 2020 14:02
-
-
Save stigok/57f6e87bb5ec81f317ba9e3e16a2aa6c to your computer and use it in GitHub Desktop.
Betaling med Vipps i Python 3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
En enkel demo for å initialisere en Vipps-transaksjon. | |
Returnerer en URL som kunden kan bruke til å fullføre transaksjonen. | |
Denne URL kan for eksempel enkodes som en QR-kode og skannes. | |
Koden er lisensiert som CC-BY | |
2020 stigok | |
https://creativecommons.org/licenses/by/4.0/legalcode.no | |
""" | |
import datetime | |
import json | |
import secrets | |
import sys | |
import requests | |
#api_url = "https://api.vipps.no" | |
api_url = "https://apitest.vipps.no" | |
merchant_id = "12345" | |
client_id = "xxx" | |
client_secret = "xxx" | |
vipps_subscription_key_1 = "xxx" | |
vipps_subscription_key_2 = "xxx" | |
# Vipps will only allow callbacks to ports 80, 443 and 8080 | |
callback_url = "https://matrix.hackeriet.no/vipps-test/vipps/callback" | |
fallback_url_format = "https://matrix.hackeriet.no/vipps-test/vipps/fallback/%s" | |
def generate_order_id(): | |
""" | |
Generates a unique order ID. This implementation is time-based. | |
You should most probably be using sequenced ID's instead, like the number | |
from an auto-incremented SQL column. | |
""" | |
n = int(datetime.datetime.now().timestamp()) | |
s = "{:012}".format(n) | |
return "-".join([merchant_id, s[:4], s[4:8], s[8:]]) | |
def get_access_token(): | |
"""Return an access token string for authentication with the Vipps API""" | |
url = api_url + "/accessToken/get" | |
headers = { | |
"client_id": client_id, | |
"client_secret": client_secret, | |
"Ocp-Apim-Subscription-Key": vipps_subscription_key_1, | |
} | |
logging.debug("Request details %s", | |
json.dumps(dict(url=url, headers=headers), indent=2)) | |
res = requests.post(url, headers=headers) | |
res.raise_for_status() | |
return res.json()["access_token"] | |
def api_req(endpoint, payload, *, access_token): | |
"""Make an HTTP POST request to the API endpoint with the given payload""" | |
url = api_url + endpoint | |
headers = { | |
"Authorization": "Bearer %s" % access_token, | |
"Ocp-Apim-Subscription-Key": vipps_subscription_key_1, | |
"X-Request-Id": secrets.token_urlsafe(8), | |
} | |
logging.debug("Request details %s", | |
json.dumps(dict(url=url, headers=headers, payload=payload), indent=2)) | |
res = requests.post(url, json=payload, headers=headers) | |
res.raise_for_status() | |
return res.json() | |
def initiate_payment(*, amount, description, access_token): | |
order_id = generate_order_id() | |
payload = { | |
"customerInfo": {}, | |
"merchantInfo": { | |
"merchantSerialNumber": str(merchant_id), | |
"callbackPrefix": callback_url, | |
"fallBack": fallback_url_format % order_id, | |
}, | |
"transaction": { | |
"orderId": order_id, | |
"amount": amount, | |
"transactionText": description, | |
}, | |
} | |
return api_req("/ecomm/v2/payments", payload, access_token=access_token) | |
if __name__ == "__main__": | |
import logging | |
logging.basicConfig(level=logging.DEBUG) | |
logging.debug("API URL %s", api_url) | |
token = get_access_token() | |
order = initiate_payment(amount=3500, description="Club Mate", | |
access_token=token) | |
print("Vennligst betal kr 35.00 for din Club Mate") | |
print() | |
print("Ordre #", order["orderId"]) | |
print(order["url"]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
requests==2.23.0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment