Skip to content

Payment Method Documentation

Overview

The Payment Method model (payment.method) defines the different methods by which payments can be made or received. It supports various payment types including cash, bank transfer, cheque, credit card, and integrations with payment gateways like PayPal, Paysbuy, and SCB Gateway.


Model Information

Model Name: payment.method Display Name: Payment Method Key Fields: None (no unique constraint defined)

Features

  • ❌ Audit logging enabled (_audit_log)
  • ❌ Multi-company support (company_id)
  • ❌ Full-text content search (_content_search)
  • ✅ Multiple payment type support
  • ✅ Payment gateway integration (PayPal, Paysbuy, SCB)
  • ✅ Account linking for automatic posting
  • ✅ Sequence ordering

Key Fields Reference

Core Fields

Field Type Required Description
name Char Payment method name (searchable)
code Char Method code (searchable)
sequence Integer Display order
type Selection Payment method type
account_id Many2One Default GL account for this method
instructions Text Payment instructions for customers
service_charge Decimal Service charge amount
require_report Boolean Whether report is required

Payment Types

Type Code Description
Cash cash Cash payment
Bank Transfer bank Bank transfer/wire
Cheque cheque Cheque payment
Credit Card credit_card Credit card payment
PayPal paypal PayPal gateway
SCB Gateway scb_gateway SCB payment gateway
Paysbuy paysbuy Paysbuy gateway

PayPal Integration Fields

Field Type Description
paypal_url Selection Server URL (test/production)
paypal_user Char PayPal API username
paypal_password Char PayPal API password
paypal_signature Char PayPal API signature

Paysbuy Integration Fields

Field Type Description
paysbuy_id Char Paysbuy merchant ID
paysbuy_username Char Paysbuy username
paysbuy_securecode Char Paysbuy secure code
paysbuy_resp_back_url Char Response callback URL
paysbuy_url Selection Server URL (test/production)

SCB Gateway Integration Fields

Field Type Description
scb_mid Char SCB Merchant ID
scb_terminal Char SCB Terminal ID
scb_url Selection Server URL (test/production)

Relationship Fields

Field Type Description
comments One2Many Related comments/messages

Default Ordering

Records are ordered by sequence, then by name:

_order = "sequence,name"

API Methods

1. Create Payment Method

Method: create(vals, context)

Creates a new payment method.

Parameters:

vals = {
    "name": "Bank Transfer",           # Required: Method name
    "code": "BANK",                    # Optional: Code
    "type": "bank",                    # Optional: Payment type
    "account_id": bank_account_id,     # Optional: GL account
    "sequence": 10,                    # Optional: Display order
    "instructions": "Transfer to...", # Optional: Instructions
}

Returns: int - New record ID

Example:

# Create a bank transfer method
method_id = get_model("payment.method").create({
    "name": "Bank Transfer - USD Account",
    "code": "BANK_USD",
    "type": "bank",
    "account_id": usd_bank_account_id,
    "sequence": 10,
    "instructions": """
Please transfer to:
Bank: ABC Bank
Account: 1234567890
Swift: ABCDSGSG
    """,
})


2. Start Payment

Method: start_payment(ids, context)

Initiates a payment process (placeholder for gateway integration).

Example:

get_model("payment.method").start_payment([method_id])


3. Payment Received

Method: payment_received(context)

Callback method for payment gateway notifications.

Context Parameters:

context = {
    "transaction_no": "TXN123456",     # Transaction reference
    "amount": 100.00,                   # Payment amount
    "currency_id": currency_id,         # Currency
    "type": "paypal",                   # Payment type
}

Behavior: 1. Finds invoice by transaction number 2. Validates currency and payment method match 3. Creates and posts payment record 4. Logs payment receipt in audit log

Returns: Navigation to payment view

Example:

# Called by payment gateway callback
result = get_model("payment.method").payment_received(context={
    "transaction_no": "PAY-2024-001",
    "amount": 250.00,
    "currency_id": usd_currency_id,
    "type": "paypal",
})


