Skip to content

Commit c9fb719

Browse files
Merge pull request #122 from Flutterwave/dev
Pull changes from dev
2 parents a0d0b92 + 46e9d46 commit c9fb719

File tree

1,290 files changed

+383582
-98
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,290 files changed

+383582
-98
lines changed

.DS_Store

0 Bytes
Binary file not shown.

.github/workflows/change-review.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
- name: run unit tests and coverage scan
3131
env:
3232
PUBLIC_KEY: ${{ secrets.PUBLIC_KEY }}
33-
RAVE_SECRET_KEY: ${{ secrets.SECRET_KEY }}
33+
SECRET_KEY: ${{ secrets.SECRET_KEY }}
3434
run: |
3535
pip install coverage
3636
coverage run test.py

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ staging
2525
zero
2626
.coverage
2727
example.py
28+
randomTester.py

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2693,15 +2693,16 @@ This is used to create virtual account for transfers.
26932693

26942694
### ```.create(accountDetails)```
26952695

2696-
This allows a customer to create a virtual card. It requires a dict ```vcardDetails``` containing ```email```, ```seckey```, ```is_permanant```, ```frequency```, ```duration``` and ```narration```.
2696+
This allows a customer to create a virtual account. It requires a dict ```vaccountDetails``` containing ```email```, ```seckey```, ```is_permanant```, ```frequency```, ```bvn```, ```duration``` and ```narration```.
26972697

26982698
A sample Create call is:
26992699

27002700
```py
27012701
res = rave.VirtualAccount.create({
27022702
"email": "[email protected]",
2703-
"seckey": "FLWSECK-****************************-X",
2704-
"is_permanent": true
2703+
"bvn": "12345678901",
2704+
"is_permanent": true,
2705+
"narration": "Cornelius A-O"
27052706
})
27062707
print(res)
27072708
```

rave_python/__pycache__/.DS_Store

-6 KB
Binary file not shown.

rave_python/rave.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
from rave_python.rave_account import Account
2+
from rave_python.rave_applepay import ApplePay
23
from rave_python.rave_bills import Bills
34
from rave_python.rave_card import Card
45
from rave_python.rave_ebills import Ebills
6+
from rave_python.rave_fawrypay import FawryPay
57
from rave_python.rave_francophone import Francophone
68
from rave_python.rave_ghmobile import GhMobile
9+
from rave_python.rave_googlepay import GooglePay
710
from rave_python.rave_mpesa import Mpesa
811
from rave_python.rave_paymentplan import PaymentPlan
912
from rave_python.rave_preauth import Preauth
@@ -30,12 +33,15 @@ class Rave:
3033
def __init__(self, publicKey, secretKey, production=False, usingEnv=True):
3134
""" This is main organizing object. It contains the following:\n
3235
rave.Account -- For bank account transactions\n
36+
rave.ApplePay -- For Apple Pay wallet transactions\n
3337
rave.BankTransfer -- For pay with bank transfer transaction\n
3438
rave.Bills -- For Bills payments\n
3539
rave.Card -- For card transactions\n
3640
rave.Enaira -- For enaira wallet payments\n
41+
rave.FawryPay -- For Egyptian collections via Fawry Pay\n
3742
rave.Francophone -- For West African Francophone mobile money transactions\n
3843
rave.GhMobile -- For Ghana mobile money transactions\n
44+
rave.GooglePay -- For Google Pay wallet transactions\n
3945
rave.Mpesa -- For mpesa transactions\n
4046
rave.PaymentPlan -- For payment plan creation and operation\n
4147
rave.Preauth -- For preauthorized transactions\n
@@ -54,13 +60,16 @@ def __init__(self, publicKey, secretKey, production=False, usingEnv=True):
5460

5561
classes = (
5662
Account,
63+
ApplePay,
5764
BankTransfer,
5865
Bills,
5966
Card,
6067
Ebills,
6168
Enaira,
69+
FawryPay,
6270
Francophone,
6371
GhMobile,
72+
GooglePay,
6473
Mpesa,
6574
PaymentPlan,
6675
Preauth,

rave_python/rave_applepay.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
from rave_python.rave_payment import Payment
2+
from rave_python.rave_exceptions import AccountChargeError
3+
from rave_python.rave_misc import generateTransactionReference
4+
5+
class ApplePay(Payment):
6+
""" This is the rave object for Apple Pay transactions. It contains the following public functions:\n
7+
.charge -- This is for charging a Customer with Apple Pay\n
8+
.verify -- This checks the status of your transaction\n
9+
.refund -- This initiates the refund for the transaction\n
10+
"""
11+
12+
def _handleChargeResponse(self, response, txRef, request=None):
13+
""" This handles account charge responses """
14+
# This checks if we can parse the json successfully
15+
res = self._preliminaryResponseChecks(
16+
response, AccountChargeError, txRef=txRef)
17+
18+
response_json = res['json']
19+
# change - added data before flwRef
20+
response_data = response_json['data']
21+
flw_ref = response_data['flwRef']
22+
auth_url = response_data['authurl']
23+
24+
# If all preliminary checks are passed
25+
data = {
26+
'error': False,
27+
'validationRequired': True,
28+
'authurl': auth_url,
29+
'txRef': txRef,
30+
'flwRef': flw_ref,
31+
'message': "Kindly redirect your user to the authurl. This url is only supported by Safari browsers and Apple Pay enabled devices."
32+
}
33+
34+
return data
35+
36+
def charge(self, requestDetails, hasFailed=False):
37+
""" This is the charge method for Apple Pay payments.\n
38+
Parameters include:\n
39+
requestDetails (dict) -- The request parameters for charging your customers with this payment method\n
40+
hasFailed (boolean) -- This is a flag to determine if the attempt had previously failed due to a timeout\n
41+
"""
42+
43+
# setting the endpoint
44+
endpoint = self._baseUrl + self._endpointMap['account']['charge']
45+
feature_name = "ApplePay"
46+
47+
# It is faster to just update rather than check if it is already
48+
# present
49+
50+
requestDetails.update({'payment_type': 'applepay'})
51+
52+
# Generate transaction reference if txRef doesn't exist
53+
requestDetails.setdefault('txRef', generateTransactionReference())
54+
55+
# Checking for required account components
56+
requiredParameters = [
57+
'amount',
58+
'email',
59+
'firstname',
60+
'lastname',
61+
'currency'
62+
]
63+
64+
return super(ApplePay, self).charge(feature_name, requestDetails, requiredParameters, endpoint)
65+
66+
"""
67+
TO DOs
68+
1. Get mocking credentials to test the verify and refund methods for Apple Pay Transactions.
69+
2. Add unittests for verify and refund methods.
70+
"""
71+
72+
# def verify(self, txRef):
73+
# endpoint = self._baseUrl + self._endpointMap['account']['verify']
74+
# feature_name = "Verify eNaira"
75+
# return super(ApplePay, self).verify(feature_name, txRef, endpoint)
76+
77+
# def refund(self, flwRef, amount):
78+
# feature_name = "Refund eNaira"
79+
# endpoint = self._baseUrl + self._endpointMap["account"]["refund"]
80+
# return super(ApplePay, self).refund(feature_name, flwRef, amount)

rave_python/rave_base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,11 @@ def __init__(
115115
# If we are using environment variables to store secretKey
116116
if (usingEnv):
117117
self.__publicKey = publicKey
118-
self.__secretKey = os.getenv("RAVE_SECRET_KEY", None)
118+
self.__secretKey = os.getenv("SECRET_KEY", None)
119119

120120
if (not self.__publicKey) or (not self.__secretKey):
121121
raise ValueError(
122-
"Please set your RAVE_SECRET_KEY environment variable. Otherwise, pass publicKey and secretKey as arguments and set usingEnv to false")
122+
"Please set your SECRET_KEY environment variable. Otherwise, pass publicKey and secretKey as arguments and set usingEnv to false")
123123

124124
# If we are not using environment variables
125125
else:

rave_python/rave_enaira.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class Enaira(Payment):
66
""" This is the rave object for eNaira wallet transactions. It contains the following public functions:\n
77
.charge -- This is for charging the eNaira wallet\n
88
.verify -- This checks the status of your transaction\n
9-
.refunds -- This initiates the refund for the transaction\n
9+
.refund -- This initiates the refund for the transaction\n
1010
"""
1111

1212
def _handleChargeResponse(self, response, txRef, request=None):

rave_python/rave_exceptions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ class IncompletePaymentDetailsError(RaveError):
143143
""" Raised when card details are incomplete """
144144

145145
def __init__(self, value, requiredParameters):
146-
msg = "\n\"" + value + "\" was not defined in your dictionary. Please ensure you have supplied the following in the payload: \n " + \
147-
' \n '.join(requiredParameters)
146+
msg = "\"" + value + "\" was not defined in your dictionary. Please ensure you have supplied the following in the payload: " + \
147+
', '.join(requiredParameters)
148148
super(IncompletePaymentDetailsError, self).__init__(msg)
149149

150150

rave_python/rave_fawrypay.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
from rave_python.rave_payment import Payment
2+
from rave_python.rave_exceptions import AccountChargeError
3+
from rave_python.rave_misc import generateTransactionReference
4+
5+
class FawryPay(Payment):
6+
""" This is the rave object for Fawry Pay transactions. It contains the following public functions:\n
7+
.charge -- Charge your Customers with Fawry Pay. This is only supported in Egypt.\n
8+
.verify -- This checks the status of your transaction\n
9+
.refund -- This initiates the refund for the transaction\n
10+
"""
11+
12+
def _handleChargeResponse(self, response, txRef, request=None):
13+
""" This handles account charge responses """
14+
# This checks if we can parse the json successfully
15+
res = self._preliminaryResponseChecks(
16+
response, AccountChargeError, txRef=txRef)
17+
18+
response_json = res['json']
19+
# change - added data before flwRef
20+
response_data = response_json['data']
21+
flw_ref = response_data['flwRef']
22+
23+
# If all preliminary checks are passed
24+
data = {
25+
'error': False,
26+
'validationRequired': True,
27+
'txRef': txRef,
28+
'flwRef': flw_ref,
29+
'message': "Please make payment with the flwRef returned in the response which should be the same as the reference sent via SMS"
30+
}
31+
32+
return data
33+
34+
def charge(self, requestDetails, hasFailed=False):
35+
""" This is the charge method for Fawry Pay payments.\n
36+
Parameters include:\n
37+
requestDetails (dict) -- The request parameters for charging your customers with this payment method\n
38+
hasFailed (boolean) -- This is a flag to determine if the attempt had previously failed due to a timeout\n
39+
"""
40+
41+
# setting the endpoint
42+
endpoint = self._baseUrl + self._endpointMap['account']['charge']
43+
feature_name = "FawryPay"
44+
45+
# It is faster to just update rather than check if it is already
46+
# present
47+
48+
requestDetails.update(
49+
{
50+
'payment_type': 'fawry_pay',
51+
'currency': 'EGP'
52+
}
53+
)
54+
55+
# Generate transaction reference if txRef doesn't exist
56+
requestDetails.setdefault('txRef', generateTransactionReference())
57+
58+
# Checking for required account components
59+
requiredParameters = [
60+
'amount',
61+
'email',
62+
'firstname',
63+
'lastname',
64+
'phonenumber'
65+
]
66+
67+
return super(FawryPay, self).charge(feature_name, requestDetails, requiredParameters, endpoint)
68+
69+
"""
70+
TO DOs
71+
1. Get mocking credentials to test the verify and refund methods for FawryPay Transactions.
72+
2. Add unittests for verify and refund methods.
73+
"""
74+
75+
# def verify(self, txRef):
76+
# endpoint = self._baseUrl + self._endpointMap['account']['verify']
77+
# feature_name = "Verify eNaira"
78+
# return super(FawryPay, self).verify(feature_name, txRef, endpoint)
79+
80+
# def refund(self, flwRef, amount):
81+
# feature_name = "Refund eNaira"
82+
# endpoint = self._baseUrl + self._endpointMap["account"]["refund"]
83+
# return super(FawryPay, self).refund(feature_name, flwRef, amount)

rave_python/rave_googlepay.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
from rave_python.rave_payment import Payment
2+
from rave_python.rave_exceptions import AccountChargeError
3+
from rave_python.rave_misc import generateTransactionReference
4+
5+
class GooglePay(Payment):
6+
""" This is the rave object for Google Pay transactions. It contains the following public functions:\n
7+
.charge -- This is for charging a Customer with Google Pay\n
8+
.verify -- This checks the status of your transaction\n
9+
.refund -- This initiates the refund for the transaction\n
10+
"""
11+
12+
def _handleChargeResponse(self, response, txRef, request=None):
13+
""" This handles account charge responses """
14+
# This checks if we can parse the json successfully
15+
res = self._preliminaryResponseChecks(
16+
response, AccountChargeError, txRef=txRef)
17+
18+
response_json = res['json']
19+
# change - added data before flwRef
20+
response_data = response_json['data']
21+
flw_ref = response_data['flwRef']
22+
auth_url = response_data['authurl']
23+
24+
# If all preliminary checks are passed
25+
data = {
26+
'error': False,
27+
'validationRequired': True,
28+
'authurl': auth_url,
29+
'txRef': txRef,
30+
'flwRef': flw_ref,
31+
'message': "Kindly redirect your user to the authurl to complete the payment using their Google Pay Wallets."
32+
}
33+
34+
return data
35+
36+
def charge(self, requestDetails, hasFailed=False):
37+
""" This is the charge method for Google Pay payments.\n
38+
Parameters include:\n
39+
requestDetails (dict) -- The request parameters for charging your customers with this payment method\n
40+
hasFailed (boolean) -- This is a flag to determine if the attempt had previously failed due to a timeout\n
41+
"""
42+
43+
# setting the endpoint
44+
endpoint = self._baseUrl + self._endpointMap['account']['charge']
45+
feature_name = "GooglePay"
46+
47+
# It is faster to just update rather than check if it is already
48+
# present
49+
50+
requestDetails.update({'payment_type': 'googlepay'})
51+
52+
# Generate transaction reference if txRef doesn't exist
53+
requestDetails.setdefault('txRef', generateTransactionReference())
54+
55+
# Checking for required account components
56+
requiredParameters = [
57+
'amount',
58+
'email',
59+
'firstname',
60+
'lastname',
61+
'currency'
62+
]
63+
64+
return super(GooglePay, self).charge(feature_name, requestDetails, requiredParameters, endpoint)
65+
66+
"""
67+
TO DOs
68+
1. Get mocking credentials to test the verify and refund methods for GooglePay Transactions.
69+
2. Add unittests for verify and refund methods.
70+
"""
71+
72+
# def verify(self, txRef):
73+
# endpoint = self._baseUrl + self._endpointMap['account']['verify']
74+
# feature_name = "Verify eNaira"
75+
# return super(GooglePay, self).verify(feature_name, txRef, endpoint)
76+
77+
# def refund(self, flwRef, amount):
78+
# feature_name = "Refund eNaira"
79+
# endpoint = self._baseUrl + self._endpointMap["account"]["refund"]
80+
# return super(GooglePay, self).refund(feature_name, flwRef, amount)

0 commit comments

Comments
 (0)