API Entegrasyonu Rehberi: Ödeme, Kargo ve CRM Sistemleri
Web ve mobil uygulamalarda API entegrasyonu nasıl yapılır? İyzico, Aras Kargo, CRM sistemleri ve RESTful API best practices.
API Entegrasyonu Rehberi: Ödeme, Kargo ve CRM Sistemleri
Modern web ve mobil uygulamalarda API entegrasyonları vazgeçilmez. Ödeme almak, kargo göndermek veya CRM sistemi kullanmak için API entegrasyonları şart.
Bu kapsamlı rehberde, en çok kullanılan API’lerin nasıl entegre edileceğini, best practice’leri ve güvenlik önlemlerini öğreneceksiniz.
API Nedir?
API (Application Programming Interface), iki yazılımın birbirleriyle iletişim kurmasını sağlayan arayüzdür.
API Tipleri
- RESTful API (En yaygın)
- GraphQL (Modern)
- SOAP (Eski, bankacılık)
- WebSocket (Real-time)
REST API Temelleri
// GET - Veri çekme
fetch('https://api.example.com/users')
.then((res) => res.json())
.then((data) => console.log(data));
// POST - Veri gönderme
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer YOUR_TOKEN',
},
body: JSON.stringify({
name: 'Ahmet Yılmaz',
email: '[email protected]',
}),
})
.then((res) => res.json())
.then((data) => console.log(data));
HTTP Metodları:
| Metod | Kullanım | Örnek |
|---|---|---|
| GET | Veri okuma | GET /api/users |
| POST | Yeni veri oluşturma | POST /api/users |
| PUT | Veri güncelleme (tam) | PUT /api/users/123 |
| PATCH | Veri güncelleme (kısmi) | PATCH /api/users/123 |
| DELETE | Veri silme | DELETE /api/users/123 |
Ödeme API’leri
İyzico Entegrasyonu
İyzico, Türkiye’nin en popüler ödeme gateway’i.
1. Kurulum
npm install iyzipay
2. Konfigürasyon
// config/iyzico.js
const Iyzipay = require('iyzipay');
const iyzipay = new Iyzipay({
apiKey: process.env.IYZICO_API_KEY,
secretKey: process.env.IYZICO_SECRET_KEY,
uri: process.env.NODE_ENV === 'production' ? 'https://api.iyzipay.com' : 'https://sandbox-api.iyzipay.com',
});
module.exports = iyzipay;
3. Ödeme Başlatma
// controllers/paymentController.js
const iyzipay = require('../config/iyzico');
exports.createPayment = async (req, res) => {
const { price, paidPrice, basketId, buyer, shippingAddress, billingAddress, basketItems } = req.body;
const request = {
locale: Iyzipay.LOCALE.TR,
conversationId: basketId,
price: price.toString(),
paidPrice: paidPrice.toString(),
currency: Iyzipay.CURRENCY.TRY,
installment: '1',
basketId: basketId,
paymentChannel: Iyzipay.PAYMENT_CHANNEL.WEB,
paymentGroup: Iyzipay.PAYMENT_GROUP.PRODUCT,
// Callback URLs
callbackUrl: `${process.env.APP_URL}/payment/callback`,
// Alıcı bilgileri
buyer: {
id: buyer.id,
name: buyer.name,
surname: buyer.surname,
gsmNumber: buyer.phone,
email: buyer.email,
identityNumber: buyer.tcNo,
registrationAddress: buyer.address,
ip: req.ip,
city: buyer.city,
country: 'Turkey',
},
// Teslimat adresi
shippingAddress: {
contactName: shippingAddress.name,
city: shippingAddress.city,
country: 'Turkey',
address: shippingAddress.fullAddress,
},
// Fatura adresi
billingAddress: {
contactName: billingAddress.name,
city: billingAddress.city,
country: 'Turkey',
address: billingAddress.fullAddress,
},
// Sepet ürünleri
basketItems: basketItems.map((item) => ({
id: item.id,
name: item.name,
category1: item.category,
itemType: Iyzipay.BASKET_ITEM_TYPE.PHYSICAL,
price: item.price.toString(),
})),
};
try {
iyzipay.checkoutFormInitialize.create(request, (err, result) => {
if (err) {
console.error('İyzico Error:', err);
return res.status(500).json({
success: false,
message: 'Ödeme başlatılamadı',
});
}
// 3D Secure sayfasına yönlendir
res.json({
success: true,
checkoutFormContent: result.checkoutFormContent,
token: result.token,
});
});
} catch (error) {
console.error(error);
res.status(500).json({ success: false });
}
};
4. Ödeme Doğrulama (Callback)
// routes/payment.js
exports.paymentCallback = async (req, res) => {
const { token } = req.body;
const request = {
locale: Iyzipay.LOCALE.TR,
conversationId: Date.now().toString(),
token: token,
};
iyzipay.checkoutForm.retrieve(request, async (err, result) => {
if (err) {
return res.redirect('/payment/failed');
}
if (result.status === 'success') {
// Ödeme başarılı
const paymentId = result.paymentId;
const paidPrice = result.paidPrice;
// Veritabanına kaydet
await Order.updateOne(
{ basketId: result.basketId },
{
status: 'paid',
paymentId: paymentId,
paidAt: new Date(),
}
);
// Email gönder
await sendOrderConfirmationEmail(result.basketId);
res.redirect('/payment/success');
} else {
res.redirect('/payment/failed');
}
});
};
PayTR Entegrasyonu
PayTR, düşük komisyon oranları ile popüler.
const crypto = require('crypto');
const axios = require('axios');
exports.createPayTRPayment = async (req, res) => {
const { merchantId, merchantKey, merchantSalt, emailAddress, amount, orderId, basket } = req.body;
// Hash oluştur
const hashSTR = `${merchantId}${req.ip}${orderId}${emailAddress}${amount}${basket}1${merchantSalt}`;
const paytrToken = crypto.createHmac('sha256', merchantKey).update(hashSTR).digest('base64');
const params = {
merchant_id: merchantId,
user_ip: req.ip,
merchant_oid: orderId,
email: emailAddress,
payment_amount: amount,
paytr_token: paytrToken,
user_basket: basket,
debug_on: 0,
no_installment: 0,
max_installment: 12,
user_name: 'Ahmet Yılmaz',
user_address: 'İstanbul',
user_phone: '05514917388',
merchant_ok_url: `${process.env.APP_URL}/payment/success`,
merchant_fail_url: `${process.env.APP_URL}/payment/failed`,
timeout_limit: 30,
currency: 'TL',
};
try {
const response = await axios.post('https://www.paytr.com/odeme/api/get-token', new URLSearchParams(params));
if (response.data.status === 'success') {
res.json({
success: true,
token: response.data.token,
});
} else {
res.status(400).json({
success: false,
message: response.data.reason,
});
}
} catch (error) {
console.error(error);
res.status(500).json({ success: false });
}
};
Kargo API’leri
Aras Kargo Entegrasyonu
// services/arasKargo.js
const axios = require('axios');
const xml2js = require('xml2js');
class ArasKargoService {
constructor() {
this.baseURL = 'https://customerservicestest.araskargo.com.tr/ArasCargoCustomerIntegrationService.asmx';
this.username = process.env.ARAS_USERNAME;
this.password = process.env.ARAS_PASSWORD;
this.customerId = process.env.ARAS_CUSTOMER_ID;
}
async createShipment(shipmentData) {
const {
receiverName,
receiverPhone,
receiverAddress,
receiverCity,
receiverDistrict,
weight, // KG
paymentType, // 1: Alıcı Ödemeli, 2: Gönderici Ödemeli
} = shipmentData;
const xmlRequest = `<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ShippingOrderSave xmlns="http://tempuri.org/">
<username>${this.username}</username>
<password>${this.password}</password>
<customerId>${this.customerId}</customerId>
<order>
<ReceiverName>${receiverName}</ReceiverName>
<ReceiverPhone>${receiverPhone}</ReceiverPhone>
<ReceiverAddress>${receiverAddress}</ReceiverAddress>
<ReceiverCityName>${receiverCity}</ReceiverCityName>
<ReceiverTownName>${receiverDistrict}</ReceiverTownName>
<Weight>${weight}</Weight>
<PaymentType>${paymentType}</PaymentType>
<Description>E-Ticaret Siparişi</Description>
</order>
</ShippingOrderSave>
</soap:Body>
</soap:Envelope>`;
try {
const response = await axios.post(this.baseURL, xmlRequest, {
headers: {
'Content-Type': 'text/xml; charset=utf-8',
SOAPAction: 'http://tempuri.org/ShippingOrderSave',
},
});
const parser = new xml2js.Parser();
const result = await parser.parseStringPromise(response.data);
return {
success: true,
trackingNumber:
result['soap:Envelope']['soap:Body'][0]['ShippingOrderSaveResponse'][0]['ShippingOrderSaveResult'][0][
'TrackingNumber'
][0],
};
} catch (error) {
console.error('Aras Kargo Error:', error);
return { success: false, error: error.message };
}
}
async trackShipment(trackingNumber) {
const xmlRequest = `<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<QueryByReferenceNumber xmlns="http://tempuri.org/">
<username>${this.username}</username>
<password>${this.password}</password>
<referenceNumber>${trackingNumber}</referenceNumber>
</QueryByReferenceNumber>
</soap:Body>
</soap:Envelope>`;
try {
const response = await axios.post(this.baseURL, xmlRequest, {
headers: {
'Content-Type': 'text/xml; charset=utf-8',
},
});
const parser = new xml2js.Parser();
const result = await parser.parseStringPromise(response.data);
return {
success: true,
status: result.status,
currentLocation: result.location,
};
} catch (error) {
return { success: false, error: error.message };
}
}
}
module.exports = new ArasKargoService();
Yurtiçi Kargo API
// services/yurticiKargo.js
class YurticiKargoService {
constructor() {
this.apiKey = process.env.YURTICI_API_KEY;
this.baseURL = 'https://api.yurticikargo.com/api/v1';
}
async createShipment(data) {
const shipmentRequest = {
sender: {
name: data.senderName,
phone: data.senderPhone,
address: data.senderAddress,
city: data.senderCity,
district: data.senderDistrict,
},
receiver: {
name: data.receiverName,
phone: data.receiverPhone,
address: data.receiverAddress,
city: data.receiverCity,
district: data.receiverDistrict,
},
package: {
weight: data.weight,
desi: this.calculateDesi(data.dimensions),
value: data.packageValue,
description: data.description,
},
paymentType: data.paymentType, // 'SENDER' or 'RECEIVER'
};
try {
const response = await axios.post(`${this.baseURL}/shipments`, shipmentRequest, {
headers: {
Authorization: `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
},
});
return {
success: true,
trackingNumber: response.data.trackingNumber,
shipmentId: response.data.shipmentId,
};
} catch (error) {
return {
success: false,
error: error.response?.data?.message || error.message,
};
}
}
calculateDesi(dimensions) {
// Desi = (En x Boy x Yükseklik) / 3000
const { width, height, length } = dimensions;
return (width * height * length) / 3000;
}
}
module.exports = new YurticiKargoService();
CRM Entegrasyonları
HubSpot CRM Entegrasyonu
// services/hubspot.js
const axios = require('axios');
class HubSpotService {
constructor() {
this.apiKey = process.env.HUBSPOT_API_KEY;
this.baseURL = 'https://api.hubapi.com';
}
// İletişim (Contact) oluştur
async createContact(contactData) {
const { email, firstName, lastName, phone, company } = contactData;
try {
const response = await axios.post(
`${this.baseURL}/crm/v3/objects/contacts`,
{
properties: {
email: email,
firstname: firstName,
lastname: lastName,
phone: phone,
company: company,
},
},
{
headers: {
Authorization: `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
},
}
);
return {
success: true,
contactId: response.data.id,
};
} catch (error) {
console.error('HubSpot Error:', error.response?.data);
return { success: false, error: error.message };
}
}
// Deal (Fırsat) oluştur
async createDeal(dealData) {
const { dealName, amount, stage, contactId } = dealData;
try {
const response = await axios.post(
`${this.baseURL}/crm/v3/objects/deals`,
{
properties: {
dealname: dealName,
amount: amount,
dealstage: stage,
pipeline: 'default',
},
associations: [
{
to: { id: contactId },
types: [
{
associationCategory: 'HUBSPOT_DEFINED',
associationTypeId: 3, // Contact to Deal
},
],
},
],
},
{
headers: {
Authorization: `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
},
}
);
return {
success: true,
dealId: response.data.id,
};
} catch (error) {
return { success: false, error: error.message };
}
}
// Not ekle
async addNote(contactId, noteContent) {
try {
await axios.post(
`${this.baseURL}/crm/v3/objects/notes`,
{
properties: {
hs_note_body: noteContent,
hs_timestamp: Date.now(),
},
associations: [
{
to: { id: contactId },
types: [
{
associationCategory: 'HUBSPOT_DEFINED',
associationTypeId: 10, // Note to Contact
},
],
},
],
},
{
headers: {
Authorization: `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
},
}
);
return { success: true };
} catch (error) {
return { success: false, error: error.message };
}
}
}
module.exports = new HubSpotService();
Salesforce Entegrasyonu
// services/salesforce.js
const jsforce = require('jsforce');
class SalesforceService {
constructor() {
this.conn = new jsforce.Connection({
loginUrl: process.env.SALESFORCE_LOGIN_URL,
});
}
async connect() {
try {
await this.conn.login(
process.env.SALESFORCE_USERNAME,
process.env.SALESFORCE_PASSWORD + process.env.SALESFORCE_TOKEN
);
return { success: true };
} catch (error) {
return { success: false, error: error.message };
}
}
async createLead(leadData) {
const { firstName, lastName, company, email, phone, status } = leadData;
try {
const result = await this.conn.sobject('Lead').create({
FirstName: firstName,
LastName: lastName,
Company: company,
Email: email,
Phone: phone,
Status: status || 'Open',
LeadSource: 'Website',
});
return {
success: result.success,
leadId: result.id,
};
} catch (error) {
return { success: false, error: error.message };
}
}
async convertLeadToOpportunity(leadId) {
try {
const result = await this.conn.sobject('Lead').convertLead({
leadId: leadId,
convertedStatus: 'Qualified',
});
return {
success: true,
accountId: result.accountId,
contactId: result.contactId,
opportunityId: result.opportunityId,
};
} catch (error) {
return { success: false, error: error.message };
}
}
}
module.exports = new SalesforceService();
RESTful API Best Practices
1. Versiyonlama
// ✅ URL versiyonlama
app.use('/api/v1', routesV1);
app.use('/api/v2', routesV2);
// Örnek:
// GET /api/v1/users
// GET /api/v2/users (yeni özellikler)
2. HTTP Status Kodları
// Success
200 OK // GET, PUT, PATCH başarılı
201 Created // POST ile yeni kayıt oluşturuldu
204 No Content // DELETE başarılı
// Client Errors
400 Bad Request // Geçersiz istek
401 Unauthorized // Authentication gerekli
403 Forbidden // Yetki yok
404 Not Found // Kaynak bulunamadı
422 Unprocessable // Validasyon hatası
// Server Errors
500 Internal Error // Sunucu hatası
503 Service Unavailable // Servis down
3. Endpoint Naming Convention
// ✅ İyi Örnekler
GET /api/v1/users // Tüm kullanıcılar
GET /api/v1/users/123 // Belirli kullanıcı
POST /api/v1/users // Yeni kullanıcı
PUT /api/v1/users/123 // Kullanıcı güncelle (tüm alan)
PATCH /api/v1/users/123 // Kullanıcı güncelle (kısmi)
DELETE /api/v1/users/123 // Kullanıcı sil
// İlişkili kaynaklar
GET /api/v1/users/123/orders // Kullanıcının siparişleri
POST /api/v1/users/123/orders // Yeni sipariş
// ❌ Kötü Örnekler
GET /api/getUsers
POST /api/createUser
GET /api/user-detail?id=123
4. Pagination
// controllers/userController.js
exports.getUsers = async (req, res) => {
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 20;
const skip = (page - 1) * limit;
try {
const users = await User.find().limit(limit).skip(skip).sort({ createdAt: -1 });
const total = await User.countDocuments();
res.json({
success: true,
data: users,
pagination: {
page: page,
limit: limit,
total: total,
totalPages: Math.ceil(total / limit),
hasNextPage: page < Math.ceil(total / limit),
hasPrevPage: page > 1,
},
});
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
};
// Kullanım:
// GET /api/v1/users?page=2&limit=50
5. Filtering ve Sorting
exports.getProducts = async (req, res) => {
const { category, minPrice, maxPrice, sort } = req.query;
// Filtreler
let filter = {};
if (category) filter.category = category;
if (minPrice || maxPrice) {
filter.price = {};
if (minPrice) filter.price.$gte = parseFloat(minPrice);
if (maxPrice) filter.price.$lte = parseFloat(maxPrice);
}
// Sıralama
let sortOption = {};
if (sort) {
const sortFields = sort.split(',');
sortFields.forEach((field) => {
if (field.startsWith('-')) {
sortOption[field.substring(1)] = -1; // Descending
} else {
sortOption[field] = 1; // Ascending
}
});
}
try {
const products = await Product.find(filter).sort(sortOption);
res.json({ success: true, data: products });
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
};
// Kullanım:
// GET /api/v1/products?category=electronics&minPrice=100&maxPrice=1000&sort=-price,name
API Güvenliği
1. JWT Authentication
// middleware/auth.js
const jwt = require('jsonwebtoken');
exports.protect = async (req, res, next) => {
let token;
if (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) {
token = req.headers.authorization.split(' ')[1];
}
if (!token) {
return res.status(401).json({
success: false,
message: 'Bu işlem için giriş yapmalısınız',
});
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = await User.findById(decoded.id);
next();
} catch (error) {
return res.status(401).json({
success: false,
message: 'Geçersiz token',
});
}
};
// Kullanım:
// app.get('/api/v1/profile', protect, getUserProfile);
2. API Key Authentication
// middleware/apiKey.js
exports.validateApiKey = (req, res, next) => {
const apiKey = req.headers['x-api-key'];
if (!apiKey) {
return res.status(401).json({
success: false,
message: 'API key gerekli'
});
}
// Veritabanından kontrol et
const validApiKey = await ApiKey.findOne({ key: apiKey, isActive: true });
if (!validApiKey) {
return res.status(403).json({
success: false,
message: 'Geçersiz API key'
});
}
req.apiKey = validApiKey;
next();
};
3. Rate Limiting
const rateLimit = require('express-rate-limit');
// Genel rate limiter
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 dakika
max: 100, // Max 100 istek
message: 'Çok fazla istek gönderdiniz, lütfen daha sonra tekrar deneyin',
});
app.use('/api/', limiter);
// Login için daha sıkı rate limit
const loginLimiter = rateLimit({
windowMs: 60 * 60 * 1000, // 1 saat
max: 5, // Max 5 deneme
message: 'Çok fazla giriş denemesi, 1 saat sonra tekrar deneyin',
});
app.post('/api/v1/auth/login', loginLimiter, login);
Webhooks
Webhook Nedir?
Webhook, bir olayı gerçek zamanlı olarak diğer sistem ve bildirir.
Webhook İmplementasyonu
// models/Webhook.js
const WebhookSchema = new mongoose.Schema({
url: { type: String, required: true },
events: [{ type: String }], // ['order.created', 'order.updated']
secret: { type: String },
isActive: { type: Boolean, default: true },
});
// services/webhook.js
const axios = require('axios');
const crypto = require('crypto');
class WebhookService {
async trigger(event, data) {
// Bu event'i dinleyen webhook'ları bul
const webhooks = await Webhook.find({
events: event,
isActive: true,
});
for (const webhook of webhooks) {
await this.sendWebhook(webhook, event, data);
}
}
async sendWebhook(webhook, event, data) {
const payload = {
event: event,
data: data,
timestamp: new Date().toISOString(),
};
// HMAC imza oluştur
const signature = crypto.createHmac('sha256', webhook.secret).update(JSON.stringify(payload)).digest('hex');
try {
await axios.post(webhook.url, payload, {
headers: {
'Content-Type': 'application/json',
'X-Webhook-Signature': signature,
},
timeout: 5000,
});
console.log(`Webhook sent to ${webhook.url}`);
} catch (error) {
console.error(`Webhook failed: ${webhook.url}`, error.message);
// Retry logic eklenebilir
}
}
}
// Kullanım:
// Sipariş oluşturulduğunda
await webhookService.trigger('order.created', {
orderId: order.id,
amount: order.amount,
status: 'pending',
});
Webhook Güvenliği
// Webhook signature doğrulama
exports.validateWebhookSignature = (req, res, next) => {
const signature = req.headers['x-webhook-signature'];
const secret = process.env.WEBHOOK_SECRET;
const expectedSignature = crypto.createHmac('sha256', secret).update(JSON.stringify(req.body)).digest('hex');
if (signature !== expectedSignature) {
return res.status(403).json({
success: false,
message: 'Geçersiz webhook signature',
});
}
next();
};
Sonuç
API entegrasyonları modern uygulamaların olmazsa olmazıdır. Bu rehberde öğrendikleriniz:
✅ Ödeme sistemleri (İyzico, PayTR) ✅ Kargo entegrasyonları (Aras, Yurtiçi) ✅ CRM sistemleri (HubSpot, Salesforce) ✅ RESTful API best practices ✅ Güvenlik ve rate limiting ✅ Webhook implementasyonu
Yılmaz Soft API Entegrasyon Hizmetleri
Projeniz için API Entegrasyonları
✅ Ödeme gateway’leri ✅ Kargo firması entegrasyonları ✅ CRM ve ERP sistemleri ✅ Özel API geliştirme ✅ Webhook ve real-time sistemler
Son güncelleme: 22 Ocak 2025 Yazar: Yılmaz Soft Backend Ekibi
Etiketler:
Yılmaz Soft
Yılmaz Soft olarak web geliştirme, mobil uygulama ve dijital pazarlama alanlarında profesyonel çözümler sunuyoruz. Müşterilerimizin dijital dönüşüm süreçlerinde yanlarında olmaktan gurur duyuyoruz.
İletişime Geçin