Skip to content

Python Examples

Complete examples for integrating EasySlip API with Python.

Installation

bash
pip install requests

API Client Class

python
# easyslip.py
import os
import requests
from typing import Optional, Dict, Any
from dataclasses import dataclass

@dataclass
class SlipData:
    payload: str
    trans_ref: str
    date: str
    amount: float
    sender_name: Optional[str]
    sender_bank: Optional[str]
    receiver_name: Optional[str]
    receiver_bank: Optional[str]

class EasySlipClient:
    def __init__(self, api_key: str, version: str = 'v2'):
        self.api_key = api_key
        self.base_url = f'https://developer.easyslip.com/api/{version}'
        self.session = requests.Session()
        self.session.headers.update({
            'Authorization': f'Bearer {api_key}'
        })

    def _request(
        self,
        endpoint: str,
        method: str = 'GET',
        json_data: Optional[Dict] = None,
        files: Optional[Dict] = None,
        data: Optional[Dict] = None
    ) -> Dict[str, Any]:
        url = f'{self.base_url}{endpoint}'

        response = self.session.request(
            method=method,
            url=url,
            json=json_data,
            files=files,
            data=data,
            timeout=30
        )

        return response.json()

    def verify_by_payload(
        self,
        payload: str,
        remark: Optional[str] = None,
        match_account: bool = False,
        match_amount: Optional[float] = None,
        check_duplicate: bool = True
    ) -> Dict[str, Any]:
        """Verify slip by QR payload."""
        data = {
            'payload': payload,
            'checkDuplicate': check_duplicate
        }

        if remark:
            data['remark'] = remark
        if match_account:
            data['matchAccount'] = match_account
        if match_amount is not None:
            data['matchAmount'] = match_amount

        return self._request('/verify/bank', 'POST', json_data=data)

    def verify_by_url(
        self,
        url: str,
        remark: Optional[str] = None,
        match_account: bool = False,
        match_amount: Optional[float] = None,
        check_duplicate: bool = True
    ) -> Dict[str, Any]:
        """Verify slip by image URL."""
        data = {
            'url': url,
            'checkDuplicate': check_duplicate
        }

        if remark:
            data['remark'] = remark
        if match_account:
            data['matchAccount'] = match_account
        if match_amount is not None:
            data['matchAmount'] = match_amount

        return self._request('/verify/bank', 'POST', json_data=data)

    def verify_by_base64(
        self,
        base64_data: str,
        remark: Optional[str] = None,
        match_account: bool = False,
        match_amount: Optional[float] = None,
        check_duplicate: bool = True
    ) -> Dict[str, Any]:
        """Verify slip by Base64 encoded image."""
        data = {
            'base64': base64_data,
            'checkDuplicate': check_duplicate
        }

        if remark:
            data['remark'] = remark
        if match_account:
            data['matchAccount'] = match_account
        if match_amount is not None:
            data['matchAmount'] = match_amount

        return self._request('/verify/bank', 'POST', json_data=data)

    def verify_by_image(
        self,
        file_path: str,
        remark: Optional[str] = None,
        match_account: bool = False,
        match_amount: Optional[float] = None,
        check_duplicate: bool = True
    ) -> Dict[str, Any]:
        """Verify slip by image file."""
        with open(file_path, 'rb') as f:
            files = {'image': f}
            data = {'checkDuplicate': 'true' if check_duplicate else 'false'}

            if remark:
                data['remark'] = remark
            if match_account:
                data['matchAccount'] = 'true'
            if match_amount is not None:
                data['matchAmount'] = str(match_amount)

            return self._request('/verify/bank', 'POST', files=files, data=data)

    def get_info(self) -> Dict[str, Any]:
        """Get application information."""
        return self._request('/info')

    @staticmethod
    def parse_slip_data(response: Dict[str, Any]) -> Optional[SlipData]:
        """Parse API response into SlipData object."""
        if not response.get('success'):
            return None

        raw = response['data']['rawSlip']

        return SlipData(
            payload=raw.get('payload', ''),
            trans_ref=raw.get('transRef', ''),
            date=raw.get('date', ''),
            amount=raw['amount']['amount'],
            sender_name=raw.get('sender', {}).get('account', {}).get('name', {}).get('th'),
            sender_bank=raw.get('sender', {}).get('bank', {}).get('short'),
            receiver_name=raw.get('receiver', {}).get('account', {}).get('name', {}).get('th'),
            receiver_bank=raw.get('receiver', {}).get('bank', {}).get('short'),
        )

