aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2023-01-31 21:24:45 +0700
committerShulhan <ms@kilabit.info>2023-02-01 11:02:09 +0700
commitb4b6699c27b04893c73c50553070682799220080 (patch)
tree2579635e56702449a6427ac0a8586524e2adf3b6
parentd8b4bd20f3755a1f323c3a563167f240cdb11e23 (diff)
downloadduitku-b4b6699c27b04893c73c50553070682799220080.tar.xz
all: split the merchant into DefaultMerchant and PaymentMerchant
The PaymentMerchant will be used if the payment method during inquiry exist as the key in it; otherwise it will use DefaultMerchant
-rw-r--r--client_options.go61
-rw-r--r--client_options_test.go56
-rw-r--r--merchant.go27
-rw-r--r--payment_method.go6
-rw-r--r--testdata/client_options_test.txt39
5 files changed, 162 insertions, 27 deletions
diff --git a/client_options.go b/client_options.go
index b365ac0..fa6ad1c 100644
--- a/client_options.go
+++ b/client_options.go
@@ -18,30 +18,12 @@ type ClientOptions struct {
// The hostname extracted from ServerUrl.
host string
- // The merchant code is the project code obtained from the Duitku
- // merchant page.
- // This code is useful as an identifier of your project in each
- // request using the /merchant/* APIs.
- // You can get this code on every project you register on the
- // [merchant portal].
- //
- // [merchant portal]: https://passport.duitku.com/merchant/Project
- MerchantCode string `ini:"duitku::merchant_code"`
+ // DefaultMerchant default merchant to be used for payment.
+ DefaultMerchant Merchant `ini:"default-merchant"`
- // MerchantApiKey The API key for signing merchant related request.
- MerchantApiKey string `ini:"duitku::merchant_api_key"`
-
- // MerchantCallbackUrl The URL that will be used by Duitku to
- // confirm payments made by your customers.
- MerchantCallbackUrl string `ini:"duitku::merchant_callback_url"`
-
- // MerchantReturnUrl The URL that Duitku will direct the customer
- // after the transaction is successful or canceled.
- MerchantReturnUrl string `ini:"duitku::merchant_return_url"`
-
- // Merchant code and API key for payment through Indomaret.
- IndomaretMerchantCode string `ini:"duitku::indomaret_merchant_code"`
- IndomaretApiKey string `ini:"duitku::indomaret_api_key"`
+ // PaymentMerchant specific merchant to be used based on payment
+ // method.
+ PaymentMerchant map[string]Merchant `ini:"merchant"`
// DisburseApiKey API key for signing disbursement request.
DisburseApiKey string `ini:"duitku::disburse_api_key"`
@@ -74,8 +56,23 @@ func LoadClientOptions(file string) (opts *ClientOptions, err error) {
return opts, nil
}
-// validate each field values.
-func (opts *ClientOptions) validate() (err error) {
+// Merchant return the PaymentMerchant based on paymentMethod.
+// If no key found, it will return DefaultMerchant.
+func (opts *ClientOptions) Merchant(paymentMethod string) (merchant Merchant) {
+ var (
+ found bool
+ )
+
+ merchant, found = opts.PaymentMerchant[paymentMethod]
+ if !found {
+ merchant = opts.DefaultMerchant
+ }
+
+ return merchant
+}
+
+// initAndValidate each field values.
+func (opts *ClientOptions) initAndValidate() (err error) {
var (
urlServer *url.URL
)
@@ -96,5 +93,19 @@ func (opts *ClientOptions) validate() (err error) {
return fmt.Errorf(`invalid or empty DisburseApiKey: %s`, opts.DisburseApiKey)
}
+ var (
+ method string
+ merchant Merchant
+ )
+ for method, merchant = range opts.PaymentMerchant {
+ if len(merchant.CallbackUrl) == 0 {
+ merchant.CallbackUrl = opts.DefaultMerchant.CallbackUrl
+ }
+ if len(merchant.ReturnUrl) == 0 {
+ merchant.ReturnUrl = opts.DefaultMerchant.ReturnUrl
+ }
+ opts.PaymentMerchant[method] = merchant
+ }
+
return nil
}
diff --git a/client_options_test.go b/client_options_test.go
new file mode 100644
index 0000000..0d865f3
--- /dev/null
+++ b/client_options_test.go
@@ -0,0 +1,56 @@
+// SPDX-FileCopyrightText: 2023 M. Shulhan <ms@kilabit.info>
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package duitku
+
+import (
+ "encoding/json"
+ "testing"
+
+ "github.com/shuLhan/share/lib/ini"
+ "github.com/shuLhan/share/lib/test"
+)
+
+func TestLoadClientOptions(t *testing.T) {
+ var (
+ tdata *test.Data
+ err error
+ )
+
+ tdata, err = test.LoadData(`testdata/client_options_test.txt`)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ var (
+ opts ClientOptions
+ tag string
+ data []byte
+ )
+
+ data = tdata.Input[`all.conf`]
+
+ err = ini.Unmarshal(data, &opts)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = opts.initAndValidate()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ var (
+ exp []byte
+ got []byte
+ )
+
+ got, err = json.MarshalIndent(&opts, ``, ` `)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ tag = `all.json`
+ exp = tdata.Output[tag]
+ test.Assert(t, tag, string(exp), string(got))
+}
diff --git a/merchant.go b/merchant.go
new file mode 100644
index 0000000..7d7d2c5
--- /dev/null
+++ b/merchant.go
@@ -0,0 +1,27 @@
+// SPDX-FileCopyrightText: 2023 M. Shulhan <ms@kilabit.info>
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package duitku
+
+type Merchant struct {
+ // The merchant code is the project code obtained from the Duitku
+ // merchant page.
+ // This code is useful as an identifier of your project in each
+ // request using the /merchant/* APIs.
+ // You can get this code on every project you register on the
+ // [merchant portal].
+ //
+ // [merchant portal]: https://passport.duitku.com/merchant/Project
+ Code string `ini:"::code"`
+
+ // The API key for signing merchant request.
+ ApiKey string `ini:"::api_key"`
+
+ // The URL that will be used by Duitku to confirm payments made by
+ // your customers.
+ CallbackUrl string `ini:"::callback_url"`
+
+ // The URL that Duitku will direct the customer after the transaction
+ // is successful or canceled.
+ ReturnUrl string `ini:"::return_url"`
+}
diff --git a/payment_method.go b/payment_method.go
index b5e95fa..9dffcda 100644
--- a/payment_method.go
+++ b/payment_method.go
@@ -45,19 +45,21 @@ func (req *PaymentMethod) SetDateTime(t time.Time) {
// Signature.
func (req *PaymentMethod) Sign(opts ClientOptions) {
var (
+ merchant = opts.DefaultMerchant
+
plain string
hash [sha256.Size]byte
)
if len(req.MerchantCode) == 0 {
- req.MerchantCode = opts.MerchantCode
+ req.MerchantCode = merchant.Code
}
if len(req.DateTime) == 0 {
req.SetDateTime(time.Now())
}
- plain = fmt.Sprintf(`%s%d%s%s`, req.MerchantCode, req.Amount, req.DateTime, opts.MerchantApiKey)
+ plain = fmt.Sprintf(`%s%d%s%s`, req.MerchantCode, req.Amount, req.DateTime, merchant.ApiKey)
hash = sha256.Sum256([]byte(plain))
req.Signature = hex.EncodeToString(hash[:])
diff --git a/testdata/client_options_test.txt b/testdata/client_options_test.txt
new file mode 100644
index 0000000..5d4d34e
--- /dev/null
+++ b/testdata/client_options_test.txt
@@ -0,0 +1,39 @@
+>>> all.conf
+[duitku]
+server_url = https://sandbox.duitku.com
+disburse_user_id = 1111
+disburse_email = my@company.com
+disburse_api_key = abcd
+
+[default-merchant]
+code = DXXXX
+api_key = d3f4ult
+callback_url = https://example.com/callback
+return_url = https://example.com/payment
+
+## Payment using Indomaret use this merchant.
+[merchant "IR"]
+code = DYYYY
+api_key = 1ndom4r3t
+
+<<< all.json
+{
+ "ServerUrl": "https://sandbox.duitku.com",
+ "DefaultMerchant": {
+ "Code": "DXXXX",
+ "ApiKey": "d3f4ult",
+ "CallbackUrl": "https://example.com/callback",
+ "ReturnUrl": "https://example.com/payment"
+ },
+ "PaymentMerchant": {
+ "IR": {
+ "Code": "DYYYY",
+ "ApiKey": "1ndom4r3t",
+ "CallbackUrl": "https://example.com/callback",
+ "ReturnUrl": "https://example.com/payment"
+ }
+ },
+ "DisburseApiKey": "abcd",
+ "DisburseEmail": "my@company.com",
+ "DisburseUserID": 1111
+}