Mhamdans17 commited on
Commit ·
da65302
1
Parent(s): 1328d27
feat: add QRIS topup endpoint and handle webhook for topup
Browse files- controllers/order_controller.go +53 -0
- controllers/wallet_controller.go +70 -0
- main.go +1 -0
controllers/order_controller.go
CHANGED
|
@@ -660,6 +660,59 @@ func TripayWebhook(c *gin.Context) {
|
|
| 660 |
}
|
| 661 |
}()
|
| 662 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 663 |
var order models.Order
|
| 664 |
if err := tx.Preload("Items.Product").Where("order_number = ?", merchantRefStr).First(&order).Error; err != nil {
|
| 665 |
tx.Rollback()
|
|
|
|
| 660 |
}
|
| 661 |
}()
|
| 662 |
|
| 663 |
+
// Cek apakah ini Topup atau Order biasa
|
| 664 |
+
if len(merchantRefStr) > 6 && merchantRefStr[:6] == "TOPUP-" {
|
| 665 |
+
// Ini adalah Topup via Tripay
|
| 666 |
+
topupIDStr := merchantRefStr[6:]
|
| 667 |
+
|
| 668 |
+
var topup models.TopupRequest
|
| 669 |
+
if err := tx.First(&topup, topupIDStr).Error; err != nil {
|
| 670 |
+
tx.Rollback()
|
| 671 |
+
c.JSON(http.StatusNotFound, gin.H{"detail": "Request Top-up tidak ditemukan"})
|
| 672 |
+
return
|
| 673 |
+
}
|
| 674 |
+
|
| 675 |
+
if topup.Status != "pending" {
|
| 676 |
+
tx.Rollback()
|
| 677 |
+
c.JSON(http.StatusOK, gin.H{"success": true, "message": "Sudah diproses sebelumnya"})
|
| 678 |
+
return
|
| 679 |
+
}
|
| 680 |
+
|
| 681 |
+
switch tripayStatus {
|
| 682 |
+
case "PAID":
|
| 683 |
+
topup.Status = "approved"
|
| 684 |
+
tx.Save(&topup)
|
| 685 |
+
|
| 686 |
+
var company models.Company
|
| 687 |
+
tx.First(&company, topup.CompanyID)
|
| 688 |
+
|
| 689 |
+
company.WalletBalance += topup.Amount
|
| 690 |
+
tx.Save(&company)
|
| 691 |
+
|
| 692 |
+
walletTx := models.WalletTransaction{
|
| 693 |
+
CompanyID: company.ID,
|
| 694 |
+
Amount: topup.Amount,
|
| 695 |
+
Type: "topup_qris",
|
| 696 |
+
RefID: merchantRefStr,
|
| 697 |
+
Desc: "Top-up Saldo via QRIS/Tripay",
|
| 698 |
+
}
|
| 699 |
+
tx.Create(&walletTx)
|
| 700 |
+
case "EXPIRED", "FAILED":
|
| 701 |
+
topup.Status = "rejected"
|
| 702 |
+
tx.Save(&topup)
|
| 703 |
+
}
|
| 704 |
+
|
| 705 |
+
if err := tx.Commit().Error; err != nil {
|
| 706 |
+
tx.Rollback()
|
| 707 |
+
c.JSON(http.StatusInternalServerError, gin.H{"detail": "Gagal commit topup"})
|
| 708 |
+
return
|
| 709 |
+
}
|
| 710 |
+
c.JSON(http.StatusOK, gin.H{"success": true})
|
| 711 |
+
return
|
| 712 |
+
}
|
| 713 |
+
|
| 714 |
+
// === Jika bukan TOPUP, berarti Order biasa ===
|
| 715 |
+
|
| 716 |
var order models.Order
|
| 717 |
if err := tx.Preload("Items.Product").Where("order_number = ?", merchantRefStr).First(&order).Error; err != nil {
|
| 718 |
tx.Rollback()
|
controllers/wallet_controller.go
CHANGED
|
@@ -5,6 +5,8 @@ import (
|
|
| 5 |
"net/http"
|
| 6 |
"service-warungpos-go/config"
|
| 7 |
"service-warungpos-go/models"
|
|
|
|
|
|
|
| 8 |
|
| 9 |
"github.com/gin-gonic/gin"
|
| 10 |
)
|
|
@@ -66,6 +68,74 @@ func RequestTopupManual(c *gin.Context) {
|
|
| 66 |
c.JSON(http.StatusCreated, gin.H{"message": "Pengajuan top-up berhasil dibuat, menunggu persetujuan admin", "data": topup})
|
| 67 |
}
|
| 68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
// ==================== SUPER ADMIN ENDPOINTS ====================
|
| 70 |
|
| 71 |
// AdminGetPendingTopups melihat semua pengajuan topup yang menunggu
|
|
|
|
| 5 |
"net/http"
|
| 6 |
"service-warungpos-go/config"
|
| 7 |
"service-warungpos-go/models"
|
| 8 |
+
"service-warungpos-go/services"
|
| 9 |
+
"time"
|
| 10 |
|
| 11 |
"github.com/gin-gonic/gin"
|
| 12 |
)
|
|
|
|
| 68 |
c.JSON(http.StatusCreated, gin.H{"message": "Pengajuan top-up berhasil dibuat, menunggu persetujuan admin", "data": topup})
|
| 69 |
}
|
| 70 |
|
| 71 |
+
// RequestTopupQris mengajukan penambahan saldo menggunakan QRIS Tripay
|
| 72 |
+
func RequestTopupQris(c *gin.Context) {
|
| 73 |
+
userVal, _ := c.Get("user")
|
| 74 |
+
user := userVal.(*models.User)
|
| 75 |
+
|
| 76 |
+
var req TopupManualRequest
|
| 77 |
+
if err := c.ShouldBindJSON(&req); err != nil {
|
| 78 |
+
c.JSON(http.StatusBadRequest, gin.H{"detail": err.Error()})
|
| 79 |
+
return
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
// 1. Buat record TopupRequest dengan status pending
|
| 83 |
+
topup := models.TopupRequest{
|
| 84 |
+
CompanyID: *user.CompanyID,
|
| 85 |
+
Amount: req.Amount,
|
| 86 |
+
ProofURL: "QRIS TRIPAY", // Tandai bahwa ini via QRIS
|
| 87 |
+
Status: "pending",
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
if err := config.DB.Create(&topup).Error; err != nil {
|
| 91 |
+
c.JSON(http.StatusInternalServerError, gin.H{"detail": "Gagal membuat request topup"})
|
| 92 |
+
return
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
merchantRef := fmt.Sprintf("TOPUP-%d", topup.ID)
|
| 96 |
+
|
| 97 |
+
var company models.Company
|
| 98 |
+
config.DB.First(&company, *user.CompanyID)
|
| 99 |
+
|
| 100 |
+
tripayItems := []services.TripayItem{
|
| 101 |
+
{
|
| 102 |
+
SKU: "TOPUP",
|
| 103 |
+
Name: "Top-up Saldo Dompet",
|
| 104 |
+
Price: int(req.Amount),
|
| 105 |
+
Quantity: 1,
|
| 106 |
+
},
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
// 2. Request QRIS ke Tripay
|
| 110 |
+
tripayRes, err := services.CreateTripayTransaction(
|
| 111 |
+
merchantRef,
|
| 112 |
+
int(req.Amount),
|
| 113 |
+
"QRIS", // Paksa QRIS
|
| 114 |
+
user.Name,
|
| 115 |
+
user.Email,
|
| 116 |
+
user.Phone,
|
| 117 |
+
tripayItems,
|
| 118 |
+
user.CompanyID,
|
| 119 |
+
)
|
| 120 |
+
|
| 121 |
+
if err != nil {
|
| 122 |
+
// Batalkan topup request jika gagal
|
| 123 |
+
topup.Status = "rejected"
|
| 124 |
+
config.DB.Save(&topup)
|
| 125 |
+
c.JSON(http.StatusBadRequest, gin.H{"detail": fmt.Sprintf("Gagal generate QRIS Tripay: %v", err)})
|
| 126 |
+
return
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
c.JSON(http.StatusOK, gin.H{
|
| 130 |
+
"message": "Berhasil generate QRIS Top-up",
|
| 131 |
+
"topup_id": topup.ID,
|
| 132 |
+
"qr_url": tripayRes.Data.QrURL,
|
| 133 |
+
"checkout_url": tripayRes.Data.CheckoutURL,
|
| 134 |
+
"amount": tripayRes.Data.Amount,
|
| 135 |
+
"expired_time": tripayRes.Data.ExpiredTime,
|
| 136 |
+
})
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
// ==================== SUPER ADMIN ENDPOINTS ====================
|
| 140 |
|
| 141 |
// AdminGetPendingTopups melihat semua pengajuan topup yang menunggu
|
main.go
CHANGED
|
@@ -244,6 +244,7 @@ func main() {
|
|
| 244 |
{
|
| 245 |
wallet.GET("/", controllers.GetWalletDetail)
|
| 246 |
wallet.POST("/topup/manual", controllers.RequestTopupManual)
|
|
|
|
| 247 |
}
|
| 248 |
}
|
| 249 |
|
|
|
|
| 244 |
{
|
| 245 |
wallet.GET("/", controllers.GetWalletDetail)
|
| 246 |
wallet.POST("/topup/manual", controllers.RequestTopupManual)
|
| 247 |
+
wallet.POST("/topup/qris", controllers.RequestTopupQris)
|
| 248 |
}
|
| 249 |
}
|
| 250 |
|