Usage Examples

Basic Verification

python
from easyslip import EasySlipClient
import os

client = EasySlipClient(os.environ['EASYSLIP_API_KEY'])

# Verify by payload
result = client.verify_by_payload('YOUR_QR_PAYLOAD')

if result['success']:
    slip = result['data']['rawSlip']
    print(f"Transaction: {slip['transRef']}")
    print(f"Amount: {slip['amount']['amount']} THB")
    print(f"Sender: {slip['sender']['account']['name']['th']}")
    print(f"Receiver: {slip['receiver']['account']['name']['th']}")

    if result['data']['isDuplicate']:
        print("Warning: This slip was verified before!")
else:
    print(f"Error: {result['error']['message']}")

Flask Integration

python
# app.py
from flask import Flask, request, jsonify
from easyslip import EasySlipClient
import os

app = Flask(__name__)
client = EasySlipClient(os.environ['EASYSLIP_API_KEY'])

@app.route('/verify', methods=['POST'])
def verify_slip():
    # Handle file upload
    if 'slip' in request.files:
        file = request.files['slip']
        temp_path = f'/tmp/{file.filename}'
        file.save(temp_path)

        try:
            result = client.verify_by_image(
                temp_path,
                remark=request.form.get('order_id'),
                match_amount=float(request.form.get('amount', 0)) or None,
                check_duplicate=True
            )
        finally:
            os.remove(temp_path)

    # Handle payload
    elif request.json and 'payload' in request.json:
        result = client.verify_by_payload(
            request.json['payload'],
            remark=request.json.get('order_id'),
            match_amount=request.json.get('amount'),
            check_duplicate=True
        )

    # Handle URL
    elif request.json and 'url' in request.json:
        result = client.verify_by_url(
            request.json['url'],
            remark=request.json.get('order_id'),
            match_amount=request.json.get('amount'),
            check_duplicate=True
        )

    else:
        return jsonify({'error': 'No slip data provided'}), 400

    if not result['success']:
        return jsonify({'error': result['error']['message']}), 400

    data = result['data']

    if data['isDuplicate']:
        return jsonify({'error': 'Slip already used'}), 400

    if 'isAmountMatched' in data and not data['isAmountMatched']:
        return jsonify({
            'error': 'Amount mismatch',
            'expected': data.get('amountInOrder'),
            'actual': data['rawSlip']['amount']['amount']
        }), 400

    return jsonify({
        'success': True,
        'transRef': data['rawSlip']['transRef'],
        'amount': data['rawSlip']['amount']['amount'],
        'sender': data['rawSlip']['sender']['account']['name'].get('th'),
        'receiver': data['rawSlip']['receiver']['account']['name'].get('th')
    })

if __name__ == '__main__':
    app.run(debug=True)

FastAPI Integration

python
# main.py
from fastapi import FastAPI, File, UploadFile, HTTPException
from pydantic import BaseModel
from typing import Optional
import os
import tempfile
from easyslip import EasySlipClient

app = FastAPI()
client = EasySlipClient(os.environ['EASYSLIP_API_KEY'])

class PayloadRequest(BaseModel):
    payload: str
    order_id: Optional[str] = None
    amount: Optional[float] = None

class UrlRequest(BaseModel):
    url: str
    order_id: Optional[str] = None
    amount: Optional[float] = None

@app.post('/verify/payload')
async def verify_by_payload(req: PayloadRequest):
    result = client.verify_by_payload(
        req.payload,
        remark=req.order_id,
        match_amount=req.amount,
        check_duplicate=True
    )

    return handle_result(result)

@app.post('/verify/url')
async def verify_by_url(req: UrlRequest):
    result = client.verify_by_url(
        req.url,
        remark=req.order_id,
        match_amount=req.amount,
        check_duplicate=True
    )

    return handle_result(result)

