中东支付网关API快速接入教程

中东支付网关API快速接入教程

1. 准备工作

在开始接入中东支付网关前,请确保您已完成以下准备:

  • 商户账户:已在目标支付平台(如PayTabs、Telr、PayFort等)注册并开通商户账户
  • API凭证:获取了Merchant ID和API Key/Secret
  • HTTPS支持:您的网站必须支持HTTPS加密连接
  • IP白名单:将您的服务器IP添加到支付平台的允许列表中(如需)

2. API基础信息

常用中东支付网关端点

沙箱环境: https://api-sandbox.paytabs.com/v3/
生产环境: https://api.paytabs.com/v3/

常见接口:
POST /payment/request # 创建支付请求
GET /payment/{trans_id}/query # 查询交易状态
POST /payment/{trans_id}/refund # 退款请求

HTTP头信息要求

Authorization: Bearer your_api_key_here
Content-Type: application/json

3. PHP示例代码 – 创建付款请求

<?php

$apiKey = 'YOUR_API_KEY';
$merchantId = 'YOUR_MERCHANT_ID';

$payload = [
"profile_id" => $merchantId,
"tran_type" => "sale",
"tran_class" => "ecom",
"cart_description" => "Order #12345",
"cart_id" => "12345",
"cart_currency" => "AED", // AED, SAR等中东常用货币代码
"cart_amount" => 100.00,
// callback_url用于接收异步通知,return_url用于用户返回商家页面
// (注意这两个URL必须是HTTPS且已备案)

];

// ...省略其他必填字段...

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.paytabs.com/v3/payment/request');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_HTTPHEADER,[
'Authorization:Bearer '.$apiKey,
'Content-Type:application/json'
]);

$response = curl_exec($ch);
if(curl_errno($ch)) {
echo 'Error:' . curl_error($ch);}
else{
print_r(json_decode ($response ,true));}
?>

Python示例代码 – Webhook验证签名(Python Flask)



from flask import Flask , request ,jsonify
import hashlib ,hmac

app=Flask(__name__)
SECRET_KEY='your_payment_gateway_secret'

@app.route('/webhook',methods=['POST'])
def webhook():
data=request.json

signature_received=data.get('signature')
del data['signature']

message=str(data).encode('utf8')
key=bytes(SECRET_KEY,'utf8')
digest=hmac.new(key ,
msg=message ,
digestmod=
hashlib.sha256 ).hexdigest()

if hmac.compare_digest(digest,signature_received):
process_payment(data)#处理业务逻辑

return jsonify({'status':'success'}),200

else:
return jsonify({'error':'Invalid signature'}),
401


def process_payment(payload):
order_id=
payload['reference_no']
amount=
float(payload['amount'])
#更新订单状态为已付款...
pass


if __name__=='__main__':
app.run(port=5000)

Java示例代码 -发起付款请求

中东支付网关API快速接入教程(续)

4. Java示例代码 – 发起付款请求

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.json.JSONObject;

public class MiddleEastPaymentGateway {

private static final String API_URL = "https://api.paytabs.com/v3/payment/request";
private static final String API_KEY = "your_api_key_here";

public static void main(String[] args) {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpPost postRequest = new HttpPost(API_URL);

// 设置请求头
postRequest.setHeader("Authorization", "Bearer " + API_KEY);
postRequest.setHeader("Content-Type", "application/json");

// 构建请求体
JSONObject paymentData = new JSONObject();
paymentData.put("profile_id", "YOUR_MERCHANT_ID");
paymentData.put("tran_type", "sale");
paymentData.put("tran_class", "ecom");
paymentData.put("cart_id", UUID.randomUUID().toString());
paymentData.put("cart_currency", "AED"); // UAE Dirham

paymentData.put(
"customer_details",
new JSONObject()
.put(
"name",
"John Doe")
.put(
"email",
"[email protected]")
.put(
"phone",
"+971501234567")//阿联酋号码格式示例

);

StringEntity requestEntity =
new StringEntity(paymentData.toString());
postRequest.setEntity(requestEntity);

try (
CloseableHttpResponse response=
httpClient.execute(postRequest)
){
int statusCode=response.getStatusLine().getStatusCode();
if(statusCode==200||statusCode==201){
System.out.println(IOUtils.toString(response.getEntity().getContent(),StandardCharsets.UTF_8));
}else{
System.err.println(IOUtils.toString(response.getE ntity().getContent(),StandardCharsets.UTF_8));
}
}catch(Exception e){e.printStackTrace();}

}catch(Exception ex){ex.printStackTrace();}
}

5.Node.js示例-处理异步通知



const express=require('express');
const crypto=require('crypto');

const app=express();
app.use(express.json());

const WEBHOOK_SECRET='your_secret_key';

app.post('/payment/webhook',async(req,res)=>{
try{
//验证签名
const receivedSignature=
req.headers['x-paytabs-signature'];
const payloadString=
JSON.stringify(req.body);

const expectedSignature=crypto.createHmac('sha256',
WEBHOOK_SECRET).update(payloadString).digest('hex');

if(receivedSignature!==expectedSignature){
return res.status(401).send({error:'Invalid signature'});
}

/*成功验证后处理业务逻辑*/
switch(req.body.payment_result.response_status){
case'A':
console.log(`订单${req.body.cart_id}支付成功`);
await updateOrderStatus(req.body.cart_id,'paid');break;case'V':console.log(`订单${req.body.cart_id}已过期`);break;default:console.warn(`未知状态:${req.body.payment_result.response_status}`);}

res.status(200).end();

}catch(err){console.error(err);res.status500.send({error:'Internal server error'});}});


