Rumah > Java > javaTutorial > Merekabentuk Sistem Pembelian Kredit Internet

Merekabentuk Sistem Pembelian Kredit Internet

Susan Sarandon
Lepaskan: 2025-01-15 18:05:45
asal
696 orang telah melayarinya

Semasa salah satu temu bual teknikal yang saya hadapi, saya diminta untuk mereka bentuk sistem e-dagang yang membolehkan pengguna membeli kredit internet daripada penyedia pihak ketiga.

Dengan yakin, saya mencadangkan penyelesaian yang mudah: paparkan pakej yang tersedia, benarkan pengguna memilih satu, proses pembayaran melalui gerbang luar dan berinteraksi dengan penyedia untuk menyampaikan kredit. Walau bagaimanapun, apabila ditanya tentang senario kegagalan—seperti pembekal kehabisan stok selepas pengguna menyelesaikan pembayaran—saya menyedari reka bentuk saya tidak mempunyai daya tahan untuk menangani isu sedemikian dengan berkesan.

Beberapa minggu yang lalu, saya menjalankan penyelidikan ke dalam sistem jualan kilat dan corak tempahan inventori, terutamanya memfokuskan pada strategi tempahan inventori. Jualan kilat sering berurusan dengan permintaan tinggi dan stok terhad, memerlukan mekanisme canggih untuk mengekalkan kestabilan sistem dan mengurus jangkaan pelanggan. Satu konsep yang saya temui ialah tempahan inventori sementara, yang membantu mengelakkan penjualan berlebihan semasa waktu puncak.

Penyelidikan ini mengingatkan saya tentang pengalaman temu duga saya. Saya menyedari bahawa menggunakan strategi tempahan inventori ini boleh menangani kelemahan dalam reka bentuk awal saya. Dengan memasukkan penahanan sementara pada inventori semasa proses pembayaran, sistem boleh mengendalikan senario dengan berkesan apabila stok pembekal kehabisan.

Dalam dokumentasi penyelidikan ini, saya berhasrat untuk berkongsi pandangan yang diperoleh daripada penyelidikan saya dan mencadangkan pendekatan yang diperhalusi untuk mereka bentuk sistem pembelian kredit internet. Dengan menyepadukan strategi tempahan inventori, kami boleh membina platform yang teguh dan mesra pengguna, mampu mengendalikan pelbagai senario kegagalan sambil memberikan pengalaman yang lancar.

1. Pertimbangan Reka Bentuk Utama

Apabila mereka bentuk sistem pembelian kredit internet, terdapat beberapa faktor utama yang perlu dipertimbangkan untuk memastikan pengalaman pengguna yang lancar, selamat dan menyeronokkan. Mari pecahkan mereka:

1.1 Pengurusan Kuota

  • Pengesahan Kuota Masa Nyata: Sistem harus segera menyemak sama ada pakej kredit internet ada dalam stok, jadi pengguna tidak sengaja memilih pilihan yang tidak tersedia.
  • Tempahan Kuota Sementara: Tambahkan mekanisme untuk memegang pakej terpilih untuk tempoh yang singkat, memberikan pengguna masa yang cukup untuk menyelesaikan pembelian mereka tanpa risiko kehilangan item.
  • Mengendalikan Konflik Kuota: Kembangkan strategi untuk mengurus situasi di mana berbilang pengguna cuba membeli pakej yang sama pada masa yang sama, memastikan peruntukan yang adil.
  • Pengurusan Cache untuk Maklumat Pakej: Pastikan data cache tepat dan terkini supaya pengguna sentiasa melihat butiran dan ketersediaan yang betul.

1.2 Pemprosesan Pembayaran

  • Pengendalian Pembayaran Selamat: Laksanakan langkah keselamatan yang kukuh untuk melindungi butiran pembayaran pengguna semasa transaksi.
  • Sistem Escrow untuk Perlindungan Pembayaran: Gunakan perkhidmatan escrow untuk menyimpan dana sehingga kredit dihantar, memastikan kedua-dua pembeli dan pembekal selamat.
  • Penyatuan Gerbang Pembayaran: Pastikan sistem bersambung dengan lancar dengan gerbang pembayaran yang boleh dipercayai untuk memastikan transaksi tanpa kerumitan.
  • Mekanisme Bayaran Balik: Buat proses yang jelas dan mesra pengguna untuk mengeluarkan bayaran balik sekiranya pembayaran atau pembatalan gagal.

1.3 Penyepaduan Pembekal

  • Ketersediaan Sistem: Rakan kongsi dengan penyedia yang mempunyai sistem yang boleh dipercayai untuk memastikan pembelian diproses tanpa gangguan.
  • Kebolehpercayaan API: Bekerjasama dengan penyedia yang menawarkan API yang stabil dan didokumentasikan dengan baik untuk penyepaduan yang lancar.
  • Pengesahan Pengaktifan Perkhidmatan: Sertakan semakan untuk mengesahkan bahawa kredit yang dibeli diaktifkan dengan betul dan segera.
  • Pengendalian Ralat dan Percubaan Semula: Laksanakan protokol untuk menangkap dan menyelesaikan ralat dengan cepat, dengan mekanisme cuba semula untuk sebarang proses yang gagal.

1.4 Keselamatan Transaksi

  • Kawalan Aliran Wang: Pastikan dana hanya dikeluarkan selepas transaksi berjaya diselesaikan.
  • Ketekalan Transaksi: Simpan rekod yang tepat dan konsisten bagi semua transaksi untuk mengelakkan ralat.
  • Mekanisme Timbal Balik: Mempunyai rancangan untuk mengembalikan transaksi jika berlaku kesilapan, melindungi kedua-dua pengguna dan sistem.
  • Jejak Audit: Kekalkan log terperinci untuk membantu memantau dan menyelesaikan masalah dengan berkesan.

1.5 Pengalaman Pengguna

  • Kosongkan Mesej Ralat: Berikan pengguna mesej ralat yang boleh difahami dan bermaklumat untuk membimbing mereka melalui sebarang isu yang dihadapi.
  • Keterlihatan Status Transaksi: Benarkan pengguna menjejaki status pembelian mereka dengan mudah dalam masa nyata, meningkatkan ketelusan.
  • Pemuatan Pakej Pantas: Optimumkan sistem untuk memuatkan pakej yang tersedia dengan pantas, mengurangkan masa menunggu untuk pengguna.
  • Kemas Kini Masa Nyata: Pastikan pengguna dimaklumkan tentang sebarang perubahan atau kemas kini pada transaksi atau pakej yang tersedia dengan segera.

Dengan mengambil kira pertimbangan ini, kami boleh mereka bentuk sistem pembelian kredit internet yang cekap, selamat dan mesra pengguna, yang membawa kepada kepuasan dan kepercayaan pengguna yang lebih tinggi.

2. Reka Bentuk dan Aliran Sistem

Berdasarkan pertimbangan asas yang digariskan di atas, langkah seterusnya ialah menterjemahkan prinsip ini kepada reka bentuk sistem yang mantap dan berkesan. Dengan memetakan interaksi antara pelbagai komponen dengan teliti, kami boleh memastikan bahawa sistem bukan sahaja memenuhi keperluan fungsian tetapi juga menyediakan pengalaman pengguna yang lancar sambil mengekalkan kebolehpercayaan dan kebolehskalaan.

Dalam bahagian ini, kami akan menyelidiki seni bina dan aliran sistem, mempamerkan cara fungsi teras—seperti pengurusan kuota, pemprosesan pembayaran dan pengaktifan perkhidmatan—dilaksanakan secara padu. Matlamatnya adalah untuk menyerlahkan cara setiap pilihan reka bentuk menyumbang kepada menangani potensi cabaran dan menyampaikan platform pembelian kredit e-dagang yang boleh dipercayai.

Mari kita mulakan dengan gambaran keseluruhan aliran sistem, digambarkan melalui carta alir, untuk menggambarkan cara pengguna berinteraksi dengan sistem dari awal hingga akhir.

2.1 Rajah Carta Alir

Designing an Internet Credit Purchase System

Aliran sistem dibahagikan kepada enam fasa untuk kejelasan:

Fasa Pemilihan Pakej

  • Pertama, pengguna melawati halaman pemilihan pakej, tempat apl mengambil data pakej daripada cache. Data ini termasuk pakej yang tersedia dan maklumat kuota cachenya, yang kemudiannya dipaparkan kepada pengguna.
  • Pengguna memilih pakej dan mengklik "Beli."
  • Jika kuota untuk pakej itu tidak tersedia, apl menunjukkan mesej "Tidak Tersedia" dan membawa pengguna kembali ke halaman pilihan. Jika tidak, sistem menyimpan kuota untuk pengguna buat sementara waktu.

Permulaan Pembelian

  • Seterusnya, sistem cuba menempah kuota untuk pakej yang dipilih.
  • Jika tempahan gagal, pengguna melihat mesej ralat dan dialihkan semula ke halaman pilihan.
  • Jika tempahan berjaya, pengguna bergerak ke hadapan ke halaman pembayaran.
Fasa Pembayaran
  • Pada peringkat ini, pengguna memulakan proses pembayaran dan diubah hala ke gerbang pembayaran pihak ketiga.
  • Apl menunggu jawapan (panggilan balik) daripada gerbang pembayaran untuk mengesahkan status pembayaran.
Pemprosesan Pembayaran
  • Apl menyemak panggilan balik gerbang pembayaran untuk mengesahkan pembayaran:
    • Untuk panggilan balik yang tidak sah, sistem merekodkan isu dan menghentikan langkah selanjutnya.
    • Untuk panggilan balik yang sah:
      • Jika pembayaran gagal: Sistem mengeluarkan kuota rizab dan memberitahu pengguna tentang isu tersebut.
      • Jika pembayaran berjaya: Sistem mengesahkan pembayaran, menyimpan dana dalam eskrow dan membuat pesanan baharu.
Pengaktifan Perkhidmatan
  • Setelah pembayaran berjaya, sistem meminta pembekal untuk mengaktifkan perkhidmatan.
    • Jika pengaktifan gagal: Dana escrow akan dikembalikan kepada pelanggan dan mereka dimaklumkan tentang kegagalan tersebut.
    • Jika pengaktifan berjaya: Sistem mengesahkan pengaktifan.
      • Jika pengesahan gagal, pelanggan mendapat bayaran balik.
      • Jika pengesahan berjaya, dana escrow akan dikeluarkan kepada pembekal dan pelanggan menerima pemberitahuan.
Proses Latar Belakang
  • Kemas Kini Cache Berkala: Cache data pakej dikemas kini dengan kerap.
  • Kemas Kini Kuota Masa Nyata: Perubahan kuota disampaikan melalui sambungan WebSocket.

Aliran ini memastikan pengalaman yang lancar dan boleh dipercayai untuk pengguna, di samping mengurus sumber dan kemungkinan ralat dengan berkesan.

2.2 Rajah Jujukan

Rajah jujukan di bawah membantu untuk menggambarkan interaksi antara peranan dan komponen yang berbeza.

Designing an Internet Credit Purchase System

Aliran sistem dibahagikan kepada enam fasa untuk kejelasan:

Fasa Pemilihan Pakej

  • Pelanggan bermula dengan melawati halaman pemilihan pakej.
  • Halaman hadapan mendapatkan semula data pakej daripada cache dan memaparkan semua pakej yang tersedia, bersama-sama dengan maklumat kuota cache mereka, kepada pelanggan.

Permulaan Pembelian

  • Setelah pelanggan memilih pakej dan mengklik "Beli", bahagian hadapan menghantar permintaan pembelian ke bahagian belakang.
  • Halaman belakang menyemak dengan pembekal untuk melihat sama ada kuota pakej yang dipilih masih tersedia dalam masa nyata.
  • Jika kuota tersedia, bahagian belakang menyimpannya buat sementara waktu dengan pembekal selama 15 minit.
  • Halaman belakang kemudian menghantar pengesahan tempahan ke bahagian hadapan, dan pelanggan dialihkan ke halaman pembayaran.

Fasa Pembayaran

  • Pelanggan meneruskan ke halaman pembayaran dan menyerahkan butiran pembayaran mereka.
  • Halaman hadapan menghantar maklumat ini ke bahagian belakang, yang memulakan sesi pembayaran dengan gerbang pembayaran.
  • Setelah sesi pembayaran sedia, bahagian belakang berkongsi butiran sesi dengan bahagian hadapan.
  • Halaman hadapan mengubah hala pelanggan ke gerbang pembayaran untuk menyelesaikan pembayaran.

Pemprosesan Pembayaran

  • Di gerbang pembayaran, pelanggan memasukkan maklumat pembayaran mereka dan menyelesaikan proses pembayaran.
  • Gerbang pembayaran memberitahu bahagian belakang status pembayaran melalui panggilan balik:
    • Jika pembayaran berjaya:
      • Halaman belakang mengesahkan status pembayaran dengan gerbang pembayaran.
      • Pembayaran ditahan dalam eskrow, dan bahagian belakang mengesahkan penahanan eskrow.
    • Jika pembayaran gagal:
      • Bagian belakang melepaskan kuota yang ditempah dengan pembekal dan mengemas kini status pembayaran untuk menggambarkan kegagalan.
    • Jika tiada panggilan balik diterima dalam masa yang dijangkakan:
      • Pinggir belakang meninjau gerbang pembayaran secara berkala untuk menyemak status pembayaran. Jika pembayaran gagal atau tamat tempoh, bahagian belakang melepaskan kuota yang ditempah.

Pengaktifan Perkhidmatan

  • Jika pembayaran berjaya, bahagian belakang meminta pembekal untuk mengaktifkan perkhidmatan.
  • Pembekal membalas dengan status pengaktifan, dan bahagian belakang mengesahkan pengaktifan:
    • Jika pengaktifan berjaya:
      • Bahagian belakang mengeluarkan pembayaran daripada escrow kepada pembekal.
      • Pemberitahuan kejayaan dihantar kepada pelanggan, memberitahu mereka bahawa perkhidmatan sudah sedia.
    • Jika pengaktifan gagal:
      • Bahagian belakang membayar balik dana yang disimpan kepada pelanggan.
      • Pemberitahuan kegagalan dihantar untuk memaklumkan pelanggan tentang isu tersebut.

Proses Latar Belakang

  • Pembekal menghantar kemas kini masa nyata tentang kuota pakej ke bahagian belakang melalui sambungan WebSocket.
  • Kemas kini ini memastikan cache sentiasa dikemas kini, jadi pelanggan melihat ketersediaan pakej yang paling tepat semasa menyemak imbas.

3. Pelaksanaan Teknikal

Sekarang kami telah menggariskan aliran dan interaksi sistem, tiba masanya untuk menyelami cara semuanya digabungkan dalam kod. Bahagian ini membahagikan pelaksanaan langkah demi langkah, menunjukkan cara reka bentuk diterjemahkan kepada bahagian yang berfungsi yang mengendalikan segala-galanya daripada mengurus pesanan kepada berinteraksi dengan pembekal dan sistem pembayaran.

// Domain Models
@Getter @Setter
@Entity
public class Package {
    @Id
    private String id;
    private String name;
    private BigDecimal price;
    private BigDecimal providerCost;
    private String description;
    private boolean active;
}

@Getter @Setter
@Entity
public class Order {
    @Id
    private String id;
    private String customerId;
    private String packageId;
    private String reservationId;
    private String paymentId;
    private String escrowId;
    private OrderStatus status;
    private BigDecimal amount;
    private BigDecimal providerCost;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

@Getter @Setter
@Entity
public class QuotaReservation {
    @Id
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

// Enums
public enum OrderStatus {
    CREATED, RESERVED, PAYMENT_PENDING, PAYMENT_COMPLETED, 
    IN_ESCROW, ACTIVATING, ACTIVATION_FAILED, COMPLETED, REFUNDED
}

public enum ReservationStatus {
    ACTIVE, EXPIRED, USED, CANCELLED
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Inilah yang dilakukan oleh kelas ini:

  • Pakej: Di sinilah kami mentakrifkan pakej kredit internet yang boleh dibeli oleh pengguna. Ia menjejaki butiran seperti ID pakej, nama, harga, kos pembekal, perihalan dan sama ada pakej itu aktif atau tidak.

  • Pesan: Anggap ini sebagai rekod pembelian pengguna. Ia termasuk maklumat seperti ID pesanan, ID pelanggan, ID pakej yang dipilih dan butiran berkaitan seperti ID tempahan, ID pembayaran, ID escrow, status pesanan, jumlah pembayaran, kos pembekal dan cap masa.

  • Tempahan Kuota: Ini mengendalikan tempahan sementara untuk kuota pakej. Ia merekodkan ID tempahan, pakej yang terikat dengannya, apabila ia tamat tempoh dan status semasanya (seperti aktif atau tamat tempoh).

  • OrderStatus Enum: Enum ini memetakan semua peringkat kemungkinan yang boleh dilalui oleh pesanan, daripada DIBUAT dan DIPELIHARA kepada PEMBAYARAN_TERBENTANG, DISELESAIKAN, atau DIBAYAR BALIK.

  • ReservationStatus Enum: Begitu juga, enum ini menjejaki keadaan tempahan kuota, sama ada AKTIF, TAMAT TEMPOH, DIGUNAKAN atau DIBATALKAN.

Bersama-sama, kelas dan enum ini membina tulang belakang untuk menguruskan pakej, pesanan dan tempahan kuota dalam sistem. Ia merupakan pendekatan yang mudah tetapi tersusun untuk mengendalikan fungsi e-dagang dengan berkesan.

// Request/Response DTOs
@Getter @Setter
public class OrderRequest {
    private String customerId;
    private String packageId;
    private BigDecimal amount;
}

@Getter @Setter
public class PaymentCallback {
    private String orderId;
    private String paymentId;
    private String status;
    private BigDecimal amount;
    private LocalDateTime timestamp;
}

@Getter @Setter
public class QuotaResponse {
    private String packageId;
    private boolean available;
    private Integer remainingQuota;
    private LocalDateTime timestamp;
}

@Getter @Setter
public class ReservationResponse {
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

@Getter @Setter
public class ActivationResponse {
    private String orderId;
    private boolean success;
    private String activationId;
    private String errorCode;
    private String errorMessage;
}

@Getter @Setter
public class VerificationResponse {
    private String orderId;
    private String activationId;
    private boolean success;
    private String status;
    private LocalDateTime activatedAt;
}

@Getter @Setter
public class PaymentRequest {
    private String orderId;
    private BigDecimal amount;
    private String currency;
    private String customerId;
    private String returnUrl;
    private String callbackUrl;
}

@Getter @Setter
public class PaymentSession {
    private String sessionId;
    private String paymentUrl;
    private LocalDateTime expiresAt;
    private String status;
}

@Getter @Setter
public class EscrowResponse {
    private String id;
    private String paymentId;
    private BigDecimal amount;
    private String status;
    private LocalDateTime createdAt;
}
Salin selepas log masuk
Salin selepas log masuk

Mari kita pecahkan:

  • Permintaan Pesanan: Ini semua tentang data yang diperlukan untuk membuat pesanan baharu. Ia termasuk ID pelanggan, pakej yang mereka ingin beli dan jumlah amaun yang akan mereka bayar.

  • PaymentCallback: Anggap ini sebagai pemberitahuan daripada gerbang pembayaran. Selepas percubaan pembayaran, ia memberikan butiran seperti ID pesanan, ID pembayaran, status (berjaya atau gagal), jumlah yang dibayar dan masa pembayaran berlaku.

  • QuotaResponse: Yang ini mengenai menyemak ketersediaan. Ia memberitahu kami jika pakej tersedia, jumlah kuota yang tinggal dan masa maklumat dikemas kini terakhir.

  • ReservationResponse: Setelah pakej ditempah, ini memberikan anda semua butiran: ID tempahan, pakej yang berkaitan, apabila tempahan tamat tempoh dan status semasanya (seperti aktif atau tamat tempoh) .

  • ActivationResponse: Ini memberitahu kami bagaimana pengaktifan perkhidmatan berjalan. Jika ia berjaya atau gagal, ia memberi kami ID pengaktifan dan butiran ralat jika berlaku kesilapan.

  • VerificationResponse: Selepas pengaktifan, kami mengesahkan sama ada semuanya berjalan lancar. Ini termasuk ID pesanan, ID pengaktifan, status kejayaan dan masa ia diaktifkan.

  • PaymentRequest: Sebelum memulakan proses pembayaran, DTO ini mengumpulkan butiran yang diperlukan seperti ID pesanan, amaun yang perlu dibayar, mata wang, ID pelanggan dan URL panggil balik.

  • PaymentSession: Inilah yang terhasil apabila proses pembayaran bermula. Ia termasuk ID sesi, URL pembayaran (tempat pengguna pergi untuk membayar), apabila ia tamat tempoh dan status sesi.

  • EscrowResponse: Jika dana disimpan dalam escrow, ini memberitahu kita semua tentangnya—seperti ID escrow, ID pembayaran, jumlah yang dipegang, status dan masa ia dibuat.

Semua kelas ini mentakrifkan blok binaan untuk komunikasi antara bahagian sistem yang berlainan—sama ada permintaan yang dikeluarkan atau respons yang kembali. Mereka memastikan semua orang (dan semuanya) berada di halaman yang sama.

// Domain Models
@Getter @Setter
@Entity
public class Package {
    @Id
    private String id;
    private String name;
    private BigDecimal price;
    private BigDecimal providerCost;
    private String description;
    private boolean active;
}

@Getter @Setter
@Entity
public class Order {
    @Id
    private String id;
    private String customerId;
    private String packageId;
    private String reservationId;
    private String paymentId;
    private String escrowId;
    private OrderStatus status;
    private BigDecimal amount;
    private BigDecimal providerCost;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

@Getter @Setter
@Entity
public class QuotaReservation {
    @Id
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

// Enums
public enum OrderStatus {
    CREATED, RESERVED, PAYMENT_PENDING, PAYMENT_COMPLETED, 
    IN_ESCROW, ACTIVATING, ACTIVATION_FAILED, COMPLETED, REFUNDED
}

public enum ReservationStatus {
    ACTIVE, EXPIRED, USED, CANCELLED
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Perkhidmatan Cache
1. Tujuan:

Perkhidmatan ini menjaga cache setempat yang menyimpan data pakej. Matlamatnya adalah untuk menjadikan sistem lebih pantas dan mengurangkan panggilan yang tidak perlu kepada API pembekal.

2. Ciri-ciri Utama:
  • updateCache(): Kaedah ini menyegarkan cache setempat setiap 5 minit dengan mengambil semua data pakej daripada pembekal. Ia memastikan cache kekal terkini.
  • getPackage(): Kaedah ini mendapatkan semula maklumat pakej daripada cache menggunakan IDnya.
  • updatePackageQuota(): Apabila butiran kuota berubah, kaedah ini mengemas kini cache dengan maklumat baharu untuk pakej tertentu.
Integrasi Pembekal
1. Tujuan:

Perkhidmatan ini mengendalikan komunikasi dengan API pembekal. Ia mengurus tugas seperti menyemak kuota, menempah pakej, mengaktifkan perkhidmatan dan mengesahkan pengaktifan tersebut.

2. Ciri-ciri Utama:
  • checkQuota(): Kaedah ini menyemak sama ada pakej mempunyai kuota yang mencukupi dengan menghubungi API pembekal.
  • reserveQuota(): Ia menyimpan kuota pakej untuk pelanggan dengan menghantar permintaan kepada pembekal.
  • activateService(): Apabila tiba masanya untuk mengaktifkan perkhidmatan untuk pesanan, kaedah ini mengendalikan permintaan kepada pembekal.
  • verifyActivation(): Selepas pengaktifan, kaedah ini mengesahkan sama ada semuanya berjaya.
  • getAllPackages(): Kaedah ini mendapatkan semula semua pakej yang tersedia daripada pembekal, yang berguna untuk mengemas kini cache atau memaparkan pilihan pakej kepada pengguna.
3. Mekanisme Cuba Semula:

Perkhidmatan menggunakan RetryTemplate untuk mencuba semula permintaan secara automatik kepada API penyedia apabila terdapat isu sementara. Ini memastikan sistem kekal andal dan berdaya tahan walaupun semasa cegukan kecil.

Dengan menggabungkan ciri ini, kod ini memastikan sistem mengurus data pakej dengan cekap sambil mengekalkan komunikasi yang lancar dan boleh dipercayai dengan API pembekal.

// Domain Models
@Getter @Setter
@Entity
public class Package {
    @Id
    private String id;
    private String name;
    private BigDecimal price;
    private BigDecimal providerCost;
    private String description;
    private boolean active;
}

@Getter @Setter
@Entity
public class Order {
    @Id
    private String id;
    private String customerId;
    private String packageId;
    private String reservationId;
    private String paymentId;
    private String escrowId;
    private OrderStatus status;
    private BigDecimal amount;
    private BigDecimal providerCost;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

@Getter @Setter
@Entity
public class QuotaReservation {
    @Id
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

// Enums
public enum OrderStatus {
    CREATED, RESERVED, PAYMENT_PENDING, PAYMENT_COMPLETED, 
    IN_ESCROW, ACTIVATING, ACTIVATION_FAILED, COMPLETED, REFUNDED
}

public enum ReservationStatus {
    ACTIVE, EXPIRED, USED, CANCELLED
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Integrasi Gerbang Pembayaran

Kelas ini memainkan peranan penting dalam mengurus cara sistem berinteraksi dengan gerbang pembayaran untuk mengendalikan transaksi kewangan dengan lancar dan selamat.

1. initializePayment(Permintaan PaymentRequest):
  • Anggap ini sebagai permulaan proses pembayaran. Ia menghantar permintaan ke gerbang pembayaran dengan semua butiran pembayaran.
  • Ia mengembalikan objek PaymentSession, yang merangkumi maklumat seperti URL pembayaran dan status sesi.
2. holdInEscrow(String paymentId):
  • Kaedah ini menjamin pembayaran dalam akaun escrow menggunakan ID pembayaran yang diberikan.
  • Ia menyediakan objek EscrowResponse yang mengandungi semua butiran tentang dana yang disimpan.
3. releaseToProvider(String escrowId):
  • Selepas perkhidmatan berjaya diaktifkan, kaedah ini melepaskan dana daripada escrow kepada pembekal perkhidmatan.
  • ID escrow digunakan untuk mengenal pasti dan mengeluarkan dana yang betul.
4. refundToCustomer(String escrowId):
  • Jika berlaku masalah—seperti pengaktifan perkhidmatan gagal, kaedah ini mengembalikan dana yang disimpan kembali kepada pelanggan.
  • Ia menggunakan ID escrow untuk memproses bayaran balik.
Ciri-ciri Utama:
  • Kelas menggunakan WebClient untuk menghantar permintaan HTTP ke REST API get laluan pembayaran, memastikan penyepaduan yang lancar.
  • Ia mengendalikan operasi kritikal seperti memulakan pembayaran, mengurus eskrow dan memproses bayaran balik.
  • Semua kaedah menggunakan panggilan segerak (melalui .block()) untuk memastikan operasi selesai sebelum meneruskan, memastikan kebolehpercayaan.

Kelas ini merupakan bahagian penting dalam teka-teki dalam hal mengurus urus niaga kewangan yang selamat dan cekap dalam sistem.

// Domain Models
@Getter @Setter
@Entity
public class Package {
    @Id
    private String id;
    private String name;
    private BigDecimal price;
    private BigDecimal providerCost;
    private String description;
    private boolean active;
}

@Getter @Setter
@Entity
public class Order {
    @Id
    private String id;
    private String customerId;
    private String packageId;
    private String reservationId;
    private String paymentId;
    private String escrowId;
    private OrderStatus status;
    private BigDecimal amount;
    private BigDecimal providerCost;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

@Getter @Setter
@Entity
public class QuotaReservation {
    @Id
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

// Enums
public enum OrderStatus {
    CREATED, RESERVED, PAYMENT_PENDING, PAYMENT_COMPLETED, 
    IN_ESCROW, ACTIVATING, ACTIVATION_FAILED, COMPLETED, REFUNDED
}

public enum ReservationStatus {
    ACTIVE, EXPIRED, USED, CANCELLED
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
DTO Pemberitahuan
1. Pemberitahuan E-mel:
  • Anggap ini sebagai pelan tindakan untuk menghantar pemberitahuan e-mel. Ia termasuk:
    • E-mel penerima (kepada).
    • Subjek e-mel.
    • ID templat untuk menentukan format.
    • Data dinamik (templateData) untuk memperibadikan kandungan.
2. SmsNotification:
  • Serupa dengan pemberitahuan e-mel tetapi disesuaikan untuk SMS. Ia termasuk:
    • Nombor telefon penerima (Nombor telefon).
    • ID templat untuk format mesej.
    • Data dinamik (templateData) untuk pemperibadian.
Perkhidmatan Pemberitahuan

Perkhidmatan ini mengendalikan semua pemberitahuan yang dihantar kepada pengguna tentang status pesanan mereka. Begini caranya:

1. sendSuccessNotification(Pesanan pesanan):
  • Kaedah ini mengendalikan penghantaran pemberitahuan kejayaan. Ia menggunakan:
    • buildSuccessEmail untuk membuat pemberitahuan e-mel.
    • buildSuccessSms untuk membuat pemberitahuan SMS.
    • Ia juga menghantar kemas kini masa nyata melalui WebSocket menggunakan QuotaWebSocketHandler.
2. sendFailureNotification(Pesanan pesanan):
  • Yang ini menjaga pemberitahuan kegagalan. Ia menggunakan:
    • buildFailureEmail untuk mesej e-mel.
    • buildFailureSms untuk mesej SMS.
    • Seperti pemberitahuan kejayaan, ia juga menghantar kemas kini WebSocket.
3. Kaedah Pembantu:
  • buildSuccessEmail dan buildFailureEmail: Kaedah ini mencipta pemberitahuan e-mel berdasarkan sama ada pesanan itu berjaya atau gagal. Mereka menggunakan templat dan butiran pesanan.
  • buildSuccessSms dan buildFailureSms: Ini melakukan perkara yang sama tetapi untuk pemberitahuan SMS.
Ciri-ciri tambahan:
  • Kemas Kini WebSocket: Memastikan bahagian hadapan dikemas kini dalam masa nyata menggunakan QuotaWebSocketHandler.
  • Ralat Pengelogan: Jika berlaku kesilapan, ia merekodkan ralat untuk nyahpepijat.

Perkhidmatan ini memastikan pengguna sentiasa mengetahui tentang pesanan mereka, sama ada melalui e-mel, SMS atau kemas kini masa nyata.

// Domain Models
@Getter @Setter
@Entity
public class Package {
    @Id
    private String id;
    private String name;
    private BigDecimal price;
    private BigDecimal providerCost;
    private String description;
    private boolean active;
}

@Getter @Setter
@Entity
public class Order {
    @Id
    private String id;
    private String customerId;
    private String packageId;
    private String reservationId;
    private String paymentId;
    private String escrowId;
    private OrderStatus status;
    private BigDecimal amount;
    private BigDecimal providerCost;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

@Getter @Setter
@Entity
public class QuotaReservation {
    @Id
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

// Enums
public enum OrderStatus {
    CREATED, RESERVED, PAYMENT_PENDING, PAYMENT_COMPLETED, 
    IN_ESCROW, ACTIVATING, ACTIVATION_FAILED, COMPLETED, REFUNDED
}

public enum ReservationStatus {
    ACTIVE, EXPIRED, USED, CANCELLED
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Kelas Kemas Kini Kuota
  • Fikirkan kelas ini sebagai penghantar ringkas untuk kemas kini kuota. Ia membawa tiga maklumat penting:
    • packageId: ID pakej yang sedang dikemas kini.
    • availableQuota: Berapakah baki kuota untuk pakej ini.
    • cap masa: Apabila kemas kini dibuat.
Konfigurasi WebSocket
1. WebSocketConfig:
  • Ini ialah persediaan yang membolehkan komunikasi WebSocket.
  • Ia mendaftarkan pengendali (quotaWebSocketHandler) untuk mendengar sambungan WebSocket di /ws/quota.
  • Ia juga membenarkan sambungan dari mana-mana asal dengan menetapkan dibenarkanOrigins("*").
2. kuotaWebSocketHandler():
  • Ini mentakrifkan kacang pengendali WebSocket yang akan mengurus mesej dan sambungan masuk.
QuotaWebSocketHandler

Di sinilah semua keajaiban WebSocket berlaku! Ia menguruskan kemas kini masa nyata antara pelayan dan pelanggan.

1. Medan:
  • PackageCacheService: Membantu mengemas kini cache setempat apabila kemas kini kuota masuk.
  • ObjectMapper: Mengendalikan penukaran muatan JSON kepada objek Java dan begitu juga sebaliknya.
  • sesi: Menjejaki semua sesi WebSocket yang aktif (pelanggan disambungkan pada masa ini).
2. Kaedah:
  • afterConnectionEstablished(WebSocketSession session):
    • Menambahkan sesi pelanggan baharu pada senarai aktif sebaik sahaja mereka bersambung.
  • afterConnectionClosed(WebSocketSession session, status CloseStatus):
    • Mengalih keluar sesi pelanggan apabila mereka memutuskan sambungan.
  • handleTextMessage(WebSocketSession session, TextMessage message):
    • Memproses mesej masuk.
    • Menukar JSON yang diterima menjadi objek QuotaUpdate dan mengemas kini cache setempat.
3. sendOrderUpdate(Pesanan pesanan):
  • Menghantar kemas kini masa nyata tentang perubahan pesanan kepada semua pelanggan yang berkaitan.
  • Menukar objek Pesanan kepada JSON dan menghantarnya sebagai mesej kepada sesi WebSocket aktif.
  • Pastikan hanya sambungan terbuka menerima kemas kini.
Ciri-ciri Utama Kod:
  • Kemas Kini Masa Nyata:
    • Memastikan pelanggan dimaklumkan serta-merta tentang perubahan kuota dan kemas kini pesanan.
  • Pengurusan Selamat Benang:
    • Menggunakan ConcurrentHashSet untuk mengendalikan pelanggan yang disambungkan, memastikan tiada konflik apabila berbilang pelanggan aktif.
  • Pengendalian Ralat:
    • Merakam ralat apabila terdapat isu menghantar mesej, menjadikannya lebih mudah untuk menyelesaikan masalah.

Persediaan ini memastikan komunikasi lancar dan segera antara bahagian belakang dan bahagian hadapan, jadi pengguna sentiasa mempunyai maklumat terkini tentang ketersediaan kuota dan status pesanan.

// Domain Models
@Getter @Setter
@Entity
public class Package {
    @Id
    private String id;
    private String name;
    private BigDecimal price;
    private BigDecimal providerCost;
    private String description;
    private boolean active;
}

@Getter @Setter
@Entity
public class Order {
    @Id
    private String id;
    private String customerId;
    private String packageId;
    private String reservationId;
    private String paymentId;
    private String escrowId;
    private OrderStatus status;
    private BigDecimal amount;
    private BigDecimal providerCost;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

@Getter @Setter
@Entity
public class QuotaReservation {
    @Id
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

// Enums
public enum OrderStatus {
    CREATED, RESERVED, PAYMENT_PENDING, PAYMENT_COMPLETED, 
    IN_ESCROW, ACTIVATING, ACTIVATION_FAILED, COMPLETED, REFUNDED
}

public enum ReservationStatus {
    ACTIVE, EXPIRED, USED, CANCELLED
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Berikut ialah pecahan kelas pengecualian tersuai ini dan cara ia digunakan untuk mengendalikan senario ralat tertentu dalam sistem:

QuotaNotAvailableException:

  • Pengecualian ini dicetuskan apabila pengguna cuba membeli pakej, tetapi kuota untuk pakej itu sudah hilang.
  • Ia disertakan dengan mesej lalai yang jelas: "Kuota pakej tidak tersedia", jadi kedua-dua pembangun dan pengguna mendapat pemahaman yang jelas tentang isu itu.

OrderNotFoundException:

  • Yang ini bermula apabila sistem tidak dapat mencari pesanan berdasarkan orderId yang disediakan.
  • Ia termasuk mesej ralat terperinci seperti, "Pesanan tidak ditemui: [orderId]," menjadikannya mudah untuk menentukan dengan tepat pesanan yang tiada.

PaymentVerificationException:

  • Jika terdapat isu mengesahkan pembayaran—mungkin jumlahnya tidak sepadan atau status pembayaran tidak jelas—pengecualian ini akan dibuang.
  • Ia membolehkan anda menghantar mesej tersuai, menambahkan fleksibiliti dan konteks untuk mendiagnosis isu pembayaran.

Dengan menggunakan pengecualian ini, sistem mengendalikan ralat dengan cara yang bersih dan boleh diramal. Mereka bukan sahaja menjadikan penyahpepijatan lebih cekap untuk pembangun tetapi juga memastikan pengguna menerima maklum balas yang jelas dan boleh diambil tindakan apabila berlaku masalah.

// Request/Response DTOs
@Getter @Setter
public class OrderRequest {
    private String customerId;
    private String packageId;
    private BigDecimal amount;
}

@Getter @Setter
public class PaymentCallback {
    private String orderId;
    private String paymentId;
    private String status;
    private BigDecimal amount;
    private LocalDateTime timestamp;
}

@Getter @Setter
public class QuotaResponse {
    private String packageId;
    private boolean available;
    private Integer remainingQuota;
    private LocalDateTime timestamp;
}

@Getter @Setter
public class ReservationResponse {
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

@Getter @Setter
public class ActivationResponse {
    private String orderId;
    private boolean success;
    private String activationId;
    private String errorCode;
    private String errorMessage;
}

@Getter @Setter
public class VerificationResponse {
    private String orderId;
    private String activationId;
    private boolean success;
    private String status;
    private LocalDateTime activatedAt;
}

@Getter @Setter
public class PaymentRequest {
    private String orderId;
    private BigDecimal amount;
    private String currency;
    private String customerId;
    private String returnUrl;
    private String callbackUrl;
}

@Getter @Setter
public class PaymentSession {
    private String sessionId;
    private String paymentUrl;
    private LocalDateTime expiresAt;
    private String status;
}

@Getter @Setter
public class EscrowResponse {
    private String id;
    private String paymentId;
    private BigDecimal amount;
    private String status;
    private LocalDateTime createdAt;
}
Salin selepas log masuk
Salin selepas log masuk

Kelas OrderService mengendalikan tugasan yang berat apabila mengurus pesanan. Mari kita pecahkan cara ia berfungsi:

Tanggungjawab Utama
  1. buat Pesanan(Permintaan Pesanan):

    • Kaedah ini adalah tentang membuat pesanan baharu. Ia menyemak sama ada pakej tersedia, mengambil butiran, menyimpan kuota dan menyimpan pesanan ke pangkalan data dengan status awal TERPELIHARA.
  2. ProcessPayment(String orderId, PaymentCallback callback):

    • Di sini, pembayaran akan diuruskan. Sistem mengesahkan butiran pembayaran, mengemas kini pesanan, meletakkan pembayaran dalam eskrow dan memulakan proses pengaktifan perkhidmatan. Jika berlaku kesilapan, ia menguruskan kegagalan dengan anggun.
  3. sahkanPengaktifan(Pesanan pesanan):

    • Kaedah ini menyemak semula jika pengaktifan perkhidmatan berjalan lancar. Ia mencuba sehingga tiga kali, dan jika masih gagal, sistem akan kembali untuk menangani kegagalan.
  4. Pesanan lengkap(Pesanan pesanan):

    • Setelah semuanya disemak, kaedah ini memuktamadkan pesanan. Ia mengeluarkan dana escrow kepada pembekal, mengemas kini status dan memberitahu pengguna tentang kejayaan.
  5. mengendalikanActivationFailure(Pesanan pesanan):

    • Jika pengaktifan gagal, kaedah ini memastikan pelanggan mendapat bayaran balik dan pemberitahuan tentang masalah yang berlaku.
  6. getOrder(String orderId):

