0

I'm using balanced-payments and their version 1.1 of balanced.js within Meteor.

I'm trying to create a new customer using balanced.marketplace.customers.create(formData);

Here is my CheckFormSubmitEvents.js file

Template.CheckFormSubmit.events({
    'submit form': function (e, tmpl) {
        e.preventDefault();
        var recurringStatus = $(e.target).find('[name=is_recurring]').is(':checked');
        var checkForm = {
            name: $(e.target).find('[name=name]').val(),
            account_number: $(e.target).find('[name=account_number]').val(),
            routing_number: $(e.target).find('[name=routing_number]').val(),
            recurring: { is_recurring: recurringStatus },
            created_at: new Date
        }
        checkForm._id = Donations.insert(checkForm);

            Meteor.call("balancedCardCreate", checkForm, function(error, result) {
                console.log(result);
                // Successful tokenization
            if(result.status_code === 201 && result.href) {
                // Send to your backend
                jQuery.post(responseTarget, {
                    uri: result.href
                }, function(r) {
                    // Check your backend result
                    if(r.status === 201) {
                        // Your successful logic here from backend
                    } else {
                        // Your failure logic here from backend
                    }
                });
            } else {
                // Failed to tokenize, your error logic here
            }

            // Debuging, just displays the tokenization result in a pretty div
            $('#response .panel-body pre').html(JSON.stringify(result, false, 4));
            $('#response').slideDown(300);
            });
      }
});

Here is my Methods.js file

var wrappedDelayedFunction = Async.wrap(balanced.marketplace.customers.create);

Meteor.methods({
    balancedCardCreate: function (formData) {
        console.log(formData);
        var response =  wrappedDelayedFunction(formData);
        console.log(response);
        return response;    
    }
});

I get nothing back when I submit the form, except that on the server console I do see the log of the form data.

I'm sure I'm not calling some of these async functions correctly. The hard part for me here is that the balanced function are async, but I don't know if they fit into the same mold as some of the examples I've seen.

I've tried to follow this example code. http://meteorhacks.com/improved-async-utilities-in-meteor-npm.html

Is there a specific change that needs to be done in regard to working with balanced here? Does anyone have any tips for working with Async functions or see something specific about my code that I've done wrong?

Thanks

JoshJoe
  • 1,482
  • 2
  • 17
  • 35

3 Answers3

2

The NPM utilities Async.wrap does the same thing as the undocumented Meteor function Meteor._wrapAsync, in that it takes an asynchronous function with the last argument function(err, result) {} and turns it into a synchronous function which takes the same arguments, but either returns a result or throws an error instead of using the callback. The function yields in a Fiber until the asynchronous callback returns, so that other code in the event loop can run.

One pitfall with this is that you need to make sure that the function you wrap is called with the correct context. So if balanced.marketplace.customers.create is a prototype method that expects this to be set to something, it will not be set properly unless you bind it yourself, using function.bind or any of the other various library polyfills.

For more information, see https://stackoverflow.com/a/21542356/586086.

Community
  • 1
  • 1
Andrew Mao
  • 35,740
  • 23
  • 143
  • 224
0

What I ended up doing was using a future. This works great, I just need to do better at catching errors. Which will be a question for a pro I think ; - )

Credit should go to user3374348 for answering another similar question of mine, which solved both of these. https://stackoverflow.com/a/23777507/582309

    var Future = Npm.require("fibers/future");

      function extractFromPromise(promise) {
        var fut = new Future();
        promise.then(function (result) {
          fut["return"](result);
        }, function (error) {
          fut["throw"](error);
        });
        return fut.wait();
      }

    Meteor.methods({
      createCustomer: function (data) {
      balanced.configure(Meteor.settings.balancedPaymentsAPI);

      var customerData =  extractFromPromise(balanced.marketplace.customers.create({
        'name': data.fname + " " + data.lname,
        "address": {
          "city": data.city,
          "state": data.region,
          "line1": data.address_line1,
          "line2": data.address_line2,
          "postal_code": data.postal_code,
        },
        'email': data.email_address, 
        'phone': data.phone_number
        }));
var card = extractFromPromise(balanced.marketplace.cards.create({
          'number': data.card_number,
          'expiration_year': data.expiry_year,
          'expiration_month': data.expiry_month,
          'cvv': data.cvv
        }));
          var associate = extractFromPromise(card.associate_to_customer(customerData.href).debit({
          "amount": data.total_amount*100,
          "appears_on_statement_as": "Trash Mountain" })); 
    });
Community
  • 1
  • 1
JoshJoe
  • 1,482
  • 2
  • 17
  • 35
0

As Andrew mentioned, you need to set the context for the method.

Here's the way you can do that with Async.wrap

Async.wrap(balanced.marketplace.customers, "create");
Arunoda Susiripala
  • 2,516
  • 1
  • 25
  • 30
  • When I use this the function never seems to return from the server call. It is like the async function is not passing on to the next step – JoshJoe Jul 01 '14 at 18:48
  • Okay, balanced has a promise API. This does not work then. You need to use futures directly or Async.runSync – Arunoda Susiripala Jul 01 '14 at 22:16
  • Ok, do I still need to set the context for the method before running Async.runSync? Do you have more examples of Aysnc.runSync? I'm trying to use it now, but I'm getting undefined data, I still don't believe I have it setup correctly. – JoshJoe Jul 02 '14 at 04:44