Package Exports
- payload-sep-gateway-plugin
- payload-sep-gateway-plugin/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (payload-sep-gateway-plugin) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
payload-sep-gateway-plugin
A comprehensive Payload CMS plugin for SEP (Saman Electronic Payment) gateway integration with correct REST API implementation. This plugin provides complete payment processing capabilities including collections, API handlers, and utilities for Iranian e-commerce applications.
⚠️ Important: Version 2.0 Breaking Changes
Version 2.0 includes major updates to align with the correct SEP Gateway documentation:
- ✅ Fixed Token Creation: Now uses correct REST API endpoint (
https://sep.shaparak.ir/onlinepg/onlinepg) - ✅ Fixed Payment URL: Updated to correct OnlinePG endpoint (
https://sep.shaparak.ir/OnlinePG/OnlinePG) - ✅ Fixed Verification: Uses proper verification endpoint with correct parameters
- ✅ Updated Parameters: Changed from
MIDtoTerminalIdthroughout - ✅ Added Reverse Transactions: Complete refund/reversal functionality
- ✅ Enhanced Security: Proper amount validation and double-spend prevention
Features
- 🏪 E-Commerce Collections: Orders, Products, and Payment Transactions
- 💳 Correct SEP Gateway Integration: Token-based payments with proper REST API
- 🔐 Transaction Verification: Real-time payment verification with SEP
- 🔄 Reverse Transactions: Complete refund/reversal functionality
- 📊 Admin Dashboard: Full Payload CMS admin interface
- 🧪 Test Mode: Built-in testing capabilities
- 🌐 TypeScript Support: Full type safety and IntelliSense
- 🔧 Highly Configurable: Customizable collections and fields
- 🛡️ Security Features: Amount validation, double-spend prevention, IP whitelist support
Installation
npm install payload-sep-gateway-plugin@^2.0.0
# or
yarn add payload-sep-gateway-plugin@^2.0.0Quick Start
1. Basic Setup
// payload.config.ts
import { buildConfig } from 'payload/config'
import { sepGatewayPlugin } from 'payload-sep-gateway-plugin'
export default buildConfig({
// ... your existing config
plugins: [
sepGatewayPlugin({
testMode: true, // Set to false for production
sepConfig: {
terminalId: 'your-terminal-id', // Changed from mid
redirectUrl: 'https://yourdomain.com/api/sep/payment/callback',
},
}),
],
})2. Environment Variables
# SEP Gateway Configuration (Updated)
SEP_TERMINAL_ID=your_terminal_id_here
SEP_REDIRECT_URL=https://yourdomain.com/api/sep/payment/callback
# Optional: Custom URLs (uses correct defaults)
SEP_PAYMENT_URL=https://sep.shaparak.ir/OnlinePG/OnlinePG
SEP_TOKEN_URL=https://sep.shaparak.ir/onlinepg/onlinepg
SEP_VERIFY_URL=https://sep.shaparak.ir/verifyTxnRandomSessionkey/ipg/VerifyTransaction
SEP_REVERSE_URL=https://sep.shaparak.ir/verifyTxnRandomSessionkey/ipg/ReverseTransaction3. API Routes Setup
Create API routes in your Next.js app:
// app/api/sep/payment/initiate/route.ts
import { POST } from 'payload-sep-gateway-plugin/api-routes/initiate'
export { POST }
// app/api/sep/payment/token/route.ts
import { POST } from 'payload-sep-gateway-plugin/api-routes/token'
export { POST }
// app/api/sep/payment/callback/route.ts
import { POST } from 'payload-sep-gateway-plugin/api-routes/callback'
export { POST }
// app/api/sep/payment/verify/route.ts
import { POST } from 'payload-sep-gateway-plugin/api-routes/verify'
export { POST }
// app/api/sep/payment/reverse/route.ts
import { POST } from 'payload-sep-gateway-plugin/api-routes/reverse'
export { POST }Configuration
Plugin Configuration Options
interface SEPPluginConfig {
// Enable test mode for development
testMode?: boolean
// SEP Gateway Configuration (Updated)
sepConfig?: {
terminalId?: string // Changed from mid
redirectUrl?: string
paymentUrl?: string
tokenUrl?: string // New
verifyUrl?: string
reverseUrl?: string // New
}
// Custom collection slugs
collections?: {
orders?: string
paymentTransactions?: string
products?: string
}
// Custom field configurations
fields?: {
orders?: any[]
paymentTransactions?: any[]
products?: any[]
}
// API endpoints configuration
api?: {
prefix?: string
endpoints?: {
initiate?: boolean
token?: boolean
callback?: boolean
verify?: boolean
reverse?: boolean // New
}
}
// UI Configuration
ui?: {
showGatewayInfo?: boolean
labels?: {
orders?: string
paymentTransactions?: string
products?: string
}
}
}Advanced Configuration Example
sepGatewayPlugin({
testMode: process.env.NODE_ENV === 'development',
sepConfig: {
terminalId: process.env.SEP_TERMINAL_ID,
redirectUrl: process.env.SEP_REDIRECT_URL,
},
collections: {
orders: 'custom-orders',
paymentTransactions: 'custom-transactions',
products: 'custom-products',
},
fields: {
orders: [
{
name: 'customField',
type: 'text',
admin: {
description: 'Custom order field',
},
},
],
},
api: {
prefix: '/api/custom-sep',
endpoints: {
initiate: true,
token: true,
callback: true,
verify: true,
reverse: true, // Enable reverse transactions
},
},
ui: {
showGatewayInfo: true,
labels: {
orders: 'سفارشات',
paymentTransactions: 'تراکنشهای پرداخت',
products: 'محصولات',
},
},
})Usage Examples
Correct SEP Payment Integration
// Correct token-based payment (Recommended)
const handlePayment = async (ev: React.FormEvent) => {
ev.preventDefault()
setLoading(true)
setError('')
const amount = 12000 // amount in Rials
const resNum = 'order-12345' // your unique order id
try {
// 1) Ask your server to create token
const response = await fetch('/api/sep/payment/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
amount,
resNum,
redirectUrl: `${window.location.origin}/api/sep/payment/callback`
})
})
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || data.errorDesc || 'Token request failed')
}
// 2) Build a form and submit to gateway (post token)
const form = document.createElement('form')
form.method = 'POST'
form.action = 'https://sep.shaparak.ir/OnlinePG/OnlinePG'
form.style.display = 'none'
const tokenInput = document.createElement('input')
tokenInput.name = 'Token'
tokenInput.value = data.token
form.appendChild(tokenInput)
const getMethodInput = document.createElement('input')
getMethodInput.name = 'GetMethod'
getMethodInput.value = '' // or 'true' if you want GET behavior
form.appendChild(getMethodInput)
document.body.appendChild(form)
form.submit()
} catch (err) {
setError(err instanceof Error ? err.message : 'Payment failed')
} finally {
setLoading(false)
}
}Payment Callback Handling
// Handle payment callback from SEP
const handlePaymentCallback = async () => {
const urlParams = new URLSearchParams(window.location.search)
const callbackData = {
State: urlParams.get('State'),
RefNum: urlParams.get('RefNum'),
ResNum: urlParams.get('ResNum'),
TraceNo: urlParams.get('TraceNo'),
SecurePan: urlParams.get('SecurePan'),
}
const response = await fetch('/api/sep/payment/callback', {
method: 'POST',
body: new URLSearchParams(callbackData),
})
const result = await response.json()
if (result.success) {
// Payment processed successfully
console.log('Payment processed:', result.message)
} else {
// Handle error
console.error('Payment error:', result.error)
}
}Reverse Transaction (Refund)
// Reverse a transaction
const reverseTransaction = async (transactionId: string) => {
const response = await fetch('/api/sep/payment/reverse', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ transactionId }),
})
const result = await response.json()
if (result.success) {
console.log('Transaction reversed:', result.data.message)
} else {
console.error('Reversal failed:', result.error)
}
}Collections
Orders Collection
The Orders collection manages customer orders with the following fields:
orderNumber: Auto-generated unique order numbercustomer: Customer information (name, email, phone, address)items: Array of order items with product, quantity, and pricingtotalAmount: Total order amount in Rialsstatus: Order status (pending, processing, paid, failed, cancelled, refunded)paymentTransaction: Reference to associated payment transactionnotes: Additional order notes
Payment Transactions Collection
The Payment Transactions collection tracks SEP gateway interactions:
order: Reference to associated orderreferenceNumber: Unique transaction referencereservationNumber: SEP reservation numberamount: Transaction amount in RialsterminalId: SEP terminal ID (updated from merchantId)status: Transaction statussepResponse: SEP gateway response dataverificationResult: Verification result codeverificationStatus: Verification statusreverseResult: Reverse transaction result (new)reverseStatus: Reverse transaction status (new)errorMessage: Error message if transaction failed
Products Collection
The Products collection manages your product catalog:
name: Product namedescription: Rich text product descriptionprice: Product price in Rialsimage: Main product imageimages: Additional product imagescategory: Product categorysku: Stock Keeping Unitstock: Available stock quantityisActive: Whether product is activeisDigital: Whether product is digitalweight: Product weight in gramsdimensions: Product dimensionstags: Product tags for searchmeta: SEO metadata
Test Mode
The plugin includes comprehensive test mode capabilities:
sepGatewayPlugin({
testMode: true, // Enable test mode
})In test mode:
- Mock responses are generated instead of real SEP calls
- No real money is charged
- All verification results are simulated
- Test scenarios can be easily configured
API Reference
Payment Initiation
POST /api/sep/payment/initiate
// Request Body
{
orderId: string
amount: number
redirectUrl: string
}
// Response
{
success: boolean
data?: {
paymentTransactionId: string
reservationNumber: string
paymentFormData: Record<string, string>
paymentUrl: string
}
error?: string
}Token Payment (Recommended)
POST /api/sep/payment/token
// Request Body
{
orderId: string
amount: number
redirectUrl: string
}
// Response
{
success: boolean
data?: {
token: string
paymentTransactionId: string
reservationNumber: string
paymentUrl: string
}
error?: string
}Payment Callback
POST /api/sep/payment/callback
// Request Body (FormData)
{
State: string
RefNum: string
ResNum: string
TraceNo: string
SecurePan?: string
MID?: string
Status?: string
RRN?: string
Amount?: number
Wage?: number
HashedCardNumber?: string
}
// Response
{
success: boolean
message?: string
error?: string
}Transaction Verification
POST /api/sep/payment/verify
// Request Body
{
transactionId: string
}
// Response
{
success: boolean
data?: {
verificationResult: number
message: string
}
error?: string
}Reverse Transaction (New)
POST /api/sep/payment/reverse
// Request Body
{
transactionId: string
}
// Response
{
success: boolean
data?: {
reverseResult: number
message: string
}
error?: string
}Security Features
IP Whitelist Support
- Your server IP must be registered with SEP for token-based calls
- Configure
terminalIdfor proper IP whitelist validation
Amount Validation
- Verifies transaction amounts match expected values
- Prevents amount manipulation attacks
Double-Spend Prevention
- Checks RefNum to prevent duplicate processing
- Stores processed RefNums in database
Proper Verification
- Always calls VerifyTransaction before marking payments as successful
- Validates all transaction details server-to-server
Error Handling
The plugin provides comprehensive error handling with Persian error messages:
// SEP Error Codes
const errorMessages = {
[0]: 'Success',
[-1]: 'TP_ERROR - خطا در بررسی صحت رسید دیجیتالی',
[-2]: 'ACCOUNTS_DONT_MATCH - خطا در تأیید رسید دیجیتالی',
[-3]: 'BAD_INPUT - خطا در پردازش رسید دیجیتالی',
// ... more error codes
}
// Transaction States
const stateMessages = {
'OK': 'تراکنش موفق',
'Canceled By User': 'تراکنش توسط خریدار کنسل شد',
'No Sufficient Funds': 'موجودی ناکافی',
// ... more states
}Migration Guide (v1.x to v2.x)
Breaking Changes
- Parameter Names: Change
midtoterminalIdin configuration - Environment Variables: Update
SEP_MIDtoSEP_TERMINAL_ID - API Endpoints: All endpoints now use correct SEP URLs
- Verification Response: Updated to handle new response format
- Dependencies: Removed
axiosandsoap, now uses nativefetch
Migration Steps
Update package version:
npm install payload-sep-gateway-plugin@^2.0.0
Update environment variables:
# Old SEP_MID=your-merchant-id # New SEP_TERMINAL_ID=your-terminal-idUpdate configuration:
// Old sepConfig: { mid: process.env.SEP_MID, } // New sepConfig: { terminalId: process.env.SEP_TERMINAL_ID, }
Update frontend code to use correct form submission (see examples above)
Contributing
Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.
License
MIT License - see LICENSE file for details.
Support
For support and questions:
- GitHub Issues: Create an issue
- Documentation: Full documentation
Changelog
v2.0.0 (Breaking Changes)
- ✅ Fixed Token Creation: Now uses correct REST API endpoint
- ✅ Fixed Payment URL: Updated to correct OnlinePG endpoint
- ✅ Fixed Verification: Uses proper verification endpoint
- ✅ Updated Parameters: Changed from
MIDtoTerminalId - ✅ Added Reverse Transactions: Complete refund/reversal functionality
- ✅ Enhanced Security: Amount validation and double-spend prevention
- ✅ Removed Dependencies: No longer requires
axiosorsoap - ✅ Updated Examples: All examples now show correct implementation
v1.0.0
- Initial release
- Basic SEP gateway integration
- E-commerce collections
- Test mode support
- TypeScript support