activemerchant 1.42.6 → 1.90.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.
Files changed (450) hide show
  1. checksums.yaml +5 -13
  2. data/CHANGELOG +1420 -2
  3. data/CONTRIBUTORS +106 -0
  4. data/README.md +107 -103
  5. data/lib/active_merchant/billing/apple_pay_payment_token.rb +22 -0
  6. data/lib/active_merchant/billing/avs_result.rb +12 -13
  7. data/lib/active_merchant/billing/base.rb +13 -16
  8. data/lib/active_merchant/billing/check.rb +35 -24
  9. data/lib/active_merchant/billing/compatibility.rb +117 -0
  10. data/lib/active_merchant/billing/credit_card.rb +196 -81
  11. data/lib/active_merchant/billing/credit_card_formatting.rb +6 -4
  12. data/lib/active_merchant/billing/credit_card_methods.rb +199 -75
  13. data/lib/active_merchant/billing/cvv_result.rb +15 -15
  14. data/lib/active_merchant/billing/gateway.rb +171 -39
  15. data/lib/active_merchant/billing/gateways/adyen.rb +380 -0
  16. data/lib/active_merchant/billing/gateways/allied_wallet.rb +205 -0
  17. data/lib/active_merchant/billing/gateways/authorize_net.rb +933 -604
  18. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +417 -0
  19. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +74 -54
  20. data/lib/active_merchant/billing/gateways/axcessms.rb +181 -0
  21. data/lib/active_merchant/billing/gateways/balanced.rb +130 -370
  22. data/lib/active_merchant/billing/gateways/bank_frick.rb +225 -0
  23. data/lib/active_merchant/billing/gateways/banwire.rb +23 -12
  24. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +351 -0
  25. data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +6 -6
  26. data/lib/active_merchant/billing/gateways/be2bill.rb +2 -2
  27. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +109 -32
  28. data/lib/active_merchant/billing/gateways/beanstream.rb +59 -13
  29. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +12 -9
  30. data/lib/active_merchant/billing/gateways/blue_pay.rb +520 -498
  31. data/lib/active_merchant/billing/gateways/blue_snap.rb +347 -0
  32. data/lib/active_merchant/billing/gateways/bogus.rb +80 -46
  33. data/lib/active_merchant/billing/gateways/borgun.rb +220 -0
  34. data/lib/active_merchant/billing/gateways/bpoint.rb +277 -0
  35. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +15 -2
  36. data/lib/active_merchant/billing/gateways/braintree.rb +2 -2
  37. data/lib/active_merchant/billing/gateways/braintree_blue.rb +311 -121
  38. data/lib/active_merchant/billing/gateways/braintree_orange.rb +4 -4
  39. data/lib/active_merchant/billing/gateways/bridge_pay.rb +244 -0
  40. data/lib/active_merchant/billing/gateways/cams.rb +230 -0
  41. data/lib/active_merchant/billing/gateways/card_connect.rb +311 -0
  42. data/lib/active_merchant/billing/gateways/card_save.rb +6 -7
  43. data/lib/active_merchant/billing/gateways/card_stream.rb +235 -89
  44. data/lib/active_merchant/billing/gateways/cardknox.rb +327 -0
  45. data/lib/active_merchant/billing/gateways/cardprocess.rb +254 -0
  46. data/lib/active_merchant/billing/gateways/cashnet.rb +219 -0
  47. data/lib/active_merchant/billing/gateways/cc5.rb +50 -8
  48. data/lib/active_merchant/billing/gateways/cecabank.rb +27 -14
  49. data/lib/active_merchant/billing/gateways/cenpos.rb +327 -0
  50. data/lib/active_merchant/billing/gateways/checkout.rb +214 -0
  51. data/lib/active_merchant/billing/gateways/checkout_v2.rb +233 -0
  52. data/lib/active_merchant/billing/gateways/citrus_pay.rb +22 -0
  53. data/lib/active_merchant/billing/gateways/clearhaus.rb +220 -0
  54. data/lib/active_merchant/billing/gateways/commercegate.rb +142 -0
  55. data/lib/active_merchant/billing/gateways/conekta.rb +91 -97
  56. data/lib/active_merchant/billing/gateways/creditcall.rb +271 -0
  57. data/lib/active_merchant/billing/gateways/credorax.rb +356 -0
  58. data/lib/active_merchant/billing/gateways/ct_payment.rb +268 -0
  59. data/lib/active_merchant/billing/gateways/culqi.rb +277 -0
  60. data/lib/active_merchant/billing/gateways/cyber_source.rb +294 -158
  61. data/lib/active_merchant/billing/gateways/d_local.rb +226 -0
  62. data/lib/active_merchant/billing/gateways/data_cash.rb +59 -347
  63. data/lib/active_merchant/billing/gateways/dibs.rb +199 -0
  64. data/lib/active_merchant/billing/gateways/digitzs.rb +292 -0
  65. data/lib/active_merchant/billing/gateways/ebanx.rb +296 -0
  66. data/lib/active_merchant/billing/gateways/efsnet.rb +24 -39
  67. data/lib/active_merchant/billing/gateways/elavon.rb +146 -147
  68. data/lib/active_merchant/billing/gateways/element.rb +356 -0
  69. data/lib/active_merchant/billing/gateways/epay.rb +41 -31
  70. data/lib/active_merchant/billing/gateways/evo_ca.rb +1 -1
  71. data/lib/active_merchant/billing/gateways/eway.rb +79 -78
  72. data/lib/active_merchant/billing/gateways/eway_managed.rb +35 -36
  73. data/lib/active_merchant/billing/gateways/eway_rapid.rb +369 -228
  74. data/lib/active_merchant/billing/gateways/exact.rb +32 -26
  75. data/lib/active_merchant/billing/gateways/ezic.rb +195 -0
  76. data/lib/active_merchant/billing/gateways/fat_zebra.rb +90 -64
  77. data/lib/active_merchant/billing/gateways/federated_canada.rb +6 -14
  78. data/lib/active_merchant/billing/gateways/finansbank.rb +3 -3
  79. data/lib/active_merchant/billing/gateways/first_giving.rb +142 -0
  80. data/lib/active_merchant/billing/gateways/first_pay.rb +128 -122
  81. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +190 -64
  82. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +446 -0
  83. data/lib/active_merchant/billing/gateways/flo2cash.rb +215 -0
  84. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +20 -0
  85. data/lib/active_merchant/billing/gateways/forte.rb +270 -0
  86. data/lib/active_merchant/billing/gateways/garanti.rb +29 -27
  87. data/lib/active_merchant/billing/gateways/global_collect.rb +340 -0
  88. data/lib/active_merchant/billing/gateways/global_transport.rb +194 -0
  89. data/lib/active_merchant/billing/gateways/hdfc.rb +35 -36
  90. data/lib/active_merchant/billing/gateways/hps.rb +305 -0
  91. data/lib/active_merchant/billing/gateways/iats_payments.rb +271 -16
  92. data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +15 -0
  93. data/lib/active_merchant/billing/gateways/inspire.rb +29 -32
  94. data/lib/active_merchant/billing/gateways/instapay.rb +5 -6
  95. data/lib/active_merchant/billing/gateways/ipp.rb +175 -0
  96. data/lib/active_merchant/billing/gateways/iridium.rb +247 -41
  97. data/lib/active_merchant/billing/gateways/itransact.rb +4 -5
  98. data/lib/active_merchant/billing/gateways/iveri.rb +251 -0
  99. data/lib/active_merchant/billing/gateways/jetpay.rb +198 -71
  100. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +437 -0
  101. data/lib/active_merchant/billing/gateways/komoju.rb +115 -0
  102. data/lib/active_merchant/billing/gateways/kushki.rb +219 -0
  103. data/lib/active_merchant/billing/gateways/latitude19.rb +411 -0
  104. data/lib/active_merchant/billing/gateways/linkpoint.rb +45 -43
  105. data/lib/active_merchant/billing/gateways/litle.rb +328 -444
  106. data/lib/active_merchant/billing/gateways/mastercard.rb +267 -0
  107. data/lib/active_merchant/billing/gateways/maxipago.rb +145 -115
  108. data/lib/active_merchant/billing/gateways/mercado_pago.rb +277 -0
  109. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +37 -19
  110. data/lib/active_merchant/billing/gateways/merchant_one.rb +13 -15
  111. data/lib/active_merchant/billing/gateways/merchant_partners.rb +245 -0
  112. data/lib/active_merchant/billing/gateways/merchant_ware.rb +57 -60
  113. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +59 -48
  114. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +38 -19
  115. data/lib/active_merchant/billing/gateways/mercury.rb +77 -54
  116. data/lib/active_merchant/billing/gateways/metrics_global.rb +11 -30
  117. data/lib/active_merchant/billing/gateways/micropayment.rb +183 -0
  118. data/lib/active_merchant/billing/gateways/migs.rb +81 -22
  119. data/lib/active_merchant/billing/gateways/modern_payments.rb +3 -3
  120. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +23 -25
  121. data/lib/active_merchant/billing/gateways/monei.rb +307 -0
  122. data/lib/active_merchant/billing/gateways/moneris.rb +146 -64
  123. data/lib/active_merchant/billing/gateways/moneris_us.rb +197 -53
  124. data/lib/active_merchant/billing/gateways/money_movers.rb +6 -15
  125. data/lib/active_merchant/billing/gateways/mundipagg.rb +292 -0
  126. data/lib/active_merchant/billing/gateways/nab_transact.rb +86 -64
  127. data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +165 -0
  128. data/lib/active_merchant/billing/gateways/net_registry.rb +11 -5
  129. data/lib/active_merchant/billing/gateways/netaxept.rb +21 -22
  130. data/lib/active_merchant/billing/gateways/netbanx.rb +290 -0
  131. data/lib/active_merchant/billing/gateways/netbilling.rb +70 -35
  132. data/lib/active_merchant/billing/gateways/netpay.rb +5 -6
  133. data/lib/active_merchant/billing/gateways/network_merchants.rb +241 -0
  134. data/lib/active_merchant/billing/gateways/nmi.rb +274 -10
  135. data/lib/active_merchant/billing/gateways/ogone.rb +90 -47
  136. data/lib/active_merchant/billing/gateways/omise.rb +324 -0
  137. data/lib/active_merchant/billing/gateways/openpay.rb +48 -20
  138. data/lib/active_merchant/billing/gateways/opp.rb +369 -0
  139. data/lib/active_merchant/billing/gateways/optimal_payment.rb +79 -44
  140. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +22 -21
  141. data/lib/active_merchant/billing/gateways/orbital.rb +346 -102
  142. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +48 -29
  143. data/lib/active_merchant/billing/gateways/pagarme.rb +246 -0
  144. data/lib/active_merchant/billing/gateways/pago_facil.rb +122 -0
  145. data/lib/active_merchant/billing/gateways/pay_conex.rb +245 -0
  146. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +67 -48
  147. data/lib/active_merchant/billing/gateways/pay_hub.rb +213 -0
  148. data/lib/active_merchant/billing/gateways/pay_junction.rb +20 -26
  149. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +188 -0
  150. data/lib/active_merchant/billing/gateways/pay_secure.rb +7 -15
  151. data/lib/active_merchant/billing/gateways/paybox_direct.rb +40 -36
  152. data/lib/active_merchant/billing/gateways/payeezy.rb +410 -0
  153. data/lib/active_merchant/billing/gateways/payex.rb +38 -30
  154. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +62 -36
  155. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +11 -7
  156. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +3 -3
  157. data/lib/active_merchant/billing/gateways/payflow.rb +74 -27
  158. data/lib/active_merchant/billing/gateways/payflow_express.rb +77 -81
  159. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +2 -3
  160. data/lib/active_merchant/billing/gateways/payflow_uk.rb +5 -6
  161. data/lib/active_merchant/billing/gateways/payment_express.rb +54 -45
  162. data/lib/active_merchant/billing/gateways/paymentez.rb +304 -0
  163. data/lib/active_merchant/billing/gateways/paymill.rb +160 -66
  164. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +54 -7
  165. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +4 -0
  166. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +17 -3
  167. data/lib/active_merchant/billing/gateways/paypal.rb +36 -27
  168. data/lib/active_merchant/billing/gateways/paypal_ca.rb +1 -1
  169. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +7 -6
  170. data/lib/active_merchant/billing/gateways/paypal_express.rb +32 -4
  171. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +3 -3
  172. data/lib/active_merchant/billing/gateways/payscout.rb +2 -13
  173. data/lib/active_merchant/billing/gateways/paystation.rb +96 -88
  174. data/lib/active_merchant/billing/gateways/payu_in.rb +248 -0
  175. data/lib/active_merchant/billing/gateways/payu_latam.rb +445 -0
  176. data/lib/active_merchant/billing/gateways/payway.rb +8 -8
  177. data/lib/active_merchant/billing/gateways/pin.rb +74 -18
  178. data/lib/active_merchant/billing/gateways/plugnpay.rb +66 -76
  179. data/lib/active_merchant/billing/gateways/pro_pay.rb +326 -0
  180. data/lib/active_merchant/billing/gateways/psigate.rb +30 -30
  181. data/lib/active_merchant/billing/gateways/psl_card.rb +27 -34
  182. data/lib/active_merchant/billing/gateways/qbms.rb +65 -54
  183. data/lib/active_merchant/billing/gateways/quantum.rb +18 -18
  184. data/lib/active_merchant/billing/gateways/quickbooks.rb +290 -0
  185. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +184 -0
  186. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +295 -0
  187. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +226 -0
  188. data/lib/active_merchant/billing/gateways/quickpay.rb +10 -350
  189. data/lib/active_merchant/billing/gateways/qvalent.rb +236 -0
  190. data/lib/active_merchant/billing/gateways/realex.rb +78 -48
  191. data/lib/active_merchant/billing/gateways/redsys.rb +310 -170
  192. data/lib/active_merchant/billing/gateways/s5.rb +246 -0
  193. data/lib/active_merchant/billing/gateways/safe_charge.rb +262 -0
  194. data/lib/active_merchant/billing/gateways/sage.rb +415 -119
  195. data/lib/active_merchant/billing/gateways/sage_pay.rb +195 -90
  196. data/lib/active_merchant/billing/gateways/sallie_mae.rb +11 -12
  197. data/lib/active_merchant/billing/gateways/secure_net.rb +51 -43
  198. data/lib/active_merchant/billing/gateways/secure_pay.rb +182 -10
  199. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +25 -14
  200. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +10 -18
  201. data/lib/active_merchant/billing/gateways/securion_pay.rb +264 -0
  202. data/lib/active_merchant/billing/gateways/skip_jack.rb +35 -38
  203. data/lib/active_merchant/billing/gateways/smart_ps.rb +50 -42
  204. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +9 -9
  205. data/lib/active_merchant/billing/gateways/spreedly_core.rb +62 -12
  206. data/lib/active_merchant/billing/gateways/stripe.rb +536 -103
  207. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +12 -18
  208. data/lib/active_merchant/billing/gateways/telr.rb +274 -0
  209. data/lib/active_merchant/billing/gateways/tns.rb +22 -0
  210. data/lib/active_merchant/billing/gateways/trans_first.rb +143 -30
  211. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +608 -0
  212. data/lib/active_merchant/billing/gateways/transact_pro.rb +224 -0
  213. data/lib/active_merchant/billing/gateways/transax.rb +5 -6
  214. data/lib/active_merchant/billing/gateways/transnational.rb +2 -232
  215. data/lib/active_merchant/billing/gateways/trexle.rb +218 -0
  216. data/lib/active_merchant/billing/gateways/trust_commerce.rb +86 -57
  217. data/lib/active_merchant/billing/gateways/usa_epay.rb +4 -4
  218. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +196 -89
  219. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +157 -32
  220. data/lib/active_merchant/billing/gateways/vanco.rb +294 -0
  221. data/lib/active_merchant/billing/gateways/verifi.rb +42 -49
  222. data/lib/active_merchant/billing/gateways/viaklix.rb +11 -24
  223. data/lib/active_merchant/billing/gateways/visanet_peru.rb +233 -0
  224. data/lib/active_merchant/billing/gateways/webpay.rb +26 -28
  225. data/lib/active_merchant/billing/gateways/wepay.rb +237 -0
  226. data/lib/active_merchant/billing/gateways/wirecard.rb +153 -31
  227. data/lib/active_merchant/billing/gateways/world_net.rb +344 -0
  228. data/lib/active_merchant/billing/gateways/worldpay.rb +207 -63
  229. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +215 -0
  230. data/lib/active_merchant/billing/gateways/worldpay_us.rb +221 -0
  231. data/lib/active_merchant/billing/gateways.rb +8 -11
  232. data/lib/active_merchant/billing/model.rb +30 -0
  233. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +39 -0
  234. data/lib/active_merchant/billing/payment_token.rb +21 -0
  235. data/lib/active_merchant/billing/rails.rb +3 -0
  236. data/lib/active_merchant/billing/response.rb +31 -24
  237. data/lib/active_merchant/billing.rb +7 -1
  238. data/lib/active_merchant/connection.rb +195 -0
  239. data/lib/active_merchant/country.rb +335 -0
  240. data/lib/active_merchant/empty.rb +20 -0
  241. data/lib/active_merchant/errors.rb +35 -0
  242. data/lib/active_merchant/net_http_ssl_connection.rb +10 -0
  243. data/lib/active_merchant/network_connection_retries.rb +80 -0
  244. data/lib/active_merchant/post_data.rb +25 -0
  245. data/lib/active_merchant/posts_data.rb +92 -0
  246. data/lib/active_merchant/version.rb +1 -1
  247. data/lib/active_merchant.rb +23 -27
  248. data/lib/activemerchant.rb +1 -1
  249. data/lib/certs/cacert.pem +3988 -0
  250. data/lib/support/gateway_support.rb +7 -9
  251. data/lib/support/outbound_hosts.rb +13 -10
  252. data/lib/support/ssl_verify.rb +6 -7
  253. data/lib/support/ssl_version.rb +87 -0
  254. metadata +148 -323
  255. checksums.yaml.gz.sig +0 -0
  256. data/gem-public_cert.pem +0 -21
  257. data/lib/active_merchant/billing/expiry_date.rb +0 -34
  258. data/lib/active_merchant/billing/gateways/app55.rb +0 -185
  259. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +0 -314
  260. data/lib/active_merchant/billing/gateways/certo_direct.rb +0 -277
  261. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +0 -249
  262. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +0 -13
  263. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +0 -29
  264. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +0 -66
  265. data/lib/active_merchant/billing/gateways/orbital/avs_result.rb +0 -93
  266. data/lib/active_merchant/billing/gateways/orbital/cvv_result.rb +0 -34
  267. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +0 -93
  268. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +0 -114
  269. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +0 -102
  270. data/lib/active_merchant/billing/gateways/samurai.rb +0 -118
  271. data/lib/active_merchant/billing/gateways/vindicia.rb +0 -361
  272. data/lib/active_merchant/billing/integrations/a1agregator/helper.rb +0 -31
  273. data/lib/active_merchant/billing/integrations/a1agregator/notification.rb +0 -186
  274. data/lib/active_merchant/billing/integrations/a1agregator/status.rb +0 -38
  275. data/lib/active_merchant/billing/integrations/a1agregator.rb +0 -26
  276. data/lib/active_merchant/billing/integrations/action_view_helper.rb +0 -74
  277. data/lib/active_merchant/billing/integrations/alipay/helper.rb +0 -34
  278. data/lib/active_merchant/billing/integrations/alipay/notification.rb +0 -101
  279. data/lib/active_merchant/billing/integrations/alipay.rb +0 -18
  280. data/lib/active_merchant/billing/integrations/authorize_net_sim/helper.rb +0 -229
  281. data/lib/active_merchant/billing/integrations/authorize_net_sim/notification.rb +0 -340
  282. data/lib/active_merchant/billing/integrations/authorize_net_sim.rb +0 -38
  283. data/lib/active_merchant/billing/integrations/bit_pay/helper.rb +0 -64
  284. data/lib/active_merchant/billing/integrations/bit_pay/notification.rb +0 -74
  285. data/lib/active_merchant/billing/integrations/bit_pay/return.rb +0 -10
  286. data/lib/active_merchant/billing/integrations/bit_pay.rb +0 -30
  287. data/lib/active_merchant/billing/integrations/bogus/helper.rb +0 -17
  288. data/lib/active_merchant/billing/integrations/bogus/notification.rb +0 -11
  289. data/lib/active_merchant/billing/integrations/bogus/return.rb +0 -10
  290. data/lib/active_merchant/billing/integrations/bogus.rb +0 -23
  291. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +0 -120
  292. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +0 -158
  293. data/lib/active_merchant/billing/integrations/chronopay/return.rb +0 -10
  294. data/lib/active_merchant/billing/integrations/chronopay.rb +0 -23
  295. data/lib/active_merchant/billing/integrations/citrus/helper.rb +0 -40
  296. data/lib/active_merchant/billing/integrations/citrus/notification.rb +0 -133
  297. data/lib/active_merchant/billing/integrations/citrus/return.rb +0 -40
  298. data/lib/active_merchant/billing/integrations/citrus.rb +0 -51
  299. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +0 -200
  300. data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +0 -76
  301. data/lib/active_merchant/billing/integrations/direc_pay/return.rb +0 -32
  302. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +0 -37
  303. data/lib/active_merchant/billing/integrations/direc_pay.rb +0 -41
  304. data/lib/active_merchant/billing/integrations/directebanking/helper.rb +0 -90
  305. data/lib/active_merchant/billing/integrations/directebanking/notification.rb +0 -120
  306. data/lib/active_merchant/billing/integrations/directebanking/return.rb +0 -11
  307. data/lib/active_merchant/billing/integrations/directebanking.rb +0 -47
  308. data/lib/active_merchant/billing/integrations/doku/helper.rb +0 -102
  309. data/lib/active_merchant/billing/integrations/doku/notification.rb +0 -69
  310. data/lib/active_merchant/billing/integrations/doku/return.rb +0 -10
  311. data/lib/active_merchant/billing/integrations/doku.rb +0 -24
  312. data/lib/active_merchant/billing/integrations/dotpay/helper.rb +0 -77
  313. data/lib/active_merchant/billing/integrations/dotpay/notification.rb +0 -86
  314. data/lib/active_merchant/billing/integrations/dotpay/return.rb +0 -11
  315. data/lib/active_merchant/billing/integrations/dotpay.rb +0 -22
  316. data/lib/active_merchant/billing/integrations/dwolla/common.rb +0 -23
  317. data/lib/active_merchant/billing/integrations/dwolla/helper.rb +0 -43
  318. data/lib/active_merchant/billing/integrations/dwolla/notification.rb +0 -64
  319. data/lib/active_merchant/billing/integrations/dwolla/return.rb +0 -49
  320. data/lib/active_merchant/billing/integrations/dwolla.rb +0 -23
  321. data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +0 -34
  322. data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +0 -84
  323. data/lib/active_merchant/billing/integrations/e_payment_plans.rb +0 -48
  324. data/lib/active_merchant/billing/integrations/easy_pay/common.rb +0 -40
  325. data/lib/active_merchant/billing/integrations/easy_pay/helper.rb +0 -36
  326. data/lib/active_merchant/billing/integrations/easy_pay/notification.rb +0 -59
  327. data/lib/active_merchant/billing/integrations/easy_pay.rb +0 -30
  328. data/lib/active_merchant/billing/integrations/epay/helper.rb +0 -55
  329. data/lib/active_merchant/billing/integrations/epay/notification.rb +0 -110
  330. data/lib/active_merchant/billing/integrations/epay.rb +0 -21
  331. data/lib/active_merchant/billing/integrations/first_data/helper.rb +0 -61
  332. data/lib/active_merchant/billing/integrations/first_data/notification.rb +0 -56
  333. data/lib/active_merchant/billing/integrations/first_data.rb +0 -38
  334. data/lib/active_merchant/billing/integrations/gestpay/common.rb +0 -42
  335. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +0 -70
  336. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +0 -85
  337. data/lib/active_merchant/billing/integrations/gestpay/return.rb +0 -10
  338. data/lib/active_merchant/billing/integrations/gestpay.rb +0 -25
  339. data/lib/active_merchant/billing/integrations/helper.rb +0 -117
  340. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +0 -58
  341. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +0 -59
  342. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +0 -68
  343. data/lib/active_merchant/billing/integrations/hi_trust.rb +0 -27
  344. data/lib/active_merchant/billing/integrations/ipay88/helper.rb +0 -118
  345. data/lib/active_merchant/billing/integrations/ipay88/notification.rb +0 -103
  346. data/lib/active_merchant/billing/integrations/ipay88/return.rb +0 -29
  347. data/lib/active_merchant/billing/integrations/ipay88.rb +0 -23
  348. data/lib/active_merchant/billing/integrations/liqpay/helper.rb +0 -43
  349. data/lib/active_merchant/billing/integrations/liqpay/notification.rb +0 -89
  350. data/lib/active_merchant/billing/integrations/liqpay/return.rb +0 -83
  351. data/lib/active_merchant/billing/integrations/liqpay.rb +0 -30
  352. data/lib/active_merchant/billing/integrations/maksuturva/helper.rb +0 -119
  353. data/lib/active_merchant/billing/integrations/maksuturva/notification.rb +0 -48
  354. data/lib/active_merchant/billing/integrations/maksuturva.rb +0 -86
  355. data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +0 -75
  356. data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +0 -123
  357. data/lib/active_merchant/billing/integrations/moneybookers.rb +0 -26
  358. data/lib/active_merchant/billing/integrations/nochex/helper.rb +0 -68
  359. data/lib/active_merchant/billing/integrations/nochex/notification.rb +0 -94
  360. data/lib/active_merchant/billing/integrations/nochex/return.rb +0 -10
  361. data/lib/active_merchant/billing/integrations/nochex.rb +0 -88
  362. data/lib/active_merchant/billing/integrations/notification.rb +0 -71
  363. data/lib/active_merchant/billing/integrations/paxum/common.rb +0 -24
  364. data/lib/active_merchant/billing/integrations/paxum/helper.rb +0 -42
  365. data/lib/active_merchant/billing/integrations/paxum/notification.rb +0 -33
  366. data/lib/active_merchant/billing/integrations/paxum.rb +0 -44
  367. data/lib/active_merchant/billing/integrations/pay_fast/common.rb +0 -42
  368. data/lib/active_merchant/billing/integrations/pay_fast/helper.rb +0 -50
  369. data/lib/active_merchant/billing/integrations/pay_fast/notification.rb +0 -134
  370. data/lib/active_merchant/billing/integrations/pay_fast/return.rb +0 -10
  371. data/lib/active_merchant/billing/integrations/pay_fast.rb +0 -70
  372. data/lib/active_merchant/billing/integrations/paydollar/helper.rb +0 -41
  373. data/lib/active_merchant/billing/integrations/paydollar/notification.rb +0 -60
  374. data/lib/active_merchant/billing/integrations/paydollar/return.rb +0 -15
  375. data/lib/active_merchant/billing/integrations/paydollar.rb +0 -59
  376. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +0 -116
  377. data/lib/active_merchant/billing/integrations/payflow_link/notification.rb +0 -78
  378. data/lib/active_merchant/billing/integrations/payflow_link.rb +0 -21
  379. data/lib/active_merchant/billing/integrations/paypal/helper.rb +0 -119
  380. data/lib/active_merchant/billing/integrations/paypal/notification.rb +0 -227
  381. data/lib/active_merchant/billing/integrations/paypal/return.rb +0 -10
  382. data/lib/active_merchant/billing/integrations/paypal.rb +0 -39
  383. data/lib/active_merchant/billing/integrations/paypal_payments_advanced/helper.rb +0 -15
  384. data/lib/active_merchant/billing/integrations/paypal_payments_advanced.rb +0 -20
  385. data/lib/active_merchant/billing/integrations/paysbuy/helper.rb +0 -15
  386. data/lib/active_merchant/billing/integrations/paysbuy/notification.rb +0 -39
  387. data/lib/active_merchant/billing/integrations/paysbuy.rb +0 -36
  388. data/lib/active_merchant/billing/integrations/payu_in/helper.rb +0 -76
  389. data/lib/active_merchant/billing/integrations/payu_in/notification.rb +0 -154
  390. data/lib/active_merchant/billing/integrations/payu_in/return.rb +0 -36
  391. data/lib/active_merchant/billing/integrations/payu_in.rb +0 -36
  392. data/lib/active_merchant/billing/integrations/payu_in_paisa/helper.rb +0 -19
  393. data/lib/active_merchant/billing/integrations/payu_in_paisa/notification.rb +0 -13
  394. data/lib/active_merchant/billing/integrations/payu_in_paisa/return.rb +0 -16
  395. data/lib/active_merchant/billing/integrations/payu_in_paisa.rb +0 -30
  396. data/lib/active_merchant/billing/integrations/platron/helper.rb +0 -32
  397. data/lib/active_merchant/billing/integrations/platron/notification.rb +0 -113
  398. data/lib/active_merchant/billing/integrations/platron.rb +0 -28
  399. data/lib/active_merchant/billing/integrations/pxpay/helper.rb +0 -112
  400. data/lib/active_merchant/billing/integrations/pxpay/notification.rb +0 -157
  401. data/lib/active_merchant/billing/integrations/pxpay/return.rb +0 -25
  402. data/lib/active_merchant/billing/integrations/pxpay.rb +0 -31
  403. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +0 -96
  404. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +0 -137
  405. data/lib/active_merchant/billing/integrations/quickpay.rb +0 -21
  406. data/lib/active_merchant/billing/integrations/rbkmoney/helper.rb +0 -23
  407. data/lib/active_merchant/billing/integrations/rbkmoney/notification.rb +0 -91
  408. data/lib/active_merchant/billing/integrations/rbkmoney.rb +0 -17
  409. data/lib/active_merchant/billing/integrations/return.rb +0 -42
  410. data/lib/active_merchant/billing/integrations/robokassa/common.rb +0 -19
  411. data/lib/active_merchant/billing/integrations/robokassa/helper.rb +0 -50
  412. data/lib/active_merchant/billing/integrations/robokassa/notification.rb +0 -55
  413. data/lib/active_merchant/billing/integrations/robokassa/return.rb +0 -17
  414. data/lib/active_merchant/billing/integrations/robokassa.rb +0 -49
  415. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +0 -33
  416. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +0 -136
  417. data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +0 -210
  418. data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +0 -31
  419. data/lib/active_merchant/billing/integrations/sage_pay_form.rb +0 -37
  420. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +0 -107
  421. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +0 -171
  422. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +0 -58
  423. data/lib/active_merchant/billing/integrations/two_checkout.rb +0 -44
  424. data/lib/active_merchant/billing/integrations/valitor/helper.rb +0 -86
  425. data/lib/active_merchant/billing/integrations/valitor/notification.rb +0 -13
  426. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +0 -97
  427. data/lib/active_merchant/billing/integrations/valitor/return.rb +0 -13
  428. data/lib/active_merchant/billing/integrations/valitor.rb +0 -33
  429. data/lib/active_merchant/billing/integrations/verkkomaksut/helper.rb +0 -88
  430. data/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb +0 -59
  431. data/lib/active_merchant/billing/integrations/verkkomaksut.rb +0 -20
  432. data/lib/active_merchant/billing/integrations/web_pay/common.rb +0 -50
  433. data/lib/active_merchant/billing/integrations/web_pay/helper.rb +0 -68
  434. data/lib/active_merchant/billing/integrations/web_pay/notification.rb +0 -51
  435. data/lib/active_merchant/billing/integrations/web_pay.rb +0 -45
  436. data/lib/active_merchant/billing/integrations/webmoney/common.rb +0 -17
  437. data/lib/active_merchant/billing/integrations/webmoney/helper.rb +0 -40
  438. data/lib/active_merchant/billing/integrations/webmoney/notification.rb +0 -47
  439. data/lib/active_merchant/billing/integrations/webmoney.rb +0 -43
  440. data/lib/active_merchant/billing/integrations/wirecard_checkout_page/common.rb +0 -104
  441. data/lib/active_merchant/billing/integrations/wirecard_checkout_page/helper.rb +0 -145
  442. data/lib/active_merchant/billing/integrations/wirecard_checkout_page/notification.rb +0 -101
  443. data/lib/active_merchant/billing/integrations/wirecard_checkout_page/return.rb +0 -35
  444. data/lib/active_merchant/billing/integrations/wirecard_checkout_page.rb +0 -39
  445. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +0 -101
  446. data/lib/active_merchant/billing/integrations/world_pay/notification.rb +0 -160
  447. data/lib/active_merchant/billing/integrations/world_pay.rb +0 -34
  448. data/lib/active_merchant/billing/integrations.rb +0 -17
  449. data.tar.gz.sig +0 -0
  450. metadata.gz.sig +0 -1
