I don't think anything has happened after that thread regarding this.
But there are a couple of options:
1. Create a "placeholder" payment earlier
First I'd say that you try to move the creation of the Payment object to when you create the billing address. So the payment can be created, but not populated with payment options etc.
Then populate it properly once you reach the point where it is applicable to do so.
2. HACK THE PLANET, HAAAAAAACKK THEEEEE PLAAAANEEEEETTT!
If you can't move the payment creation, you can hack your way through this problem. But you'll need to do it differently depending on if you have Serializable Carts enabled or not:
Serializable Carts
The approach that I came up with here would be to temporarily store the BillingAddress in the Properties field. On creation it'd look something like this:
var tempBillingAddress = Cart.CreateOrderAddress("BillingAddressId");
tempBillingAddress.City = "Ankeborg";
tempBillingAddress.FirstName = "Jeff";
tempBillingAddress.LastName = "Valdez";
Cart.Properties["TempBillingAddress"] = tempBillingAddress;
Then when you create your payment, you'll do this:
var payment = Cart.CreatePayment();
payment.BillingAddress = Cart.Properties["TempBillingAddress"] as IOrderAddress;
Cart.Properties.Remove("TempBillingAddress");
Cart.AddPayment(payment);
ShoppingCart
If you're not running Serializable Carts you'll have to go to a zen place, because this will be even uglier:
var tempBillingAddress = Cart.CreateOrderAddress("BillingAddressId");
tempBillingAddress.City = "Ankeborg";
tempBillingAddress.FirstName = "Jeff";
tempBillingAddress.LastName = "Valdez";
((OrderGroup) Cart).OrderAddresses.Add((OrderAddress) tempBillingAddress);
Then when it's time to create the payment:
var payment = Cart.CreatePayment();
payment.BillingAddress = ((OrderGroup) Cart).OrderAddresses.FirstOrDefault(x => x.Name == "BillingAddressId");
Cart.AddPayment(payment);
3. Wait for Quan to come up with a better solution
Self explanatory.
-----
Hope this helps. :)
Hi Jafet,
Thanks for your response. I'm going to try and avoid the "Hack the Planet" methods to hopefully prevent the head trauma that it may cause later, though I'm having a bit of a problem at the moment.
I'm trying to create the Payment when saving the address, by doing the below.
IOrderRepository orderRepository = ServiceLocator.Current.GetInstance<IOrderRepository>();
IOrderGroupFactory orderGroupFactory = ServiceLocator.Current.GetInstance<IOrderGroupFactory>();
var cart = orderRepository.LoadOrCreateCart<ICart>(userId, "Default");
// check if payment exists
var orderPayment = cart.GetFirstForm().Payments.FirstOrDefault();
if (orderPayment == null)
{
cart.CreatePayment(orderGroupFactory);
}
// Don't know if needed
orderRepository.Save(cart);
// Bellow results in a 'Object reference not set to an instance of an object.' error
var billingAddress = cart.GetFirstForm().Payments.FirstOrDefault().BillingAddress != null ? (OrderAddress)cart.GetFirstForm().Payments.FirstOrDefault().BillingAddress : new OrderAddress();
I'm sure I'm misunderstanding how to make the Payment as I just saw it in the dot notation and the documentation for it didn't really help me too much. Is there a different way to create the Payment that I'm missing, or am I just using the CreatePayment method incorrectly?
Thank you,
Kevin Larsen
Man, noone ever goes for the hack the planet approach. :P
But yeah, you're only missing the:
cart.AddPayment(payment);
Do that after creating it.
Also there should be no reason to cast to OrderAddress. You should be able to work with IOrderAddress by doing:
cart.CreateOrderAddress(yourAddressId); // AddressId usually being "BillingAddressId", but can be whatever you want.
Finally, avoid saving until you're completely done with everything you need to do in that process. So add payment, add address then save in the case above. This will save you in some performance!
I'm sure if someone looked at some of the code I've done they would think I'm already going with the hack the planet approach ha
I cast to OrderAddress because all of our old saved addresses use the OrderAddress.State property which from what I've experienced isn't accessible using IOrderAddress as there is only RegionName and RegionCode.
Hello,
In the process of upgrading away from the CartHelper to using the interfaces I ran into an almost exact issue as the below post. I see that a support ticket was opened about this, but unfortunately there wasn't any solution for what to do with the billing address if it is created/saved in a step before the payment is created.
https://world.episerver.com/forum/developer-forum/Episerver-Commerce/Thread-Container/2016/8/address-in-iordergroup/
Was there something done since this post that solves the issue of saving a billing address before a payment would be created or is a payment needed to be created at the time the billing address is being saved?
Thank you,
Kevin Larsen