aboutsummaryrefslogtreecommitdiffstats
path: root/callback_handler_test.go
blob: d1ed083fee83d84a71ee960edf3ee5d63af9f388 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package xmrpayclnt_test

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/http/httptest"
	"net/url"
	"time"

	"gitlab.com/moneropay/moneropay/v2/pkg/model"

	xmrpay "git.samanthony.xyz/xmrpayclnt"
)

func ExampleCallbackHandler() {
	// Mock the MoneroPay server's POST /receive endpoint for the
	// sake of the example
	xmrPaySrv := httptest.NewServer(mockReceivePostHandler{})
	xmrPaySrvUrl, err := url.Parse(xmrPaySrv.URL)
	if err != nil {
		log.Fatal(err)
	}

	// Create a callback handler that will listen on
	// http://localhost:57904/moneropay?abcxyz... for callbacks from
	// the MoneroPay server
	cbUrl, err := url.Parse("http://localhost:57904/moneropay")
	if err != nil {
		log.Fatal(err)
	}
	cbSrv := http.NewServeMux()
	cbHlr := xmrpay.NewCallbackHandler(cbUrl)
	cbSrv.Handle("POST "+cbUrl.Path, cbHlr)
	go func() {
		if err := http.ListenAndServe(cbUrl.Host, cbSrv); err != nil {
			log.Fatal(err)
		}
	}()

	// Request a transfer and register a callback for it
	clnt := xmrpay.New(xmrPaySrvUrl)
	resp, cb, err := clnt.NewTxWithCallback(123, "lorem ipsum", cbHlr)
	if err != nil {
		log.Fatal(err)
	}
	defer cb.Close()
	fmt.Printf("POST /receive response: %s %d %q\n", resp.Address, resp.Amount, resp.Description)

	// Wait for the transaction to finish
	<-cb.Complete
	fmt.Println("funds have been received")

	// Output:
	// POST /receive response: abcxyz 123 "lorem ipsum"
	// funds have been received
}

type mockReceivePostHandler struct{}

func (mockReceivePostHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost || r.URL.Path != "/receive" {
		panic(fmt.Sprintf("bad request: %s %s", r.Method, r.URL))
	}

	var req model.ReceivePostRequest
	dec := json.NewDecoder(r.Body)
	if err := dec.Decode(&req); err != nil {
		panic(err)
	}

	// Send callbacks
	go func() {
		var cb model.CallbackResponse
		cb.Amount.Expected = req.Amount
		cb.Description = req.Description
		cbData, err := json.Marshal(cb)
		if err != nil {
			panic(err)
		}
		period := time.Second
		timer := time.NewTimer(period)
		for i := 0; i < 3; i++ {
			<-timer.C
			timer.Reset(period)
			_, err := http.Post(req.CallbackUrl, "application/json", bytes.NewBuffer(cbData))
			if err != nil {
				panic(err)
			}
		}

		// Transaction is finally complete
		cb.Complete = true
		cbData, err = json.Marshal(cb)
		if err != nil {
			panic(err)
		}
		_, err = http.Post(req.CallbackUrl, "application/json", bytes.NewBuffer(cbData))
		if err != nil {
			panic(err)
		}
	}()

	resp := model.ReceivePostResponse{
		Address:     "abcxyz",
		Amount:      req.Amount,
		Description: req.Description,
	}
	enc := json.NewEncoder(w)
	if err := enc.Encode(resp); err != nil {
		panic(err)
	}
}