优化乐刷通知与钱包充值流程
This commit is contained in:
@@ -110,8 +110,18 @@ func (h *Handler) LeshuaNotify(c *gin.Context) {
|
||||
c.String(http.StatusBadRequest, "FAIL")
|
||||
return
|
||||
}
|
||||
log.Printf("[payment] leshua notify received third_order_id=%s leshua_order_id=%s status=%s amount=%s", params["third_order_id"], params["leshua_order_id"], params["status"], params["amount"])
|
||||
result, err := h.service.HandleLeshuaNotify(params)
|
||||
rawPayload := string(body)
|
||||
contentType := c.GetHeader("Content-Type")
|
||||
log.Printf(
|
||||
"[payment] leshua notify received third_order_id=%s leshua_order_id=%s status=%s amount=%s content_type=%s raw_payload=%s",
|
||||
params["third_order_id"],
|
||||
params["leshua_order_id"],
|
||||
params["status"],
|
||||
params["amount"],
|
||||
contentType,
|
||||
rawPayload,
|
||||
)
|
||||
result, err := h.service.HandleLeshuaNotify(params, rawPayload, contentType)
|
||||
if err != nil || result == nil || !result.OK {
|
||||
log.Printf("[payment] leshua notify failed third_order_id=%s err=%v", params["third_order_id"], err)
|
||||
c.String(http.StatusOK, "FAIL")
|
||||
|
||||
@@ -125,7 +125,7 @@ func (r *Repository) Start(userID uint64, orderID uint64, req StartPaymentReques
|
||||
|
||||
func (r *Repository) StartWalletRecharge(userID uint64, req WalletRechargePaymentRequest, clientIP string) (*PaymentDTO, error) {
|
||||
amountCent := moneyCent(req.Amount)
|
||||
if userID == 0 || amountCent <= 0 {
|
||||
if userID == 0 || req.Amount < MinWalletRechargeAmount || amountCent <= 0 {
|
||||
return nil, ErrPaymentCannotStart
|
||||
}
|
||||
payment, err := r.createWalletRechargePayment(userID, amountCent, req)
|
||||
@@ -241,17 +241,22 @@ func (r *Repository) Query(userID uint64, orderID uint64) (*PaymentDTO, error) {
|
||||
return &dto, nil
|
||||
}
|
||||
|
||||
func (r *Repository) HandleLeshuaNotify(params map[string]string) (*NotifyResult, error) {
|
||||
func (r *Repository) HandleLeshuaNotify(params map[string]string, rawPayload string, contentType string) (*NotifyResult, error) {
|
||||
var verify leshua.VerifyNotifyResult
|
||||
if !r.isMockMode {
|
||||
verify := r.leshua.VerifyNotifyDetail(params)
|
||||
verify = r.leshua.VerifyNotifyDetail(params)
|
||||
if !verify.OK {
|
||||
log.Printf(
|
||||
"[payment] leshua notify verify failed third_order_id=%s got=%s expected=%v keys=%v",
|
||||
"[payment] leshua notify verify failed third_order_id=%s got=%s expected=%s keys=%v base_string=%s",
|
||||
params["third_order_id"],
|
||||
shortSign(verify.Got),
|
||||
shortExpectedSigns(verify.Expected),
|
||||
verify.Got,
|
||||
verify.Expected["notify_key"],
|
||||
verify.ParamKeys,
|
||||
verify.BaseString["notify_key"],
|
||||
)
|
||||
if err := r.recordNotifyDiagnostic(params, rawPayload, contentType, verify, "verify_failed"); err != nil {
|
||||
log.Printf("[payment] leshua notify diagnostic save failed third_order_id=%s err=%v", params["third_order_id"], err)
|
||||
}
|
||||
return nil, ErrPaymentVerifyFailed
|
||||
}
|
||||
log.Printf("[payment] leshua notify verified third_order_id=%s matched_key=%s", params["third_order_id"], verify.MatchedKey)
|
||||
@@ -268,9 +273,13 @@ func (r *Repository) HandleLeshuaNotify(params map[string]string) (*NotifyResult
|
||||
return nil, err
|
||||
}
|
||||
if amount := parseCent(params["amount"]); amount > 0 && amount != payment.AmountCent {
|
||||
if err := r.recordNotifyDiagnostic(params, rawPayload, contentType, verify, "amount_mismatch"); err != nil {
|
||||
log.Printf("[payment] leshua notify diagnostic save failed third_order_id=%s err=%v", params["third_order_id"], err)
|
||||
}
|
||||
return nil, ErrPaymentVerifyFailed
|
||||
}
|
||||
if err := r.applyChannelStatus(&payment, params["status"], params["pay_time"], params, channelSourceNotify); err != nil {
|
||||
raw := withNotifyDiagnostic(params, rawPayload, contentType, verify, "verified")
|
||||
if err := r.applyChannelStatus(&payment, params["status"], params["pay_time"], raw, channelSourceNotify); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &NotifyResult{OK: true, Message: "000000"}, nil
|
||||
@@ -531,6 +540,40 @@ func withRawSource(raw map[string]string, source string) map[string]string {
|
||||
return out
|
||||
}
|
||||
|
||||
func (r *Repository) recordNotifyDiagnostic(params map[string]string, rawPayload string, contentType string, verify leshua.VerifyNotifyResult, status string) error {
|
||||
thirdOrderID := params["third_order_id"]
|
||||
if thirdOrderID == "" {
|
||||
return nil
|
||||
}
|
||||
raw := withNotifyDiagnostic(params, rawPayload, contentType, verify, status)
|
||||
return r.db.Model(&model.PaymentOrder{}).
|
||||
Where("third_order_id = ?", thirdOrderID).
|
||||
Update("raw_response", jsonMap(raw)).Error
|
||||
}
|
||||
|
||||
func withNotifyDiagnostic(params map[string]string, rawPayload string, contentType string, verify leshua.VerifyNotifyResult, status string) map[string]string {
|
||||
raw := withRawSource(params, channelSourceNotify)
|
||||
raw["_notify_diagnostic_status"] = status
|
||||
raw["_raw_payload"] = rawPayload
|
||||
raw["_raw_content_type"] = contentType
|
||||
raw["_sign_got"] = verify.Got
|
||||
raw["_sign_matched_key"] = verify.MatchedKey
|
||||
raw["_sign_expected"] = jsonString(verify.Expected)
|
||||
raw["_sign_base_strings"] = jsonString(verify.BaseString)
|
||||
return raw
|
||||
}
|
||||
|
||||
func jsonString(value map[string]string) string {
|
||||
if len(value) == 0 {
|
||||
return "{}"
|
||||
}
|
||||
raw, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return "{}"
|
||||
}
|
||||
return string(raw)
|
||||
}
|
||||
|
||||
func newPaymentNo() (string, error) {
|
||||
buf := make([]byte, 4)
|
||||
if _, err := rand.Read(buf); err != nil {
|
||||
@@ -547,21 +590,3 @@ func firstNonEmpty(values ...string) string {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func shortExpectedSigns(values map[string]string) map[string]string {
|
||||
out := map[string]string{}
|
||||
for key, value := range values {
|
||||
out[key] = shortSign(value)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func shortSign(value string) string {
|
||||
if value == "" {
|
||||
return ""
|
||||
}
|
||||
if len(value) <= 12 {
|
||||
return value
|
||||
}
|
||||
return value[:12] + "..."
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ var (
|
||||
ErrPaymentNotFound = errors.New("payment not found")
|
||||
)
|
||||
|
||||
const MinWalletRechargeAmount = 0.01
|
||||
|
||||
type Service struct {
|
||||
repo *Repository
|
||||
}
|
||||
@@ -42,7 +44,7 @@ func (s *Service) StartWalletRecharge(userID uint64, req WalletRechargePaymentRe
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
if userID == 0 || req.Amount <= 0 {
|
||||
if userID == 0 || req.Amount < MinWalletRechargeAmount {
|
||||
return nil, ErrPaymentCannotStart
|
||||
}
|
||||
return s.repo.StartWalletRecharge(userID, req, clientIP)
|
||||
@@ -58,9 +60,9 @@ func (s *Service) QueryWalletRecharge(userID uint64, paymentID uint64) (*Payment
|
||||
return s.repo.QueryWalletRecharge(userID, paymentID)
|
||||
}
|
||||
|
||||
func (s *Service) HandleLeshuaNotify(params map[string]string) (*NotifyResult, error) {
|
||||
func (s *Service) HandleLeshuaNotify(params map[string]string, rawPayload string, contentType string) (*NotifyResult, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.HandleLeshuaNotify(params)
|
||||
return s.repo.HandleLeshuaNotify(params, rawPayload, contentType)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user