@app.post('/verify/image')
async def verify_by_image(
    slip: UploadFile = File(...),
    order_id: Optional[str] = None,
    amount: Optional[float] = None
):
    with tempfile.NamedTemporaryFile(delete=False, suffix='.jpg') as tmp:
        content = await slip.read()
        tmp.write(content)
        tmp_path = tmp.name

    try:
        result = client.verify_by_image(
            tmp_path,
            remark=order_id,
            match_amount=amount,
            check_duplicate=True
        )
    finally:
        os.unlink(tmp_path)

    return handle_result(result)

def handle_result(result: dict):
    if not result['success']:
        raise HTTPException(status_code=400, detail=result['error']['message'])

    data = result['data']

    if data['isDuplicate']:
        raise HTTPException(status_code=400, detail='Slip already used')

    if 'isAmountMatched' in data and not data['isAmountMatched']:
        raise HTTPException(
            status_code=400,
            detail=f"Amount mismatch: expected {data.get('amountInOrder')}, got {data['rawSlip']['amount']['amount']}"
        )

    return {
        'success': True,
        'transRef': data['rawSlip']['transRef'],
        'amount': data['rawSlip']['amount']['amount']
    }

Django Integration

python
# views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django.conf import settings
import json
import tempfile
import os
from easyslip import EasySlipClient

client = EasySlipClient(settings.EASYSLIP_API_KEY)

@csrf_exempt
@require_POST
def verify_slip(request):
    # Handle file upload
    if request.FILES.get('slip'):
        slip_file = request.FILES['slip']

        with tempfile.NamedTemporaryFile(delete=False, suffix='.jpg') as tmp:
            for chunk in slip_file.chunks():
                tmp.write(chunk)
            tmp_path = tmp.name

        try:
            result = client.verify_by_image(
                tmp_path,
                remark=request.POST.get('order_id'),
                match_amount=float(request.POST.get('amount')) if request.POST.get('amount') else None,
                check_duplicate=True
            )
        finally:
            os.unlink(tmp_path)

    # Handle JSON payload
    else:
        try:
            data = json.loads(request.body)
        except json.JSONDecodeError:
            return JsonResponse({'error': 'Invalid JSON'}, status=400)

        if 'payload' in data:
            result = client.verify_by_payload(
                data['payload'],
                remark=data.get('order_id'),
                match_amount=data.get('amount'),
                check_duplicate=True
            )
        elif 'url' in data:
            result = client.verify_by_url(
                data['url'],
                remark=data.get('order_id'),
                match_amount=data.get('amount'),
                check_duplicate=True
            )
        else:
            return JsonResponse({'error': 'No slip data provided'}, status=400)

    if not result['success']:
        return JsonResponse({'error': result['error']['message']}, status=400)

    slip_data = result['data']

    if slip_data['isDuplicate']:
        return JsonResponse({'error': 'Slip already used'}, status=400)

    return JsonResponse({
        'success': True,
        'transRef': slip_data['rawSlip']['transRef'],
        'amount': slip_data['rawSlip']['amount']['amount']
    })

Async Support

python
# async_client.py
import aiohttp
import os
from typing import Optional, Dict, Any

class AsyncEasySlipClient:
    def __init__(self, api_key: str, version: str = 'v2'):
        self.api_key = api_key
        self.base_url = f'https://developer.easyslip.com/api/{version}'

    async def verify_by_payload(
        self,
        payload: str,
        check_duplicate: bool = True,
        **kwargs
    ) -> Dict[str, Any]:
        data = {'payload': payload, 'checkDuplicate': check_duplicate, **kwargs}

        async with aiohttp.ClientSession() as session:
            async with session.post(
                f'{self.base_url}/verify/bank',
                headers={'Authorization': f'Bearer {self.api_key}'},
                json=data
            ) as response:
                return await response.json()

# Usage with asyncio
import asyncio

async def main():
    client = AsyncEasySlipClient(os.environ['EASYSLIP_API_KEY'])
    result = await client.verify_by_payload('YOUR_PAYLOAD')
    print(result)

asyncio.run(main())

Bank Slip Verification API for Thai Banking