4. Payment Pending

Method: payment_pending(context)

Handles pending payment notifications from gateway.

Context Parameters:

context = {
    "transaction_no": "TXN123456",
}

Returns: Navigation to invoice view


5. Payment Error

Method: payment_error(context)

Handles payment error notifications from gateway.

Context Parameters:

context = {
    "transaction_no": "TXN123456",
}

Returns: Navigation to invoice view


Model Relationship Description
account.account Many2One (account_id) Default GL account for posting
account.payment Reference Payments using this method
account.invoice Reference Invoices with this payment method
message One2Many (comments) Related comments

Common Use Cases

Use Case 1: Set Up Standard Payment Methods

# Create standard payment methods
methods = [
    {
        "name": "Cash",
        "code": "CASH",
        "type": "cash",
        "account_id": cash_account_id,
        "sequence": 1,
    },
    {
        "name": "Bank Transfer",
        "code": "BANK",
        "type": "bank",
        "account_id": bank_account_id,
        "sequence": 2,
        "instructions": "Transfer to: Bank ABC, Acc: 123456789",
    },
    {
        "name": "Cheque",
        "code": "CHQ",
        "type": "cheque",
        "account_id": bank_account_id,
        "sequence": 3,
    },
    {
        "name": "Credit Card",
        "code": "CC",
        "type": "credit_card",
        "account_id": cc_clearing_account_id,
        "sequence": 4,
        "service_charge": 3.0,  # 3% service charge
    },
]

for method in methods:
    existing = get_model("payment.method").search([["code", "=", method["code"]]])
    if not existing:
        get_model("payment.method").create(method)

Use Case 2: Configure PayPal Integration

# Set up PayPal payment method
paypal_id = get_model("payment.method").create({
    "name": "PayPal",
    "code": "PAYPAL",
    "type": "paypal",
    "account_id": paypal_account_id,
    "sequence": 5,
    "paypal_url": "production",  # or "test" for sandbox
    "paypal_user": "api_username",
    "paypal_password": "api_password",
    "paypal_signature": "api_signature",
    "instructions": "Pay securely with PayPal",
})

Use Case 3: Configure SCB Gateway

# Set up SCB payment gateway
scb_id = get_model("payment.method").create({
    "name": "SCB Payment Gateway",
    "code": "SCB",
    "type": "scb_gateway",
    "account_id": scb_account_id,
    "sequence": 6,
    "scb_mid": "MERCHANT_ID",
    "scb_terminal": "TERMINAL_ID",
    "scb_url": "production",  # or "test"
})

Use Case 4: Get Payment Methods for Customer Portal

# Get active online payment methods
online_types = ["paypal", "credit_card", "scb_gateway", "paysbuy"]

methods = get_model("payment.method").search_browse([
    ["type", "in", online_types]
], order="sequence")

available_methods = []
for method in methods:
    available_methods.append({
        "id": method.id,
        "name": method.name,
        "type": method.type,
        "instructions": method.instructions,
    })

Use Case 5: Process Gateway Payment Callback

# Example: Handle PayPal IPN callback
def handle_paypal_ipn(request):
    # Extract data from PayPal IPN
    transaction_no = request.get("custom")  # Invoice transaction number
    amount = float(request.get("mc_gross"))
    currency = request.get("mc_currency")

    # Find currency
    currency_ids = get_model("currency").search([["code", "=", currency]])
    if not currency_ids:
        raise Exception(f"Unknown currency: {currency}")

    # Process payment
    result = get_model("payment.method").payment_received(context={
        "transaction_no": transaction_no,
        "amount": amount,
        "currency_id": currency_ids[0],
        "type": "paypal",
    })

    return result

Best Practices

# Good: Account linked for automatic posting
method = get_model("payment.method").create({
    "name": "Bank Transfer",
    "type": "bank",
    "account_id": bank_account_id,  # Ensures proper GL posting
})

