mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-28 01:53:25 +00:00
@@ -36,6 +36,7 @@
|
||||
//= require ./orders/orders
|
||||
//= require ./order_cycles/order_cycles
|
||||
//= require ./payment_methods/payment_methods
|
||||
//= require ./payments/payments
|
||||
//= require ./product_import/product_import
|
||||
//= require ./products/products
|
||||
//= require ./resources/resources
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
angular.module("admin.payments").controller "PaymentCtrl", ($scope, Payment, StatusMessage) ->
|
||||
$scope.form_data = Payment.form_data
|
||||
$scope.submitted = false
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.submitPayment = () ->
|
||||
return false if $scope.submitted
|
||||
$scope.submitted = true
|
||||
StatusMessage.display 'progress', t("spree.admin.payments.source_forms.stripe.submitting_payment")
|
||||
Payment.purchase()
|
||||
@@ -0,0 +1,36 @@
|
||||
angular.module('admin.payments').directive "stripeElements", ($injector, AdminStripeElements) ->
|
||||
restrict: 'E'
|
||||
template: "<label for='card-element'>\
|
||||
<div id='card-element'></div>\
|
||||
<div id='card-errors' class='error'></div>\
|
||||
</label>"
|
||||
|
||||
link: (scope, elem, attr)->
|
||||
if $injector.has('stripeObject')
|
||||
stripe = $injector.get('stripeObject')
|
||||
|
||||
card = stripe.elements().create 'card',
|
||||
hidePostalCode: false
|
||||
style:
|
||||
base:
|
||||
fontFamily: "Roboto, Arial, sans-serif"
|
||||
fontSize: '16px'
|
||||
color: '#5c5c5c'
|
||||
'::placeholder':
|
||||
color: '#6c6c6c'
|
||||
card.mount('#card-element')
|
||||
|
||||
# Elements validates user input as it is typed. To help your customers
|
||||
# catch mistakes, you should listen to change events on the card Element
|
||||
# and display any errors:
|
||||
card.addEventListener 'change', (event) ->
|
||||
displayError = document.getElementById('card-errors')
|
||||
if event.error
|
||||
displayError.textContent = event.error.message
|
||||
else
|
||||
displayError.textContent = ''
|
||||
|
||||
return
|
||||
|
||||
AdminStripeElements.stripe = stripe
|
||||
AdminStripeElements.card = card
|
||||
1
app/assets/javascripts/admin/payments/payments.js.coffee
Normal file
1
app/assets/javascripts/admin/payments/payments.js.coffee
Normal file
@@ -0,0 +1 @@
|
||||
angular.module("admin.payments", ['ofn.admin'])
|
||||
@@ -0,0 +1,47 @@
|
||||
angular.module('admin.payments').factory 'Payment', (AdminStripeElements, currentOrderNumber, paymentMethods, PaymentMethods, PaymentResource, StatusMessage, $window)->
|
||||
new class Payment
|
||||
order: currentOrderNumber
|
||||
form_data: {}
|
||||
|
||||
paymentMethodType: ->
|
||||
PaymentMethods.byID[@form_data.payment_method].method_type
|
||||
|
||||
preprocess: ->
|
||||
munged_payment = {}
|
||||
munged_payment["payment"] = {payment_method_id: @form_data.payment_method, amount: @form_data.amount}
|
||||
munged_payment["order_id"] = @order
|
||||
# Not tested with Gateway other than Stripe. Could fall back to Rails for this?
|
||||
# Works ok without extra source_attrs for Cash, Bank Transfer etc.
|
||||
switch @paymentMethodType()
|
||||
when 'gateway'
|
||||
angular.extend munged_payment.payment, {
|
||||
source_attributes:
|
||||
number: @form_data.card_number
|
||||
month: @form_data.card_month
|
||||
year: @form_data.card_year
|
||||
verification_value: @form_data.card_verification_value
|
||||
}
|
||||
when 'stripe'
|
||||
angular.extend munged_payment.payment, {
|
||||
source_attributes:
|
||||
gateway_payment_profile_id: @form_data.token
|
||||
cc_type: @form_data.cc_type
|
||||
last_digits: @form_data.card.last4
|
||||
month: @form_data.card.exp_month
|
||||
year: @form_data.card.exp_year
|
||||
}
|
||||
munged_payment
|
||||
|
||||
purchase: ->
|
||||
if @paymentMethodType() == 'stripe'
|
||||
AdminStripeElements.requestToken(@form_data, @submit)
|
||||
else
|
||||
@submit()
|
||||
|
||||
submit: =>
|
||||
munged = @preprocess()
|
||||
PaymentResource.create({order_id: munged.order_id}, munged, (response, headers, status)=>
|
||||
$window.location.pathname = "/admin/orders/" + munged.order_id + "/payments"
|
||||
, (response) ->
|
||||
StatusMessage.display 'error', t("spree.admin.payments.source_forms.stripe.error_saving_payment")
|
||||
)
|
||||
@@ -0,0 +1,38 @@
|
||||
angular.module("admin.payments").factory 'AdminStripeElements', ($rootScope, StatusMessage) ->
|
||||
new class AdminStripeElements
|
||||
|
||||
# These are both set from the AdminStripeElements directive
|
||||
stripe: null
|
||||
card: null
|
||||
|
||||
# New Stripe Elements method
|
||||
requestToken: (secrets, submit) ->
|
||||
return unless @stripe? && @card?
|
||||
|
||||
cardData = @makeCardData(secrets)
|
||||
|
||||
@stripe.createToken(@card, cardData).then (response) =>
|
||||
if(response.error)
|
||||
StatusMessage.display 'error', response.error.message
|
||||
else
|
||||
secrets.token = response.token.id
|
||||
secrets.cc_type = @mapCC(response.token.card.brand)
|
||||
secrets.card = response.token.card
|
||||
submit()
|
||||
|
||||
# Maps the brand returned by Stripe to that required by activemerchant
|
||||
mapCC: (ccType) ->
|
||||
switch ccType
|
||||
when 'MasterCard' then return 'master'
|
||||
when 'Visa' then return 'visa'
|
||||
when 'American Express' then return 'american_express'
|
||||
when 'Discover' then return 'discover'
|
||||
when 'JCB' then return 'jcb'
|
||||
when 'Diners Club' then return 'diners_club'
|
||||
|
||||
# It doesn't matter if any of these are nil, all are optional.
|
||||
makeCardData: (secrets) ->
|
||||
{'name': secrets.name,
|
||||
'address1': secrets.address1,
|
||||
'city': secrets.city,
|
||||
'zipcode': secrets.zipcode}
|
||||
@@ -0,0 +1,5 @@
|
||||
angular.module("admin.resources").factory 'PaymentResource', ($resource) ->
|
||||
$resource('/admin/orders/:order_id/payments.json', {order_id: "@order_id"}, {
|
||||
'create':
|
||||
method: 'POST'
|
||||
})
|
||||
@@ -25,19 +25,13 @@ Darkswarm.factory 'StripeElements', ($rootScope, Loading, RailsFlashLoader) ->
|
||||
|
||||
# Maps the brand returned by Stripe to that required by activemerchant
|
||||
mapCC: (ccType) ->
|
||||
if ccType == 'MasterCard'
|
||||
return 'master'
|
||||
else if ccType == 'Visa'
|
||||
return 'visa'
|
||||
else if ccType == 'American Express'
|
||||
return 'american_express'
|
||||
else if ccType == 'Discover'
|
||||
return 'discover'
|
||||
else if ccType == 'JCB'
|
||||
return 'jcb'
|
||||
else if ccType == 'Diners Club'
|
||||
return 'diners_club'
|
||||
return
|
||||
switch ccType
|
||||
when 'MasterCard' then return 'master'
|
||||
when 'Visa' then return 'visa'
|
||||
when 'American Express' then return 'american_express'
|
||||
when 'Discover' then return 'discover'
|
||||
when 'JCB' then return 'jcb'
|
||||
when 'Diners Club' then return 'diners_club'
|
||||
|
||||
# It doesn't matter if any of these are nil, all are optional.
|
||||
makeCardData: (secrets) ->
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
/replace 'code[erb-loud]:contains("form_for @payment")'
|
||||
= form_for @payment, :url => admin_order_payments_path(@order), :html => {"ng-app" => "admin.payments", "ng-controller" => "PaymentCtrl"} do |f|
|
||||
@@ -0,0 +1,3 @@
|
||||
/ insert_before "fieldset.no-border-top"
|
||||
|
||||
%save-bar{ persist: "true" }
|
||||
@@ -0,0 +1,2 @@
|
||||
/replace 'code[erb-loud]:contains("button @order.cart?")'
|
||||
= button_tag t(:update), type: 'button', "ng-click" => "submitPayment()"
|
||||
@@ -1,8 +1,11 @@
|
||||
<%= admin_inject_json "admin.payments", "currentOrderNumber", @order.number %>
|
||||
<%= admin_inject_json_ams_array "admin.payments", "paymentMethods", @payment_methods, Api::PaymentMethodSerializer %>
|
||||
|
||||
<div data-hook="admin_payment_form_fields" class="row">
|
||||
<div class="alpha three columns">
|
||||
<div class="field">
|
||||
<%= f.label :amount, t(:amount) %>
|
||||
<%= f.text_field :amount, :value => @order.outstanding_balance, :class => 'fullwidth' %>
|
||||
<%= f.text_field :amount, :value => @order.outstanding_balance, :class => 'fullwidth', "watch-value-as" => 'form_data.amount' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="omega nine columns">
|
||||
@@ -12,7 +15,7 @@
|
||||
<% @payment_methods.each do |method| %>
|
||||
<li>
|
||||
<label data-hook="payment_method_field">
|
||||
<%= radio_button_tag 'payment[payment_method_id]', method.id, method == @payment_method, { class: "payment_methods_radios" } %>
|
||||
<%= radio_button_tag 'payment[payment_method_id]', method.id, method == @payment_method, { class: "payment_methods_radios", "ng-model" => 'form_data.payment_method' } %>
|
||||
<%= t(method.name, :scope => :payment_methods, :default => method.name) %>
|
||||
</label>
|
||||
</li>
|
||||
|
||||
@@ -1,4 +1,17 @@
|
||||
-# = render "spree/admin/payments/source_forms/gateway", payment_method: payment_method
|
||||
.stripe
|
||||
%script{:src => "https://js.stripe.com/v3/", :type => "text/javascript"}
|
||||
- if Stripe.publishable_key
|
||||
:javascript
|
||||
angular.module('admin.payments').value("stripeObject", Stripe("#{Stripe.publishable_key}"))
|
||||
|
||||
%strong
|
||||
= t('.no_payment_via_admin_backend')
|
||||
.row
|
||||
.three.columns
|
||||
= label_tag :cardholder_name, t(:cardholder_name)
|
||||
.six.columns
|
||||
= text_field_tag :cardholder_name, nil, {size: 40, "ng-model" => 'form_data.name'}
|
||||
.row
|
||||
.three.columns
|
||||
= label_tag :card_details, t(:card_details)
|
||||
.six.columns
|
||||
%stripe-elements
|
||||
|
||||
@@ -2613,7 +2613,8 @@ See the %{link} to find out more about %{sitename}'s features and to start using
|
||||
payments:
|
||||
source_forms:
|
||||
stripe:
|
||||
no_payment_via_admin_backend: Creating Stripe-based payments from the admin backend is not possible at this time
|
||||
error_saving_payment: Error saving payment
|
||||
submitting_payment: Submitting payment...
|
||||
products:
|
||||
new:
|
||||
title: 'New Product'
|
||||
|
||||
Reference in New Issue
Block a user