async function updateOrderStatus(orderId,status){

/*实现您的订单状态更新逻辑*/}


app.listen3000()=>{console.logWebhook listener running on port3000)});

6.CURL命令测试查询交易状态

curl-X GET \
-H Authorization:Bearer YOUR_API_KEY \
-H Content-Type:application/json \ https://api-sandbox.paytabs.com/v3/payment/TRANS123456789/query

响应示例:
{
tran_ref : TRN12345 ,
cart id : ORD1001 ,
tran type : sale ,
amount :150.00,
currency:AED,
payment result:{
response message:Authorised,
response code:00}}

7.SwaggerUI集成建议

大多数中东支付网关提供Swagger文档,建议:

1.下载官方提供的swagger.json文件2导入到Postman或Swagger Editor中3生成对应语言的SDK代码片段4直接用于项目开发

例如PayFort的OpenAPI文档通常位于:https://docs.payfort.com/api

8常见错误代码及解决方案

错误码 含义 解决方法
40078 无效货币 确保使用支持的货币如AED/SAR/KWD等
50066 IP未授权 在商户后台添加服务器IP白名单
40102 签名错误 检查HMAC-SHA256算法实现是否正确
30134 重复订单号 更换新的唯一cart_id值

特别提示:沙特地区需额外注意:

  • VAT税率字段必须正确传递(通常15%)
  • customer_name需包含first name和last name两个字段

中东支付网关API深度集成指南(续)

9. 高级功能实现

9.1 Token化支付(信用卡存储)

# Python示例 - 创建token
import requests

def create_payment_token(card_details):
url = "https://api.paytabs.com/v3/token/create"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}

payload = {
"profile_id": MERCHANT_ID,
"customer_email": card_details['email'],
'payment_info': {
'card_number': card_details['card_number'],
'expiry_month': card_details['exp_month'],
'expiry_year': card_details['exp_year'],
'cvv': card_details['cvv']
}
}

response = requests.post(url, json=payload, headers=headers)
return response.json()['token']

# 使用token发起免密支付
def charge_with_token(token, amount):
url = "https://api.paytabs.com/v3/payment/request"

9.2 Apple Pay/Google Pay集成

// JavaScript前端处理Apple Pay请求示例
async function initiateApplePay() {
const paymentRequest = {
countryCode: 'AE',
currencyCode:
'AED',
merchantCapabilities: ['supports3DS'],
supportedNetworks: ['visa',
'masterCard',
'mada'], // mada是沙特本地卡组织

total: { label:'订单总额',amount:'100.00'}
};

const session=new ApplePaySession(1,paymentRequest);

session.onvalidatemerchant=(event)=>{
fetch('/validate-merchant',{
method:'POST',
body:
JSON.stringify({validationUrl:
event.validationUrl})
}).then(...);
};
}

10.SDK最佳实践

官方SDK推荐

自定义封装建议

// Java通用支付客户端封装示例
public abstract class MiddleEastPaymentClient {

protected final String apiKey;
protected final String merchantId;

public MiddleEastPaymentClient(String apiKey,String merchantId){
this.apiKey=Objects.requireNonNull(apiKey);
this.merchantId=Objects.
requireNonNull(merchantId);}

public abstract PaymentResponse initiatePayment(PaymentRequest request)throws PaymentException;

protected HttpHeaders buildAuthHeaders(){
HttpHeaders headers=new HttpHeaders();
headers.set("Authorization","Bearer "+apiKey);
headers.setContentType(
MediaType.
APPLICATION_JSON);
return headers;}

// ...其他通用方法...
}

11.PCI DSS合规要点

中东地区对支付安全要求严格,必须注意:

1.敏感数据加密

  • PAN号码必须使用AES-256加密存储
  • CVV不能存储,只能即时验证

2.日志脱敏处理

// PHP日志过滤示例  
function sanitizeLog(array $data):array{
$sensitiveKeys=['card_num','cvv','password'];
foreach($sensitiveKeys as $key){
if(isset($data[$key])){
$data[$key]=str_repeat('*'strlen($data[$key]));
}}
return $data;}

3.定期安全审计

  • Saudi SAMA框架要求每季度进行渗透测试
  • UAE需通过ADHICS认证

12.本地化特殊需求

国家 特有要求
沙特 必需支持mada卡&STCPay
阿联酋 需显示NOL交通卡选项
巴林 BenefitPay二维码强制接入

阿拉伯语错误消息对照表:

"Invalid CVV":"رمز التحقق غير صحيح",  
"Expired Card":"انتهت صلاحية البطاقة",
"Insufficient Funds":"رصيد غير كاف"

13.Webhook调试技巧

使用ngrok进行本地测试:

ngrok http3000--region=me #使用中东服务器获得更稳定连接

curl-X POST\
-H Content-Type:application/json\
-d@test_payload.json\ https://your-subdomain.me.
ngrok.io/webhook

# test_payload.json应包含完整的模拟通知数据+签名头(x-signature)

如需继续了解特定国家或功能的深入实现细节,请告知具体方向。

Categories: