I’m trying to implement a fee system utilizing the PayFast on-line funds platform. I made a decision to start out by testing the ping response from the offered documentation hyperlink
from the docs, the next are the required parameters
- merchant-id,integer, 8 char | REQUIRED – I’ve created a take a look at account, which has the ID of 22307768
- model string | REQUIRED – v1
- timestamp, ISO-8601 date and time | REQUIRED – generated on the fly by a way in my code
- signature, string | REQUIRED – generated by a way in my code
From the docs, one has to make use of the next code to generate a signature
import hashlib
import urllib.parse
pfData = {
"merchant_id": "10000100",
"merchant_key": "46f0cd694581a",
"return_url": "https://www.instance.com",
"notify_url": "https://www.instance.com/notify_url",
"m_payment_id": "UniqueId",
"quantity": "200",
"item_name": "take a look at product"
}
def generateApiSignature(dataArray, passPhrase=""):
payload = ""
if passPhrase != '':
dataArray['passphrase'] = passPhrase
sortedData = sorted (dataArray)
for key in sortedData:
# Get all the information from Payfast and put together parameter string
payload += key + "=" + urllib.parse.quote_plus(dataArray[key].change("+", " ")) + "&"
# After looping via, minimize the final & or append your passphrase
payload = payload[:-1]
return hashlib.md5(payload.encode()).hexdigest()
passPhrase="jt7NOE43FZPn"
signature = generateApiSignature(pfData, passPhrase)
Since I’m implementing this inside SwiftUI, I transformed the code to Swift, imported CryptoKit and applied the next as my signature era technique
let pfData: [String: String] = [
"merchant_id": "22307768",
"merchant_key": "6p4d8gqkymobf", //from my Payfast test account
"return_url": "https://www.example.com",
"notify_url": "https://www.example.com/notify_url",
"m_payment_id": "UniqueId",
"amount": "200",
"item_name": "test product"
]
func generateApiSignature(dataArray: [String: String], passPhrase: String = "") -> String {
var payload = ""
let sortedData = Array(dataArray.keys).sorted()
for key in sortedData {
// Get all the information from Payfast and put together the parameter string
if let worth = dataArray[key]?.replacingOccurrences(of: "+", with: " ") {
payload += key + "=" + worth.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)! + "&"
}
}
// After looping via, minimize the final "&" or append your passphrase
payload = String(payload.dropLast())
if !passPhrase.isEmpty {
payload += passPhrase
}
let signature = Insecure.MD5.hash(knowledge: Knowledge(payload.utf8)).map { String(format: "%02hhx", $0) }.joined()
print(signature)
return signature
}
I then created my easy PingCheckerView as follows
struct PingCheckerView: View {
@State personal var pingResponse: String = ""
let passPhrase = "/F/canmak3y0ul0v3m3aga/n" //set inside my Payfast take a look at account
var physique: some View {
VStack {
Textual content("Ping Response:")
.font(.headline)
Textual content(pingResponse)
.font(.subheadline)
Button("Examine Ping") {
sendPingRequest()
}
.padding()
.background(Coloration.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
func sendPingRequest() {
let url = URL(string: "https://api.payfast.co.za/ping?testing=true")!
// Set header parameters
let headers = [
"merchant-id": "22307768",
"version": "v1",
"timestamp": getCurrentTimestamp(),
"signature": generateApiSignature(dataArray: pfData, passPhrase: passPhrase)
]
// Create request
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers
// Ship request
URLSession.shared.dataTask(with: request) { (knowledge, response, error) in
if let error = error {
print("Error: (error.localizedDescription)")
return
}
if let knowledge = knowledge {
if let pingResponse = String(knowledge: knowledge, encoding: .utf8) {
DispatchQueue.most important.async {
self.pingResponse = pingResponse
}
}
}
}.resume()
}
func getCurrentTimestamp() -> String {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
let timestamp = formatter.string(from: Date())
print(timestamp)
return timestamp
}
}
Nevertheless once I run this, I preserve getting an error 401, “service provider not discovered” response
I’m not sure why that is the case, my credentials are dwell and proper from inside my Payfast account
In an effort to find out whether or not this was an Xcode subject, I went on this hyperlink given at on the Payfast sandbox. I proceeded import and run the API name inside one in every of my Postman workspaces
I handed in my merchant-id, timestamp, and mD5 string signature as proven within the screengrab under
Once I make the decision, I get the next error message contained in the Postman console, as proven under
I’m on my final legs right here, I’ve used Payfast gateway a while up to now with on web site, by merely directing the consumer to a payfast server URL with all of the required transaction parameters within the question string. With this technique, the server then sends the consumer to a fee display, which prompts the consumer to enter their card particulars. When the fee goes via, the consumer is shipped to a return URL which I pre-selected on my web site to obtain fee notifications on my finish.
On condition that the iOS app I’m constructing just isn’t web-based, I’m trying to do the identical. I’m conscious that I can use a Webview, nevertheless the difficulty is that I’m not fairly sure how I’ll obtain transaction notifications as on condition that we would not have a return URL to ship the consumer to
Taking a look at Payfast documentation I can not make heads or tails of how to do that.
Any assist could be appreciated. I’m required to make use of Payfast as my fee gateway, since among the main suppliers similar to Stripe stay unavailable in South Africa presently.