Dönüş İşlemleri
Tag-QR Ping Callback entegrasyonu
Macellan SuperApp, Tag-QR ile ödemelerde Ping Callback servisine ihtiyaç duyar. Kullanıcı Tag-QR'ı mobil uygulamadan okuttuğunda, Macellan SuperApp gerekli tüm kontrolleri yapar ve son adım olarak Ping Callback servisine istek atar.
Ping Callback servisi, entegre olacak firma tarafından bu dokümanda anlatıldığı gibi hazırlanmalıdır.
Macellan SuperApp Paneli üzerinden Tag-QR oluşturulurken doldurulan formda Ping URL alanına hazırladığınız
servisin URL adresini girebilirsiniz.

URL adresi yazdığınız inputun yanındaki check işaretini tıklayarak servisin doğru çalışıp çalışmadığını test edebilirsiniz.
Akış
İstek
Hazırlanan servise istek, Macellan SuperApp tarafından Tag-QR okutup gerekli kontrolleri yaptıktan sonra tablodaki değerlerle POST olarak gönderir.
{
"price": "0.02",
"point": "0.00",
"order_id": "3307333742",
"user_id": "3b43544b-10b4-45e2-ab81-2b2b3f1917e8",
"user_phone": "905555555555",
"ref_code": "0781534070",
"callback_success_url": "https://api.altpay.dev/tag-qr/3307333742/success",
"callback_fail_url": "https://api.altpay.dev/tag-qr/3307333742/fail",
"hash": "9fe2ea5ad3f1f5b0289b151521ed1ed2d772dae0"
}| Değer | Tip | Açıklama |
|---|---|---|
price | string | Kullanıcının bakiyesinden düşülecek tutar. |
point | string | Kullanıcının puanından düşülecek tutar. |
order_id | string | Macellan SuperApp'in ödemeye atadığı sipariş numarası. |
user_id | string | İşlem yapan müşterinin tekil kullanıcı IDsi. |
user_phone | string | İşlem yapan müşterinin tekil kullanıcı telefon numarası. |
ref_code | string | Müşteri tarafından mobil uygulamadan okutulan Tag-QR'ın referans kodu. |
callback_success_url | string | İşlem sonunda işlemin başarılı olduğunu bildirebileceğiniz adres. |
callback_fail_url | string | İşlem sonunda işlemin başarısız olduğunu bildirebileceğiniz adres. |
hash | string | Hash doğrulamasında kullanılacak değer. |
Tekil kullanıcı telefon numarası firmanın ORTAK VERİ SORUMLUSU olduğunu kabul etmesi durumunda yukarıda yer olan örnekteki gibi gönderilmektedir. Aksi halde telefon numarası KVKK mevzuatı gereği maskelenmiş olarak gönderilmektedir ve kullanıcı telefon numarası tekil bir değer olarak kabul edilmemelidir.
İsteğin Macellan SuperApp'den geldiğini doğrulayabilmek için Hash Doğrulaması yapabilirsiniz.
Eğer isteği doğru bir şekilde aldıysanız yanıt olarak status kodunu 200 olarak göndermelisiniz.
İşlemin sonucu, isteği doğru alıp almadığınızı belirtir. Örneğin o işlemde bir kapı açılacaksa, kapı açma işlemini bu isteğe cevap verdikten sonra yapmalısınız.
Gelen İsteği Doğrulama
Hash doğrulamanın amacı gelen isteğin Macellan SuperApp tarafından gönderildiğine emin olmaktır.
Doğrulama, istek ile beraber gelen bellirli değerleri aşağıdaki sıra ile birleştirilip sonucun sha1 hashi alınarak yapılır.
salt değişkeni Macellan SuperApp panelinden Tag-QR oluşturulurken formdaki Salt Key değeridir.
Eğer hash değeri doğru değilse response status kodunu 403 ile yanıt verebilirsiniz.
salt + callback_fail_url + callback_success_url + pricepackage main
import (
"crypto/sha1"
"encoding/hex"
"strings"
)
type OpenGateRequest struct {
Price string `json:"price"`
Point string `json:"point"`
RefCode string `json:"ref_code"`
UserId string `json:"user_id"`
UserPhone string `json:"user_phone"`
OrderId string `json:"order_id"`
CallbackSuccessUrl string `json:"callback_success_url"`
CallbackFailUrl string `json:"callback_fail_url"`
Hash string `json:"hash"`
}
func requestHashValidator(request *OpenGateRequest) bool {
sb := []string{
os.Getenv("SALT"),
r.CallbackFailUrl,
r.CallbackSuccessUrl,
r.Price,
}
s := strings.Join(sb, "")
hasher := sha1.New()
hasher.Write([]byte(s))
cHash := hex.EncodeToString(hasher.Sum(nil))
return request.Hash == cHash
}function requestHashValidator(): bool
{
$request = json_decode(file_get_contents('php://input'), true);
$salt = 'test';
$cHash = sha1(sprintf(
'%s%s%s%s',
$salt,
$request['callback_fail_url'],
$request['callback_success_url'],
$request['price'],
));
return $request['hash'] === $cHash;
}import { createHash } from "crypto";
interface openGateRequest {
price: string;
point: string;
ref_code: string;
user_id: string;
user_phone: string;
order_id: string;
callback_success_url: string;
callback_fail_url: string;
hash: string;
}
function requestHashValidator(request: openGateRequest): boolean
{
const string: Array<string> = [
process.env.salt,
request.callback_fail_url,
request.callback_success_url,
request.price,
]
const cHash: string = createHash('sha1').update(string.join('')).digest('hex')
return request.hash == cHash
}İşlem Sonucunu Bildirme
İsteği aldıktan sonra kendi tarafınızdaki yapmanız gereken tüm işlemleri yapınız, daha sonra işlemin durumunu Macellan SuperApp'e bildirmeniz gerekmektedir.
İşlem başarılı ise ilk gelen istekteki callback_success_url değerindeki adrese POST isteği atmalısınız.
İşlem başarısız olmuşsa callback_fail_url değerindeki adrese POST isteği atılmalıdır.
Dönüş İstekleri İçin Hash Hesaplama
Dönüş isteği atılırken Macellan SuperApp'in istekte bulunanın siz olduğunuzu anlayabilmesi için hash değerine ihtiyaç duyar.
Dönüş isteklerinde göndereceğiniz hash değerinin hesaplama sırası, size gelen istek doğrulamasından farklıdır.
Hash hesaplayabilmek için ilk istekte gönderilen değerleri aşağıdaki sırayla birleştirip sha1 hashını almalısınız.
price + callback_success_url + callback_fail_url + saltpackage main
import (
"crypto/sha1"
"encoding/hex"
"strings"
)
type OpenGateRequest struct {
Price string `json:"price"`
Point string `json:"point"`
RefCode string `json:"ref_code"`
UserId string `json:"user_id"`
UserPhone string `json:"user_id"`
OrderId string `json:"order_id"`
CallbackSuccessUrl string `json:"callback_success_url"`
CallbackFailUrl string `json:"callback_fail_url"`
Hash string `json:"hash"`
}
func getCallbackHash(request *OpenGateRequest) string {
sb := []string{
r.Price,
r.CallbackSuccessUrl,
r.CallbackFailUrl,
os.Getenv("SALT"),
}
s := strings.Join(sb, "")
hasher := sha1.New()
hasher.Write([]byte(s))
cHash := hex.EncodeToString(hasher.Sum(nil))
return cHash
}function getCallbackHash(): string
{
$request = json_decode(file_get_contents('php://input'), true);
$salt = 'test';
return sha1(sprintf(
'%s%s%s%s',
$request['price'],
$request['callback_success_url'],
$request['callback_fail_url'],
$salt,
));
}import { createHash } from "crypto";
interface openGateRequest {
price: string;
point: string;
ref_code: string;
user_id: string;
user_phone: string;
order_id: string;
callback_success_url: string;
callback_fail_url: string;
hash: string;
}
function getCallbackHash(request: openGateRequest): string
{
const string: Array<string> = [
request.price,
request.callback_success_url,
request.callback_fail_url,
process.env.salt,
]
return createHash('sha1').update(string.join('')).digest('hex')
}Dönüş İstekleri
Kendi tarafınızdaki kontrolleri ve gerçekleşmesi gereken tüm işlemleri yaptıktan sonra, işlemin durumunu Macellan SuperApp'e bildirmelisiniz.
Sonucu bildirebilmek için ilk gelen istekteki callback_succes_url veya callback_fail_url adreslerini kullanabilirsiniz.
Eğer işlem sizin tarafınızda başarısız olmuş, örneğin işlem sonunda kapı açmak istiyorsanız, kapıyı açacak olan cihaz ile iletişim kuramamış olabilirsiniz veya
cihaz size hata ile dönmüşse bu durumu bildirmek için callback_fail_url deki adrese istek göndermelisiniz.
İşlemin kesin olarak başarılı olduğuna eminseniz, örneğin kapı açılacaksa cihazınızdan kapı açıldı komutu size ulaştıktan sonra
callback_succes_url e istek göndermelisiniz.
Macellan SuperApp ilk istek gönderdikten sonraki ilk 30 sn içerisinde herhangi bir dönüş yapılmayan işlemleri başarısız olarak kabul eder ve ödeme işlemini sonlandırır.
Eğer durum başarılı olarak bildirildiyse, tutar bakiyeden düşülür ve ödeme tamamlanmış olur.
package main
import (
"bytes"
"encoding/json"
"net/http"
)
type CallbackRequest struct {
Hash string `json:"hash"`
}
func callback(r *OpenGateRequest, cHash string, isSuccess bool) {
jsonData, _ := json.Marshal(CallbackRequest{
Hash: cHash,
})
var callbackUrl = r.CallbackSuccessUrl
if ! isSuccess {
callbackUrl = r.CallbackFailUrl
}
_, _ = http.Post(callbackUrl, "application/json", bytes.NewBuffer(jsonData))
}function callback(array $request, string $hash, bool $isSuccess): void
{
$callbackUrl = $isSuccess ? $request['callback_success_url'] : $request['callback_fail_url'];
$options = [
'http' => [
'header' => 'Content-type: application/json',
'method' => 'POST',
'content' => json_encode([
'hash' => $hash,
]),
],
];
$context = stream_context_create($options);
$result = file_get_contents($callbackUrl, false, $context);
}function callback(request: openGateRequest, hash: string, isSuccess: boolean): void
{
const callbackUrl: string = isSuccess ? request.callback_success_url : request.callback_fail_url
fetch(callbackUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ hash: hash })
})
.then(() => console.log('successful'))
}curl -X "POST" "https://api.altpay.dev/tag-qr/3307333742/success" \
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{
"hash": "5e7dfd7bc753dbe7a6a62ce0557db88fef305b78"
}'