@@ -21,28 +21,76 @@ module ActiveMerchant #:nodoc:
21
21
  'unchecked' => 'P'
22
22
  }
23
23
 
24
- self.supported_countries = %w(US CA GB AU IE FR NL BE DE ES)
24
+ self.supported_countries = %w(AT AU BE BR CA CH DE DK ES FI FR GB HK IE IT JP LU MX NL NO NZ PT SE SG US)
25
25
  self.default_currency = 'USD'
26
26
  self.money_format = :cents
27
- self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club]
27
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club, :maestro]
28
+ self.currencies_without_fractions = %w(BIF CLP DJF GNF JPY KMF KRW MGA PYG RWF VND VUV XAF XOF XPF UGX)
28
29
 
29
30
  self.homepage_url = 'https://stripe.com/'
30
31
  self.display_name = 'Stripe'
31
32
 
33
+ STANDARD_ERROR_CODE_MAPPING = {
34
+ 'incorrect_number' => STANDARD_ERROR_CODE[:incorrect_number],
35
+ 'invalid_number' => STANDARD_ERROR_CODE[:invalid_number],
36
+ 'invalid_expiry_month' => STANDARD_ERROR_CODE[:invalid_expiry_date],
37
+ 'invalid_expiry_year' => STANDARD_ERROR_CODE[:invalid_expiry_date],
38
+ 'invalid_cvc' => STANDARD_ERROR_CODE[:invalid_cvc],
39
+ 'expired_card' => STANDARD_ERROR_CODE[:expired_card],
40
+ 'incorrect_cvc' => STANDARD_ERROR_CODE[:incorrect_cvc],
41
+ 'incorrect_zip' => STANDARD_ERROR_CODE[:incorrect_zip],
42
+ 'card_declined' => STANDARD_ERROR_CODE[:card_declined],
43
+ 'call_issuer' => STANDARD_ERROR_CODE[:call_issuer],
44
+ 'processing_error' => STANDARD_ERROR_CODE[:processing_error],
45
+ 'incorrect_pin' => STANDARD_ERROR_CODE[:incorrect_pin],
46
+ 'test_mode_live_card' => STANDARD_ERROR_CODE[:test_mode_live_card],
47
+ 'pickup_card' => STANDARD_ERROR_CODE[:pickup_card]
48
+ }
49
+
50
+ BANK_ACCOUNT_HOLDER_TYPE_MAPPING = {
51
+ 'personal' => 'individual',
52
+ 'business' => 'company',
53
+ }
54
+
55
+ MINIMUM_AUTHORIZE_AMOUNTS = {
56
+ 'USD' => 100,
57
+ 'CAD' => 100,
58
+ 'GBP' => 60,
59
+ 'EUR' => 100,
60
+ 'DKK' => 500,
61
+ 'NOK' => 600,
62
+ 'SEK' => 600,
63
+ 'CHF' => 100,
64
+ 'AUD' => 100,
65
+ 'JPY' => 100,
66
+ 'MXN' => 2000,
67
+ 'SGD' => 100,
68
+ 'HKD' => 800
69
+ }
70
+
32
71
  def initialize(options = {})
33
72
  requires!(options, :login)
34
73
  @api_key = options[:login]
35
74
  @fee_refund_api_key = options[:fee_refund_login]
36
- @version = options[:version]
37
-
38
75
  super
39
76
  end
40
77
 
41
- def authorize(money, creditcard, options = {})
42
- post = create_post_for_auth_or_purchase(money, creditcard, options)
43
- post[:capture] = "false"
44
-
45
- commit(:post, 'charges', post, options)
78
+ def authorize(money, payment, options = {})
79
+ MultiResponse.run do |r|
80
+ if payment.is_a?(ApplePayPaymentToken)
81
+ r.process { tokenize_apple_pay_token(payment) }
82
+ payment = StripePaymentToken.new(r.params['token']) if r.success?
83
+ end
84
+ r.process do
85
+ post = create_post_for_auth_or_purchase(money, payment, options)
86
+ if emv_payment?(payment)
87
+ add_application_fee(post, options)
88
+ else
89
+ post[:capture] = 'false'
90
+ end
91
+ commit(:post, 'charges', post, options)
92
+ end
93
+ end.responses.last
46
94
  end
47
95
 
48
96
  # To create a charge on a card or a token, call
@@ -52,65 +100,120 @@ module ActiveMerchant #:nodoc:
52
100
  # To create a charge on a customer, call
53
101
  #
54
102
  # purchase(money, nil, { :customer => id, ... })
55
- def purchase(money, creditcard, options = {})
56
- post = create_post_for_auth_or_purchase(money, creditcard, options)
103
+ def purchase(money, payment, options = {})
104
+ if ach?(payment)
105
+ direct_bank_error = 'Direct bank account transactions are not supported. Bank accounts must be stored and verified before use.'
106
+ return Response.new(false, direct_bank_error)
107
+ end
57
108
 
58
- commit(:post, 'charges', post, options)
109
+ MultiResponse.run do |r|
110
+ if payment.is_a?(ApplePayPaymentToken)
111
+ r.process { tokenize_apple_pay_token(payment) }
112
+ payment = StripePaymentToken.new(r.params['token']) if r.success?
113
+ end
114
+ r.process do
115
+ post = create_post_for_auth_or_purchase(money, payment, options)
116
+ post[:card][:processing_method] = 'quick_chip' if quickchip_payment?(payment)
117
+ commit(:post, 'charges', post, options)
118
+ end
119
+ end.responses.last
59
120
  end
60
121
 
61
122
  def capture(money, authorization, options = {})
62
- post = {:amount => amount(money)}
63
- add_application_fee(post, options)
123
+ post = {}
64
124
 
65
- commit(:post, "charges/#{CGI.escape(authorization)}/capture", post, options)
125
+ if emv_tc_response = options.delete(:icc_data)
126
+ post[:card] = { emv_approval_data: emv_tc_response }
127
+ commit(:post, "charges/#{CGI.escape(authorization)}", post, options)
128
+ else
129
+ add_application_fee(post, options)
130
+ add_amount(post, money, options)
131
+ add_exchange_rate(post, options)
132
+ commit(:post, "charges/#{CGI.escape(authorization)}/capture", post, options)
133
+ end
66
134
  end
67
135
 
68
136
  def void(identification, options = {})
69
- commit(:post, "charges/#{CGI.escape(identification)}/refund", {}, options)
137
+ post = {}
138
+ post[:metadata] = options[:metadata] if options[:metadata]
139
+ post[:reason] = options[:reason] if options[:reason]
140
+ post[:expand] = [:charge]
141
+ commit(:post, "charges/#{CGI.escape(identification)}/refunds", post, options)
70
142
  end
71
143
 
72
144
  def refund(money, identification, options = {})
73
- post = {:amount => amount(money)}
145
+ post = {}
146
+ add_amount(post, money, options)
74
147
  post[:refund_application_fee] = true if options[:refund_application_fee]
148
+ post[:reverse_transfer] = options[:reverse_transfer] if options[:reverse_transfer]
149
+ post[:metadata] = options[:metadata] if options[:metadata]
150
+ post[:reason] = options[:reason] if options[:reason]
151
+ post[:expand] = [:charge]
75
152
 
76
153
  MultiResponse.run(:first) do |r|
77
- r.process { commit(:post, "charges/#{CGI.escape(identification)}/refund", post, options) }
154
+ r.process { commit(:post, "charges/#{CGI.escape(identification)}/refunds", post, options) }
78
155
 
79
- return r unless options[:refund_fee_amount]
156
+ if options[:refund_fee_amount] && options[:refund_fee_amount].to_s != '0'
157
+ r.process { fetch_application_fee(identification, options) }
158
+ r.process { refund_application_fee(options[:refund_fee_amount].to_i, application_fee_from_response(r.responses.last), options) }
159
+ end
160
+ end
161
+ end
80
162
 
81
- r.process { fetch_application_fees(identification, options) }
82
- r.process { refund_application_fee(options[:refund_fee_amount], application_fee_from_response(r), options) }
163
+ def verify(payment, options = {})
164
+ MultiResponse.run(:use_first_response) do |r|
165
+ r.process { authorize(auth_minimum_amount(options), payment, options) }
166
+ options[:idempotency_key] = nil
167
+ r.process(:ignore_result) { void(r.authorization, options) }
83
168
  end
84
169
  end
85
170
 
86
171
  def application_fee_from_response(response)
87
172
  return unless response.success?
88
-
89
- application_fees = response.params["data"].select { |fee| fee["object"] == "application_fee" }
90
- application_fees.first["id"] unless application_fees.empty?
173
+ response.params['application_fee'] unless response.params['application_fee'].empty?
91
174
  end
92
175
 
93
176
  def refund_application_fee(money, identification, options = {})
94
- return Response.new(false, "Application fee id could not be found") unless identification
177
+ return Response.new(false, 'Application fee id could not be found') unless identification
95
178
 
96
- post = {:amount => amount(money)}
97
- options.merge!(:key => @fee_refund_api_key)
179
+ post = {}
180
+ add_amount(post, money, options)
181
+ options[:key] = @fee_refund_api_key if @fee_refund_api_key
182
+ options.delete(:stripe_account)
98
183
 
99
- commit(:post, "application_fees/#{CGI.escape(identification)}/refund", post, options)
184
+ refund_fee = commit(:post, "application_fees/#{CGI.escape(identification)}/refunds", post, options)
185
+ application_fee_response!(refund_fee, "Application fee could not be refunded: #{refund_fee.message}")
100
186
  end
101
187
 
102
188
  # Note: creating a new credit card will not change the customer's existing default credit card (use :set_default => true)
103
- def store(creditcard, options = {})
189
+ def store(payment, options = {})
190
+ params = {}
104
191
  post = {}
105
- card_params = {}
106
- add_creditcard(card_params, creditcard, options)
192
+
193
+ if payment.is_a?(ApplePayPaymentToken)
194
+ token_exchange_response = tokenize_apple_pay_token(payment)
195
+ params = { card: token_exchange_response.params['token']['id'] } if token_exchange_response.success?
196
+ elsif payment.is_a?(StripePaymentToken)
197
+ add_payment_token(params, payment, options)
198
+ elsif payment.is_a?(Check)
199
+ bank_token_response = tokenize_bank_account(payment)
200
+ return bank_token_response unless bank_token_response.success?
201
+ params = { source: bank_token_response.params['token']['id'] }
202
+ else
203
+ add_creditcard(params, payment, options)
204
+ end
205
+
206
+ post[:validate] = options[:validate] unless options[:validate].nil?
107
207
  post[:description] = options[:description] if options[:description]
108
208
  post[:email] = options[:email] if options[:email]
109
209
 
110
- if options[:customer]
210
+ if options[:account]
211
+ add_external_account(post, params, payment)
212
+ commit(:post, "accounts/#{CGI.escape(options[:account])}/external_accounts", post, options)
213
+ elsif options[:customer]
111
214
  MultiResponse.run(:first) do |r|
112
215
  # The /cards endpoint does not update other customer parameters.
113
- r.process { commit(:post, "customers/#{CGI.escape(options[:customer])}/cards", card_params, options) }
216
+ r.process { commit(:post, "customers/#{CGI.escape(options[:customer])}/cards", params, options) }
114
217
 
115
218
  if options[:set_default] and r.success? and !r.params['id'].blank?
116
219
  post[:default_card] = r.params['id']
@@ -121,53 +224,183 @@ module ActiveMerchant #:nodoc:
121
224
  end
122
225
  end
123
226
  else
124
- commit(:post, 'customers', post.merge(card_params), options)
227
+ commit(:post, 'customers', post.merge(params), options)
125
228
  end
126
229
  end
127
230
 
128
- def update(customer_id, creditcard, options = {})
129
- options = options.merge(:customer => customer_id, :set_default => true)
130
- store(creditcard, options)
231
+ def update(customer_id, card_id, options = {})
232
+ commit(:post, "customers/#{CGI.escape(customer_id)}/cards/#{CGI.escape(card_id)}", options, options)
131
233
  end
132
234
 
133
235
  def update_customer(customer_id, options = {})
134
236
  commit(:post, "customers/#{CGI.escape(customer_id)}", options, options)
135
237
  end
136
238
 
137
- def unstore(customer_id, card_id = nil, options = {})
138
- if card_id.nil?
139
- commit(:delete, "customers/#{CGI.escape(customer_id)}", nil, options)
239
+ def unstore(identification, options = {}, deprecated_options = {})
240
+ customer_id, card_id = identification.split('|')
241
+
242
+ if options.kind_of?(String)
243
+ ActiveMerchant.deprecated 'Passing the card_id as the 2nd parameter is deprecated. The response authorization includes both the customer_id and the card_id.'
244
+ card_id ||= options
245
+ options = deprecated_options
246
+ end
247
+
248
+ commit(:delete, "customers/#{CGI.escape(customer_id)}/cards/#{CGI.escape(card_id)}", nil, options)
249
+ end
250
+
251
+ def tokenize_apple_pay_token(apple_pay_payment_token, options = {})
252
+ token_response = api_request(:post, "tokens?pk_token=#{CGI.escape(apple_pay_payment_token.payment_data.to_json)}")
253
+ success = !token_response.key?('error')
254
+
255
+ if success && token_response.key?('id')
256
+ Response.new(success, nil, token: token_response)
140
257
  else
141
- commit(:delete, "customers/#{CGI.escape(customer_id)}/cards/#{CGI.escape(card_id)}", nil, options)
258
+ Response.new(success, token_response['error']['message'])
142
259
  end
143
260
  end
144
261
 
262
+ def verify_credentials
263
+ begin
264
+ ssl_get(live_url + 'charges/nonexistent', headers)
265
+ rescue ResponseError => e
266
+ return false if e.response.code.to_i == 401
267
+ end
268
+
269
+ true
270
+ end
271
+
272
+ def supports_scrubbing?
273
+ true
274
+ end
275
+
276
+ def scrub(transcript)
277
+ transcript.
278
+ gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
279
+ gsub(%r((&?three_d_secure\[cryptogram\]=)[\w=]*(&?)), '\1[FILTERED]\2').
280
+ gsub(%r((card\[cryptogram\]=)[^&]+(&?)), '\1[FILTERED]\2').
281
+ gsub(%r((card\[cvc\]=)\d+), '\1[FILTERED]').
282
+ gsub(%r((card\[emv_approval_data\]=)[^&]+(&?)), '\1[FILTERED]\2').
283
+ gsub(%r((card\[emv_auth_data\]=)[^&]+(&?)), '\1[FILTERED]\2').
284
+ gsub(%r((card\[encrypted_pin\]=)[^&]+(&?)), '\1[FILTERED]\2').
285
+ gsub(%r((card\[encrypted_pin_key_id\]=)[\w=]+(&?)), '\1[FILTERED]\2').
286
+ gsub(%r((card\[number\]=)\d+), '\1[FILTERED]').
287
+ gsub(%r((card\[swipe_data\]=)[^&]+(&?)), '\1[FILTERED]\2')
288
+ end
289
+
290
+ def supports_network_tokenization?
291
+ true
292
+ end
293
+
145
294
  private
146
295
 
147
- def create_post_for_auth_or_purchase(money, creditcard, options)
296
+ class StripePaymentToken < PaymentToken
297
+ def type
298
+ 'stripe'
299
+ end
300
+ end
301
+
302
+ def create_source(money, payment, type, options = {})
148
303
  post = {}
149
- add_amount(post, money, options)
150
- add_creditcard(post, creditcard, options)
151
- add_customer(post, creditcard, options)
152
- add_customer_data(post,options)
153
- post[:description] = options[:description]
154
- post[:metadata] = { email: options[:email] } if options[:email]
155
- add_flags(post, options)
304
+ add_amount(post, money, options, true)
305
+ post[:type] = type
306
+ if type == 'card'
307
+ add_creditcard(post, payment, options)
308
+ post[:card].delete(:name)
309
+ elsif type == 'three_d_secure'
310
+ post[:three_d_secure] = {card: payment}
311
+ post[:redirect] = {return_url: options[:redirect_url]}
312
+ end
313
+ commit(:post, 'sources', post, options)
314
+ end
315
+
316
+ def create_webhook_endpoint(options, events)
317
+ post = {}
318
+ post[:url] = options[:callback_url]
319
+ post[:enabled_events] = events
320
+ commit(:post, 'webhook_endpoints', post, options)
321
+ end
322
+
323
+ def delete_webhook_endpoint(options)
324
+ commit(:delete, "webhook_endpoints/#{options[:webhook_id]}", {}, options)
325
+ end
326
+
327
+ def create_post_for_auth_or_purchase(money, payment, options)
328
+ post = {}
329
+
330
+ if payment.is_a?(StripePaymentToken)
331
+ add_payment_token(post, payment, options)
332
+ else
333
+ add_creditcard(post, payment, options)
334
+ end
335
+
336
+ if emv_payment?(payment)
337
+ add_statement_address(post, options)
338
+ add_emv_metadata(post, payment)
339
+ else
340
+ add_amount(post, money, options, true)
341
+ add_customer_data(post, options)
342
+ post[:description] = options[:description]
343
+ post[:statement_descriptor] = options[:statement_description]
344
+ post[:receipt_email] = options[:receipt_email] if options[:receipt_email]
345
+ add_customer(post, payment, options)
346
+ add_flags(post, options)
347
+ end
348
+
349
+ add_metadata(post, options)
156
350
  add_application_fee(post, options)
351
+ add_exchange_rate(post, options)
352
+ add_destination(post, options)
353
+ add_level_three(post, options)
157
354
  post
158
355
  end
159
356
 
160
- def add_amount(post, money, options)
161
- post[:amount] = amount(money)
162
- post[:currency] = (options[:currency] || currency(money)).downcase
357
+ def add_amount(post, money, options, include_currency = false)
358
+ currency = options[:currency] || currency(money)
359
+ post[:amount] = localized_amount(money, currency)
360
+ post[:currency] = currency.downcase if include_currency
163
361
  end
164
362
 
165
363
  def add_application_fee(post, options)
166
364
  post[:application_fee] = options[:application_fee] if options[:application_fee]
167
365
  end
168
366
 
367
+ def add_exchange_rate(post, options)
368
+ post[:exchange_rate] = options[:exchange_rate] if options[:exchange_rate]
369
+ end
370
+
371
+ def add_destination(post, options)
372
+ if options[:destination]
373
+ post[:destination] = {}
374
+ post[:destination][:account] = options[:destination]
375
+ post[:destination][:amount] = options[:destination_amount] if options[:destination_amount]
376
+ end
377
+ end
378
+
379
+ def add_level_three(post, options)
380
+ level_three = {}
381
+
382
+ copy_when_present(level_three, [:merchant_reference], options)
383
+ copy_when_present(level_three, [:customer_reference], options)
384
+ copy_when_present(level_three, [:shipping_address_zip], options)
385
+ copy_when_present(level_three, [:shipping_from_zip], options)
386
+ copy_when_present(level_three, [:shipping_amount], options)
387
+ copy_when_present(level_three, [:line_items], options)
388
+
389
+ unless level_three.empty?
390
+ post[:level3] = level_three
391
+ end
392
+ end
393
+
169
394
  def add_expand_parameters(post, options)
170
- post[:expand] = Array.wrap(options[:expand])
395
+ post[:expand] ||= []
396
+ post[:expand].concat(Array.wrap(options[:expand]).map(&:to_sym)).uniq!
397
+ end
398
+
399
+ def add_external_account(post, card_params, payment)
400
+ external_account = {}
401
+ external_account[:object] ='card'
402
+ external_account[:currency] = (options[:currency] || currency(payment)).downcase
403
+ post[:external_account] = external_account.merge(card_params[:card])
171
404
  end
172
405
 
173
406
  def add_customer_data(post, options)
@@ -179,7 +412,7 @@ module ActiveMerchant #:nodoc:
179
412
  end
180
413
 
181
414
  def add_address(post, options)
182
- return unless post[:card] && post[:card].kind_of?(Hash)
415
+ return unless post[:card]&.kind_of?(Hash)
183
416
  if address = options[:billing_address] || options[:address]
184
417
  post[:card][:address_line1] = address[:address1] if address[:address1]
185
418
  post[:card][:address_line2] = address[:address2] if address[:address2]
@@ -190,11 +423,36 @@ module ActiveMerchant #:nodoc:
190
423
  end
191
424
  end
192
425
 
426
+ def add_statement_address(post, options)
427
+ return unless statement_address = options[:statement_address]
428
+ return unless [:address1, :city, :zip, :state].all? { |key| statement_address[key].present? }
429
+
430
+ post[:statement_address] = {}
431
+ post[:statement_address][:line1] = statement_address[:address1]
432
+ post[:statement_address][:line2] = statement_address[:address2] if statement_address[:address2].present?
433
+ post[:statement_address][:city] = statement_address[:city]
434
+ post[:statement_address][:postal_code] = statement_address[:zip]
435
+ post[:statement_address][:state] = statement_address[:state]
436
+ end
437
+
193
438
  def add_creditcard(post, creditcard, options)
194
439
  card = {}
195
- if creditcard.respond_to?(:number)
440
+ if emv_payment?(creditcard)
441
+ add_emv_creditcard(post, creditcard.icc_data)
442
+ post[:card][:read_method] = 'contactless' if creditcard.read_method == 'contactless'
443
+ post[:card][:read_method] = 'contactless_magstripe_mode' if creditcard.read_method == 'contactless_magstripe'
444
+ if creditcard.encrypted_pin_cryptogram.present? && creditcard.encrypted_pin_ksn.present?
445
+ post[:card][:encrypted_pin] = creditcard.encrypted_pin_cryptogram
446
+ post[:card][:encrypted_pin_key_id] = creditcard.encrypted_pin_ksn
447
+ end
448
+ elsif creditcard.respond_to?(:number)
196
449
  if creditcard.respond_to?(:track_data) && creditcard.track_data.present?
197
450
  card[:swipe_data] = creditcard.track_data
451
+ if creditcard.respond_to?(:read_method)
452
+ card[:fallback_reason] = 'no_chip' if creditcard.read_method == 'fallback_no_chip'
453
+ card[:fallback_reason] = 'chip_error' if creditcard.read_method == 'fallback_chip_error'
454
+ card[:read_method] = 'contactless_magstripe_mode' if creditcard.read_method == 'contactless_magstripe'
455
+ end
198
456
  else
199
457
  card[:number] = creditcard.number
200
458
  card[:exp_month] = creditcard.month
@@ -203,11 +461,21 @@ module ActiveMerchant #:nodoc:
203
461
  card[:name] = creditcard.name if creditcard.name
204
462
  end
205
463
 
464
+ if creditcard.is_a?(NetworkTokenizationCreditCard)
465
+ card[:cryptogram] = creditcard.payment_cryptogram
466
+ card[:eci] = creditcard.eci.rjust(2, '0') if creditcard.eci =~ /^[0-9]+$/
467
+ card[:tokenization_method] = creditcard.source.to_s
468
+ end
206
469
  post[:card] = card
470
+
207
471
  add_address(post, options)
208
472
  elsif creditcard.kind_of?(String)
209
473
  if options[:track_data]
210
474
  card[:swipe_data] = options[:track_data]
475
+ elsif creditcard.include?('|')
476
+ customer_id, card_id = creditcard.split('|')
477
+ card = card_id
478
+ post[:customer] = customer_id
211
479
  else
212
480
  card = creditcard
213
481
  end
@@ -215,18 +483,48 @@ module ActiveMerchant #:nodoc:
215
483
  end
216
484
  end
217
485
 
218
- def add_customer(post, creditcard, options)
219
- post[:customer] = options[:customer] if options[:customer] && !creditcard.respond_to?(:number)
486
+ def add_emv_creditcard(post, icc_data, options = {})
487
+ post[:card] = { emv_auth_data: icc_data }
488
+ end
489
+
490
+ def add_payment_token(post, token, options = {})
491
+ post[:card] = token.payment_data['id']
492
+ end
493
+
494
+ def add_customer(post, payment, options)
495
+ if options[:customer] && !payment.respond_to?(:number)
496
+ ActiveMerchant.deprecated 'Passing the customer in the options is deprecated. Just use the response.authorization instead.'
497
+ post[:customer] = options[:customer]
498
+ end
220
499
  end
221
500
 
222
501
  def add_flags(post, options)
223
502
  post[:uncaptured] = true if options[:uncaptured]
503
+ post[:recurring] = true if options[:eci] == 'recurring' || options[:recurring]
224
504
  end
225
505
 
226
- def fetch_application_fees(identification, options = {})
227
- options.merge!(:key => @fee_refund_api_key)
506
+ def add_metadata(post, options = {})
507
+ post[:metadata] ||= {}
508
+ post[:metadata].merge!(options[:metadata]) if options[:metadata]
509
+ post[:metadata][:email] = options[:email] if options[:email]
510
+ post[:metadata][:order_id] = options[:order_id] if options[:order_id]
511
+ post.delete(:metadata) if post[:metadata].empty?
512
+ end
228
513
 
229
- commit(:get, "application_fees?charge=#{identification}", nil, options)
514
+ def add_emv_metadata(post, creditcard)
515
+ post[:metadata] ||= {}
516
+ post[:metadata][:card_read_method] = creditcard.read_method if creditcard.respond_to?(:read_method)
517
+ end
518
+
519
+ def fetch_application_fee(identification, options = {})
520
+ options[:key] = @fee_refund_api_key
521
+
522
+ fetch_charge = commit(:get, "charges/#{CGI.escape(identification)}", nil, options)
523
+ application_fee_response!(fetch_charge, "Application fee id could not be retrieved: #{fetch_charge.message}")
524
+ end
525
+
526
+ def application_fee_response!(response, message)
527
+ response.success? ? response : Response.new(false, message)
230
528
  end
231
529
 
232
530
  def parse(body)
@@ -235,91 +533,226 @@ module ActiveMerchant #:nodoc:
235
533
 
236
534
  def post_data(params)
237
535
  return nil unless params
536
+ flatten_params([], params).join('&')
537
+ end
238
538
 
239
- params.map do |key, value|
240
- next if value.blank?
539
+ def flatten_params(flattened, params, prefix = nil)
540
+ params.each do |key, value|
541
+ next if value != false && value.blank?
542
+ flattened_key = prefix.nil? ? key : "#{prefix}[#{key}]"
241
543
  if value.is_a?(Hash)
242
- h = {}
243
- value.each do |k, v|
244
- h["#{key}[#{k}]"] = v unless v.blank?
245
- end
246
- post_data(h)
544
+ flatten_params(flattened, value, flattened_key)
247
545
  elsif value.is_a?(Array)
248
- value.map { |v| "#{key}[]=#{CGI.escape(v.to_s)}" }.join("&")
546
+ flatten_array(flattened, value, flattened_key)
249
547
  else
250
- "#{key}=#{CGI.escape(value.to_s)}"
548
+ flattened << "#{flattened_key}=#{CGI.escape(value.to_s)}"
251
549
  end
252
- end.compact.join("&")
550
+ end
551
+ flattened
253
552
  end
254
553
 
255
- def headers(options = {})
256
- @@ua ||= JSON.dump({
257
- :bindings_version => ActiveMerchant::VERSION,
258
- :lang => 'ruby',
259
- :lang_version => "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})",
260
- :platform => RUBY_PLATFORM,
261
- :publisher => 'active_merchant'
262
- })
554
+ def flatten_array(flattened, array, prefix)
555
+ array.each_with_index do |item, idx|
556
+ key = "#{prefix}[#{idx}]"
557
+ if item.is_a?(Hash)
558
+ flatten_params(flattened, item, key)
559
+ elsif item.is_a?(Array)
560
+ flatten_array(flattened, item, key)
561
+ else
562
+ flattened << "#{key}=#{CGI.escape(item.to_s)}"
563
+ end
564
+ end
565
+ end
263
566
 