# Bad: No account (manual account selection needed)
method = get_model("payment.method").create({
    "name": "Bank Transfer",
    "type": "bank",
    # Missing account_id
})

2. Use Test Environment First

# Good: Start with test environment
method = get_model("payment.method").create({
    "name": "PayPal (Test)",
    "type": "paypal",
    "paypal_url": "test",  # Use sandbox first
    ...
})

# Later: Switch to production after testing
method.write({"paypal_url": "production"})

3. Provide Clear Instructions

# Good: Clear payment instructions
method = get_model("payment.method").create({
    "name": "Bank Transfer",
    "instructions": """
Bank: Singapore Banking Corporation
Account Name: ABC Company Pte Ltd
Account Number: 123-456789-001
Swift Code: SBOCSGSG

Please include your invoice number as reference.
    """,
})

4. Use Meaningful Codes

# Good: Clear, consistent codes
methods = [
    {"name": "Cash - SGD", "code": "CASH_SGD"},
    {"name": "Cash - USD", "code": "CASH_USD"},
    {"name": "Bank - DBS", "code": "BANK_DBS"},
    {"name": "Bank - OCBC", "code": "BANK_OCBC"},
]

# Bad: Generic codes
methods = [
    {"name": "Method 1", "code": "M1"},
    {"name": "Method 2", "code": "M2"},
]

Troubleshooting

"Invoice not found for transaction_no"

Cause: Invoice doesn't have matching transaction number Solution: Ensure invoice.transaction_no is set before initiating payment

"Received invoice payment in wrong currency"

Cause: Payment currency doesn't match invoice currency Solution: Verify currency settings on invoice and payment gateway

"Received invoice payment with wrong method"

Cause: Payment type doesn't match invoice's payment method type Solution: Ensure invoice.pay_method_id matches the payment gateway

"Missing account for payment method"

Cause: Payment method doesn't have account_id set Solution: Configure account_id on the payment method

"Missing invoice payment method"

Cause: Invoice doesn't have pay_method_id set Solution: Set payment method on invoice before online payment


Testing Examples

Unit Test: Create Payment Method

def test_payment_method_creation():
    # Create method
    method_id = get_model("payment.method").create({
        "name": "Test Bank Transfer",
        "code": "TEST_BANK",
        "type": "bank",
        "account_id": test_bank_account_id,
        "sequence": 99,
    })

    # Verify
    method = get_model("payment.method").browse([method_id])[0]
    assert method.name == "Test Bank Transfer"
    assert method.code == "TEST_BANK"
    assert method.type == "bank"
    assert method.account_id.id == test_bank_account_id

    # Cleanup
    get_model("payment.method").delete([method_id])

Security Considerations

Permission Model

  • Read access for users who process payments
  • Write access restricted to accounting/admin
  • Gateway credentials should be protected

Sensitive Data

  • PayPal credentials (user, password, signature)
  • Paysbuy credentials (username, securecode)
  • SCB credentials (mid, terminal)

Warning: Store gateway credentials securely and restrict access.

Audit Logging

The payment_received method uses audit logging:

audit_log("Payment received: transaction_no=%s"%transaction_no)


Configuration Requirements

For PayPal Integration

  1. Create PayPal business account
  2. Obtain API credentials (username, password, signature)
  3. Configure IPN callback URL
  4. Test with sandbox before production

For SCB Gateway

  1. Register with SCB as merchant
  2. Obtain Merchant ID and Terminal ID
  3. Configure callback URLs
  4. Test with test environment

For Paysbuy

  1. Register Paysbuy merchant account
  2. Obtain Paysbuy ID and secure code
  3. Configure response callback URL

Version History

Last Updated: December 2024 Model Version: payment_method.py Framework: Netforce


Additional Resources

  • Payment Documentation: account.payment
  • Invoice Documentation: account.invoice
  • Account Documentation: account.account

This documentation is generated for developer onboarding and reference purposes.