github.com/Ingenico-ePayments/connect-sdk-go@v0.0.0-20240318153750-1f8cd329b9c9/webhooks/Helper_test.go (about) 1 package webhooks 2 3 import ( 4 "encoding/json" 5 "testing" 6 7 "github.com/Ingenico-ePayments/connect-sdk-go/communicator/communication" 8 "github.com/Ingenico-ePayments/connect-sdk-go/domain/webhooks" 9 "io" 10 ) 11 12 var ( 13 testValidBody = `{ 14 "apiVersion": "v1", 15 "id": "8ee793f6-4553-4749-85dc-f2ef095c5ab0", 16 "created": "2017-02-02T11:24:14.040+0100", 17 "merchantId": "20000", 18 "type": "payment.paid", 19 "payment": { 20 "id": "00000200000143570012", 21 "paymentOutput": { 22 "amountOfMoney": { 23 "amount": 1000, 24 "currencyCode": "EUR" 25 }, 26 "references": { 27 "paymentReference": "200001681810" 28 }, 29 "paymentMethod": "bankTransfer", 30 "bankTransferPaymentMethodSpecificOutput": { 31 "paymentProductId": 11 32 } 33 }, 34 "status": "PAID", 35 "statusOutput": { 36 "isCancellable": false, 37 "statusCategory": "COMPLETED", 38 "statusCode": 1000, 39 "statusCodeChangeDateTime": "20170202112414", 40 "isAuthorized": true 41 } 42 } 43 }` 44 testInvalidBody = `{ 45 "apiVersion": "v1", 46 "id": "8ee793f6-4553-4749-85dc-f2ef095c5ab0", 47 "created": "2017-02-02T11:25:14.040+0100", 48 "merchantId": "20000", 49 "type": "payment.paid", 50 "payment": { 51 "id": "00000200000143570012", 52 "paymentOutput": { 53 "amountOfMoney": { 54 "amount": 1000, 55 "currencyCode": "EUR" 56 }, 57 "references": { 58 "paymentReference": "200001681810" 59 }, 60 "paymentMethod": "bankTransfer", 61 "bankTransferPaymentMethodSpecificOutput": { 62 "paymentProductId": 11 63 } 64 }, 65 "status": "PAID", 66 "statusOutput": { 67 "isCancellable": false, 68 "statusCategory": "COMPLETED", 69 "statusCode": 1000, 70 "statusCodeChangeDateTime": "20170202112514", 71 "isAuthorized": true 72 } 73 } 74 }` 75 76 testSignature = "2S7doBj/GnJnacIjSJzr5fxGM5xmfQyFAwxv1I53ZEk=" 77 testKeyID = "dummy-key-id" 78 testSecretKey = "hello+world" 79 ) 80 81 var testSignatureHeader, testKeyHeader communication.Header 82 83 type fakeMarshaller struct{} 84 85 func (m *fakeMarshaller) Marshal(v interface{}) (string, error) { 86 dataBytes, err := json.Marshal(v) 87 data := string(dataBytes) 88 89 return data, err 90 } 91 92 func (m *fakeMarshaller) Unmarshal(data string, v interface{}) error { 93 if len(data) < 1 { 94 return nil 95 } 96 97 err := json.Unmarshal([]byte(data), v) 98 if err != nil { 99 return err 100 } 101 102 fakeVersion := "v0" 103 104 event, ok := v.(*webhooks.Event) 105 if ok { 106 event.APIVersion = &fakeVersion 107 } 108 109 return nil 110 } 111 112 func (m *fakeMarshaller) UnmarshalFromReader(reader io.Reader, v interface{}) error { 113 return nil 114 } 115 116 func TestUnmarshalAPIVersionMismatch(t *testing.T) { 117 keyStore := &InMemorySecretKeyStore{} 118 keyStore.Clear() 119 keyStore.StoreSecretKey(testKeyID, testSecretKey) 120 121 helperBuilder, err := CreateHelperBuilder(keyStore) 122 if err != nil { 123 t.Fatal(err) 124 } 125 126 helper, err := helperBuilder.WithMarshaller(&fakeMarshaller{}).Build() 127 if err != nil { 128 t.Fatal(err) 129 } 130 131 requestHeaders := []communication.Header{ 132 testSignatureHeader, 133 testKeyHeader, 134 } 135 136 _, err = helper.Unmarshal(testValidBody, requestHeaders) 137 if err == nil { 138 t.Fatal("nil error") 139 } 140 141 _, ok := err.(*APIVersionMismatchError) 142 if !ok { 143 t.Fatal("wrong error returned") 144 } 145 } 146 147 func TestUnmarshalNoSecretKeyAvailable(t *testing.T) { 148 keyStore := &InMemorySecretKeyStore{} 149 keyStore.Clear() 150 151 helper, err := CreateHelper(keyStore) 152 if err != nil { 153 t.Fatal(err) 154 } 155 156 requestHeaders := []communication.Header{ 157 testSignatureHeader, 158 testKeyHeader, 159 } 160 161 _, err = helper.Unmarshal(testValidBody, requestHeaders) 162 163 if err == nil { 164 t.Fatal("nil error") 165 } 166 167 _, ok := err.(*SecretKeyNotAvailableError) 168 if !ok { 169 t.Fatal("wrong error returned") 170 } 171 } 172 173 func TestUnmarshalMissingHeaders(t *testing.T) { 174 keyStore := &InMemorySecretKeyStore{} 175 keyStore.Clear() 176 177 helper, err := CreateHelper(keyStore) 178 if err != nil { 179 t.Fatal(err) 180 } 181 182 requestHeaders := []communication.Header{} 183 184 _, err = helper.Unmarshal(testValidBody, requestHeaders) 185 186 if err == nil { 187 t.Fatal("nil error") 188 } 189 190 _, ok := err.(*SignatureValidationError) 191 if !ok { 192 t.Fatal("wrong error returned") 193 } 194 } 195 196 func TestUnmarshalDuplicateHeaders(t *testing.T) { 197 keyStore := &InMemorySecretKeyStore{} 198 keyStore.Clear() 199 200 helper, err := CreateHelper(keyStore) 201 if err != nil { 202 t.Fatal(err) 203 } 204 205 requestHeaders := []communication.Header{ 206 testSignatureHeader, 207 testKeyHeader, 208 testSignatureHeader, 209 } 210 211 _, err = helper.Unmarshal(testValidBody, requestHeaders) 212 213 if err == nil { 214 t.Fatal("nil error") 215 } 216 217 _, ok := err.(*SignatureValidationError) 218 if !ok { 219 t.Fatal("wrong error returned") 220 } 221 } 222 223 func TestUnmarshalSuccess(t *testing.T) { 224 keyStore := &InMemorySecretKeyStore{} 225 keyStore.Clear() 226 keyStore.StoreSecretKey(testKeyID, testSecretKey) 227 228 helper, err := CreateHelper(keyStore) 229 if err != nil { 230 t.Fatal(err) 231 } 232 233 requestHeaders := []communication.Header{ 234 testSignatureHeader, 235 testKeyHeader, 236 } 237 238 event, err := helper.Unmarshal(testValidBody, requestHeaders) 239 if err != nil { 240 t.Fatal(err) 241 } 242 243 if event == nil { 244 t.Fatal("nil event") 245 } 246 247 if event.APIVersion == nil || *event.APIVersion != "v1" { 248 t.Fatalf("apiVersion mismatch %v", event.APIVersion) 249 } 250 if event.ID == nil || *event.ID != "8ee793f6-4553-4749-85dc-f2ef095c5ab0" { 251 t.Fatalf("ID mismatch %v", event.ID) 252 } 253 if event.Created == nil || *event.Created != "2017-02-02T11:24:14.040+0100" { 254 t.Fatalf("created mismatch %v", event.Created) 255 } 256 if event.MerchantID == nil || *event.MerchantID != "20000" { 257 t.Fatalf("merchantID mismatch %v", event.MerchantID) 258 } 259 if event.Type == nil || *event.Type != "payment.paid" { 260 t.Fatalf("type mismatch %v", event.Type) 261 } 262 263 if event.Refund != nil { 264 t.Fatalf("non-nil refund %v", event.Refund) 265 } 266 if event.Payout != nil { 267 t.Fatalf("non-nil payout %v", event.Payout) 268 } 269 if event.Token != nil { 270 t.Fatalf("non-nil token %v", event.Token) 271 } 272 273 if event.Payment == nil { 274 t.Fatal("nil paymentResponse") 275 } 276 if event.Payment.ID != nil && *event.Payment.ID != "00000200000143570012" { 277 t.Fatalf("payment.ID mismatch %v", event.Payment.ID) 278 } 279 if event.Payment.PaymentOutput == nil { 280 t.Fatal("nil payment.PaymentOutput") 281 } 282 if event.Payment.PaymentOutput.AmountOfMoney == nil { 283 t.Fatal("nil payment.PaymentOutput.AmountOfMoney") 284 } 285 if event.Payment.PaymentOutput.AmountOfMoney.Amount == nil || *event.Payment.PaymentOutput.AmountOfMoney.Amount != 1000 { 286 t.Fatalf("payment.PaymentOutput.AmountOfMoney.Amount mismatch %v", event.Payment.PaymentOutput.AmountOfMoney.Amount) 287 } 288 if event.Payment.PaymentOutput.AmountOfMoney.CurrencyCode == nil || *event.Payment.PaymentOutput.AmountOfMoney.CurrencyCode != "EUR" { 289 t.Fatalf("payment.PaymentOutput.AmountOfMoney.CurrencyCode mismatch %v", event.Payment.PaymentOutput.AmountOfMoney.CurrencyCode) 290 } 291 if event.Payment.PaymentOutput.References == nil { 292 t.Fatal("nil payment.PaymentOutput.References") 293 } 294 if event.Payment.PaymentOutput.References.PaymentReference == nil || 295 *event.Payment.PaymentOutput.References.PaymentReference != "200001681810" { 296 t.Fatalf("payment.paymentOutput.References.PaymentReference mismatch %v", event.Payment.PaymentOutput.References.PaymentReference) 297 } 298 if event.Payment.PaymentOutput.PaymentMethod == nil || *event.Payment.PaymentOutput.PaymentMethod != "bankTransfer" { 299 t.Fatalf("payment.paymentOutput.PaymentMethod mismatch %v", event.Payment.PaymentOutput.PaymentMethod) 300 } 301 302 if event.Payment.PaymentOutput.CardPaymentMethodSpecificOutput != nil { 303 t.Fatalf("non-nil payment.PaymentOutput.CardPaymentMethodSpecificOutput %v", event.Payment.PaymentOutput.CardPaymentMethodSpecificOutput) 304 } 305 if event.Payment.PaymentOutput.DirectDebitPaymentMethodSpecificOutput != nil { 306 t.Fatalf("non-nil payment.PaymentOutput.DirectDebitPaymentMethodSpecificOutput %v", event.Payment.PaymentOutput.DirectDebitPaymentMethodSpecificOutput) 307 } 308 if event.Payment.PaymentOutput.InvoicePaymentMethodSpecificOutput != nil { 309 t.Fatalf("non-nil payment.PaymentOutput.InvoicePaymentMethodSpecificOutput %v", event.Payment.PaymentOutput.InvoicePaymentMethodSpecificOutput) 310 } 311 if event.Payment.PaymentOutput.RedirectPaymentMethodSpecificOutput != nil { 312 t.Fatalf("non-nil payment.PaymentOutput.RedirectPaymentMethodSpecificOutput %v", event.Payment.PaymentOutput.RedirectPaymentMethodSpecificOutput) 313 } 314 if event.Payment.PaymentOutput.SepaDirectDebitPaymentMethodSpecificOutput != nil { 315 t.Fatalf("non-nil payment.PaymentOutput.SepaDirectDebitPaymentMethodSpecificOutput %v", event.Payment.PaymentOutput.SepaDirectDebitPaymentMethodSpecificOutput) 316 } 317 if event.Payment.PaymentOutput.BankTransferPaymentMethodSpecificOutput == nil { 318 t.Fatal("nil payment.PaymentOutput.BankTransferPaymentMethodSpecificOutput") 319 } 320 if event.Payment.PaymentOutput.BankTransferPaymentMethodSpecificOutput.PaymentProductID != nil && 321 *event.Payment.PaymentOutput.BankTransferPaymentMethodSpecificOutput.PaymentProductID != 11 { 322 t.Fatalf("payment.PaymentOutput.BankTransferPaymentMethodSpecificOutput.PaymentProductID mismatch %v", event.Payment.PaymentOutput.BankTransferPaymentMethodSpecificOutput.PaymentProductID) 323 } 324 325 if event.Payment.Status == nil || *event.Payment.Status != "PAID" { 326 t.Fatalf("payment.Status mismatch %v", event.Payment.Status) 327 } 328 if event.Payment.StatusOutput == nil { 329 t.Fatal("nil payment.StatusOutput") 330 } 331 if event.Payment.StatusOutput.IsCancellable == nil || *event.Payment.StatusOutput.IsCancellable != false { 332 t.Fatalf("payment.StatusOutput.IsCancellable mismatch %v", event.Payment.StatusOutput.IsCancellable) 333 } 334 if event.Payment.StatusOutput.StatusCategory == nil || *event.Payment.StatusOutput.StatusCategory != "COMPLETED" { 335 t.Fatalf("payment.StatusOutput.StatusCategory mismatch %v", event.Payment.StatusOutput.StatusCategory) 336 } 337 if event.Payment.StatusOutput.StatusCode == nil || *event.Payment.StatusOutput.StatusCode != 1000 { 338 t.Fatalf("payment.StatusOutput.StatusCode mismatch %v", event.Payment.StatusOutput.StatusCode) 339 } 340 if event.Payment.StatusOutput.StatusCodeChangeDateTime == nil || *event.Payment.StatusOutput.StatusCodeChangeDateTime != "20170202112414" { 341 t.Fatalf("payment.StatusOutput.StatusCodeChangeDateTime mismatch %v", event.Payment.StatusOutput.StatusCodeChangeDateTime) 342 } 343 if event.Payment.StatusOutput.IsAuthorized == nil || *event.Payment.StatusOutput.IsAuthorized != true { 344 t.Fatalf("payment.StatusOutput.IsAuthorized mismatch %v", event.Payment.StatusOutput.IsAuthorized) 345 } 346 } 347 348 func TestUnmarshalInvalidBody(t *testing.T) { 349 keyStore := &InMemorySecretKeyStore{} 350 keyStore.Clear() 351 keyStore.StoreSecretKey(testKeyID, testSecretKey) 352 353 helper, err := CreateHelper(keyStore) 354 if err != nil { 355 t.Fatal(err) 356 } 357 358 requestHeaders := []communication.Header{ 359 testSignatureHeader, 360 testKeyHeader, 361 } 362 363 _, err = helper.Unmarshal(testInvalidBody, requestHeaders) 364 if err == nil { 365 t.Fatal("nil error") 366 } 367 368 _, ok := err.(*SignatureValidationError) 369 if !ok { 370 t.Fatal("wrong error returned") 371 } 372 } 373 374 func TestUnmarshalInvalidSecretKey(t *testing.T) { 375 keyStore := &InMemorySecretKeyStore{} 376 keyStore.Clear() 377 keyStore.StoreSecretKey(testKeyID, "1"+testSecretKey) 378 379 helper, err := CreateHelper(keyStore) 380 if err != nil { 381 t.Fatal(err) 382 } 383 384 requestHeaders := []communication.Header{ 385 testSignatureHeader, 386 testKeyHeader, 387 } 388 389 _, err = helper.Unmarshal(testValidBody, requestHeaders) 390 if err == nil { 391 t.Fatal("nil error") 392 } 393 394 _, ok := err.(*SignatureValidationError) 395 if !ok { 396 t.Fatal("wrong error returned") 397 } 398 } 399 400 func TestUnmarshalInvalidSignature(t *testing.T) { 401 keyStore := &InMemorySecretKeyStore{} 402 keyStore.Clear() 403 keyStore.StoreSecretKey(testKeyID, testSecretKey) 404 405 helper, err := CreateHelper(keyStore) 406 if err != nil { 407 t.Fatal(err) 408 } 409 410 testHeader, err := communication.NewHeader("X-GCS-Signature", "1"+testSignature) 411 if err != nil { 412 t.Fatal(err) 413 } 414 415 requestHeaders := []communication.Header{ 416 *testHeader, 417 testKeyHeader, 418 } 419 420 _, err = helper.Unmarshal(testValidBody, requestHeaders) 421 if err == nil { 422 t.Fatal("nil error") 423 } 424 425 _, ok := err.(*SignatureValidationError) 426 if !ok { 427 t.Fatal("wrong error returned") 428 } 429 } 430 431 func init() { 432 signatureHeader, err := communication.NewHeader("X-GCS-Signature", testSignature) 433 if err != nil { 434 panic(err) 435 } 436 437 keyHeader, err := communication.NewHeader("X-GCS-KeyId", testKeyID) 438 if err != nil { 439 panic(err) 440 } 441 442 testSignatureHeader = *signatureHeader 443 testKeyHeader = *keyHeader 444 }