Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
UCC
uccportal
Commits
fed18925
Commit
fed18925
authored
Jan 24, 2019
by
frekk
Browse files
added dispense stuff & more payment-related stuff
parent
7e5cb8b6
Changes
4
Hide whitespace changes
Inline
Side-by-side
gms/gms/settings.py
View file @
fed18925
...
...
@@ -33,6 +33,7 @@ MIDDLEWARE = [
'django.contrib.auth.middleware.AuthenticationMiddleware'
,
'django.contrib.messages.middleware.MessageMiddleware'
,
'django.middleware.clickjacking.XFrameOptionsMiddleware'
,
'memberdb.views.MemberMiddleware'
,
]
ROOT_URLCONF
=
'gms.urls'
...
...
@@ -139,5 +140,9 @@ LOGGING = {
'level'
:
LOG_LEVEL
,
'handlers'
:
[
'logfile'
,
'console'
],
},
'squarepay'
:
{
'level'
:
LOG_LEVEL
,
'handlers'
:
[
'logfile'
,
'console'
],
}
},
}
\ No newline at end of file
}
gms/gms/settings_local.example.py
View file @
fed18925
...
...
@@ -89,4 +89,13 @@ AUTH_LDAP_USER_FLAGS_BY_GROUP = {
# the Square app and location data (set to sandbox unless you want it to charge people)
SQUARE_APP_ID
=
'maybe-sandbox-something-something-here'
SQUARE_LOCATION
=
'CBASEDE-this-is-probably-somewhere-in-Sydney'
SQUARE_ACCESS_TOKEN
=
'keep-this-very-secret'
\ No newline at end of file
SQUARE_ACCESS_TOKEN
=
'keep-this-very-secret'
DISPENSE_BIN
=
'/usr/local/bin/dispense'
# configure the email backend (see https://docs.djangoproject.com/en/2.1/topics/email/)
EMAIL_HOST
=
"secure.ucc.asn.au"
EMAIL_PORT
=
465
EMAIL_USE_SSL
=
True
EMAIL_HOST_USER
=
"uccportal"
EMAIL_HOST_PASSWORD
=
"changeme"
gms/squarepay/dispense.py
0 → 100644
View file @
fed18925
"""
this file contains utilities for wrapping the opendispense2 CLI utility `dispense`
It is essentially a hack to avoid having to write an actual dispense client here.
"""
import
subprocess
from
subprocess
import
CalledProcessError
,
TimeoutExpired
from
django.conf
import
settings
from
.payments
import
log
DISPENSE_BIN
=
getattr
(
settings
,
'DISPENSE_BIN'
,
None
)
if
DISPENSE_BIN
is
None
:
log
.
warning
(
"DISPENSE_BIN is not defined! Lookups for prices will fail!"
)
def
run_dispense
(
*
args
):
if
DISPENSE_BIN
is
None
:
return
None
cmd
=
[
DISPENSE_BIN
]
+
args
log
.
info
(
"run_dispense: "
+
cmd
)
try
:
# get a string containing the output of the program
res
=
subprocess
.
check_output
(
cmd
,
timeout
=
4
,
universal_newlines
=
True
)
except
CalledProcessError
as
e
:
log
.
warning
(
"dispense returned error code %d, output: '%s'"
%
(
e
.
returncode
,
e
.
output
))
return
None
except
TimeoutExpired
as
e
:
log
.
error
(
e
)
return
None
return
res
def
get_item_price
(
itemid
):
""" gets the price of the given dispense item in cents """
if
(
itemid
is
None
or
itemid
==
""
):
return
None
out
=
run_dispense
(
'iteminfo'
,
itemid
)
if
(
out
is
None
):
return
123456
s
=
out
.
split
()
# get something like ['pseudo:7', '25.00', 'membership', '(non-student', 'and', 'non-guild)']
if
(
s
[
0
]
!=
itemid
):
log
.
warning
(
"get_item_price: got result for incorrect item: %s"
+
s
)
return
None
else
:
# return the price as a number of cents
return
int
(
float
(
s
[
0
])
*
100
)
\ No newline at end of file
gms/squarepay/payments.py
0 → 100644
View file @
fed18925
"""
This file contains functions for dealing with payments (although that's fairly obvious)
"""
import
logging
from
django.conf
import
settings
from
django.core.exceptions
import
ImproperlyConfigured
from
django.utils
import
timezone
import
squareconnect
from
squareconnect.rest
import
ApiException
from
squareconnect.apis.transactions_api
import
TransactionsApi
log
=
logging
.
getLogger
(
'squarepay'
)
# load the configuration values
app_id
=
getattr
(
settings
,
'SQUARE_APP_ID'
,
None
)
loc_id
=
getattr
(
settings
,
'SQUARE_LOCATION'
,
None
)
access_key
=
getattr
(
settings
,
'SQUARE_ACCESS_TOKEN'
,
None
)
# make sure the configuration values exist
if
(
app_id
is
None
)
or
(
loc_id
is
None
)
or
(
access_key
is
None
):
raise
ImproperlyConfigured
(
"Please define SQUARE_APP_ID, SQUARE_LOCATION and SQUARE_ACCESS_TOKEN in settings.py"
)
# instantiate the global squareconnect ApiClient instance (only needs to be done once)
_sqapi_inst
=
squareconnect
.
ApiClient
()
_sqapi_inst
.
configuration
.
access_token
=
access_key
def
get_transactions_api
():
return
TransactionsApi
(
_sqapi_inst
)
def
try_capture_payment
(
card_payment
,
nonce
):
"""
attempt to charge the customer associated with the given card nonce (created by the PaymentForm in JS)
Note: this can be called multiple times with the same CardPayment instance but the customer will not
be charged multiple times (using the Square idempotency key feature)
Returns either True on success or False on failure.
"""
api_inst
=
get_transactions_api
()
request_body
=
{
'idempotency_key'
:
card_payment
.
idempotency_key
,
'card_nonce'
:
nonce
,
'amount_money'
:
{
'amount'
:
card_payment
.
amount
,
'currency'
:
'AUD'
}
}
try
:
api_response
=
api_inst
.
charge
(
loc_id
,
request_body
)
set_paid
(
card_payment
)
log
.
info
(
"TransactionApi response without error, charge $%1.2f"
%
(
float
(
card_payment
.
amount
)
/
100.0
))
return
True
except
ApiException
as
e
:
log
.
error
(
"Exception while calling TransactionApi::charge: %s"
%
e
)
return
False
def
set_paid
(
card_payment
):
card_payment
.
is_paid
=
True
card_payment
.
date_paid
=
timezone
.
now
()
card_payment
.
save
()
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment