braintree 4.34.0 → 4.36.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.
- checksums.yaml +4 -4
- data/lib/braintree/apple_pay_card.rb +7 -0
- data/lib/braintree/apple_pay_gateway.rb +43 -0
- data/lib/braintree/base_module.rb +9 -0
- data/lib/braintree/credit_card_verification.rb +2 -0
- data/lib/braintree/customer.rb +2 -2
- data/lib/braintree/customer_gateway.rb +2 -0
- data/lib/braintree/error_codes.rb +20 -0
- data/lib/braintree/gateway.rb +4 -0
- data/lib/braintree/graphql/inputs/billing_address_input.rb +34 -0
- data/lib/braintree/graphql/inputs/create_local_payment_context_input.rb +44 -0
- data/lib/braintree/graphql/inputs/payer_info_input.rb +38 -0
- data/lib/braintree/graphql/inputs/shipping_address_input.rb +34 -0
- data/lib/braintree/local_payment_context.rb +108 -0
- data/lib/braintree/local_payment_context_gateway.rb +132 -0
- data/lib/braintree/local_payment_type.rb +6 -0
- data/lib/braintree/merchant_gateway.rb +16 -16
- data/lib/braintree/monetary_amount.rb +24 -0
- data/lib/braintree/payment_instrument_type.rb +1 -0
- data/lib/braintree/payment_method_parser.rb +1 -0
- data/lib/braintree/successful_result.rb +1 -0
- data/lib/braintree/test/nonce.rb +1 -0
- data/lib/braintree/test/transaction_amounts.rb +1 -0
- data/lib/braintree/transaction/visa_checkout_card_details.rb +2 -0
- data/lib/braintree/transaction.rb +8 -2
- data/lib/braintree/transaction_gateway.rb +12 -5
- data/lib/braintree/transaction_search.rb +1 -0
- data/lib/braintree/validation_error_collection.rb +1 -1
- data/lib/braintree/version.rb +1 -1
- data/lib/braintree/visa_checkout_card.rb +2 -0
- data/lib/braintree.rb +20 -3
- data/spec/integration/braintree/customer_spec.rb +550 -16
- data/spec/integration/braintree/http_spec.rb +1 -1
- data/spec/integration/braintree/local_payment_context_spec.rb +168 -0
- data/spec/integration/braintree/merchant_spec.rb +5 -169
- data/spec/integration/braintree/payment_method_spec.rb +174 -1
- data/spec/integration/braintree/payment_method_us_bank_account_spec.rb +1 -1
- data/spec/integration/braintree/test_transaction_spec.rb +6 -6
- data/spec/integration/braintree/transaction_idempotency_spec.rb +320 -0
- data/spec/integration/braintree/transaction_search_spec.rb +3 -2
- data/spec/integration/braintree/transaction_spec.rb +91 -0
- data/spec/integration/braintree/transaction_us_bank_account_spec.rb +42 -0
- data/spec/integration/braintree/visa_checkout_card_spec.rb +4 -100
- data/spec/spec_helper.rb +2 -0
- data/spec/unit/braintree/credit_card_verification_spec.rb +1 -1
- data/spec/unit/braintree/customer_spec.rb +67 -1
- data/spec/unit/braintree/graphql/billing_address_input_spec.rb +68 -0
- data/spec/unit/braintree/graphql/create_local_payment_context_input_spec.rb +63 -0
- data/spec/unit/braintree/graphql/monetary_amount_input_spec.rb +55 -0
- data/spec/unit/braintree/graphql/payer_info_input_spec.rb +92 -0
- data/spec/unit/braintree/local_payment_context_gateway_spec.rb +149 -0
- data/spec/unit/braintree/local_payment_context_spec.rb +141 -0
- data/spec/unit/braintree/monetary_amount_spec.rb +34 -0
- data/spec/unit/braintree/three_d_secure_info_spec.rb +3 -1
- data/spec/unit/braintree/transaction/apple_pay_details_spec.rb +7 -7
- data/spec/unit/braintree/transaction/google_pay_details_spec.rb +7 -7
- data/spec/unit/braintree/transaction/meta_checkout_card_details_spec.rb +6 -6
- data/spec/unit/braintree/transaction/meta_checkout_token_details_spec.rb +6 -6
- data/spec/unit/braintree/transaction/payment_receipt_spec.rb +4 -4
- data/spec/unit/braintree/transaction/visa_checkout_card_details_spec.rb +6 -6
- data/spec/unit/braintree/transaction_gateway_spec.rb +5 -3
- data/spec/unit/braintree/transaction_spec.rb +31 -0
- data/spec/unit/braintree/visa_checkout_card_spec.rb +1 -0
- data/spec/unit/credit_card_details_spec.rb +6 -6
- data/spec/unit/spec_helper.rb +9 -0
- metadata +23 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bddd5ecd987b2c8f75088ac1877e7273eebe8463165f9c1db10c92f61aa5961a
|
|
4
|
+
data.tar.gz: 7757bdac8b5bf0808812c073b5e8fcd50e759b4078c51c41def3590467651f12
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 37bba6f56222e7f56caca748920befd5d8f443669411cd42f998fe9c17d4c381605e50c38732ce5831f1e6368806ddb96ac0baa4438dd3dc34294d63db5cdfde
|
|
7
|
+
data.tar.gz: 7f2ae5944a6e3b08da6df35cb6c26aeffbac5c6baa6124d24ddf52abdc7216b6a6a3e77278124993cec2592513cff4ad9d2619eb7b65b15ea835f3fa37f239a5
|
|
@@ -44,12 +44,19 @@ module Braintree
|
|
|
44
44
|
attr_reader :subscriptions
|
|
45
45
|
attr_reader :token
|
|
46
46
|
attr_reader :updated_at
|
|
47
|
+
attr_reader :verification
|
|
47
48
|
|
|
48
49
|
def initialize(gateway, attributes)
|
|
49
50
|
@gateway = gateway
|
|
50
51
|
set_instance_variables_from_hash(attributes)
|
|
51
52
|
@billing_address = attributes[:billing_address] ? Address._new(@gateway, attributes[:billing_address]) : nil
|
|
52
53
|
@subscriptions = (@subscriptions || []).map { |subscription_hash| Subscription._new(@gateway, subscription_hash) }
|
|
54
|
+
@verification = _most_recent_verification(attributes)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def _most_recent_verification(attributes)
|
|
58
|
+
sorted_verifications = (attributes[:verifications] || []).sort_by { |verification| verification[:created_at] }.reverse.first
|
|
59
|
+
CreditCardVerification._new(sorted_verifications) if sorted_verifications
|
|
53
60
|
end
|
|
54
61
|
|
|
55
62
|
def default?
|
|
@@ -33,5 +33,48 @@ module Braintree
|
|
|
33
33
|
raise "expected :response or :api_error_response"
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
|
+
|
|
37
|
+
def self._card_signature(type)
|
|
38
|
+
billing_address_params = AddressGateway._shared_signature
|
|
39
|
+
|
|
40
|
+
options = [
|
|
41
|
+
:verification_account_type,
|
|
42
|
+
:verification_amount,
|
|
43
|
+
:verification_merchant_account_id,
|
|
44
|
+
:verify_card
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
signature = [
|
|
48
|
+
:cardholder_name,
|
|
49
|
+
:cryptogram,
|
|
50
|
+
:eci_indicator,
|
|
51
|
+
:expiration_month,
|
|
52
|
+
:expiration_year,
|
|
53
|
+
:network_transaction_id,
|
|
54
|
+
:number,
|
|
55
|
+
:token,
|
|
56
|
+
{:billing_address => billing_address_params},
|
|
57
|
+
{:options => options}
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
case type
|
|
61
|
+
when :create
|
|
62
|
+
nil
|
|
63
|
+
when :update
|
|
64
|
+
options << :make_default
|
|
65
|
+
else
|
|
66
|
+
raise ArgumentError, "Invalid signature type: #{type}"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
signature
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self._create_card_signature
|
|
73
|
+
_card_signature(:create)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def self._update_card_signature
|
|
77
|
+
_card_signature(:update)
|
|
78
|
+
end
|
|
36
79
|
end
|
|
37
80
|
end
|
|
@@ -35,6 +35,15 @@ module Braintree
|
|
|
35
35
|
def singleton_class
|
|
36
36
|
class << self; self; end
|
|
37
37
|
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def _format_hash(hash)
|
|
42
|
+
formatted_pairs = hash.map do |key, value|
|
|
43
|
+
":#{key}=>#{value.inspect}"
|
|
44
|
+
end
|
|
45
|
+
"{#{formatted_pairs.join(", ")}}"
|
|
46
|
+
end
|
|
38
47
|
end
|
|
39
48
|
|
|
40
49
|
def self.included(klass)
|
|
@@ -28,6 +28,7 @@ module Braintree
|
|
|
28
28
|
attr_reader :amount
|
|
29
29
|
attr_reader :ani_first_name_response_code
|
|
30
30
|
attr_reader :ani_last_name_response_code
|
|
31
|
+
attr_reader :apple_pay
|
|
31
32
|
attr_reader :avs_error_response_code
|
|
32
33
|
attr_reader :avs_postal_code_response_code
|
|
33
34
|
attr_reader :avs_street_address_response_code
|
|
@@ -64,6 +65,7 @@ module Braintree
|
|
|
64
65
|
:amount,
|
|
65
66
|
:ani_first_name_response_code,
|
|
66
67
|
:ani_last_name_response_code,
|
|
68
|
+
:apple_pay,
|
|
67
69
|
:avs_error_response_code,
|
|
68
70
|
:avs_postal_code_response_code,
|
|
69
71
|
:avs_street_address_response_code,
|
data/lib/braintree/customer.rb
CHANGED
|
@@ -90,7 +90,7 @@ module Braintree
|
|
|
90
90
|
@google_pay_cards = (@google_pay_cards || []).map { |pm| GooglePayCard._new gateway, pm }
|
|
91
91
|
@venmo_accounts = (@venmo_accounts || []).map { |pm| VenmoAccount._new gateway, pm }
|
|
92
92
|
@us_bank_accounts = (@us_bank_accounts || []).map { |pm| UsBankAccount._new gateway, pm }
|
|
93
|
-
@visa_checkout_cards = (@visa_checkout_cards|| []).map { |pm| VisaCheckoutCard._new gateway, pm }
|
|
93
|
+
@visa_checkout_cards = (@visa_checkout_cards|| []).map { |pm| VisaCheckoutCard._new gateway, pm } # Deprecated
|
|
94
94
|
@sepa_direct_debit_accounts = (@sepa_debit_accounts || []).map { |pm| SepaDirectDebitAccount._new gateway, pm }
|
|
95
95
|
@samsung_pay_cards = (@samsung_pay_cards|| []).map { |pm| SamsungPayCard._new gateway, pm } # Deprecated
|
|
96
96
|
@addresses = (@addresses || []).map { |addr| Address._new gateway, addr }
|
|
@@ -129,7 +129,7 @@ module Braintree
|
|
|
129
129
|
def inspect
|
|
130
130
|
first = [:id]
|
|
131
131
|
last = [:addresses, :credit_cards, :paypal_accounts, :tax_identifiers]
|
|
132
|
-
order = first + (self.class._attributes - first - last) + last
|
|
132
|
+
order = (first + ((self.class._attributes - first) - last)) + last
|
|
133
133
|
nice_attributes = order.map do |attr|
|
|
134
134
|
"#{attr}: #{send(attr).inspect}"
|
|
135
135
|
end
|
|
@@ -82,6 +82,7 @@ module Braintree
|
|
|
82
82
|
:last_name, :phone, :website,
|
|
83
83
|
:device_data, :payment_method_nonce,
|
|
84
84
|
{:risk_data => [:customer_browser, :customer_ip]},
|
|
85
|
+
{:apple_pay_card => ApplePayGateway._create_card_signature},
|
|
85
86
|
{:credit_card => credit_card_signature},
|
|
86
87
|
{:paypal_account => paypal_account_signature},
|
|
87
88
|
{:tax_identifiers => [:country_code, :identifier]},
|
|
@@ -147,6 +148,7 @@ module Braintree
|
|
|
147
148
|
{:international_phone => [:country_code, :national_number]},
|
|
148
149
|
:last_name, :phone, :website,
|
|
149
150
|
:device_data, :payment_method_nonce, :default_payment_method_token,
|
|
151
|
+
{:apple_pay_card => ApplePayGateway._update_card_signature},
|
|
150
152
|
{:credit_card => credit_card_signature},
|
|
151
153
|
{:tax_identifiers => [:country_code, :identifier]},
|
|
152
154
|
{:options => options},
|
|
@@ -51,6 +51,7 @@ module Braintree
|
|
|
51
51
|
MerchantKeysAlreadyConfigured = "93515"
|
|
52
52
|
MerchantKeysNotConfigured = "93516"
|
|
53
53
|
MerchantNotConfigured = "93514"
|
|
54
|
+
NetworkTransactionIdNotAllowed = "93532"
|
|
54
55
|
NumberIsRequired = "93508"
|
|
55
56
|
PaymentMethodNonceCardTypeIsNotAccepted = "83518"
|
|
56
57
|
PaymentMethodNonceConsumed = "93504"
|
|
@@ -58,6 +59,17 @@ module Braintree
|
|
|
58
59
|
PaymentMethodNonceUnknown = "93505"
|
|
59
60
|
PrivateKeyMismatch = "93521"
|
|
60
61
|
TokenIsInUse = "93503"
|
|
62
|
+
|
|
63
|
+
module Options
|
|
64
|
+
VerificationAccountTypeIsInvalid = "93538"
|
|
65
|
+
VerificationAccountTypeNotSupported = "93543"
|
|
66
|
+
VerificationAmountCannotBeNegative = "93535"
|
|
67
|
+
VerificationAmountFormatIsInvalid = "93534"
|
|
68
|
+
VerificationAmountIsTooLarge = "93537"
|
|
69
|
+
VerificationAmountNotSupportedByProcessor = "93536"
|
|
70
|
+
VerificationMerchantAccountIdIsInvalid = "93540"
|
|
71
|
+
VerificationMerchantAccountIsSuspended = "93541"
|
|
72
|
+
end
|
|
61
73
|
end
|
|
62
74
|
|
|
63
75
|
module CreditCard
|
|
@@ -136,6 +148,8 @@ module Braintree
|
|
|
136
148
|
IdIsNotAllowed = "91611"
|
|
137
149
|
IdIsRequired = "91613"
|
|
138
150
|
IdIsTooLong = "91612"
|
|
151
|
+
InternationalPhoneCountryCodeIsInvalid = "91625"
|
|
152
|
+
InternationalPhoneNationalNumberIsInvalid = "91626"
|
|
139
153
|
LastNameIsTooLong = "81613"
|
|
140
154
|
PhoneIsTooLong = "81614"
|
|
141
155
|
VaultedPaymentInstrumentNonceBelongsToDifferentCustomer = "91617"
|
|
@@ -365,6 +379,12 @@ module Braintree
|
|
|
365
379
|
DiscountAmountFormatIsInvalid = "915159"
|
|
366
380
|
DiscountAmountIsTooLarge = "915161"
|
|
367
381
|
ExchangeRateQuoteIdTooLong = "915229"
|
|
382
|
+
ApiRequestKeyTooLong = "915230"
|
|
383
|
+
ApiRequestKeyNotAllowed = "915231"
|
|
384
|
+
ApiRequestKeyCanBeReusedOnlyWithTheSameRequest = "915232"
|
|
385
|
+
ApiRequestKeyIsInFlight = "915233"
|
|
386
|
+
ApiRequestKeyWithFailedRequest = "915234"
|
|
387
|
+
ApiRequestKeyServerError = "915235"
|
|
368
388
|
FailedAuthAdjustmentAllowRetry = "95603"
|
|
369
389
|
FailedAuthAdjustmentHardDecline = "95602"
|
|
370
390
|
FinalAuthSubmitForSettlementForDifferentAmount = "95601"
|
data/lib/braintree/gateway.rb
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Braintree
|
|
2
|
+
class BillingAddressInput
|
|
3
|
+
include BaseModule
|
|
4
|
+
|
|
5
|
+
attr_reader :attrs
|
|
6
|
+
attr_reader :country_code_alpha2
|
|
7
|
+
attr_reader :extended_address
|
|
8
|
+
attr_reader :locality
|
|
9
|
+
attr_reader :postal_code
|
|
10
|
+
attr_reader :region
|
|
11
|
+
attr_reader :street_address
|
|
12
|
+
|
|
13
|
+
def initialize(attributes)
|
|
14
|
+
@attrs = attributes.keys
|
|
15
|
+
set_instance_variables_from_hash(attributes)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def inspect
|
|
19
|
+
inspected_attributes = @attrs.map { |attr| "#{attr}:#{send(attr).inspect}" }
|
|
20
|
+
"#<#{self.class} #{inspected_attributes.join(" ")}>"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_graphql_variables
|
|
24
|
+
{
|
|
25
|
+
"countryCode" => country_code_alpha2,
|
|
26
|
+
"extendedAddress" => extended_address,
|
|
27
|
+
"locality" => locality,
|
|
28
|
+
"postalCode" => postal_code,
|
|
29
|
+
"region" => region,
|
|
30
|
+
"streetAddress" => street_address
|
|
31
|
+
}.compact
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Braintree
|
|
2
|
+
class CreateLocalPaymentContextInput
|
|
3
|
+
include BaseModule
|
|
4
|
+
|
|
5
|
+
attr_reader :amount
|
|
6
|
+
attr_reader :attrs
|
|
7
|
+
attr_reader :cancel_url
|
|
8
|
+
attr_reader :country_code
|
|
9
|
+
attr_reader :expiry_date
|
|
10
|
+
attr_reader :merchant_account_id
|
|
11
|
+
attr_reader :order_id
|
|
12
|
+
attr_reader :payer_info
|
|
13
|
+
attr_reader :return_url
|
|
14
|
+
attr_reader :type
|
|
15
|
+
|
|
16
|
+
def initialize(attributes)
|
|
17
|
+
@attrs = attributes.keys
|
|
18
|
+
set_instance_variables_from_hash(attributes)
|
|
19
|
+
@amount = attributes[:amount] ? MonetaryAmountInput.new(attributes[:amount]) : nil
|
|
20
|
+
@payer_info = attributes[:payer_info] ? PayerInfoInput.new(attributes[:payer_info]) : nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def inspect
|
|
24
|
+
inspected_attributes = @attrs.map { |attr| "#{attr}:#{send(attr).inspect}" }
|
|
25
|
+
"#<#{self.class} #{inspected_attributes.join(" ")}>"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def to_graphql_variables
|
|
29
|
+
{
|
|
30
|
+
"paymentContext" => {
|
|
31
|
+
"amount" => amount&.to_graphql_variables,
|
|
32
|
+
"cancelUrl" => cancel_url,
|
|
33
|
+
"countryCode" => country_code,
|
|
34
|
+
"expiryDate" => expiry_date,
|
|
35
|
+
"merchantAccountId" => merchant_account_id,
|
|
36
|
+
"orderId" => order_id,
|
|
37
|
+
"payerInfo" => payer_info&.to_graphql_variables,
|
|
38
|
+
"returnUrl" => return_url,
|
|
39
|
+
"type" => type
|
|
40
|
+
}.compact
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Braintree
|
|
2
|
+
class PayerInfoInput
|
|
3
|
+
include BaseModule
|
|
4
|
+
|
|
5
|
+
attr_reader :attrs
|
|
6
|
+
attr_reader :billing_address
|
|
7
|
+
attr_reader :email
|
|
8
|
+
attr_reader :given_name
|
|
9
|
+
attr_reader :phone_country_code
|
|
10
|
+
attr_reader :phone_number
|
|
11
|
+
attr_reader :shipping_address
|
|
12
|
+
attr_reader :surname
|
|
13
|
+
|
|
14
|
+
def initialize(attributes)
|
|
15
|
+
@attrs = attributes.keys
|
|
16
|
+
set_instance_variables_from_hash(attributes)
|
|
17
|
+
@billing_address = attributes[:billing_address] ? BillingAddressInput.new(attributes[:billing_address]) : nil
|
|
18
|
+
@shipping_address = attributes[:shipping_address] ? ShippingAddressInput.new(attributes[:shipping_address]) : nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def inspect
|
|
22
|
+
inspected_attributes = @attrs.map { |attr| "#{attr}:#{send(attr).inspect}" }
|
|
23
|
+
"#<#{self.class} #{inspected_attributes.join(" ")}>"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_graphql_variables
|
|
27
|
+
{
|
|
28
|
+
"billingAddress" => billing_address&.to_graphql_variables,
|
|
29
|
+
"email" => email,
|
|
30
|
+
"givenName" => given_name,
|
|
31
|
+
"phoneCountryCode" => phone_country_code,
|
|
32
|
+
"phoneNumber" => phone_number,
|
|
33
|
+
"shippingAddress" => shipping_address&.to_graphql_variables,
|
|
34
|
+
"surname" => surname
|
|
35
|
+
}.compact
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Braintree
|
|
2
|
+
class ShippingAddressInput
|
|
3
|
+
include BaseModule
|
|
4
|
+
|
|
5
|
+
attr_reader :attrs
|
|
6
|
+
attr_reader :country_code_alpha2
|
|
7
|
+
attr_reader :extended_address
|
|
8
|
+
attr_reader :locality
|
|
9
|
+
attr_reader :postal_code
|
|
10
|
+
attr_reader :region
|
|
11
|
+
attr_reader :street_address
|
|
12
|
+
|
|
13
|
+
def initialize(attributes)
|
|
14
|
+
@attrs = attributes.keys
|
|
15
|
+
set_instance_variables_from_hash(attributes)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def inspect
|
|
19
|
+
inspected_attributes = @attrs.map { |attr| "#{attr}:#{send(attr).inspect}" }
|
|
20
|
+
"#<#{self.class} #{inspected_attributes.join(" ")}>"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_graphql_variables
|
|
24
|
+
{
|
|
25
|
+
"countryCode" => country_code_alpha2,
|
|
26
|
+
"extendedAddress" => extended_address,
|
|
27
|
+
"locality" => locality,
|
|
28
|
+
"postalCode" => postal_code,
|
|
29
|
+
"region" => region,
|
|
30
|
+
"streetAddress" => street_address
|
|
31
|
+
}.compact
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
module Braintree
|
|
2
|
+
class LocalPaymentContext
|
|
3
|
+
include BaseModule
|
|
4
|
+
|
|
5
|
+
attr_reader :amount
|
|
6
|
+
attr_reader :approval_url
|
|
7
|
+
attr_reader :approved_at
|
|
8
|
+
attr_reader :attrs
|
|
9
|
+
attr_reader :created_at
|
|
10
|
+
attr_reader :expired_at
|
|
11
|
+
attr_reader :id
|
|
12
|
+
attr_reader :legacy_id
|
|
13
|
+
attr_reader :merchant_account_id
|
|
14
|
+
attr_reader :order_id
|
|
15
|
+
attr_reader :payment_id
|
|
16
|
+
attr_reader :transacted_at
|
|
17
|
+
attr_reader :type
|
|
18
|
+
attr_reader :updated_at
|
|
19
|
+
|
|
20
|
+
def initialize(attributes)
|
|
21
|
+
@attrs = [:amount, :approval_url, :approved_at, :attrs, :created_at, :expired_at, :id, :legacy_id,
|
|
22
|
+
:merchant_account_id, :order_id, :payment_id, :transacted_at, :type, :updated_at]
|
|
23
|
+
|
|
24
|
+
if attributes.key?(:response)
|
|
25
|
+
response = attributes[:response]
|
|
26
|
+
@id = _get_value(response, "paymentContext.id")
|
|
27
|
+
@legacy_id = _get_value_optional(response, "paymentContext.legacyId")
|
|
28
|
+
@type = _get_value(response, "paymentContext.type")
|
|
29
|
+
@payment_id = _get_value_optional(response, "paymentContext.paymentId")
|
|
30
|
+
@order_id = _get_value_optional(response, "paymentContext.orderId")
|
|
31
|
+
@approval_url = _get_value_optional(response, "paymentContext.approvalUrl")
|
|
32
|
+
@merchant_account_id = _get_value_optional(response, "paymentContext.merchantAccountId")
|
|
33
|
+
@created_at = _get_value_optional(response, "paymentContext.createdAt")
|
|
34
|
+
@updated_at = _get_value_optional(response, "paymentContext.updatedAt")
|
|
35
|
+
@transacted_at = _get_value_optional(response, "paymentContext.transactedAt")
|
|
36
|
+
@approved_at = _get_value_optional(response, "paymentContext.approvedAt")
|
|
37
|
+
@expired_at = _get_value_optional(response, "paymentContext.expiredAt")
|
|
38
|
+
@amount = _extract_amount(response)
|
|
39
|
+
else
|
|
40
|
+
set_instance_variables_from_hash(attributes)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def inspect
|
|
45
|
+
inspected_attributes = @attrs.map { |attr| "#{attr}:#{send(attr).inspect}" }
|
|
46
|
+
"#<#{self.class} #{inspected_attributes.join(" ")}>"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
class << self
|
|
50
|
+
protected :new
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self._new(*args)
|
|
54
|
+
self.new(*args)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def _extract_amount(response)
|
|
60
|
+
amount_hash = _get_value_optional(response, "paymentContext.amount")
|
|
61
|
+
return nil unless amount_hash
|
|
62
|
+
|
|
63
|
+
currency = amount_hash[:currencyCode] || amount_hash["currencyCode"] ||
|
|
64
|
+
amount_hash[:currencyIsoCode] || amount_hash["currencyIsoCode"]
|
|
65
|
+
|
|
66
|
+
MonetaryAmount._new({
|
|
67
|
+
value: amount_hash[:value] || amount_hash["value"],
|
|
68
|
+
currency_code: currency
|
|
69
|
+
})
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def _get_value(response, key)
|
|
73
|
+
current_map = response
|
|
74
|
+
key_parts = key.split(".")
|
|
75
|
+
|
|
76
|
+
(0...key_parts.length - 1).each do |i|
|
|
77
|
+
sub_key = key_parts[i]
|
|
78
|
+
current_map = _pop_value(current_map, sub_key)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
last_key = key_parts[-1]
|
|
82
|
+
_pop_value(current_map, last_key)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def _get_value_optional(response, key)
|
|
86
|
+
_get_value(response, key)
|
|
87
|
+
rescue ServerError
|
|
88
|
+
nil
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def _pop_value(response, key)
|
|
92
|
+
if response.key?(key)
|
|
93
|
+
return response[key]
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
symkey = key.to_sym
|
|
97
|
+
if response.key?(symkey)
|
|
98
|
+
return response[symkey]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
if response.key?(key.to_s)
|
|
102
|
+
return response[key.to_s]
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
raise ServerError.new("Couldn't parse response")
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
module Braintree
|
|
2
|
+
class LocalPaymentContextGateway
|
|
3
|
+
CREATE_LOCAL_PAYMENT_CONTEXT = <<~GRAPHQL
|
|
4
|
+
mutation CreateLocalPaymentContext($input: CreateLocalPaymentContextInput!) {
|
|
5
|
+
createLocalPaymentContext(input: $input) {
|
|
6
|
+
paymentContext {
|
|
7
|
+
id
|
|
8
|
+
legacyId
|
|
9
|
+
type
|
|
10
|
+
paymentId
|
|
11
|
+
approvalUrl
|
|
12
|
+
merchantAccountId
|
|
13
|
+
orderId
|
|
14
|
+
createdAt
|
|
15
|
+
transactedAt
|
|
16
|
+
approvedAt
|
|
17
|
+
amount {
|
|
18
|
+
value
|
|
19
|
+
currencyCode
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
GRAPHQL
|
|
25
|
+
|
|
26
|
+
FIND_LOCAL_PAYMENT_CONTEXT = <<~GRAPHQL
|
|
27
|
+
query Node($id: ID!) {
|
|
28
|
+
node(id: $id) {
|
|
29
|
+
... on LocalPaymentContext {
|
|
30
|
+
id
|
|
31
|
+
legacyId
|
|
32
|
+
type
|
|
33
|
+
amount {
|
|
34
|
+
value
|
|
35
|
+
currencyIsoCode
|
|
36
|
+
}
|
|
37
|
+
approvalUrl
|
|
38
|
+
merchantAccountId
|
|
39
|
+
transactedAt
|
|
40
|
+
approvedAt
|
|
41
|
+
createdAt
|
|
42
|
+
updatedAt
|
|
43
|
+
expiredAt
|
|
44
|
+
paymentId
|
|
45
|
+
orderId
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
GRAPHQL
|
|
50
|
+
|
|
51
|
+
def initialize(gateway, graphql_client)
|
|
52
|
+
@gateway = gateway
|
|
53
|
+
@graphql_client = graphql_client
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def create(input)
|
|
57
|
+
variables = {"input" => input.to_graphql_variables}
|
|
58
|
+
|
|
59
|
+
begin
|
|
60
|
+
response = @graphql_client.query(CREATE_LOCAL_PAYMENT_CONTEXT, variables)
|
|
61
|
+
errors = GraphQLClient.get_validation_errors(response)
|
|
62
|
+
|
|
63
|
+
if errors
|
|
64
|
+
ErrorResult.new(@gateway, {errors: errors})
|
|
65
|
+
else
|
|
66
|
+
payment_context = extract_payment_context(response)
|
|
67
|
+
SuccessfulResult.new(:payment_context => payment_context)
|
|
68
|
+
end
|
|
69
|
+
rescue StandardError => e
|
|
70
|
+
raise UnexpectedError, e.message
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def find(id)
|
|
75
|
+
variables = {"id" => id}
|
|
76
|
+
|
|
77
|
+
begin
|
|
78
|
+
response = @graphql_client.query(FIND_LOCAL_PAYMENT_CONTEXT, variables)
|
|
79
|
+
errors = GraphQLClient.get_validation_errors(response)
|
|
80
|
+
|
|
81
|
+
if errors
|
|
82
|
+
ErrorResult.new(@gateway, {errors: errors})
|
|
83
|
+
else
|
|
84
|
+
payment_context = extract_node_payment_context(response)
|
|
85
|
+
SuccessfulResult.new(:payment_context => payment_context)
|
|
86
|
+
end
|
|
87
|
+
rescue NotFoundError
|
|
88
|
+
raise
|
|
89
|
+
rescue StandardError => e
|
|
90
|
+
raise UnexpectedError, e.message
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
def extract_payment_context(response)
|
|
97
|
+
context_hash = get_value(response, "data.createLocalPaymentContext.paymentContext")
|
|
98
|
+
LocalPaymentContext._new({:response => {"paymentContext" => context_hash}})
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def extract_node_payment_context(response)
|
|
102
|
+
node_hash = get_value(response, "data.node")
|
|
103
|
+
|
|
104
|
+
if node_hash.nil?
|
|
105
|
+
raise NotFoundError, "Payment context not found"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
LocalPaymentContext._new({:response => {"paymentContext" => node_hash}})
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def get_value(response, key)
|
|
112
|
+
map = response
|
|
113
|
+
key_parts = key.split(".")
|
|
114
|
+
|
|
115
|
+
key_parts[0..-2].each do |sub_key|
|
|
116
|
+
map = pop_value(map, sub_key)
|
|
117
|
+
raise UnexpectedError, "Couldn't parse response" unless map.is_a?(Hash)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
pop_value(map, key_parts.last)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def pop_value(map, key)
|
|
124
|
+
key = key.to_sym
|
|
125
|
+
if map.key?(key)
|
|
126
|
+
map[key]
|
|
127
|
+
else
|
|
128
|
+
raise UnexpectedError, "Couldn't parse response"
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -5,22 +5,10 @@ module Braintree
|
|
|
5
5
|
@config = gateway.config
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if response[:apple_pay]
|
|
11
|
-
SuccessfulResult.new(response[:apple_pay])
|
|
12
|
-
elsif response[:api_error_response]
|
|
13
|
-
ErrorResult.new(@gateway, response[:api_error_response])
|
|
14
|
-
else
|
|
15
|
-
raise UnexpectedError, "expected :apple_pay or :api_error_response"
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
8
|
+
# NEXT_MAJOR_VERSION remove this method
|
|
9
|
+
# The create_via_api endpoint has been disabled; this method always raises a server error
|
|
19
10
|
def create(params)
|
|
20
|
-
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def _create_merchant(params)
|
|
11
|
+
warn "[DEPRECATED] Merchant.create is deprecated and will be removed in a future version."
|
|
24
12
|
response = @config.http.post("/merchants/create_via_api", :merchant => params)
|
|
25
13
|
|
|
26
14
|
if response.has_key?(:response) && response[:response][:merchant]
|
|
@@ -31,8 +19,20 @@ module Braintree
|
|
|
31
19
|
elsif response[:api_error_response]
|
|
32
20
|
ErrorResult.new(@gateway, response[:api_error_response])
|
|
33
21
|
else
|
|
34
|
-
raise "expected :merchant or :api_error_response"
|
|
22
|
+
raise UnexpectedError, "expected :merchant or :api_error_response"
|
|
35
23
|
end
|
|
36
24
|
end
|
|
25
|
+
|
|
26
|
+
def provision_raw_apple_pay
|
|
27
|
+
response = @config.http.put("#{@config.base_merchant_path}/provision_raw_apple_pay")
|
|
28
|
+
if response[:apple_pay]
|
|
29
|
+
SuccessfulResult.new(response[:apple_pay])
|
|
30
|
+
elsif response[:api_error_response]
|
|
31
|
+
ErrorResult.new(@gateway, response[:api_error_response])
|
|
32
|
+
else
|
|
33
|
+
raise UnexpectedError, "expected :apple_pay or :api_error_response"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
37
|
end
|
|
38
38
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Braintree
|
|
2
|
+
class MonetaryAmount
|
|
3
|
+
include BaseModule
|
|
4
|
+
|
|
5
|
+
attr_reader :currency_code
|
|
6
|
+
attr_reader :value
|
|
7
|
+
|
|
8
|
+
def initialize(attributes)
|
|
9
|
+
set_instance_variables_from_hash(attributes)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def inspect
|
|
13
|
+
"#<MonetaryAmount currency_code:#{currency_code.inspect} value:#{value.inspect}>"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
protected :new
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self._new(*args)
|
|
21
|
+
self.new(*args)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|