@waffo/waffo-integrate 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,688 @@
1
+ # Go Integration Templates
2
+
3
+ ## Module
4
+
5
+ ```
6
+ github.com/waffo-com/waffo-go
7
+ ```
8
+
9
+ Install:
10
+ ```bash
11
+ go get github.com/waffo-com/waffo-go@latest
12
+ ```
13
+
14
+ ---
15
+
16
+ ## SDK Initialization
17
+
18
+ ```go
19
+ // internal/waffo/client.go
20
+ package waffo
21
+
22
+ import (
23
+ "os"
24
+ "sync"
25
+
26
+ waffogo "github.com/waffo-com/waffo-go"
27
+ "github.com/waffo-com/waffo-go/config"
28
+ )
29
+
30
+ var (
31
+ instance *waffogo.Waffo
32
+ once sync.Once
33
+ )
34
+
35
+ func GetClient() *waffogo.Waffo {
36
+ once.Do(func() {
37
+ env := config.Sandbox
38
+ if os.Getenv("WAFFO_ENVIRONMENT") == "PRODUCTION" {
39
+ env = config.Production
40
+ }
41
+
42
+ cfg := config.WaffoConfig{
43
+ ApiKey: os.Getenv("WAFFO_API_KEY"),
44
+ PrivateKey: os.Getenv("WAFFO_PRIVATE_KEY"),
45
+ WaffoPublicKey: os.Getenv("WAFFO_PUBLIC_KEY"),
46
+ MerchantId: os.Getenv("WAFFO_MERCHANT_ID"),
47
+ Environment: env,
48
+ }
49
+
50
+ instance = waffogo.NewWaffo(cfg)
51
+ })
52
+ return instance
53
+ }
54
+ ```
55
+
56
+ ---
57
+
58
+ ## Order Payment
59
+
60
+ ```go
61
+ // internal/waffo/payment.go
62
+ package waffo
63
+
64
+ import (
65
+ "context"
66
+ "fmt"
67
+ "strings"
68
+
69
+ "github.com/google/uuid"
70
+ "github.com/waffo-com/waffo-go/types/order"
71
+ )
72
+
73
+ type CreatePaymentInput struct {
74
+ MerchantOrderId string
75
+ Amount string
76
+ Currency string
77
+ Description string
78
+ NotifyUrl string
79
+ SuccessRedirectUrl string
80
+ UserId string
81
+ UserEmail string
82
+ UserTerminal string // WEB | APP | WAP | SYSTEM (default: WEB)
83
+ PayMethodType string // optional: "CREDITCARD", "EWALLET"
84
+ PayMethodName string // optional: "CC_VISA", "DANA"
85
+ }
86
+
87
+ // genRequestID generates a 32-char request ID (UUID without dashes, max length 32)
88
+ func genRequestID() string {
89
+ return strings.ReplaceAll(uuid.New().String(), "-", "")
90
+ }
91
+
92
+ func CreatePayment(ctx context.Context, input CreatePaymentInput) (*order.CreateOrderData, error) {
93
+ client := GetClient()
94
+
95
+ userTerminal := input.UserTerminal
96
+ if userTerminal == "" {
97
+ userTerminal = "WEB"
98
+ }
99
+
100
+ params := order.CreateOrderParams{
101
+ PaymentRequestId: genRequestID(),
102
+ MerchantOrderId: input.MerchantOrderId,
103
+ OrderCurrency: input.Currency,
104
+ OrderAmount: input.Amount,
105
+ OrderDescription: input.Description,
106
+ NotifyUrl: input.NotifyUrl,
107
+ SuccessRedirectUrl: input.SuccessRedirectUrl,
108
+ UserInfo: &order.UserInfo{
109
+ UserId: input.UserId,
110
+ UserEmail: input.UserEmail,
111
+ UserTerminal: userTerminal,
112
+ },
113
+ PaymentInfo: &order.PaymentInfo{
114
+ ProductName: "ONE_TIME_PAYMENT",
115
+ PayMethodType: input.PayMethodType,
116
+ PayMethodName: input.PayMethodName,
117
+ },
118
+ }
119
+
120
+ resp, err := client.Order().Create(ctx, params)
121
+ if err != nil {
122
+ return nil, fmt.Errorf("create payment error: %w", err)
123
+ }
124
+
125
+ if !resp.IsSuccess() {
126
+ return nil, fmt.Errorf("create payment failed: code=%s, msg=%s",
127
+ resp.GetCode(), resp.GetMessage())
128
+ }
129
+
130
+ data := resp.GetData()
131
+ return &data, nil
132
+ }
133
+
134
+ func QueryOrder(ctx context.Context, paymentRequestId string) (*order.InquiryOrderData, error) {
135
+ client := GetClient()
136
+
137
+ resp, err := client.Order().Inquiry(ctx, order.InquiryOrderParams{
138
+ PaymentRequestId: paymentRequestId,
139
+ })
140
+ if err != nil {
141
+ return nil, fmt.Errorf("inquiry error: %w", err)
142
+ }
143
+
144
+ if !resp.IsSuccess() {
145
+ return nil, fmt.Errorf("inquiry failed: code=%s, msg=%s",
146
+ resp.GetCode(), resp.GetMessage())
147
+ }
148
+
149
+ data := resp.GetData()
150
+ return &data, nil
151
+ }
152
+
153
+ func CancelOrder(ctx context.Context, paymentRequestId string) (*order.CancelOrderData, error) {
154
+ client := GetClient()
155
+
156
+ resp, err := client.Order().Cancel(ctx, order.CancelOrderParams{
157
+ PaymentRequestId: paymentRequestId,
158
+ })
159
+ if err != nil {
160
+ return nil, fmt.Errorf("cancel error: %w", err)
161
+ }
162
+
163
+ if !resp.IsSuccess() {
164
+ return nil, fmt.Errorf("cancel failed: code=%s, msg=%s",
165
+ resp.GetCode(), resp.GetMessage())
166
+ }
167
+
168
+ data := resp.GetData()
169
+ return &data, nil
170
+ }
171
+ ```
172
+
173
+ ---
174
+
175
+ ## Refund
176
+
177
+ ```go
178
+ // internal/waffo/refund.go
179
+ package waffo
180
+
181
+ import (
182
+ "context"
183
+ "fmt"
184
+
185
+ "strings"
186
+
187
+ "github.com/google/uuid"
188
+ "github.com/waffo-com/waffo-go/types/order"
189
+ "github.com/waffo-com/waffo-go/types/refund"
190
+ )
191
+
192
+ func RefundOrder(ctx context.Context, origPaymentRequestId, refundAmount, refundReason string) (*order.RefundOrderData, error) {
193
+ client := GetClient()
194
+
195
+ params := order.RefundOrderParams{
196
+ RefundRequestId: strings.ReplaceAll(uuid.New().String(), "-", ""),
197
+ OrigPaymentRequestId: origPaymentRequestId,
198
+ RefundAmount: refundAmount,
199
+ RefundReason: refundReason,
200
+ }
201
+
202
+ resp, err := client.Order().Refund(ctx, params)
203
+ if err != nil {
204
+ return nil, fmt.Errorf("refund error: %w", err)
205
+ }
206
+
207
+ if !resp.IsSuccess() {
208
+ return nil, fmt.Errorf("refund failed: code=%s, msg=%s",
209
+ resp.GetCode(), resp.GetMessage())
210
+ }
211
+
212
+ data := resp.GetData()
213
+ return &data, nil
214
+ }
215
+
216
+ func QueryRefund(ctx context.Context, refundRequestId string) (*refund.InquiryRefundData, error) {
217
+ client := GetClient()
218
+
219
+ resp, err := client.Refund().Inquiry(ctx, refund.InquiryRefundParams{
220
+ RefundRequestId: refundRequestId,
221
+ })
222
+ if err != nil {
223
+ return nil, fmt.Errorf("refund inquiry error: %w", err)
224
+ }
225
+
226
+ if !resp.IsSuccess() {
227
+ return nil, fmt.Errorf("refund inquiry failed: code=%s, msg=%s",
228
+ resp.GetCode(), resp.GetMessage())
229
+ }
230
+
231
+ data := resp.GetData()
232
+ return &data, nil
233
+ }
234
+ ```
235
+
236
+ ---
237
+
238
+ ## Subscription
239
+
240
+ ```go
241
+ // internal/waffo/subscription.go
242
+ package waffo
243
+
244
+ import (
245
+ "context"
246
+ "fmt"
247
+
248
+ "strings"
249
+
250
+ "github.com/google/uuid"
251
+ "github.com/waffo-com/waffo-go/types/subscription"
252
+ )
253
+
254
+ type CreateSubscriptionInput struct {
255
+ MerchantSubscriptionId string
256
+ Amount string
257
+ Currency string
258
+ Description string
259
+ NotifyUrl string
260
+ UserId string
261
+ UserEmail string
262
+ ProductId string
263
+ ProductName string
264
+ PeriodType string // DAILY, WEEKLY, MONTHLY
265
+ PeriodInterval string
266
+ GoodsId string
267
+ GoodsName string
268
+ GoodsUrl string
269
+ SuccessRedirectUrl string
270
+ }
271
+
272
+ func CreateSubscription(ctx context.Context, input CreateSubscriptionInput) (*subscription.CreateSubscriptionData, error) {
273
+ client := GetClient()
274
+
275
+ params := subscription.CreateSubscriptionParams{
276
+ SubscriptionRequest: strings.ReplaceAll(uuid.New().String(), "-", ""),
277
+ MerchantSubscriptionId: input.MerchantSubscriptionId,
278
+ Currency: input.Currency,
279
+ Amount: input.Amount,
280
+ OrderDescription: input.Description,
281
+ NotifyUrl: input.NotifyUrl,
282
+ SuccessRedirectUrl: input.SuccessRedirectUrl,
283
+ ProductInfo: &subscription.ProductInfo{
284
+ ProductId: input.ProductId,
285
+ ProductName: input.ProductName,
286
+ Description: input.Description,
287
+ PeriodType: input.PeriodType,
288
+ PeriodInterval: input.PeriodInterval,
289
+ },
290
+ GoodsInfo: &subscription.GoodsInfo{
291
+ GoodsId: input.GoodsId,
292
+ GoodsName: input.GoodsName,
293
+ GoodsUrl: input.GoodsUrl,
294
+ },
295
+ UserInfo: &subscription.UserInfo{
296
+ UserId: input.UserId,
297
+ UserEmail: input.UserEmail,
298
+ UserTerminal: input.UserTerminal, // WEB for PC, APP for mobile/tablet
299
+ },
300
+ PaymentInfo: &subscription.PaymentInfo{
301
+ ProductName: "SUBSCRIPTION",
302
+ PayMethodType: "CREDITCARD,DEBITCARD,APPLEPAY,GOOGLEPAY",
303
+ },
304
+ }
305
+
306
+ resp, err := client.Subscription().Create(ctx, params)
307
+ if err != nil {
308
+ return nil, fmt.Errorf("create subscription error: %w", err)
309
+ }
310
+
311
+ if !resp.IsSuccess() {
312
+ return nil, fmt.Errorf("create subscription failed: code=%s, msg=%s",
313
+ resp.GetCode(), resp.GetMessage())
314
+ }
315
+
316
+ data := resp.GetData()
317
+ return &data, nil
318
+ }
319
+
320
+ func QuerySubscription(ctx context.Context, subscriptionRequest string) (*subscription.InquirySubscriptionData, error) {
321
+ client := GetClient()
322
+
323
+ resp, err := client.Subscription().Inquiry(ctx, subscription.InquirySubscriptionParams{
324
+ SubscriptionRequest: subscriptionRequest,
325
+ })
326
+ if err != nil {
327
+ return nil, fmt.Errorf("inquiry error: %w", err)
328
+ }
329
+
330
+ if !resp.IsSuccess() {
331
+ return nil, fmt.Errorf("inquiry failed: code=%s, msg=%s",
332
+ resp.GetCode(), resp.GetMessage())
333
+ }
334
+
335
+ data := resp.GetData()
336
+ return &data, nil
337
+ }
338
+
339
+ func CancelSubscription(ctx context.Context, subscriptionRequest string) (*subscription.CancelSubscriptionData, error) {
340
+ client := GetClient()
341
+
342
+ resp, err := client.Subscription().Cancel(ctx, subscription.CancelSubscriptionParams{
343
+ SubscriptionRequest: subscriptionRequest,
344
+ })
345
+ if err != nil {
346
+ return nil, fmt.Errorf("cancel error: %w", err)
347
+ }
348
+
349
+ if !resp.IsSuccess() {
350
+ return nil, fmt.Errorf("cancel failed: code=%s, msg=%s",
351
+ resp.GetCode(), resp.GetMessage())
352
+ }
353
+
354
+ data := resp.GetData()
355
+ return &data, nil
356
+ }
357
+
358
+ // ManageSubscription returns a management URL for the subscription.
359
+ // Only works when the subscription is ACTIVE.
360
+ func ManageSubscription(ctx context.Context, subscriptionRequest string) (string, error) {
361
+ client := GetClient()
362
+
363
+ params := subscription.ManageSubscriptionParams{
364
+ SubscriptionRequest: subscriptionRequest,
365
+ }
366
+
367
+ resp, err := client.Subscription().Manage(ctx, params)
368
+ if err != nil {
369
+ return "", fmt.Errorf("manage error: %w", err)
370
+ }
371
+
372
+ if !resp.IsSuccess() {
373
+ return "", fmt.Errorf("manage failed: code=%s, msg=%s",
374
+ resp.GetCode(), resp.GetMessage())
375
+ }
376
+
377
+ managementURL := resp.GetData().ManagementURL
378
+ return managementURL, nil
379
+ }
380
+ ```
381
+
382
+ ---
383
+
384
+ ## Webhook Handler
385
+
386
+ ### Gin
387
+
388
+ ```go
389
+ // internal/waffo/webhook.go
390
+ package waffo
391
+
392
+ import (
393
+ "io"
394
+ "net/http"
395
+
396
+ "github.com/gin-gonic/gin"
397
+ )
398
+
399
+ func WebhookHandler() gin.HandlerFunc {
400
+ return func(c *gin.Context) {
401
+ client := GetClient()
402
+
403
+ body, err := io.ReadAll(c.Request.Body)
404
+ if err != nil {
405
+ c.JSON(http.StatusBadRequest, gin.H{"error": "failed to read body"})
406
+ return
407
+ }
408
+
409
+ signature := c.GetHeader("X-SIGNATURE")
410
+
411
+ handler := client.Webhook().
412
+ OnPayment(func(notification map[string]interface{}) {
413
+ result, _ := notification["result"].(map[string]interface{})
414
+ // TODO: Update your order status in database
415
+ _ = result
416
+ }).
417
+ OnRefund(func(notification map[string]interface{}) {
418
+ result, _ := notification["result"].(map[string]interface{})
419
+ // TODO: Update your refund status in database
420
+ _ = result
421
+ }).
422
+ OnSubscriptionStatus(func(notification map[string]interface{}) {
423
+ result, _ := notification["result"].(map[string]interface{})
424
+ // TODO: Update your subscription status in database
425
+ _ = result
426
+ }).
427
+ OnSubscriptionPeriodChanged(func(notification map[string]interface{}) {
428
+ result, _ := notification["result"].(map[string]interface{})
429
+ // TODO: Record billing period result
430
+ _ = result
431
+ }).
432
+ OnSubscriptionChange(func(notification map[string]interface{}) {
433
+ result, _ := notification["result"].(map[string]interface{})
434
+ // TODO: Handle subscription upgrade/downgrade
435
+ _ = result
436
+ })
437
+
438
+ webhookResult := handler.HandleWebhook(string(body), signature)
439
+
440
+ c.Header("X-SIGNATURE", webhookResult.ResponseSignature)
441
+ c.String(http.StatusOK, webhookResult.ResponseBody)
442
+ }
443
+ }
444
+ ```
445
+
446
+ ### Echo
447
+
448
+ ```go
449
+ // internal/waffo/webhook_echo.go
450
+ package waffo
451
+
452
+ import (
453
+ "io"
454
+ "net/http"
455
+
456
+ "github.com/labstack/echo/v4"
457
+ )
458
+
459
+ func WebhookEchoHandler(c echo.Context) error {
460
+ client := GetClient()
461
+
462
+ body, err := io.ReadAll(c.Request().Body)
463
+ if err != nil {
464
+ return c.JSON(http.StatusBadRequest, map[string]string{"error": "failed to read body"})
465
+ }
466
+
467
+ signature := c.Request().Header.Get("X-SIGNATURE")
468
+
469
+ handler := client.Webhook().
470
+ OnPayment(func(notification map[string]interface{}) {
471
+ // TODO: Handle payment
472
+ }).
473
+ OnRefund(func(notification map[string]interface{}) {
474
+ // TODO: Handle refund
475
+ })
476
+
477
+ webhookResult := handler.HandleWebhook(string(body), signature)
478
+
479
+ c.Response().Header().Set("X-SIGNATURE", webhookResult.ResponseSignature)
480
+ return c.String(http.StatusOK, webhookResult.ResponseBody)
481
+ }
482
+ ```
483
+
484
+ ### Fiber
485
+
486
+ ```go
487
+ // internal/waffo/webhook_fiber.go
488
+ package waffo
489
+
490
+ import (
491
+ "github.com/gofiber/fiber/v2"
492
+ )
493
+
494
+ func WebhookFiberHandler(c *fiber.Ctx) error {
495
+ client := GetClient()
496
+
497
+ body := string(c.Body())
498
+ signature := c.Get("X-SIGNATURE")
499
+
500
+ handler := client.Webhook().
501
+ OnPayment(func(notification map[string]interface{}) {
502
+ // TODO: Handle payment
503
+ }).
504
+ OnRefund(func(notification map[string]interface{}) {
505
+ // TODO: Handle refund
506
+ })
507
+
508
+ webhookResult := handler.HandleWebhook(body, signature)
509
+
510
+ c.Set("X-SIGNATURE", webhookResult.ResponseSignature)
511
+ return c.SendString(webhookResult.ResponseBody)
512
+ }
513
+ ```
514
+
515
+ ---
516
+
517
+ ## Test Template (Sandbox Integration)
518
+
519
+ ```go
520
+ // internal/waffo/waffo_test.go
521
+ package waffo_test
522
+
523
+ import (
524
+ "context"
525
+ "os"
526
+ "strings"
527
+ "testing"
528
+
529
+ "github.com/google/uuid"
530
+ waffogo "github.com/waffo-com/waffo-go"
531
+ "github.com/waffo-com/waffo-go/config"
532
+ "github.com/waffo-com/waffo-go/types/order"
533
+ )
534
+
535
+ func hasCredentials() bool {
536
+ return os.Getenv("WAFFO_API_KEY") != "" &&
537
+ os.Getenv("WAFFO_PRIVATE_KEY") != "" &&
538
+ os.Getenv("WAFFO_PUBLIC_KEY") != "" &&
539
+ os.Getenv("WAFFO_MERCHANT_ID") != ""
540
+ }
541
+
542
+ func newTestClient(t *testing.T) *waffogo.Waffo {
543
+ t.Helper()
544
+ if !hasCredentials() {
545
+ t.Skip("Waffo credentials not configured, skipping Sandbox test")
546
+ }
547
+
548
+ cfg := config.WaffoConfig{
549
+ ApiKey: os.Getenv("WAFFO_API_KEY"),
550
+ PrivateKey: os.Getenv("WAFFO_PRIVATE_KEY"),
551
+ WaffoPublicKey: os.Getenv("WAFFO_PUBLIC_KEY"),
552
+ MerchantId: os.Getenv("WAFFO_MERCHANT_ID"),
553
+ Environment: config.Sandbox,
554
+ }
555
+
556
+ return waffogo.NewWaffo(cfg)
557
+ }
558
+
559
+ func genRequestID() string {
560
+ return strings.ReplaceAll(uuid.New().String(), "-", "")
561
+ }
562
+
563
+ func TestCreateOrder(t *testing.T) {
564
+ client := newTestClient(t)
565
+ ctx := context.Background()
566
+ paymentRequestID := genRequestID()
567
+
568
+ params := order.CreateOrderParams{
569
+ PaymentRequestId: paymentRequestID,
570
+ MerchantOrderId: "test-go-" + uuid.New().String()[:8],
571
+ OrderCurrency: "USD",
572
+ OrderAmount: "1.00",
573
+ OrderDescription: "Go integration test order",
574
+ NotifyUrl: "https://example.com/webhook",
575
+ SuccessRedirectUrl: "https://example.com/success",
576
+ UserInfo: &order.UserInfo{
577
+ UserId: "test-user",
578
+ UserEmail: "test@example.com",
579
+ UserTerminal: "WEB",
580
+ },
581
+ PaymentInfo: &order.PaymentInfo{
582
+ ProductName: "ONE_TIME_PAYMENT",
583
+ },
584
+ }
585
+
586
+ resp, err := client.Order().Create(ctx, params)
587
+ if err != nil {
588
+ t.Fatalf("Create order error: paymentRequestID=%s, err=%v", paymentRequestID, err)
589
+ }
590
+
591
+ if !resp.IsSuccess() {
592
+ t.Fatalf("Create order failed: paymentRequestID=%s, code=%s, msg=%s, data=%+v",
593
+ paymentRequestID, resp.GetCode(), resp.GetMessage(), resp.GetData())
594
+ }
595
+
596
+ data := resp.GetData()
597
+ if data.AcquiringOrderId == "" {
598
+ t.Fatal("AcquiringOrderId is empty")
599
+ }
600
+ t.Logf("Order created: acquiringOrderId=%s", data.AcquiringOrderId)
601
+ }
602
+
603
+ func TestQueryOrder(t *testing.T) {
604
+ client := newTestClient(t)
605
+ ctx := context.Background()
606
+ paymentRequestID := genRequestID()
607
+
608
+ // Create first
609
+ _, err := client.Order().Create(ctx, order.CreateOrderParams{
610
+ PaymentRequestId: paymentRequestID,
611
+ MerchantOrderId: "test-go-" + uuid.New().String()[:8],
612
+ OrderCurrency: "USD",
613
+ OrderAmount: "1.00",
614
+ OrderDescription: "Test",
615
+ NotifyUrl: "https://example.com/webhook",
616
+ SuccessRedirectUrl: "https://example.com/success",
617
+ UserInfo: &order.UserInfo{UserId: "test-user", UserEmail: "test@example.com", UserTerminal: "WEB"},
618
+ PaymentInfo: &order.PaymentInfo{ProductName: "ONE_TIME_PAYMENT"},
619
+ })
620
+ if err != nil {
621
+ t.Fatalf("Create order error: %v", err)
622
+ }
623
+
624
+ // Then query
625
+ resp, err := client.Order().Inquiry(ctx, order.InquiryOrderParams{
626
+ PaymentRequestId: paymentRequestID,
627
+ })
628
+ if err != nil {
629
+ t.Fatalf("Inquiry error: paymentRequestID=%s, err=%v", paymentRequestID, err)
630
+ }
631
+
632
+ if !resp.IsSuccess() {
633
+ t.Fatalf("Inquiry failed: paymentRequestID=%s, code=%s, msg=%s",
634
+ paymentRequestID, resp.GetCode(), resp.GetMessage())
635
+ }
636
+ }
637
+ ```
638
+
639
+ ---
640
+
641
+ ## Merchant Config & Payment Method Query
642
+
643
+ ```go
644
+ // internal/waffo/config_query.go
645
+ package waffo
646
+
647
+ import (
648
+ "context"
649
+ "fmt"
650
+
651
+ "github.com/waffo-com/waffo-go/types/merchant"
652
+ "github.com/waffo-com/waffo-go/types/paymethod"
653
+ )
654
+
655
+ func GetMerchantConfig(ctx context.Context) (*merchant.InquiryMerchantConfigData, error) {
656
+ client := GetClient()
657
+
658
+ resp, err := client.MerchantConfig().Inquiry(ctx, merchant.InquiryMerchantConfigParams{})
659
+ if err != nil {
660
+ return nil, fmt.Errorf("merchant config error: %w", err)
661
+ }
662
+
663
+ if !resp.IsSuccess() {
664
+ return nil, fmt.Errorf("merchant config failed: code=%s, msg=%s",
665
+ resp.GetCode(), resp.GetMessage())
666
+ }
667
+
668
+ data := resp.GetData()
669
+ return &data, nil
670
+ }
671
+
672
+ func GetPaymentMethods(ctx context.Context) (*paymethod.InquiryPayMethodConfigData, error) {
673
+ client := GetClient()
674
+
675
+ resp, err := client.PayMethodConfig().Inquiry(ctx, paymethod.InquiryPayMethodConfigParams{})
676
+ if err != nil {
677
+ return nil, fmt.Errorf("pay method error: %w", err)
678
+ }
679
+
680
+ if !resp.IsSuccess() {
681
+ return nil, fmt.Errorf("pay method failed: code=%s, msg=%s",
682
+ resp.GetCode(), resp.GetMessage())
683
+ }
684
+
685
+ data := resp.GetData()
686
+ return &data, nil
687
+ }
688
+ ```