264
- key = options[:key] || @api_key
265
- version = options[:version] || @version
567
+ def headers(options = {})
568
+ key = options[:key] || @api_key
569
+ idempotency_key = options[:idempotency_key]
266
570
 
267
571
  headers = {
268
- "Authorization" => "Basic " + Base64.encode64(key.to_s + ":").strip,
269
- "User-Agent" => "Stripe/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
270
- "X-Stripe-Client-User-Agent" => @@ua,
271
- "X-Stripe-Client-User-Metadata" => {:ip => options[:ip]}.to_json
572
+ 'Authorization' => 'Basic ' + Base64.encode64(key.to_s + ':').strip,
573
+ 'User-Agent' => "Stripe/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
574
+ 'Stripe-Version' => api_version(options),
575
+ 'X-Stripe-Client-User-Agent' => stripe_client_user_agent(options),
576
+ 'X-Stripe-Client-User-Metadata' => {:ip => options[:ip]}.to_json
272
577
  }
273
- headers.merge!("Stripe-Version" => version) if version
578
+ headers['Idempotency-Key'] = idempotency_key if idempotency_key
579
+ headers['Stripe-Account'] = options[:stripe_account] if options[:stripe_account]
274
580
  headers
275
581
  end
276
582
 
277
- def commit(method, url, parameters=nil, options = {})
278
- add_expand_parameters(parameters, options) if parameters
583
+ def stripe_client_user_agent(options)
584
+ return user_agent unless options[:application]
585
+ JSON.dump(JSON.parse(user_agent).merge!({application: options[:application]}))
586
+ end
587
+
588
+ def api_version(options)
589
+ options[:version] || @options[:version] || '2015-04-07'
590
+ end
279
591
 
592
+ def api_request(method, endpoint, parameters = nil, options = {})
280
593
  raw_response = response = nil
281
- success = false
282
594
  begin
283
- raw_response = ssl_request(method, self.live_url + url, post_data(parameters), headers(options))
595
+ raw_response = ssl_request(method, self.live_url + endpoint, post_data(parameters), headers(options))
284
596
  response = parse(raw_response)
285
- success = !response.key?("error")
286
597
  rescue ResponseError => e
287
598
  raw_response = e.response.body
288
599
  response = response_error(raw_response)
289
600
  rescue JSON::ParserError
290
601
  response = json_error(raw_response)
291
602
  end
603
+ response
604
+ end
605
+
606
+ def commit(method, url, parameters = nil, options = {})
607
+ add_expand_parameters(parameters, options) if parameters
608
+ response = api_request(method, url, parameters, options)
609
+ response['webhook_id'] = options[:webhook_id] if options[:webhook_id]
610
+ success = success_from(response)
292
611
 
293
- card = response["card"] || response["active_card"] || {}
612
+ card = card_from_response(response)
294
613
  avs_code = AVS_CODE_TRANSLATOR["line1: #{card["address_line1_check"]}, zip: #{card["address_zip_check"]}"]
295
- cvc_code = CVC_CODE_TRANSLATOR[card["cvc_check"]]
614
+ cvc_code = CVC_CODE_TRANSLATOR[card['cvc_check']]
615
+
296
616
  Response.new(success,
297
- success ? "Transaction approved" : response["error"]["message"],
617
+ message_from(success, response),
298
618
  response,
299
- :test => response.has_key?("livemode") ? !response["livemode"] : false,
300
- :authorization => response["id"],
619
+ :test => response_is_test?(response),
620
+ :authorization => authorization_from(success, url, method, response),
301
621
  :avs_result => { :code => avs_code },
302
- :cvv_result => cvc_code
622
+ :cvv_result => cvc_code,
623
+ :emv_authorization => emv_authorization_from_response(response),
624
+ :error_code => success ? nil : error_code_from(response)
303
625
  )
304
626
  end
305
627
 
306
- def response_error(raw_response)
307
- begin
308
- parse(raw_response)
309
- rescue JSON::ParserError
310
- json_error(raw_response)
628
+ def authorization_from(success, url, method, response)
629
+ return response.fetch('error', {})['charge'] unless success
630
+
631
+ if url == 'customers'
632
+ [response['id'], response['sources']['data'].first['id']].join('|')
633
+ elsif method == :post && url.match(/customers\/.*\/cards/)
634
+ [response['customer'], response['id']].join('|')
635
+ else
636
+ response['id']
311
637
  end
312
638
  end
313
639
 
640
+ def message_from(success, response)
641
+ success ? 'Transaction approved' : response.fetch('error', {'message' => 'No error details'})['message']
642
+ end
643
+
644
+ def success_from(response)
645
+ !response.key?('error') && response['status'] != 'failed'
646
+ end
647
+
648
+ def response_error(raw_response)
649
+ parse(raw_response)
650
+ rescue JSON::ParserError
651
+ json_error(raw_response)
652
+ end
653
+
314
654
  def json_error(raw_response)
315
655
  msg = 'Invalid response received from the Stripe API. Please contact support@stripe.com if you continue to receive this message.'
316
656
  msg += " (The raw response returned by the API was #{raw_response.inspect})"
317
657
  {
318
- "error" => {
319
- "message" => msg
658
+ 'error' => {
659
+ 'message' => msg
320
660
  }
321
661
  }
322
662
  end
663
+
664
+ def response_is_test?(response)
665
+ if response.has_key?('livemode')
666
+ !response['livemode']
667
+ elsif response['charge'].is_a?(Hash) && response['charge'].has_key?('livemode')
668
+ !response['charge']['livemode']
669
+ else
670
+ false
671
+ end
672
+ end
673
+
674
+ def emv_payment?(payment)
675
+ payment.respond_to?(:emv?) && payment.emv?
676
+ end
677
+
678
+ def quickchip_payment?(payment)
679
+ payment.respond_to?(:read_method) && payment.read_method == 'contact_quickchip'
680
+ end
681
+
682
+ def card_from_response(response)
683
+ response['card'] || response['active_card'] || response['source'] || {}
684
+ end
685
+
686
+ def emv_authorization_from_response(response)
687
+ return response['error']['emv_auth_data'] if response['error']
688
+
689
+ card_from_response(response)['emv_auth_data']
690
+ end
691
+
692
+ def error_code_from(response)
693
+ return STANDARD_ERROR_CODE_MAPPING['processing_error'] unless response['error']
694
+
695
+ code = response['error']['code']
696
+ decline_code = response['error']['decline_code'] if code == 'card_declined'
697
+
698
+ error_code = STANDARD_ERROR_CODE_MAPPING[decline_code]
699
+ error_code ||= STANDARD_ERROR_CODE_MAPPING[code]
700
+ error_code
701
+ end
702
+
703
+ def tokenize_bank_account(bank_account, options = {})
704
+ account_holder_type = BANK_ACCOUNT_HOLDER_TYPE_MAPPING[bank_account.account_holder_type]
705
+
706
+ post = {
707
+ bank_account: {
708
+ account_number: bank_account.account_number,
709
+ country: 'US',
710
+ currency: 'usd',
711
+ routing_number: bank_account.routing_number,
712
+ name: bank_account.name,
713
+ account_holder_type: account_holder_type,
714
+ }
715
+ }
716
+
717
+ token_response = api_request(:post, "tokens?#{post_data(post)}")
718
+ success = token_response['error'].nil?
719
+
720
+ if success && token_response['id']
721
+ Response.new(success, nil, token: token_response)
722
+ else
723
+ Response.new(success, token_response['error']['message'])
724
+ end
725
+ end
726
+
727
+ def ach?(payment_method)
728
+ case payment_method
729
+ when String, nil
730
+ false
731
+ else
732
+ card_brand(payment_method) == 'check'
733
+ end
734
+ end
735
+
736
+ def auth_minimum_amount(options)
737
+ return 100 unless options[:currency]
738
+ return MINIMUM_AUTHORIZE_AMOUNTS[options[:currency].upcase] || 100
739
+ end
740
+
741
+ def copy_when_present(dest, dest_path, source, source_path = nil)
742
+ source_path ||= dest_path
743
+ source_path.each do |key|
744
+ return nil unless source[key]
745
+ source = source[key]
746
+ end
747
+
748
+ if source
749
+ dest_path.first(dest_path.size - 1).each do |key|
750
+ dest[key] ||= {}
751
+ dest = dest[key]
752
+ end
753
+ dest[dest_path.last] = source
754
+ end
755
+ end
323
756
  end
324
757
  end
325
758
  end