Bu blog yazısının içeriği doğada teknik, bu yüzden kuru bir okuma biraz olabilir. Umarım, bu uygun bir referans kılavuzu veya benzer projeler üstlenen herhangi bir geliştiriciler için iyi bir başlangıç noktası olarak hizmet vermektedir!
İçindekiler
Genel bakış
Bu tam bir yığın Düğüm.js projesidir. Okta adlı bir hizmet kullanıcı kimlik doğrulaması için kullanılır. Arka uç veritabanı MongoDB üzerinden işlenir ve ön uç CodyHouse Framework bileşenleri ile tasarlanmıştır. Ödeme için PayPal akıllı düğmeleri kullanılır. Tüm bu teknolojiler, atlamayı kolaylaştırmak için kendi bölümlerinde ayrıntılı olarak anlatılır. Ayrıca bu sistemi sıfırdan tasarlamaktan önemli paketler de dahil ettim.
Okta Kullanıcı Kimlik Doğrulaması
Okta, web uygulamalarına girişleri entegre etmeyi ve kullanıcıları grafik arabirimlerinden yönetmeyi kolaylaştırır. Bu projede, müşterinin sepetindeki öğeleri hesabına kaydetmek ve sipariş ayrıntılarını müşteri kimliğine göre düzenlemek için kullanıcı kimlik doğrulaması istiyorum. Okta’yı Node.js komut dosyama nasıl entegre ettiğime ve web uygulamamı kurmak için kullandığım rotalara dair resimler ekledim. Ben çoğunlukla bir referans olarak bu kılavuzu izleyin.
app.use(
require('express-session')({
secret: process.env.APP_SECRET,
resave: true,
saveUninitialized: false
})
);
const { ExpressOIDC } = require('@okta/oidc-middleware');
const oidc = new ExpressOIDC({
issuer: `${process.env.OKTA_ORG_URL}/oauth2/default`,
client_id: process.env.OKTA_CLIENT_ID,
client_secret: process.env.OKTA_CLIENT_SECRET,
redirect_uri: `${process.env.HOST_URL}/authorization-code/callback`,
routes:{
callback:{
defaultRedirect: "/BLTHcrew"
}
},
scope: 'openid profile'
});
app.use(oidc.router);
Bu proje için OIDC Middleware kullanma. Okta Panosu’ndan ‘env’ değişkenleri oluşturuldu. Satır 16’da, giriş URL’sini ürün sayfasına yönlendirmek için bir geri arama JSON oluşturdum.
MongoDB Koleksiyonları
Bu bölümü anlamak için, MongoDB içindeki öğelerin hiyerarşisini kavramak önemlidir. Anahtar değer çiftleri veya alanlar, belgeadı verilen tek bir nesne de birlikte gruplandırılabilir. Çeşitli belgeler bir koleksiyonoluşturur. Çeşitli koleksiyonlar bir veritabanıoluşturur. Veritabanımda iki koleksiyon var: bir Müşteri koleksiyonu ve bir Sipariş koleksiyonu.
Müşteri belgesi aşağıdaki alanları içerir: oktaSub, oktaName, ve oktaUsername. ‘oktaSub’bir kullanıcıya atanan benzersiz bir kimlik,’oktaName’ kayıtlı kullanıcının tam adıve ‘oktaUsername’ kullanıcının e-posta adresidir. Her üç Müşteri alanının da dize değerleri vardır.
Yeni bir Sipariş oluşturulduğunda, aşağıdaki alanları içerir: oktaSub, S, M, L, ve openOrder. Daha önce olduğu gibi, ‘oktaSub’ kullanıcının benzersiz kimliğidir. ‘S’,’M’, ve ‘L’ kullanıcının sepetine ekleyen her ürün boyutu miktarına karşılık gelen tamsayı değerlerini alır (S = küçük, M = orta, L = büyük). ‘openOrder’boolean değerine sahiptir ve son satın alma siparişinin PayPal üzerinden gönderilip gönderilmediğini belirleyerek siparişin tamamlanıp tamamlanmadığına karşılık gelir.
Bir kullanıcı başarılı bir şekilde bir ödeme gönderdiğinde, Sipariş belgesine üç ek alan eklenir. Bu alanlar paypalAddress, paypalAreave paypalNamevardır. ‘paypalAddress’ ve ‘paypalArea’ kombine edildiğinde tam sevkiyat adresi oluşturan iki dizeleri vardır. Adından da anlaşılacağı gibi, ‘paypalName’ PayPal hesabına kayıtlı adı ifade eder. ‘oktaName’ farklı durumda bu alanı dahil.
Kapalı Sipariş belgesi örneği. ‘M’ değeri 1’dir, bu da kullanıcının şu anda sepetinde 1 orta sweatshirt’ü olduğu anlamına gelir. ‘openOrder’ değeri yanlıştır, bu da kullanıcının başarılı bir şekilde kullanıma aldığı anlamına gelir. Bu nedenle, üç ek ‘paypal’ alanları eklenmiştir.
Yeni Müşteri ve Sipariş belgeleri, bir kullanıcı ilk kez oturum açtıktan sonra oluşturulur. Yeni Sipariş belgeleri, başarılı bir ödemeden sonra da oluşturulabilir. Bunun ‘openOrder’ alanı ile ‘false’ değerlerini değiştirme ve üç ‘paypal’ alanı nın eklenmesiyle kategorize edilmiş olduğunu hatırlayın.
CodyHouse Çerçeve Bileşenleri
Çerçeveler, daha karmaşık uygulamaların geliştirilebileceği yazılım ‘tuvalleri’dir. CodyHouse Framework, gerekli tüm HTML, SCSS ve JavaScript’in zaten eklenmiş olduğu önceden oluşturulmuş e-ticaret bileşenlerini içerir. Bu projede, kendi web sitesinde bulabileceğiniz aşağıdaki bileşenleri kullanın: Ürün, SepetÇekmece, Dialog, Dolgu Yükleyici, Kahraman, Uyarı.
Çalışma ortamını ayarlamak için bu kılavuzu takip ediyorum.
PayPal Akıllı Düğmeler
PayPal’ın kapsamlı bir geliştirici API’si vardır, ancak ödemeyi entegre etmenin en basit yolu PayPal geliştirici sitesinde sağlanan JavaScript’tir. Ben buradabağlı onların resmi kılavuzu izleyin.
PayPal düğme oluşturma işlevine iki işlem eklenir. Bunlardan ilki, hareket miktarını içeren bir satınalma siparişi oluşturan ‘createOrder’tır. İkincisi, başarılı bir ödemeden sonra tetiklenen ‘onApprove’dır. Özel işlemler bu aşamada yazılabilir ve gerçekleştirilebilir. Projemde görünmez bir form oluşturuyorum ve PayPal kullanıcısının adını, adresini ve alanını içeren gizli giriş alanları ekliyorum. Ben de gizli bir gönder düğmesi oluşturmak ve bir AJAX isteği işlemek için JavaScript kullanarak tıklayın. Kod daha fazla netlik için aşağıda verilmiştir.
paypal.Buttons({
style: {
layout: 'vertical',
height: 40
},
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: '' + subtotal,
//value: '0.01'
}
}]
});
},
PayPal Smart Button render kodu. Sipariş 6 ile 14 satırlarında oluşturulur. Satır 10’da işlem tutarı USD cinsinden belirtilir. ‘subtotal’ AJAX isteği ile güncelleştirilen küresel değişkendir (daha sonraki bir bölümde bu konuda daha fazla bilgi).
onApprove: function(data, actions) {
document.getElementsByClassName('loadingbar')[0].style.visibility = "visible";
// This function captures the funds from the transaction.
return actions.order.capture().then(function(details) {
console.log(details.purchase_units[0].shipping.address.admin_area_2 + ", " + details.purchase_units[0].shipping.address.admin_area_1 + " " + details.purchase_units[0].shipping.address.postal_code);
let ppName = document.createElement("input");
ppName.type = "text";
ppName.name = "ppName";
ppName.id = "ppName";
ppName.style = "visibility:hidden";
ppName.value = details.purchase_units[0].shipping.name.full_name;
let ppAddress = document.createElement("input");
ppAddress.type = "text";
ppAddress.name = "ppAddress";
ppAddress.id = "ppAddress";
ppAddress.style = "visibility:hidden";
ppAddress.value = details.purchase_units[0].shipping.address.address_line_1;
let ppArea = document.createElement("input");
ppArea.type = "text";
ppArea.name = "ppArea";
ppArea.id = "ppArea";
ppArea.style = "visibility:hidden";
ppArea.value = details.purchase_units[0].shipping.address.admin_area_2 + ", " + details.purchase_units[0].shipping.address.admin_area_1 + " " + details.purchase_units[0].shipping.address.postal_code;
// This function sets up the details of the transaction, including the amount and line item details.
let el = document.createElement("input");
el.type = "submit";
el.id = "btnSubmit";
el.style = "visibility:hidden";
document.getElementById('dynForm').appendChild(el);
document.getElementById('dynForm').appendChild(ppName);
document.getElementById('dynForm').appendChild(ppAddress);
document.getElementById('dynForm').appendChild(ppArea);
document.getElementById('btnSubmit').click();
document.getElementById('btnSubmit').remove();
document.getElementById('ppName').remove();
document.getElementById('ppAddress').remove();
document.getElementById('ppArea').remove();
//close the checkout dialog
closeCheckout();
});
}
‘onApprove’ işlevinden sonra alınan işlemler. ‘ayrıntılar’ PayPal verileri içeren bir JSON nesnesidir. Birkaç gizli giriş öğeleri oluşturulur ve değerleri ‘ayrıntılar’ JSON çeşitli değerlere ayarlanır. Bu öğeler daha sonra eklenir ve daha sonra kodda daha önce oluşturulan bir form nesnesi olan ‘dynForm’a eklenir. Gizli bir gönder girişi de oluşturulur ve satır 33’e tıklanır. Tüm elementler sunulduktan sonra ‘dynform’dan çıkarılır.
$('#dynForm').on('submit', function (event) {
console.log("last step is passed thru");
var ppName = $('#dynForm').find('input[name = "ppName"]').val();
var ppAddress = $('#dynForm').find('input[name = "ppAddress"]').val();
var ppArea = $('#dynForm').find('input[name = "ppArea"]').val();
console.log(ppName);
// console.log(elemSize);
event.preventDefault(); // Stop the form from causing a page refresh
var data ={
//size: elemSize,
//qty: elemQty
//oktaSub: oktaSub
paypalName: ppName,
paypalAddress: ppAddress,
paypalArea: ppArea
};
$.ajax({
//url: 'http://localhost:3000/BLTHhoodie/checkout',
//url: 'http://ec2-3-94-86-1.compute-1.amazonaws.com:3000/BLTHhoodie/checkout',
url: 'https://shopblth.com/BLTHcrew/checkout',
data: data,
method: 'POST'
}).then(function (response) {
// Do stuff with the response, like add it to the page dynamically.
//$('body').append(response);
console.log("ajax response success");
//console.log(response);
//checkoutTotal = response.subtotal;
}).catch(function (err) {
console.error(err);
});
});
Formun işlenmesi dynForm gönder. Satır 11, form gönderildikten sonra sayfanın yenilenmesini engeller. Bir JSON paketi, bir POST isteği takip ve nihayet yanıt işleme hazırlanır.
router.post('/checkout', function(req,res){
console.log("made it to index.js in routes for checkout");
//console.log(req.body);
var ppName = req.body.paypalName;
var ppAddress = req.body.paypalAddress;
var ppArea = req.body.paypalArea;
MongoClient.connect(uri, function(err, client) {
if(err) {
console.log('Error occurred while connecting to MongoDB Atlas...\n',err);
}
console.log('Connected...');
const collection = client.db("MerchData").collection("OrderData");
collection.updateOne(
{$and: [{'oktaSub': oktaSubSave}, {'openOrder': true}]},
{$set: {openOrder: false, paypalName: ppName, paypalAddress: ppAddress, paypalArea: ppArea}}
);
collection.insertOne({'oktaSub': oktaSubSave, 'S': 0, 'M': 0, 'L': 0, 'openOrder': true}, function(err, ress){
//create a document for the user in the customer collection
if (err) throw err;
console.log("1 document inserted into order");
});
client.close();
});
res.json({pass: true});
})
Çıkış için Node.js komut dosyası içinde Rota. Sipariş toplama MongoDB bölümünde açıklandığı gibi güncelleştirilir.
Anahtar Paket #1: PayPal Akıllı Düğmeler değişken olmayan satın almaişlemleri için tasarlanmıştır
Bu özellikle PayPal tarafından özetlenen olmasına rağmen, ben göz ardı etmeye karar verdi bir uyarı. Başlangıçta, kod zaten sağlanan ve entegre etmek kolay görünüyordu, çünkü akıllı düğmeleri kullanmayı seçti. PayPal bölümündeönceki bir resimde gösterildiği gibi, bir satınalma siparişi oluşturulduğunda bir hareket değeri belirtilmelidir. Belirli bir fiyat için, bu değeri atamak kolaydır. Ancak, dinamik fiyatları ayarlamak için bazı güvenlik konuları vardır.
En büyük sorunlardan biri, işlem toplamının HTML DOM. DOM öğelerinden alınamamasıdır. uOrigin gibi Reklam Engelleyiciler birincil işlevlerinden biri olarak bu tekniği kullanmak, bu nedenle niyet her zaman kötü niyetli değildir ama yine de ödeme sırasında sorunlara neden olabilir. Benim geçici çözüm her AJAX isteği (takeaway #2 bu konuda daha fazla ilgileniyorsanız) sonra küresel bir ‘subtotal’ değişkeni güncellemek oldu.
Ben hala bu çözüm ne kadar “hackable” olduğunu bilmiyorum gibi ben canlı ödemeler aşağı aldı sonraya kadar bilerek bu makaleyi yayınlama kapalı tuttum. Ben DOM elemanları subtotal çekerek çok daha iyi olduğunu biliyorum, ama bu konuda düşünme hala beni rahatsız ediyor. Ben doğru çözüm bir Düğüm.js rota ve PayPal geliştirici API kullanarak bu karmaşa işlemek için hayal.
Anahtar Takeaway #2: HTML <div>
Ben Takeaway #1 bu ima, ama öğrendim genel bir ders, DOM unsurları dayalı bilgileri güncelleme gerçekten aptalca olmasıdır. Yine, DOM öğeleri kullanıcı tarafından manipüle edilebilir. Hassas alanların değeri hiçbir zaman bir HTML öğesinden güncelleştirilmelidir. Ben istihdam geçici arka uç etkileyecek her düğmeye basmak sırasında bir AJAX isteği gönderiyordu. İlgili tüm düğmelerin listesi aşağıdaki şekilde verilmiştir.
Anahtar Paket #3: Tarayıcı çerezlerinden arka ucu güncellemeyin
Tüm bu paket ler, kullanıcı tarafından manipüle edilebilen şeylerden hassas bilgileri güncellemeyinbenzer bir tema izleyin. Tarayıcı tanımlama bilgilerini kullanmak, kullanıcıların sepetlerini kaydetmek için kaydolmasını gerektirmeme avantajına sahiptir. Ne yazık ki, bir kullanıcı tarayıcı geçmişini sıfırlamaya karar verdiğinde çerezler istemeden silinebilir. Benim geçici çözüm kullanıcıların kendi sepeti kaydetmek için oturum açmalarını talep etmek oldu. Takeaway #2’daki şekilde gösterildiği gibi, bir kullanıcının sepetini AJAX istekleri yle güncellemek için düğmeleri kullandım. Okta üzerinden kayıt olmak için bir kullanıcı için ekstra bir güçlük olmasına rağmen, ben gerekli bir rahatsızlık olarak kabul etti.
Çözülmemiş sorunlar
Bu bölümde, ben arka brülör üzerine koyarak bu projede bazı çözülmemiş sorunlar kısa bir genel bakış sağlamak istiyorum. Ben bu proje emekli planlıyorum, ama bu blog diğer geliştiricilere yardımcı olmak için yapılabilir bazı kalan sorunlar ve iyileştirmeler bir rapor olmadan tam olmaz.
Öncelikle, ben mücadele ve sonuçta vazgeçti bir konu başarısız PayPal ödemeleri ele olduğunu. Bir kart reddedilirse veya kullanıcı bilgilerini yanlış girerse, kullanıcının bilgileri yeniden girmek yerine sayfasını yenilemesi gerekir. Sadece tekrar kendi bilgilerini koyarak bir hataya neden olmaz, ancak ödeme işleminin geri kalanı erişen kullanıcı “yumuşak kilit” olur. Bazı araştırma online yaparak, paypal bir kullanıcı doğru ödeme başarısız olduktan sonra daha önce açılan sipariş istek oturumu hatırlamak mümkün değil gibi görünüyor.
Geliştirme başka bir alan Okta kurmak için kullanılan “OIDC” middleware yerine olabilir. Ben bu alanda çok araştırma yapmadım, ama daha yaygın bir uygulama yerine Passport.js kullanmak olduğuna inanıyoruz. Bu, geliştiricilerin kayıt tan sonra özelleştirilmiş onay e-postaları gönderme olanağı da dahil olmak üzere daha fazla esneklik sağlamasına olanak tanır.
Sonuç Açıklamaları
Muhtemelen tüm önceki proje ve staj deneyimi kombine daha bu projenin taahhüt tam bir yığın uygulamanın her bileşeni hakkında en çok öğrendim. Yine de, her yaz bu projelerden birini deniyorum, her zaman yüzeyi zar zor çiziyormuşum gibi hissediyorum. Öğrendiklerimden yararlanmak ve bir sonraki maceramda üzerine inşa etmek için sabırsızlanıyorum. Okuduğunuz için teşekkürler!
Dilerseniz Bir Sonra Ki Blog Sayfalarımıza Göz Atabilirsiniz..
Görüşmek Üzere Hoşçakalın WebOdasıyla Kalın..
Hata!
Yorumunuz Çok Kısa, Yorum yapabilmek için en az En az 10 karakter gerekli