payments: accept CoinPay crypto_amount as number or string

The live CoinPay API returns crypto_amount as a bare JSON number (e.g.
0.0031), but the struct decoded it as a string, so /payments/create failed
with "cannot unmarshal number into ... crypto_amount of type string" and
join@ showed "Payment is temporarily unavailable". The unit test had hidden
the bug by sending the value quoted.

Add a flexStr type that unmarshals from either a JSON number or string and
use it for crypto_amount; update the test to send a number and add a direct
flexStr decode test for both forms.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Anthony Ettinger 2026-06-14 11:45:21 +00:00
parent 641fa01d9a
commit d5135cd1fe
2 changed files with 48 additions and 8 deletions

View file

@ -20,7 +20,8 @@ func TestCreateAndVerifyPremium(t *testing.T) {
_ = json.Unmarshal(b, &body)
gotBlockchain, _ = body["blockchain"].(string)
gotBusiness, _ = body["business_id"].(string)
_, _ = w.Write([]byte(`{"payment":{"id":"pay_1","payment_address":"0xABC","crypto_amount":"0.0031","crypto_currency":"ETH","status":"pending"}}`))
// crypto_amount comes back as a bare JSON number from the live API.
_, _ = w.Write([]byte(`{"payment":{"id":"pay_1","payment_address":"0xABC","crypto_amount":0.0031,"crypto_currency":"ETH","status":"pending"}}`))
case r.Method == http.MethodGet && r.URL.Path == "/payments/pay_1":
_, _ = w.Write([]byte(`{"payment":{"id":"pay_1","status":"confirmed"}}`))
default:
@ -76,3 +77,18 @@ func TestNotConfigured(t *testing.T) {
t.Fatal("unconfigured verify must not be checked")
}
}
func TestFlexStrDecodesNumberOrString(t *testing.T) {
for _, raw := range []string{
`{"payment":{"crypto_amount":0.0031}}`, // live API: bare number
`{"payment":{"crypto_amount":"0.0031"}}`, // legacy: quoted string
} {
var env paymentEnvelope
if err := json.Unmarshal([]byte(raw), &env); err != nil {
t.Fatalf("unmarshal %s: %v", raw, err)
}
if got := string(env.Payment.CryptoAmount); got != "0.0031" {
t.Fatalf("crypto_amount from %s = %q, want 0.0031", raw, got)
}
}
}