Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support sending for WhatsApp URNs #1267

Merged
merged 1 commit into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion flows/actions/testdata/transfer_airtime.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"type": "error",
"created_on": "2018-10-18T14:20:30.000123456Z",
"step_uuid": "59d74b86-3e2f-4a93-aece-b05d2fdcde0c",
"text": "can't transfer airtime to contact without a tel URN"
"text": "can't transfer airtime to contact without a phone number"
},
{
"type": "run_result_changed",
Expand Down
12 changes: 7 additions & 5 deletions flows/actions/transfer_airtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,18 @@ func (a *TransferAirtimeAction) transfer(run flows.Run, logEvent flows.EventCall
contact := run.Contact()

// fail if the contact doesn't have a tel URN
telURNs := contact.URNs().WithScheme(urns.Phone.Prefix)
telURNs := contact.URNs().WithScheme(urns.Phone.Prefix, urns.WhatsApp.Prefix)
if len(telURNs) == 0 {
return nil, errors.New("can't transfer airtime to contact without a tel URN")
return nil, errors.New("can't transfer airtime to contact without a phone number")
}

recipient := telURNs[0].URN()

// if contact's preferred channel is a phone number, use that as the sender
var sender urns.URN
channel := contact.PreferredChannel()
if channel != nil && channel.SupportsScheme(urns.Phone.Prefix) {
sender, _ = urns.Parse("tel:" + channel.Address())
if channel != nil && channel.SupportsScheme(recipient.Scheme()) {
sender, _ = urns.Parse(recipient.Scheme() + ":" + channel.Address())
}

svc, err := run.Session().Engine().Services().Airtime(run.Session().Assets())
Expand All @@ -85,7 +87,7 @@ func (a *TransferAirtimeAction) transfer(run flows.Run, logEvent flows.EventCall

httpLogger := &flows.HTTPLogger{}

transfer, err := svc.Transfer(sender, telURNs[0].URN(), a.Amounts, httpLogger.Log)
transfer, err := svc.Transfer(sender, recipient, a.Amounts, httpLogger.Log)
if transfer != nil {
logEvent(events.NewAirtimeTransferred(transfer, httpLogger.Logs))
}
Expand Down
7 changes: 4 additions & 3 deletions flows/urn.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package flows
import (
"fmt"
"net/url"
"slices"

"github.com/go-playground/validator/v10"
"github.com/nyaruka/gocommon/urns"
Expand Down Expand Up @@ -173,11 +174,11 @@ func (l URNList) clone() URNList {
return urns
}

// WithScheme returns a new URN list containing of only URNs of the given scheme
func (l URNList) WithScheme(scheme string) URNList {
// WithScheme returns a new URN list containing of only URNs of the given schemes
func (l URNList) WithScheme(schemes ...string) URNList {
var matching URNList
for _, u := range l {
if u.urn.Scheme() == scheme {
if slices.Contains(schemes, u.urn.Scheme()) {
matching = append(matching, u)
}
}
Expand Down
11 changes: 8 additions & 3 deletions services/airtime/dtone/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import (
"fmt"
"net/http"
"strings"

"github.com/nyaruka/gocommon/httpx"
"github.com/nyaruka/gocommon/stringsx"
Expand Down Expand Up @@ -34,8 +35,12 @@
DesiredAmount: decimal.Zero,
ActualAmount: decimal.Zero,
}
recipientPhoneNumber := recipient.Path()
if !strings.HasPrefix(recipientPhoneNumber, "+") {
recipientPhoneNumber = "+" + recipientPhoneNumber

Check warning on line 40 in services/airtime/dtone/service.go

View check run for this annotation

Codecov / codecov/patch

services/airtime/dtone/service.go#L40

Added line #L40 was not covered by tests
}

operators, trace, err := s.client.LookupMobileNumber(recipient.Path())
operators, trace, err := s.client.LookupMobileNumber(recipientPhoneNumber)
if trace != nil {
logHTTP(flows.NewHTTPLog(trace, flows.HTTPStatusFromCode, s.redactor))
}
Expand All @@ -52,7 +57,7 @@
}
}
if operator == nil {
return transfer, fmt.Errorf("unable to find operator for number %s", recipient.Path())
return transfer, fmt.Errorf("unable to find operator for number %s", recipientPhoneNumber)
}

// fetch available products for this operator
Expand Down Expand Up @@ -94,7 +99,7 @@
transfer.DesiredAmount = amounts[transfer.Currency]

// request synchronous confirmed transaction for this product
tx, trace, err := s.client.TransactionAsync(string(transfer.UUID), product.ID, recipient.Path())
tx, trace, err := s.client.TransactionAsync(string(transfer.UUID), product.ID, recipientPhoneNumber)
if trace != nil {
logHTTP(flows.NewHTTPLog(trace, flows.HTTPStatusFromCode, s.redactor))
}
Expand Down
Loading