Oyun İçi satın alımlar
Kullanıcıların oyun içi satın alma yapmasına izin vererek gelir elde edebilirsiniz. Örneğin, bir seviyeyi tamamlamak için ekstra süre veya oyun karakteri için aksesuarlar. Bunun için:
- Yandex Games geliştirici konsolunda Oyun içi satın almayı bağlayın.
- SDK'da alışveriş özelliğini ayarlayın.
- İşlenmemiş satın alımları kontrol edin.
- Satın alımları test edin.
Dikkat
Satın alımları, tüketimlerini bağladıktan sonra test edebilirsiniz. Aksi takdirde işlenmemiş ödemeler ortaya çıkabilir, bu da moderasyon sürecini geçilmesini imkansız kılabilir.
Bağlantı şartları
Satın alma eklendikten ve taslak oyunu yayınladıktan sonra games-partners@yandex-team.ru adresine satın almanın etkinleştirilmesini talep eden bir e-posta gönderin. E-postanıza oyunun adını ve tanımlayıcısını (ID) eklediğinizden emin olun.
games-partners@yandex-team.ru adresinden satın alma işlemlerine izin verildiğini onaylayan bir yanıt geldikten sonra gerekli ayarları ve testleri yapabilirsiniz.
Başlatma
Oyuncuların uygulama içi satın alımlar yapabilmesi için payments
nesnesini kullanabilirsiniz. İki seçeneğiniz var:
-
Doğrudan
ysdk.payments
üzerinden erişim. Satın alma işlemleri, nesnenin herhangi bir metoduna ilk çağrı yapıldığında başlatılır, bu nedenle ilk çağrı biraz daha yavaş olabilir. -
ysdk.getPayments()
metodu ile nesneyi başlatın. Bu yöntem,payments
metodları için gerekli verileri önceden yükler. Böylece ilk çağrıda gecikme yaşanmaz.
Dikkat
YaGames.init()
ve ysdk.getPayments()
fonksiyonlarına, isteğe bağlı signed: boolean
parametresi geçirilebilir. Bu parametre sahtekarlığa karşı koruma için kullanılır. Değer seçimi, ödemelerin nerede işlendiğine bağlıdır:
-
İstemci tarafında işleniyorsa — metotları parametresiz çağırın veya
signed: false
geçirin. Satın alma metodları verileri açık şekilde döndürür. -
Sunucu tarafında işleniyorsa —
signed: true
geçirin. Bu durumda payments.getPurchases() ve payments.purchase() metodlarının yanıtlarında tüm veriler yalnızca şifrelenmiş şekilde_signature
parametresinde döndürülür.
Varsayılan parametre ile başlatma (signed: false
).
Yöntem 1: Basit Kullanım
YaGames.init() // Veya YaGames.init({ signed: false }).
.then(ysdk => {
// Satın alma metodlarına ysdk.payments üzerinden erişilebilir.
console.log(ysdk.payments);
}).catch(err => {
// Satın alımlar kullanılamıyor.
});
Yöntem 2: getPayments() ile ön yükleme
var payments = null;
YaGames.init()
.then(ysdk => {
ysdk.getPayments()
.then(_payments => {
// Satın alma metodlarına payments üzerinden erişilebilir.
payments = _payments;
console.log(payments);
}).catch(err => {
// Satın alımlar kullanılamıyor.
});
});
signed: true
parametresi ile başlatma.
Yöntem 1: SDK başlatılırken
YaGames.init({ signed: true }) // Satın alımlar için imza desteğini etkinleştirir.
.then(ysdk => {
// Satın alma metodlarına ysdk.payments üzerinden erişilebilir.
console.log(ysdk.payments);
}).catch(err => {
// Satın alımlar kullanılamıyor.
});
Yöntem 2: getPayments() ile detaylı yapılandırma
var payments = null;
YaGames.init()
.then(ysdk => {
ysdk.getPayments({ signed: true })
.then(_payments => {
// Satın alma metodlarına payments üzerinden erişilebilir.
payments = _payments;
console.log(payments);
}).catch(err => {
// Satın alımlar kullanılamıyor.
});
});
Satın alma sürecinin etkinleştirilmesi
Oyun içi satın almayı etkinleştirmek için, payments.purchase({ id, developerPayload })
metodunu kullanın.
id: string
– geliştirici konsolunda belirlenmiş olan ürün ID'si.developerPayload: string
– isteğe bağlı parametre. Satın alma hakkında sunucunuza iletmek istediğiniz ek bilgiler (signature parametresinde iletilecektir).
Metot, ödeme ağ geçidini içeren bir çerçeve açar.
Varsayılan parametre ile Başlatma (signed: false
).
Promise<Purchase>
döner.
Purchase: object
— satın alma bilgileri. Aşağıdaki özellikleri içerir:
productID: string
— ürün ID'si.purchaseToken: string
— satın alma kullanımı için token.developerPayload: string
— satın alma hakkında ek veriler.
Başlatma parametre ile signed: true
.
Promise<{ signature }>
döner.
signature: string
— oyuncunun kimliğini doğrulamak için satın alma verileri ve imzası şifrelenmiştir.
Oyuncu başarılı bir şekilde satın alma işlemini gerçekleştirdikten sonra, Promise
"resolved" durumuna geçer. Oyuncu satın alma işlemi yapmamış ve pencereyi kapatmışsa, Promise
"rejected" durumuna geçer.
Dikkat
İnternet bağlantısı kötüyse, oyuncunun bir satın alma işlemi yaptığı ancak bunun oyunda görüntülenemediği durumlar olabilir. Bunu önlemek için, satın alımları işlemek üzere İşlenmemiş satın almaları kontrol etme ve Satın almaları ve oyun içi para birimini işleme bölümlerinde açıklanan yöntemleri kullanın.
Bu talimatlara uyulmaması, uygulama içinde oyun içi satın almaların devre dışı bırakılmasına veya uygulamanın yayından kaldırılmasına neden olabilir.
Kullanıcı, oturum açmadan satın alma işlemi yapabilir, ancak kendisine önceden veya satın alma işlemi sırasında hesabına giriş yapmasını teklif etmenizi öneririz.
Örnek
Genel olarak:
payments.purchase({ id: 'gold500' })
.then(purchase => {
// Satın alma işlemi başarıyla tamamlandı!
}).catch(err => {
// Satın alma başarısız oldu: Bu id'ye sahip ürün, geliştirici konsoluna eklenmemiş
// kullanıcı giriş yapmadı, fikrini değiştirdi ve ödeme penceresini kapattı,
// satın alma için ayrılan süre doldu, yeterli para yok, vb.
});
developerPayload
isteğe bağlı parametresini kullanarak:
payments.purchase({ id: 'gold500', developerPayload: '{serverId:42}' })
.then(purchase => {
// purchase.developerPayload === '{serverId:42}'
});
Satın alınan ürünlerin listesini alma
payments.getPurchases()
metodunu kullanarak:
-
oyuncunun daha önce hangi alışverişleri yaptığını öğrenin;
-
işlenmemiş alışverişlerin varlığını kontrol edin;
-
sürekli alışverişleri işleyin.
Varsayılan parametre ile Başlatma (signed: false
).
Promise<Purchase[]>
döner.
Purchase[]: array
— oyuncu tarafından yapılan satın almaların listesi. Listenin şu özelliği var:
productID: string
— ürün ID'si.purchaseToken: string
— satın alma kullanımı için token.developerPayload: string
— satın alma hakkında ek veriler.
Örnek
var SHOW_ADS = true;
payments.getPurchases()
.then(purchases => {
if (purchases.some(purchase => purchase.productID === 'disable_ads')) {
SHOW_ADS = false;
}
}).catch(err => {
// Giriş yapmamış kullanıcılar için USER_NOT_AUTHORIZED istisnası gösteriliyor.
});
Başlatma parametre ile signed: true
.
Promise<{ signature }>
döner.
signature: string
— oyuncunun kimliğini doğrulamak için satın alma verileri ve imzası şifrelenmiştir.
Örnek
payments.getPurchases()
.then(purchases => {
fetch('https://your.game.server?purchase', {
method: 'POST',
headers: { 'Content-Type': 'text/plain' },
body: purchases.signature
});
});
Tüm ürünlerin kataloğunu alma
Mevcut satın almaların ve fiyatlarının bir listesini almak için payments.getCatalog()
yöntemini kullanın.
Metot Promise<Product[]>
döndürür.
Product[]: array
— kullanıcının kullanabileceği ürünlerin listesi. Geliştirici konsolunun In-app purchases sekmesindeki tablodan oluşturulmuştur. Her Product
şu özellikleri içerir:
id: string
— ürün tanımlayıcısı.title: string
– ad.description: string
– açıklama.imageURI: string
— görüntünün URL'si.price: string
— ürünün<price> <currency code>
biçimindeki fiyatı.priceValue: string
— ürünün<price>
biçimindeki maliyeti.priceCurrencyCode: string
— para birimi kodu.
Product.getPriceCurrencyImage(size)
— Para birimi ikonunun adresini almak için kullanılan yöntem.
-
size: string
— isteğe bağlı parametre. Olası değerler:-
small
(varsayılan) — küçük bir simge alınır. -
medium
— orta boyutlu bir ikon alınması. -
svg
— vektör ikon alınması.
-
Metot string
döndürür — ikon adresi, örneğin //yastatic.net/s3/games-static/static-data/images/payments/sdk/currency-icon-s@2x.png
.
Örnek
var gameShop = []
payments.getCatalog()
.then(products => {
gameShop = products;
});
Portal Para Birimi Gösterimi
Oyun içinde portal para biriminin ismini ve ikonunu göstermek için SDK'nın imkanlarından faydalanın:
Product.price: string
— para birimi kodu ile birlikte fiyat.Product.priceCurrencyCode: string
— para birimi kodu.Product.getPriceCurrencyImage()
string
döndürür — para birimi ikonunun adresi.
Product
objesi hakkında daha fazla bilgi için Tüm Ürünlerin Katalogunu Alma bölümüne bakın.
Satın almaların işlenmesi ve oyun içi para biriminin hesaba yüklenmesi
İki tür satın alma vardır, kalıcı (reklamları devre dışı bırakma gibi) ve kullanılan (oyun içi para birimi gibi).
Kalıcı satın almaları işlemek için payments.getPurchases() yöntemini uygulayın.
Kullanılan satın almaları işlemek için payments.consumePurchase()
yöntemini uygulayın.
payments.consumePurchase()
Yöntem, işlem başarılı olduysa Promise
öğesini "resolved" durumunda veya hata oluştuysa "rejected" durumunda döndürür.
Dikkat
Payments.consumePurchase()
yöntemi çağrıldıktan sonra, işlenen satın alma işlemi hiçbir kurtarma olasılığı olmadan silinir. Bu nedenle önce oyuncu verilerini player.setStats() veya player.incrementStats() yöntemleriyle değiştirin ve ardından satın alma işlemini gerçekleştirin.
Örnek
payments.purchase({ id: 'gold500' })
.then(purchase => {
// Satın alma işlemi başarıyla tamamlandı!
// Bakiyeye 500 altın yüklüyoruz ve satın alma işlemini kullanıyoruz.
addGold(500).then(() => payments.consumePurchase(purchase.purchaseToken));
});
function addGold(value) {
return player.incrementStats({ gold: value });
// Daha fazla ayrıntı için Oyuncu verileri bölümüne bakın.
}
purchaseToken: string
– payments.purchase() ve payments.getPurchases() yöntemleriyle döndürülen token.
İşlenmemiş satın almaların doğrulanması
Oyun içi satın alma işlemi sırasında kullanıcının internet bağlantısı kesilirse veya sunucunuz kullanılamazsa, satın alma işlemi gerçekleştirilemeyebilir. Bu durumdan kaçınmak için, örneğin oyunu her çalıştırdığınızda payments.getPurchases() yöntemini kullanarak işlenmemiş satın almaları kontrol edin.
Dikkat
Satın alımları ekleyebilmeniz için, lütfen işlenmemiş ödemeleri kontrol etme ayarını yapın.
Bu kontrol, moderasyon sürecinden geçebilmek için zorunludur, bu yüzden test satın alımları için bile onu ayarlamak önemlidir. Eğer oyuna satın alımlar eklenir ve tüketim ayarları yapılmadan test edilirse, testler sonrasında işlenmemiş ödemeler kalabilir ve bu da moderasyon sürecinden geçilmesini imkansız hale getirebilir.
Varsayılan parametre ile Başlatma (signed: false
).
Örnek
payments.getPurchases().then(purchases => purchases.forEach(consumePurchase));
function consumePurchase(purchase) {
if (purchase.productID === 'gold500') {
player.incrementStats({ gold: 500 })
.then(() => {
payments.consumePurchase(purchase.purchaseToken)
});
}
}
Başlatma parametre ile signed: true
.
Örnek
payments.getPurchases()
.then(purchases => {
fetch('https://your.game.server?purchase', {
method: 'POST',
headers: { 'Content-Type': 'text/plain' },
body: purchases.signature
});
});
Hileye karşı koruma
Oyun içinde olası hileli istatistik artışlarından korunmak için, satın alımları sunucu tarafında işleyin:
YaGames.init()
veyaysdk.getPayments()
fonksiyonlarını{ signed: true }
parametresi ile başlatın.- payments.purchase() ve payments.getPurchases() yanıtlarında alınan imzayı kendi sunucunuza gönderin ve gizli anahtarınızı kullanarak bu imzayı deşifre edin.
- Kendi sunucunuzda, oyuncuya oyun içinde kazandığı eşyaları tahsis edin.
// Satın almaların { signed: true } parametresiyle başlatıldığından emin olun
payments.purchase({ id: 'gold500' })
.then(purchase => {
// Satın alma başarıyla tamamlandı!
// Sunucuda 500 altını hesaba yüklüyoruz...
serverPurchase(purchase.signature); // Oyuncuya verileri doğrulayıp tanımlıyoruz.
});
function serverPurchase(signature) {
return fetch('https://your.game.server?purchase', {
method: 'POST',
headers: { 'Content-Type': 'text/plain' },
body: signature
});
}
Sunucuya iletilen signature
parametresi satın alma verilerini ve imzayı içerir. base64
: <imza>.<satın alma verileriyle JSON>
kodlamasında iki dizeyi temsil eder.
Signature örneği
hQ8adIRJWD29Nep+0P36Z6edI5uzj6F3tddz6Dqgclk=.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImlzc3VlZEF0IjoxNTcxMjMzMzcxLCJyZXF1ZXN0UGF5bG9hZCI6InF3ZSIsImRhdGEiOnsidG9rZW4iOiJkODVhZTBiMS05MTY2LTRmYmItYmIzOC02ZDJhNGNhNDQxNmQiLCJzdGF0dXMiOiJ3YWl0aW5nIiwiZXJyb3JDb2RlIjoiIiwiZXJyb3JEZXNjcmlwdGlvbiI6IiIsInVybCI6Imh0dHBzOi8veWFuZGV4LnJ1L2dhbWVzL3Nkay9wYXltZW50cy90cnVzdC1mYWtlLmh0bWwiLCJwcm9kdWN0Ijp7ImlkIjoibm9hZHMiLCJ0aXRsZSI6ItCR0LXQtyDRgNC10LrQu9Cw0LzRiyIsImRlc2NyaXB0aW9uIjoi0J7RgtC60LvRjtGH0LjRgtGMINGA0LXQutC70LDQvNGDINCyINC40LPRgNC1IiwicHJpY2UiOnsiY29kZSI6IlJVUiIsInZhbHVlIjoiNDkifSwiaW1hZ2VQcmVmaXgiOiJodHRwczovL2F2YXRhcnMubWRzLnlhbmRleC5uZXQvZ2V0LWdhbWVzLzE4OTI5OTUvMmEwMDAwMDE2ZDFjMTcxN2JkN2EwMTQ5Y2NhZGM4NjA3OGExLyJ9fX0=
JSON
biçiminde)
Satın alma ile ilgili iletilen veriler örneği (serverPurchase(signature)
işlevindeki signature
parametresi veri formatının payments.getPurchases() yönteminde kullanılandan farklı olduğunu unutmayın.
payments.getPurchases()
yönteminde, signature
parametresi data
alanında bir dizi satın alma nesnesi içerir. serverPurchase(signature)
işlevinde satın alma nesnesidir.
{
"algorithm": "HMAC-SHA256",
"issuedAt": 1571233371,
"requestPayload": "qwe",
"data": {
"token": "d85ae0b1-9166-4fbb-bb38-6d2a4ca4416d",
"status": "waiting",
"errorCode": "",
"errorDescription": "",
"url": "https://yandex.ru/games/sdk/payments/trust-fake.html",
"product": {
"id": "noads",
"title": "Reklam yok",
"description": "Oyunda reklamı devre dışı bırak",
"price": {
"code": "YAN",
"value": "49"
},
"imagePrefix": "https://avatars.mds.yandex.net/get-games/1892995/2a0000016d1c1717bd7a0149ccadc86078a1/"
},
"developerPayload": "TEST DEVELOPER PAYLOAD"
}
}
Gizli anahtar örneği
t0p$ecret
İmza doğrulama için gizli anahtar oyuna özgüdür. Geliştirici konsolunda satın almalar oluşturulurken, bu da otomatik olarak oluşturulur. Satın alma tablosu altında yayınlanmıştır.
Sunucuda imza doğrulama örneği
import hashlib
import hmac
import base64
import json
usedTokens = {}
key = 't0p$ecret' # Anahtarı gizli tutun.
secret = bytes(key, 'utf-8')
signature = 'hQ8adIRJWD29Nep+0P36Z6edI5uzj6F3tddz6Dqgclk=.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImlzc3VlZEF0IjoxNTcxMjMzMzcxLCJyZXF1ZXN0UGF5bG9hZCI6InF3ZSIsImRhdGEiOnsidG9rZW4iOiJkODVhZTBiMS05MTY2LTRmYmItYmIzOC02ZDJhNGNhNDQxNmQiLCJzdGF0dXMiOiJ3YWl0aW5nIiwiZXJyb3JDb2RlIjoiIiwiZXJyb3JEZXNjcmlwdGlvbiI6IiIsInVybCI6Imh0dHBzOi8veWFuZGV4LnJ1L2dhbWVzL3Nkay9wYXltZW50cy90cnVzdC1mYWtlLmh0bWwiLCJwcm9kdWN0Ijp7ImlkIjoibm9hZHMiLCJ0aXRsZSI6ItCR0LXQtyDRgNC10LrQu9Cw0LzRiyIsImRlc2NyaXB0aW9uIjoi0J7RgtC60LvRjtGH0LjRgtGMINGA0LXQutC70LDQvNGDINCyINC40LPRgNC1IiwicHJpY2UiOnsiY29kZSI6IlJVUiIsInZhbHVlIjoiNDkifSwiaW1hZ2VQcmVmaXgiOiJodHRwczovL2F2YXRhcnMubWRzLnlhbmRleC5uZXQvZ2V0LWdhbWVzLzE4OTI5OTUvMmEwMDAwMDE2ZDFjMTcxN2JkN2EwMTQ5Y2NhZGM4NjA3OGExLyJ9fX0='
sign, data = signature.split('.')
message = base64.b64decode(data)
purchaseData = json.loads(message)
result = base64.b64encode(hmac.new(secret, message, digestmod=hashlib.sha256).digest())
if result.decode('utf-8') == sign:
print('Signature check ok!')
if not purchaseData['data']['token'] in usedTokens:
usedTokens[purchaseData['data']['token']] = True; # Veritabanını kullanın.
print('Double spend check ok!')
print('Apply purchase:', purchaseData['data']['product'])
# Burada satın aldıklarınızı güvenle hesaba geçirebilirsiniz.
const crypto = require('crypto');
const usedTokens = {};
const key = 't0p$ecret'; // Anahtarı gizli tutun.
const signature = 'hQ8adIRJWD29Nep+0P36Z6edI5uzj6F3tddz6Dqgclk=.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImlzc3VlZEF0IjoxNTcxMjMzMzcxLCJyZXF1ZXN0UGF5bG9hZCI6InF3ZSIsImRhdGEiOnsidG9rZW4iOiJkODVhZTBiMS05MTY2LTRmYmItYmIzOC02ZDJhNGNhNDQxNmQiLCJzdGF0dXMiOiJ3YWl0aW5nIiwiZXJyb3JDb2RlIjoiIiwiZXJyb3JEZXNjcmlwdGlvbiI6IiIsInVybCI6Imh0dHBzOi8veWFuZGV4LnJ1L2dhbWVzL3Nkay9wYXltZW50cy90cnVzdC1mYWtlLmh0bWwiLCJwcm9kdWN0Ijp7ImlkIjoibm9hZHMiLCJ0aXRsZSI6ItCR0LXQtyDRgNC10LrQu9Cw0LzRiyIsImRlc2NyaXB0aW9uIjoi0J7RgtC60LvRjtGH0LjRgtGMINGA0LXQutC70LDQvNGDINCyINC40LPRgNC1IiwicHJpY2UiOnsiY29kZSI6IlJVUiIsInZhbHVlIjoiNDkifSwiaW1hZ2VQcmVmaXgiOiJodHRwczovL2F2YXRhcnMubWRzLnlhbmRleC5uZXQvZ2V0LWdhbWVzLzE4OTI5OTUvMmEwMDAwMDE2ZDFjMTcxN2JkN2EwMTQ5Y2NhZGM4NjA3OGExLyJ9fX0=';
const [sign, data] = signature.split('.');
const purchaseDataString = Buffer.from(data, 'base64').toString('utf8');
const hmac = crypto.createHmac('sha256', key);
hmac.update(purchaseDataString);
const purchaseData = JSON.parse(purchaseDataString);
if (sign === hmac.digest('base64')) {
console.log('Signature check ok!');
if (!usedTokens[purchaseData.data.token]) {
usedTokens[purchaseData.data.token] = true; // Veri tabanını kullanın.
console.log('Double spend check ok!');
console.log('Apply purchase:', purchaseData.data.product);
// Burada satın aldıklarınızı güvenle hesaba geçirebilirsiniz.
}
}
Not
Destek ekibi, hazır oyunu Yandex Oyun platformuna yerleştirmenize yardımcı olur. Geliştirme ve test etme konularındaki uygulamalı sorulara ise diğer geliştiriciler Discord Topluluğu yanıt verir.
Yandex Games SDK kullanırken sorunla karşılaşırsanız veya sorunuz varsa, lütfen destek ekibiyle iletişime geçin:
id: string
— geliştirici konsolunda belirlenmiş ürün ID'si.
developerPayload: string
— isteğe bağlı parametre. Satın alma hakkında sunucunuza iletmek istediğiniz ek bilgiler (signature
parametresinde iletilecektir).
Sunucuya gönderilen isteğin signature
parametresi satın alma verilerini ve imzayı içerir. base64
: <imza>.<satın alma verileriyle JSON>
kodlamasında iki dizeyi temsil eder.
purchaseToken: string
— payments.purchase() ve payments.getPurchases() yöntemleriyle döndürülen token.
Eğer satın alımları ysdk.getPayments()
ile başlatmadıysanız, doğrudan ysdk.payments
kullanabilirsiniz.
- Monetizasyonu etkinleştirin.
- Geliştirici Konsolu üzerinden In-app purchases sekmesine gidin ve aşağıdakileri kontrol edin:
- En az bir uygulama içi ürün içeren bir tablo olmalı.
- Purchases are enabled yazısı görünür olmalı.