优化结构
This commit is contained in:
@@ -33,10 +33,6 @@ func (r *emailRepo) email() *config.Email {
|
||||
return config.Email
|
||||
}
|
||||
|
||||
func (r *emailRepo) Enabled() bool {
|
||||
return emailEnabled(r.email())
|
||||
}
|
||||
|
||||
func (r *emailRepo) DefaultRecipients() []string {
|
||||
config := r.email()
|
||||
if config == nil || strings.TrimSpace(config.To) == "" {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package payment
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
bizpayment "kra/internal/biz/payment"
|
||||
"strings"
|
||||
@@ -9,12 +8,11 @@ import (
|
||||
|
||||
// Adapter is the provider boundary used by the payment repository. Provider
|
||||
// SDK types stay in this package and are normalized to biz/payment results.
|
||||
type Adapter interface {
|
||||
Create(context.Context, *bizpayment.PaymentRequest, map[string]any) (*bizpayment.PaymentResult, error)
|
||||
Query(context.Context, string, map[string]any) (*bizpayment.PaymentResult, error)
|
||||
Refund(context.Context, *bizpayment.PaymentRefundRequest, map[string]any) (*bizpayment.PaymentResult, error)
|
||||
Callback(context.Context, *bizpayment.PaymentCallback, map[string]any) (*bizpayment.PaymentResult, error)
|
||||
}
|
||||
type Adapter = bizpayment.PaymentAdapter
|
||||
|
||||
type Factory struct{}
|
||||
|
||||
func NewFactory() *Factory { return &Factory{} }
|
||||
|
||||
type adapterFactory func() Adapter
|
||||
|
||||
@@ -51,3 +49,7 @@ func New(provider string) (Adapter, error) {
|
||||
}
|
||||
return factory(), nil
|
||||
}
|
||||
|
||||
func (*Factory) New(provider string) (bizpayment.PaymentAdapter, error) {
|
||||
return New(provider)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
bizpayment "kra/internal/biz/payment"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -569,21 +568,6 @@ func verifyAlipayResponse(raw []byte, method string, c map[string]any) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func alipaySignContent(v url.Values) string {
|
||||
keys := make([]string, 0, len(v))
|
||||
for key := range v {
|
||||
if key != "sign" && v.Get(key) != "" {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
}
|
||||
sort.Strings(keys)
|
||||
parts := make([]string, 0, len(keys))
|
||||
for _, key := range keys {
|
||||
parts = append(parts, key+"="+v.Get(key))
|
||||
}
|
||||
return strings.Join(parts, "&")
|
||||
}
|
||||
|
||||
func verifyAlipay(fields map[string]string, c map[string]any) error {
|
||||
if text(c, "app_id") == "" || text(c, "public_key") == "" || fields["sign"] == "" {
|
||||
return errors.New("支付宝回调验签配置或 sign 缺失")
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"kra/pkg/paymentkit"
|
||||
"kra/internal/paymentkit"
|
||||
|
||||
gopayAlipay "github.com/go-pay/gopay/alipay"
|
||||
gopayDouyin "github.com/go-pay/gopay/douyin"
|
||||
@@ -177,7 +177,7 @@ func TestWechatV2GoPayCallbackVerificationAndSandboxAmount(t *testing.T) {
|
||||
t.Errorf("read request: %v", err)
|
||||
return
|
||||
}
|
||||
requestValues, err = paymentutil.XMLValues(body)
|
||||
requestValues, err = paymentkit.XMLValues(body)
|
||||
if err != nil {
|
||||
t.Errorf("parse request: %v", err)
|
||||
return
|
||||
@@ -190,7 +190,7 @@ func TestWechatV2GoPayCallbackVerificationAndSandboxAmount(t *testing.T) {
|
||||
}
|
||||
response := map[string]string{"return_code": "SUCCESS", "return_msg": "OK", "result_code": "SUCCESS", "prepay_id": "prepay"}
|
||||
response["sign"] = wechatV2Sign(response, key, "MD5")
|
||||
_, _ = w.Write(paymentutil.XMLEncode(response))
|
||||
_, _ = w.Write(paymentkit.XMLEncode(response))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
@@ -219,7 +219,7 @@ func TestWechatV2GoPayCallbackVerificationAndSandboxAmount(t *testing.T) {
|
||||
if callbackValues["sign"] != originalSign {
|
||||
t.Fatal("verification mutated source values")
|
||||
}
|
||||
callbackBody := paymentutil.XMLEncode(callbackValues)
|
||||
callbackBody := paymentkit.XMLEncode(callbackValues)
|
||||
callbackResult, err := (&wechatV2Adapter{}).Callback(context.Background(), &bizpayment.PaymentCallback{Body: callbackBody}, map[string]any{
|
||||
"app_id": "wx-test", "merchant_id": "mch-test", "mch_key": key,
|
||||
})
|
||||
@@ -243,7 +243,7 @@ func TestWechatV2MicropayUsesGoPaySDKAndValidatesIdentities(t *testing.T) {
|
||||
t.Errorf("read request: %v", err)
|
||||
return
|
||||
}
|
||||
requestValues, err = paymentutil.XMLValues(body)
|
||||
requestValues, err = paymentkit.XMLValues(body)
|
||||
if err != nil {
|
||||
t.Errorf("parse request: %v", err)
|
||||
return
|
||||
@@ -263,7 +263,7 @@ func TestWechatV2MicropayUsesGoPaySDKAndValidatesIdentities(t *testing.T) {
|
||||
"transaction_id": "WX-TRANSACTION-1", "total_fee": "123", "cash_fee": "123", "fee_type": "CNY",
|
||||
}
|
||||
response["sign"] = wechatV2Sign(response, key, "MD5")
|
||||
_, _ = w.Write(paymentutil.XMLEncode(response))
|
||||
_, _ = w.Write(paymentkit.XMLEncode(response))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
@@ -344,7 +344,7 @@ func TestWechatV2MicropayRejectsInvalidSuccessResponse(t *testing.T) {
|
||||
}
|
||||
tc.mutate(response)
|
||||
response["sign"] = wechatV2Sign(response, key, "MD5")
|
||||
_, _ = w.Write(paymentutil.XMLEncode(response))
|
||||
_, _ = w.Write(paymentkit.XMLEncode(response))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
|
||||
@@ -6,10 +6,39 @@ import (
|
||||
"encoding/base64"
|
||||
bizpayment "kra/internal/biz/payment"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
gopayWechat "github.com/go-pay/gopay/wechat"
|
||||
gopayWechatV3 "github.com/go-pay/gopay/wechat/v3"
|
||||
)
|
||||
|
||||
func wechatV2Sign(values map[string]string, key, signType string) string {
|
||||
body := toGoPayBodyMap(values)
|
||||
body.Remove("sign")
|
||||
return gopayWechat.GetReleaseSign(key, wechatV2SignType(signType), body)
|
||||
}
|
||||
|
||||
func decryptWechatV3(ciphertext, nonce, associatedData, key string) ([]byte, error) {
|
||||
return gopayWechatV3.V3DecryptNotifyCipherTextToBytes(ciphertext, nonce, associatedData, key)
|
||||
}
|
||||
|
||||
func alipaySignContent(values url.Values) string {
|
||||
keys := make([]string, 0, len(values))
|
||||
for key := range values {
|
||||
if key != "sign" && values.Get(key) != "" {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
}
|
||||
sort.Strings(keys)
|
||||
parts := make([]string, 0, len(keys))
|
||||
for _, key := range keys {
|
||||
parts = append(parts, key+"="+values.Get(key))
|
||||
}
|
||||
return strings.Join(parts, "&")
|
||||
}
|
||||
|
||||
func TestWechatV2SignOfficialStyle(t *testing.T) {
|
||||
values := map[string]string{
|
||||
"appid": "wxd930ea5d5a258f4f", "mch_id": "10000100", "device_info": "1000",
|
||||
|
||||
@@ -385,11 +385,6 @@ func paypalOrderResult(order *paypal.OrderDetail, queryID, fallbackTradeNo strin
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func paypalOrderTradeNo(order *paypal.OrderDetail) string {
|
||||
tradeNo, _ := paypalOrderIdentity(order)
|
||||
return tradeNo
|
||||
}
|
||||
|
||||
func paypalOrderIdentity(order *paypal.OrderDetail) (string, error) {
|
||||
if order == nil {
|
||||
return "", nil
|
||||
@@ -648,17 +643,6 @@ func paypalAmountScale(currency string, c map[string]any) (int64, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func normalizePayPalOrderState(state string) string {
|
||||
switch strings.ToUpper(strings.TrimSpace(state)) {
|
||||
case "COMPLETED":
|
||||
return "success"
|
||||
case "VOIDED":
|
||||
return "failed"
|
||||
default:
|
||||
return "pending"
|
||||
}
|
||||
}
|
||||
|
||||
func normalizePayPalCaptureState(state string) string {
|
||||
switch strings.ToUpper(strings.TrimSpace(state)) {
|
||||
case "COMPLETED", "PARTIALLY_REFUNDED", "REFUNDED":
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"kra/pkg/paymentkit"
|
||||
"kra/internal/paymentkit"
|
||||
|
||||
"github.com/go-pay/gopay"
|
||||
gopayQQ "github.com/go-pay/gopay/qq"
|
||||
@@ -55,7 +55,7 @@ func TestQQCreateKeepsClientPaymentDataOutOfDurableIdentities(t *testing.T) {
|
||||
http.Error(w, "invalid XML", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
values, err := paymentutil.XMLValues(body)
|
||||
values, err := paymentkit.XMLValues(body)
|
||||
if err != nil {
|
||||
t.Errorf("parse request XML: %v", err)
|
||||
http.Error(w, "invalid XML", http.StatusBadRequest)
|
||||
@@ -81,7 +81,7 @@ func TestQQCreateKeepsClientPaymentDataOutOfDurableIdentities(t *testing.T) {
|
||||
for key, value := range response {
|
||||
encoded[key] = fmt.Sprint(value)
|
||||
}
|
||||
_, _ = w.Write(paymentutil.XMLEncode(encoded))
|
||||
_, _ = w.Write(paymentkit.XMLEncode(encoded))
|
||||
}))
|
||||
|
||||
result, err := (&qqAdapter{}).Create(context.Background(), &bizpayment.PaymentRequest{
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"kra/pkg/paymentkit"
|
||||
"kra/internal/paymentkit"
|
||||
)
|
||||
|
||||
func callbackFields(callback *bizpayment.PaymentCallback) map[string]string {
|
||||
@@ -56,57 +56,53 @@ func first(values map[string]string, keys ...string) string {
|
||||
}
|
||||
|
||||
func text(values map[string]any, key string) string {
|
||||
return paymentutil.Text(values, key)
|
||||
return paymentkit.Text(values, key)
|
||||
}
|
||||
|
||||
func firstAny(values map[string]any, keys ...string) string {
|
||||
return paymentutil.FirstText(values, keys...)
|
||||
return paymentkit.FirstText(values, keys...)
|
||||
}
|
||||
|
||||
// Compatibility shims keep channel adapters focused on protocol and
|
||||
// persistence concerns while stateless parsing rules live in paymentutil.
|
||||
// persistence concerns while stateless parsing rules live in paymentkit.
|
||||
func normalizePaymentStatus(value, fallback string) string {
|
||||
return paymentutil.NormalizeStatus(value, fallback)
|
||||
return paymentkit.NormalizeStatus(value, fallback)
|
||||
}
|
||||
|
||||
func parseIntegerAmount(value string) (int64, error) {
|
||||
return paymentutil.ParseIntegerAmount(value)
|
||||
return paymentkit.ParseIntegerAmount(value)
|
||||
}
|
||||
|
||||
func parseDecimalAmount(value string, scale int64) (int64, error) {
|
||||
return paymentutil.ParseDecimalAmount(value, scale)
|
||||
return paymentkit.ParseDecimalAmount(value, scale)
|
||||
}
|
||||
|
||||
func formatDecimalAmount(amount, scale int64) (string, error) {
|
||||
return paymentutil.FormatDecimalAmount(amount, scale)
|
||||
return paymentkit.FormatDecimalAmount(amount, scale)
|
||||
}
|
||||
|
||||
func configuredInt64(values map[string]any, key string, fallback int64) int64 {
|
||||
return paymentutil.ConfiguredInt64(values, key, fallback)
|
||||
return paymentkit.ConfiguredInt64(values, key, fallback)
|
||||
}
|
||||
|
||||
func jsonObject(raw []byte) map[string]any {
|
||||
return paymentutil.JSONObject(raw)
|
||||
}
|
||||
|
||||
func nestedString(value any, keys ...string) string {
|
||||
return paymentutil.NestedString(value, keys...)
|
||||
return paymentkit.JSONObject(raw)
|
||||
}
|
||||
|
||||
func valueAtPath(value any, path string) any {
|
||||
return paymentutil.ValueAtPath(value, path)
|
||||
return paymentkit.ValueAtPath(value, path)
|
||||
}
|
||||
|
||||
func stringAtPath(value any, path string) string {
|
||||
return paymentutil.StringAtPath(value, path)
|
||||
return paymentkit.StringAtPath(value, path)
|
||||
}
|
||||
|
||||
func configuredValues(values map[string]any, key string) []string {
|
||||
return paymentutil.ConfiguredValues(values, key)
|
||||
return paymentkit.ConfiguredValues(values, key)
|
||||
}
|
||||
|
||||
func containsFold(values []string, value string) bool {
|
||||
return paymentutil.ContainsFold(values, value)
|
||||
return paymentkit.ContainsFold(values, value)
|
||||
}
|
||||
|
||||
// parseConfiguredAmount reads a provider amount field using an explicit unit
|
||||
@@ -138,12 +134,3 @@ func parseConfiguredAmount(object any, config map[string]any, fieldKey, scaleKey
|
||||
}
|
||||
return amount, true, nil
|
||||
}
|
||||
|
||||
func amountFromDecimalField(values map[string]any, key string, fallback int64) (int64, bool, error) {
|
||||
value := strings.TrimSpace(fmt.Sprint(values[key]))
|
||||
if value == "" || value == "<nil>" {
|
||||
return 0, false, nil
|
||||
}
|
||||
amount, err := parseDecimalAmount(value, fallback)
|
||||
return amount, true, err
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"kra/pkg/paymentkit"
|
||||
"kra/internal/paymentkit"
|
||||
)
|
||||
|
||||
type vendorProfile string
|
||||
@@ -133,8 +133,13 @@ func (a *vendorPaymentAdapter) call(ctx context.Context, endpointKey string, pay
|
||||
}
|
||||
result := &bizpayment.PaymentResult{Provider: a.provider, Status: "created", TradeNo: tradeNo, Payload: ensureJSON(body)}
|
||||
if endpointKey != "query_url" {
|
||||
if object := jsonObject(body); object != nil {
|
||||
operation := strings.TrimSuffix(endpointKey, "_url")
|
||||
operation := strings.TrimSuffix(endpointKey, "_url")
|
||||
object := jsonObject(body)
|
||||
if object == nil {
|
||||
if operation == "refund" {
|
||||
return nil, fmt.Errorf("%s 退款响应不是 JSON 对象", a.provider)
|
||||
}
|
||||
} else {
|
||||
statusField := text(c, operation+"_status_field")
|
||||
if statusField == "" {
|
||||
statusField = text(c, "query_status_field")
|
||||
@@ -158,8 +163,20 @@ func (a *vendorPaymentAdapter) call(ctx context.Context, endpointKey string, pay
|
||||
case containsFold(configuredValues(c, operation+"_success_values"), state):
|
||||
result.Status = "created"
|
||||
default:
|
||||
result.Status = normalizePaymentStatus(state, "created")
|
||||
if operation == "refund" {
|
||||
normalized := normalizePaymentStatus(state, "")
|
||||
switch normalized {
|
||||
case "success", "pending", "failed":
|
||||
result.Status = normalized
|
||||
default:
|
||||
return nil, fmt.Errorf("%s 退款响应状态无法识别: %s", a.provider, state)
|
||||
}
|
||||
} else {
|
||||
result.Status = normalizePaymentStatus(state, "created")
|
||||
}
|
||||
}
|
||||
} else if operation == "refund" {
|
||||
return nil, fmt.Errorf("%s 退款响应缺少业务状态", a.provider)
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
@@ -273,18 +290,18 @@ func (a *vendorPaymentAdapter) signRequest(request *http.Request, payload map[st
|
||||
digest := sha256.Sum256([]byte(appID + timestamp + nonceValue + string(raw) + secret))
|
||||
request.Header.Set("Authorization", "OPEN-BODY-SIG AppId="+appID+", Timestamp="+timestamp+", Nonce="+nonceValue+", Signature="+hex.EncodeToString(digest[:]))
|
||||
case vendorSFT:
|
||||
request.Header.Set("X-SFT-Sign", paymentutil.MD5Canonical(payload, secret))
|
||||
request.Header.Set("X-SFT-Sign", paymentkit.MD5Canonical(payload, secret))
|
||||
case vendorWechatGame:
|
||||
request.Header.Set("X-Wechat-Game-Sign", paymentutil.HMACSHA256Hex(raw, secret, false))
|
||||
request.Header.Set("X-Wechat-Game-Sign", paymentkit.HMACSHA256Hex(raw, secret, false))
|
||||
if token := text(c, "access_token"); token != "" {
|
||||
query := request.URL.Query()
|
||||
query.Set("access_token", token)
|
||||
request.URL.RawQuery = query.Encode()
|
||||
}
|
||||
case vendorDouyinGame:
|
||||
request.Header.Set("X-TT-Pay-Sign", paymentutil.MD5Canonical(payload, secret))
|
||||
request.Header.Set("X-TT-Pay-Sign", paymentkit.MD5Canonical(payload, secret))
|
||||
default:
|
||||
request.Header.Set("X-Payment-Sign", paymentutil.HMACSHA256Hex(raw, secret, false))
|
||||
request.Header.Set("X-Payment-Sign", paymentkit.HMACSHA256Hex(raw, secret, false))
|
||||
}
|
||||
}
|
||||
func (a *vendorPaymentAdapter) verify(fields map[string]string, raw []byte, headers map[string]string, c map[string]any) error {
|
||||
@@ -327,9 +344,9 @@ func (a *vendorPaymentAdapter) verify(fields map[string]string, raw []byte, head
|
||||
values[key] = value
|
||||
}
|
||||
}
|
||||
actual = paymentutil.MD5Canonical(values, secret)
|
||||
actual = paymentkit.MD5Canonical(values, secret)
|
||||
default:
|
||||
actual = paymentutil.HMACSHA256Hex(raw, secret, false)
|
||||
actual = paymentkit.HMACSHA256Hex(raw, secret, false)
|
||||
}
|
||||
if !hmac.Equal([]byte(strings.ToLower(expected)), []byte(strings.ToLower(actual))) {
|
||||
return errors.New("支付回调签名校验失败")
|
||||
|
||||
@@ -56,3 +56,23 @@ func TestVendorRefundMapsBusinessFailureStatus(t *testing.T) {
|
||||
t.Fatalf("Refund() result = %#v, want failed status", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVendorRefundRejectsUnknownBusinessStatus(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"status":"UNKNOWN"}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
adapter := &vendorPaymentAdapter{provider: "vendor", profile: vendorSFT}
|
||||
result, err := adapter.Refund(context.Background(), &bizpayment.PaymentRefundRequest{TradeNo: "trade-1", RefundNo: "refund-1", Amount: 100, TotalAmount: 100, Currency: "CNY"}, map[string]any{
|
||||
"refund_url": server.URL,
|
||||
"app_key": "secret",
|
||||
})
|
||||
if err == nil || !strings.Contains(err.Error(), "状态无法识别") {
|
||||
t.Fatalf("Refund() error = %v, want unknown-status error", err)
|
||||
}
|
||||
if result != nil {
|
||||
t.Fatalf("Refund() result = %#v, want nil", result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,12 +44,6 @@ func wechatV2SignType(value string) string {
|
||||
return gopayWechat.SignType_MD5
|
||||
}
|
||||
|
||||
func wechatV2Sign(values map[string]string, key, signType string) string {
|
||||
body := toGoPayBodyMap(values)
|
||||
body.Remove("sign")
|
||||
return gopayWechat.GetReleaseSign(key, wechatV2SignType(signType), body)
|
||||
}
|
||||
|
||||
func (a *wechatV2Adapter) Create(ctx context.Context, req *bizpayment.PaymentRequest, c map[string]any) (*bizpayment.PaymentResult, error) {
|
||||
if req == nil {
|
||||
return nil, errors.New("微信支付 v2 下单请求为空")
|
||||
@@ -581,12 +575,6 @@ func nonce() string {
|
||||
}
|
||||
return fmt.Sprintf("%d", time.Now().UnixNano())
|
||||
}
|
||||
func stringOr(extra map[string]any, key, fallback string) string {
|
||||
if value, ok := extra[key].(string); ok {
|
||||
return value
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
func stringMap(values map[string]any) map[string]string {
|
||||
result := map[string]string{}
|
||||
for key, value := range values {
|
||||
|
||||
@@ -596,10 +596,3 @@ func parseJSONInteger(object map[string]any, key string) (int64, bool, error) {
|
||||
amount, err := parseIntegerAmount(fmt.Sprint(raw))
|
||||
return amount, true, err
|
||||
}
|
||||
|
||||
func decryptWechatV3(ciphertext, nonce, associatedData, key string) ([]byte, error) {
|
||||
if len(key) != 32 {
|
||||
return nil, errors.New("微信支付 v3 api_v3_key 必须为 32 字节")
|
||||
}
|
||||
return gopayWechatV3.V3DecryptNotifyCipherTextToBytes(ciphertext, nonce, associatedData, key)
|
||||
}
|
||||
|
||||
@@ -5,10 +5,12 @@ package integration
|
||||
|
||||
import (
|
||||
integrationbiz "kra/internal/biz/integration"
|
||||
bizpayment "kra/internal/biz/payment"
|
||||
"kra/internal/biz/system"
|
||||
"kra/internal/integration/cache"
|
||||
"kra/internal/integration/email"
|
||||
mqintegration "kra/internal/integration/mq"
|
||||
paymentintegration "kra/internal/integration/payment"
|
||||
"kra/internal/integration/storage"
|
||||
websocketintegration "kra/internal/integration/websocket"
|
||||
"kra/pkg/mq"
|
||||
@@ -20,6 +22,8 @@ import (
|
||||
var ProviderSet = wire.NewSet(
|
||||
cache.New,
|
||||
email.NewEmailRepo,
|
||||
paymentintegration.NewFactory,
|
||||
wire.Bind(new(bizpayment.PaymentAdapterFactory), new(*paymentintegration.Factory)),
|
||||
storage.NewFileStorage,
|
||||
NewConnectivityTester,
|
||||
wire.Bind(new(integrationbiz.IntegrationConnectionTester), new(*ConnectivityTester)),
|
||||
|
||||
Reference in New Issue
Block a user