Skip to content

Checkout

Tip

  • All requests are Post requests, and the data format is json
Brief Description
  • None
Payment Methods
wayCode Description
MPESA M-Pesa mobile wallet
AIRTEL Airtel Money mobile wallet
TKASH T-Kash mobile wallet
Request URL
  • /v1/vexora/checkout
Request Method
  • Method: POST
  • Content-Type: application/json
header Required Type Description
merchantNo Yes String None
Body
Parameter Required Type Description
sign Yes String Except for the sign field, all remaining fields should be sorted alphabetically by their first letter, combined into key1=value1key2=value2, and encrypted using the app secret as salt via MD5. The final sign value should be in lowercase.
timestamp Yes long Timestamp (1715941383720)
amount Yes String Payment amount (KSH 50 or above is recommended; integers only)
remark No String Remark, this field will be returned as-is
tradeNo Yes String Transaction number (uniqueness recommended: year, month, day, hour, minute, second + random number)
notifyUrl Yes String Asynchronous callback URL
wayCode No String Payment channel. If omitted, MPESA is used by default. See the payment methods list above for supported values.
Request Parameter Example
{
  "sign": "000000",
  "timestamp": "1715941383720",
  "amount": "50",
  "remark": "000000",
  "tradeNo": "00000001",
  "notifyUrl": "https://google.com",
  "wayCode": "MPESA"
}
Response Result
Parameter Required Type Description
msg Yes String Request result (when returning success, it only indicates that the request was successful and cannot be used for merchant-side logic judgment)
code Yes String Request response code (when returning 0000, it only indicates that the request was successful and cannot be used for merchant-side logic judgment). For specific error codes, please refer to the business error code enumeration.
timestamp Yes Integer Transaction time in milliseconds
success Yes Boolean Transaction result
data Yes Object Return object
data.serialNumber Yes String Result ID returned by vexora, unique
data.status Yes String Request result, merchants can use this for logic processing. When the result is 0000, it indicates a successful transaction; 0015 indicates processing; all other codes indicate errors and can be treated as failures.
data.payUrl Yes String Aggregate payment link
data.remark Yes String Request return content (returned as-is)
Successful Response Example
{
    "msg": "success",
    "code": "0000",
    "timestamp": 1719829837779,
    "success": true,
    "data": {
        "serialNumber": "5286e98841194687a95d25b5f3be346d",
        "status": "0015",
        "payUrl": "https://xxxxx.com/5286e98841194687a95d25b5f3be346d",
        "remark": ""
    }
}

Exit the WebView flow (goBackFlag=1)

When the user completes the payment, the Vexora checkout displays a completion page with a [GO BACK] button. When the user clicks [GO BACK], the message will be pushed to the business party, who will need to handle it on their own.

Parameter Required Type Description
tradeNo Yes String Transaction Number
result Yes String Transaction results,Merchants can process subsequent workflows based on the returned status in the transaction result. For details, please refer to the status code reference table.
{
    "tradeNo": "accc0000000001",
    "result": "0000",
}

Processing of several environments (for reference only)

  • Android
package com.example.myapplication;  

import android.os.Bundle;  
import android.webkit.JavascriptInterface;  
import android.webkit.WebView;  
import android.webkit.WebViewClient;  

import androidx.appcompat.app.AppCompatActivity;  

public class MainActivity extends AppCompatActivity {  


    private WebView webView;  

    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity\_main);  

        webView = findViewById(R.id.webView);  
        webView.getSettings().setJavaScriptEnabled(true);  

        // setup WebViewClient  
        webView.setWebViewClient(new WebViewClient() {  
            @Override  
            public void onPageFinished(WebView view, String url) {  
                // inject JavaScript code  
                webView.evaluateJavascript(  
                        "window.postMessage = function(message) { postMessageHandler.postMessage(message); };",  
                        null  
                );  
            }  
        });  

        // add JavaScript interface  
        webView.addJavascriptInterface(new WebAppInterface(), "postMessageHandler");  

        // load URL  
        webView.loadUrl("http://192.168.50.244:3000/pay/abcd");  
    }  

    // JavaScript interface  
    public class WebAppInterface {  
        @JavascriptInterface  
        public void postMessage(String message) {  
            // receive JavaScript message  
            System.out.println("Received message from JavaScript: " \+ message);  
        }  
    }  
}
  • IOS
import SwiftUI  
import WebKit  
struct WebView: UIViewRepresentable {  
    let url: URL  
    let messageHandlerName: String  

    func makeUIView(context: Context) -> WKWebView {  
        // Configure the WebView
        let webView = WKWebView()  
        webView.navigationDelegate = context.coordinator  

        let userContentController = WKUserContentController()  
        userContentController.add(context.coordinator, name: messageHandlerName)  

        let configuration = WKWebViewConfiguration()  
        configuration.userContentController = userContentController  

        // Create and return the WKWebView
        let webViewWithConfig = WKWebView(frame: .zero, configuration: configuration)  
        webViewWithConfig.navigationDelegate = context.coordinator  
        return webViewWithConfig  
    }  

    func updateUIView(\_ webView: WKWebView, context: Context) {  
        let request = URLRequest(url: url)  
        webView.load(request)  
    }  

    func makeCoordinator() -> Coordinator {  
        Coordinator(self)  
    }  

    class Coordinator: NSObject, WKNavigationDelegate, WKScriptMessageHandler {  
        var parent: WebView  

        init(\_ parent: WebView) {  
            self.parent = parent  
        }  

        func webView(\_ webView: WKWebView, didFinish navigation: WKNavigation!) {  
            // Inject JavaScript code  
            let js = """  
            window.postMessage = function(message) {                window.webkit.messageHandlers.\\(parent.messageHandlerName).postMessage(message);  
            };            """  
            webView.evaluateJavaScript(js, completionHandler: nil)  
        }  

        // Receive messages from JavaScript  
        func userContentController(\_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {  
            if message.name == parent.messageHandlerName {  
                if let messageBody = message.body as? String {  
                    print("Received message from JavaScript: \\(messageBody)")  
                }  
            }  
        }  
    }  
}  
struct ContentView: View {  
    var body: some View {  
        WebView(url: URL(String: "http://192.168.50.244:3000/test")!, messageHandlerName: "postMessageHandler")  
            .edgesIgnoringSafeArea(.all)  
    }  
}
  • IFRAME
<!DOCTYPE html\>  
<html>  
<head>  
    <title>Parent Page</title>  
</head>  
<body>  
    <h1>Parent Page</h1>  
    <iframe id\="childFrame" src\="http://example.com" style\="width: 100%; height: 300px;"\></iframe>  
    <button onclick\="sendMessageToChild()"\>Send Message to Child</button>  

    <script>        function sendMessageToChild() {  
            const childFrame = document.getElementById('childFrame').contentWindow;  
            childFrame.postMessage('Hello from Parent', '\*'); // '\*'        }  


        window.addEventListener('message', function(event) {  
            if (event.origin !== 'http://example.com') {   
                return;  
            }  
            console.log('Message from child:', event.data);  
        });  
    </script>  
</body>  
</html>