diff --git a/gateways/paygent/paygent.go b/gateways/paygent/paygent.go index a739506..1abbd4d 100644 --- a/gateways/paygent/paygent.go +++ b/gateways/paygent/paygent.go @@ -38,7 +38,7 @@ type Config struct { CAFilePath string // this is required, if CAFileContent is blank CAFileContent string // this is required, if CAFilePath is blank - ProductionMode bool + ProductionMode bool SecurityCodeUse bool } @@ -188,7 +188,6 @@ func (paygent *Paygent) Request(telegramKind string, params gomerchant.Params) ( } response, err = client.Post(serviceURL.String(), "application/x-www-form-urlencoded", strings.NewReader(urlValues.Encode())) - if err == nil { if response.StatusCode == 200 { defer response.Body.Close() @@ -224,7 +223,6 @@ func (paygent *Paygent) Request(telegramKind string, params gomerchant.Params) ( err = errors.New("failed to process this request") } } - return results, err } } @@ -243,7 +241,6 @@ func (paygent *Paygent) Authorize(amount uint64, params gomerchant.AuthorizePara "trading_id": params.OrderID, "payment_amount": amount, "payment_class": 10, - } ) @@ -257,18 +254,18 @@ func (paygent *Paygent) Authorize(amount uint64, params gomerchant.AuthorizePara if paymentMethod := params.PaymentMethod; paymentMethod != nil { if paygent.Config.SecurityCodeUse { - requestParams["security_code_use"]=1 + requestParams["security_code_use"] = 1 } if savedCreditCard := paymentMethod.SavedCreditCard; savedCreditCard != nil { requestParams["stock_card_mode"] = 1 requestParams["customer_id"] = savedCreditCard.CustomerID requestParams["customer_card_id"] = savedCreditCard.CreditCardID - requestParams["card_conf_number"]=savedCreditCard.CVC + requestParams["card_conf_number"] = savedCreditCard.CVC } else if creditCard := paymentMethod.CreditCard; creditCard != nil { requestParams["card_number"] = creditCard.Number requestParams["card_valid_term"] = getValidTerm(creditCard) - requestParams["card_conf_number"]=creditCard.CVC + requestParams["card_conf_number"] = creditCard.CVC } else { return response, gomerchant.ErrNotSupportedPaymentMethod @@ -365,3 +362,229 @@ func (paygent *Paygent) Query(transactionID string) (gomerchant.Transaction, err transaction.Params = results.Params return transaction, err } + +func (paygent *Paygent) InquiryNotification(noticeID string) (response gomerchant.InquiryResponse, err error) { + reqParam := gomerchant.Params{} + if len(noticeID) != 0 { + reqParam["payment_notice_id"] = noticeID + } + results, err := paygent.Request("091", reqParam) + response.Params = results.Params + if paymentID, ok := getPaymentID(results); ok { + response.TransactionID = paymentID + if tradingID, ok := results.Get("trading_id"); ok { + response.TradingID = fmt.Sprint(tradingID) + } + + if paymentNoticeID, ok := results.Get("payment_notice_id"); ok { + response.PaymentNoticeID = fmt.Sprint(paymentNoticeID) + } + + if paymentInitDate, ok := results.Get("payment_init_date"); ok { + response.PaymentInitDate = fmt.Sprint(paymentInitDate) + } + + if paymentChangeDate, ok := results.Get("change_date"); ok { + response.PaymentChangeDate = fmt.Sprint(paymentChangeDate) + } + + if paymentAmount, ok := results.Get("payment_amount"); ok { + response.PaymentAmount = fmt.Sprint(paymentAmount) + } + + if basePaymentID, ok := results.Get("base_payment_id"); ok { + response.BasePaymentID = fmt.Sprint(basePaymentID) + } + + if paymentStatus, ok := results.Get("payment_status"); ok { + response.PaymentStatus = fmt.Sprint(paymentStatus) + } + } + + if successCode, ok := results.Get("success_code"); ok { + response.SuccessCode = fmt.Sprint(successCode) + } + + if successDetail, ok := results.Get("success_detail"); ok { + response.SuccessDetail = fmt.Sprint(successDetail) + } + return response, err +} + +// This is rakuten pay authorize function +// Before user confirmed on rakuten page status is 10:already applid +// After user confirmed status change to 20: Authorization OK +func (paygent *Paygent) RakutePayApplicationMessage(amount uint64, params gomerchant.ApplicationParams) (gomerchant.ApplicationResponse, error) { + var ( + requestParams = gomerchant.Params{ + "payment_amount": amount, + "merchandise_type": params.MerchandiseType, + "pc_mobile_type": params.PCMobileType, + "button_type": params.ButtonType, + "return_url": params.ReturnUrl, + "cancel_url": params.CancelUrl, + } + ) + + for i, g := range params.Goods { + requestParams[fmt.Sprintf("goods[%d]", i)] = g.Name + requestParams[fmt.Sprintf("goods_id[%d]", i)] = g.ID + requestParams[fmt.Sprintf("goods_price[%d]", i)] = g.Price + requestParams[fmt.Sprintf("goods_amount[%d]", i)] = g.Amount + } + var res gomerchant.ApplicationResponse + results, err := paygent.Request("270", requestParams) + if err == nil { + if paymentID, ok := results.Get("payment_id"); ok { + res.TransactionID = fmt.Sprint(paymentID) + } + + if tradeGenerationDate, ok := results.Get("trade_generation_date"); ok { + res.TradeGenerationDate = fmt.Sprint(tradeGenerationDate) + } + + //Rakuten pay reponse redirect_html can not be find, so here need to do more logic + redirectHTML := strings.Split(results.RawBody, "redirect_html=") + if len(redirectHTML) == 2 { + res.RedirectHTML = redirectHTML[1] + + } + return res, nil + } + return res, err +} + +// This is rakuten pay capture function +func (paygent *Paygent) RakutenPaySalesMessage(transactionID string) (gomerchant.CaptureResponse, error) { + var ( + response gomerchant.CaptureResponse + requestParams = gomerchant.Params{ + "payment_id": transactionID, + } + ) + + results, err := paygent.Request("271", requestParams) + if err == nil { + if paymentID, ok := results.Get("payment_id"); ok { + response.TransactionID = fmt.Sprint(paymentID) + } + } + response.Params = results.Params + return response, err +} + +// This is rakuten pay void function +func (paygent *Paygent) RakutenPayCancellationMessage(transactionID string) (gomerchant.VoidResponse, error) { + var ( + response gomerchant.VoidResponse + requestParams = gomerchant.Params{ + "payment_id": transactionID, + } + ) + + results, err := paygent.Request("272", requestParams) + if err == nil { + if paymentID, ok := results.Get("payment_id"); ok { + response.TransactionID = fmt.Sprint(paymentID) + } + } + response.Params = results.Params + return response, err +} + +func (paygent *Paygent) RakutenPayCorrectionMessage(transactionID string, amount uint) (gomerchant.RefundResponse, error) { + var ( + response gomerchant.RefundResponse + requestParams = gomerchant.Params{ + "payment_id": transactionID, + "payment_amount": amount, + //Because it's hard to specify every item price in our system + //Like order with discount, it's so hard to calculate every item price and need equals total amounts. + //So we set whole order as a goods to rakuten pay + //If we could fix this problem later. Should be care with `del_flg`. Please read the documentation carefully [https://theplanttokyo.atlassian.net/browse/LAX-3319] + "goods_id[0]": gomerchant.RAKUTEN_PAY_PRODUCT_ID, + "goods_price[0]": amount, + "goods_amount[0]": 1, + } + ) + + results, err := paygent.Request("273", requestParams) + if err == nil { + if paymentID, ok := results.Get("payment_id"); ok { + response.TransactionID = fmt.Sprint(paymentID) + } + } + response.Params = results.Params + return response, err +} + +// Paypay authrioze function +func (paygent *Paygent) PayPayApplicationMessage(amount uint64, params gomerchant.ApplicationParams) (gomerchant.ApplicationResponse, error) { + var ( + requestParams = gomerchant.Params{ + "payment_amount": amount, + "return_url": params.ReturnUrl, + "cancel_url": params.CancelUrl, + } + ) + var res gomerchant.ApplicationResponse + results, err := paygent.Request("420", requestParams) + if err == nil { + if paymentID, ok := results.Get("payment_id"); ok { + res.TransactionID = fmt.Sprint(paymentID) + } + + if tradeGenerationDate, ok := results.Get("trade_generation_date"); ok { + res.TradeGenerationDate = fmt.Sprint(tradeGenerationDate) + } + + //Rakuten pay reponse redirect_html can not be find, so here need to do more logic + redirectHTML := strings.Split(results.RawBody, "redirect_html=") + if len(redirectHTML) == 2 { + res.RedirectHTML = redirectHTML[1] + + } + return res, nil + } + return res, err +} + +func (paygent *Paygent) PayPaySalesMessage(transactionID string) (gomerchant.CaptureResponse, error) { + var ( + response gomerchant.CaptureResponse + requestParams = gomerchant.Params{ + "payment_id": transactionID, + } + ) + + results, err := paygent.Request("422", requestParams) + if err == nil { + if paymentID, ok := results.Get("payment_id"); ok { + response.TransactionID = fmt.Sprint(paymentID) + } + } + response.Params = results.Params + return response, err +} + +func (paygent *Paygent) PayPayCancelAndRefundMessage(transactionID string, amount uint) (gomerchant.RefundResponse, error) { + var ( + response gomerchant.RefundResponse + requestParams = gomerchant.Params{ + "payment_id": transactionID, + } + ) + + if amount > 0 { + requestParams["repayment_amount"] = amount + } + + results, err := paygent.Request("421", requestParams) + if err == nil { + if paymentID, ok := results.Get("payment_id"); ok { + response.TransactionID = fmt.Sprint(paymentID) + } + } + response.Params = results.Params + return response, err +} diff --git a/gateways/paygent/url.go b/gateways/paygent/url.go index 72eaf01..027987c 100644 --- a/gateways/paygent/url.go +++ b/gateways/paygent/url.go @@ -37,4 +37,13 @@ var TelegramServiceURLs = map[string]string{ "13": "/n/paypal/request", // ###電子マネー決済URL### "15": "/n/emoney/request", + //rakuten pay + "270": "/n/rakutenid/request", + "271": "/n/rakutenid/request", + "272": "/n/rakutenid/request", + "273": "/n/rakutenid/request", + //pay pay + "420": "/n/paypay/request", + "421": "/n/paypay/request", + "422": "/n/paypay/request", } diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..db741bc --- /dev/null +++ b/go.mod @@ -0,0 +1,16 @@ +module github.com/qor/gomerchant + +go 1.21 + +require ( + github.com/jinzhu/configor v1.2.1 + github.com/stripe/stripe-go v70.15.0+incompatible + golang.org/x/text v0.8.0 +) + +require ( + github.com/BurntSushi/toml v0.3.1 // indirect + github.com/stretchr/testify v1.8.2 // indirect + golang.org/x/net v0.8.0 // indirect + gopkg.in/yaml.v2 v2.2.2 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..42c9c6f --- /dev/null +++ b/go.sum @@ -0,0 +1,29 @@ +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/jinzhu/configor v1.2.1 h1:OKk9dsR8i6HPOCZR8BcMtcEImAFjIhbJFZNyn5GCZko= +github.com/jinzhu/configor v1.2.1/go.mod h1:nX89/MOmDba7ZX7GCyU/VIaQ2Ar2aizBl2d3JLF/rDc= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stripe/stripe-go v70.15.0+incompatible h1:hNML7M1zx8RgtepEMlxyu/FpVPrP7KZm1gPFQquJQvM= +github.com/stripe/stripe-go v70.15.0+incompatible/go.mod h1:A1dQZmO/QypXmsL0T8axYZkSN/uA/T/A64pfKdBAMiY= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/payment_gateway.go b/payment_gateway.go index ce43615..149d464 100644 --- a/payment_gateway.go +++ b/payment_gateway.go @@ -78,3 +78,44 @@ type VoidResponse struct { TransactionID string Params } + +type InquiryResponse struct { + TransactionID string + TradingID string + PaymentNoticeID string + PaymentInitDate string + PaymentChangeDate string + PaymentAmount string + BasePaymentID string + PaymentStatus string + SuccessCode string + SuccessDetail string + Params +} + +type ApplicationParams struct { + MerchandiseType uint64 + PCMobileType uint64 + ButtonType string + ReturnUrl string + CancelUrl string + Goods []Good + Params +} + +type ApplicationResponse struct { + TransactionID string + OrderCode string + TradeGenerationDate string + RedirectHTML string + Params +} + +type Good struct { + ID string + Name string + Price float64 + Amount uint64 +} + +const RAKUTEN_PAY_PRODUCT_ID = "WholeOrderAmount"