    • Kaedah mudah ini mendapatkan semula pesanan mengikut IDnya. Jika pesanan itu tidak wujud, ia memberikan pengecualian khusus.
Mengapa Ia Berfungsi
  • Ia memastikan urus niaga sama ada selesai atau ditarik balik, berkat sifat transaksinya.
  • Dengan pengendalian ralat dan percubaan semula yang jelas, ia cukup teguh untuk menangani gangguan dunia sebenar.
  • Pemberitahuan memastikan pengguna sentiasa mengikuti setiap langkah.

Perkhidmatan ini adalah tulang belakang proses pengurusan pesanan, menggabungkan segala-galanya untuk pengalaman pengguna yang lancar.

// Domain Models
@Getter @Setter
@Entity
public class Package {
    @Id
    private String id;
    private String name;
    private BigDecimal price;
    private BigDecimal providerCost;
    private String description;
    private boolean active;
}

@Getter @Setter
@Entity
public class Order {
    @Id
    private String id;
    private String customerId;
    private String packageId;
    private String reservationId;
    private String paymentId;
    private String escrowId;
    private OrderStatus status;
    private BigDecimal amount;
    private BigDecimal providerCost;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

@Getter @Setter
@Entity
public class QuotaReservation {
    @Id
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

// Enums
public enum OrderStatus {
    CREATED, RESERVED, PAYMENT_PENDING, PAYMENT_COMPLETED, 
    IN_ESCROW, ACTIVATING, ACTIVATION_FAILED, COMPLETED, REFUNDED
}

public enum ReservationStatus {
    ACTIVE, EXPIRED, USED, CANCELLED
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kelas OrderController menjaga titik akhir REST API yang mengurus pesanan dalam sistem. Fikirkan adalah jambatan antara pelanggan yang membuat permintaan dan perkhidmatan bahagian belakang yang melakukan tugas berat.

Titik Akhir Utama
  1. POST /api/orders (createOrder):

    • Titik akhir ini mengendalikan pembuatan pesanan baharu.
    • Inilah yang berlaku:
      • Permintaan Pesanan daripada pelanggan.
      • Panggil OrderService.createOrder untuk memproses permintaan dan membuat pesanan.
      • Menghantar kembali:
        • Sambutan 200 OK dengan pesanan yang baru dibuat jika semuanya berjalan lancar.
        • A 409 Konflik jika kuota pakej tidak tersedia.
        • Ralat Pelayan Dalaman 500 untuk sebarang isu yang tidak dijangka.
  2. POST /api/orders/callback (handlePaymentCallback):

    • Yang ini memproses kemas kini pembayaran yang dihantar oleh gerbang pembayaran.
    • Berikut adalah alirannya:
      • Ia menerima PaymentCallback dengan semua butiran pembayaran.
      • Panggil OrderService.processPayment untuk mengendalikan pembayaran dan mengemas kini status pesanan.
      • Tindak balas yang mungkin adalah:
        • 200 OK jika pembayaran berjaya dikendalikan.
        • 404 Tidak Ditemui jika ID pesanan yang diberikan tidak wujud.
        • 422 Entiti Tidak Boleh Diproses jika terdapat ketidakpadanan dalam pengesahan pembayaran.
        • 500 Ralat Pelayan Dalaman untuk apa-apa yang tidak dijangka.
  3. DAPATKAN /api/orders/{orderId} (getOrder):

    • Titik akhir ini mengambil butiran pesanan tertentu mengikut IDnya.
    • Begini cara ia berfungsi:
      • Ia memanggil OrderService.getOrder untuk mendapatkan semula pesanan.
      • Pemulangan:
        • Respons OK 200 dengan butiran pesanan jika ditemui.
        • A 404 Tidak Ditemui jika ID pesanan tidak sepadan dengan mana-mana rekod.
Ciri-ciri
  • Pemisahan Kebimbangan: OrderController mewakilkan semua logik perniagaan kepada OrderService, memastikan keadaan bersih dan fokus.
  • Pengesahan: Muatan permintaan disahkan menggunakan anotasi @Valid untuk memastikan data yang masuk memenuhi jangkaan.
  • Pengendalian Ralat:
    • Menyediakan respons khusus dan membantu untuk isu biasa, seperti kuota yang tidak tersedia atau pesanan yang tiada.
    • Merakam sebarang isu untuk memudahkan penyahpepijatan.
  • Pengelogan: Menjejaki peristiwa penting seperti permintaan masuk, ralat dan butiran pesanan untuk keterlihatan yang lebih baik.

Pengawal ini memastikan pelanggan dan bahagian belakang berkomunikasi dengan lancar, menjadikan pengurusan pesanan selancar mungkin.

Kesimpulan

Dokumentasi penyelidikan ini meletakkan asas untuk mereka bentuk sistem jualan kredit e-dagang, menangani cabaran penting seperti pengurusan kuota, pemprosesan pembayaran dan pengaktifan perkhidmatan. Walaupun reka bentuk ini merangkumi perkara asas, sentiasa ada ruang untuk menjadikan perkara lebih baik!

Berikut ialah beberapa idea untuk menambah baik reka bentuk ini:

  • Gunakan seni bina dipacu peristiwa untuk menjadikan sistem lebih fleksibel dan berskala.
  • Tambah pemprosesan berasaskan baris gilir mesej untuk mengendalikan banyak transaksi dengan lancar.
  • Teroka strategi caching lanjutan untuk mempercepatkan dan mengurangkan pergantungan pada API luaran.
  • Pertimbangkan corak sistem yang diedarkan untuk penskalaan yang lebih mudah dan kebolehpercayaan yang lebih baik.
  • Laksanakan pemutus litar untuk menangani gangguan perkhidmatan pihak ketiga dengan baik.
  • Sediakan pemantauan dan makluman untuk mengetahui isu lebih awal dan membetulkannya dengan cepat.
  • Kuatkan langkah keselamatan untuk melindungi pengguna dan data mereka.

Terima kasih banyak kerana membaca! Saya harap dokumentasi ini berguna dan memberikan kejelasan kepada sesiapa sahaja yang meneroka cabaran yang serupa. Sudah tentu, reka bentuk ini tidak sempurna-sentiasa ada ruang untuk penambahbaikan. Jika anda mempunyai sebarang pendapat atau cadangan, saya ingin mendengarnya.

sumber:

  • Menyelami Seni Bina Bersih dan Prinsip PADAT
  • Reka Bentuk Aplikasi E-Dagang dengan Seni Bina Microservices
  • Mereka bentuk Bahagian Belakang Boleh Skala untuk Jualan Flash
  • Escrow di Wikipedia

Atas ialah kandungan terperinci Merekabentuk Sistem Pembelian Kredit Internet. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan