How to handle Stripe subscriptions based on Currency? - stripe-payments

I'm using the Stripe payment gateway for my SAAS app.
I have created a Product and multiple Plans are linked to it. Plans price is in USD.
I have created a new customer. Then I'm trying to subscribe to a Plan, but I'm getting the below error
You cannot combine currencies on a single customer. This customer has had a subscription, coupon, or invoice item with currency inr
I have seen their documentation, it is not allowing me to change the Currency of the customer.
Is there anyway I can convert USD to the currency of the customer before subscribing?

My recommendation would be to, prior to attaching the subscription, retrieve the customer object for which you'd like to have a subscription attached, determine the currency of the customer, and create a new plan (in the currency) if necessary. To do this though, you'd probably want to use a currency conversion API from a third-party, as Stripe does not support that.
Example in Python:
plan_id = ... # This would have been retrieved from your form, most likely (eg. 'basic-plan')
usd_plan = stripe.Plan.retrieve(plan_id)
cus = stripe.Customer.retrieve()
if cus.currency is not 'usd': # if the currency of the customer is not "usd"
# create a new plan id for currency (eg. 'basic-plan-cad')
plan_id = plan_id + '-' + cus.currency # check if there is a
# use a 3rd party to get the currency
amount_in_currency = amount * <API_CONVERSION_RATE>
# check that the plan doesn't already exist and create it otherwise
try:
stripe.Plan.create(
amount=amount_in_currency,
interval=usd_plan.interval,
product={
"name": usd_plan.product
},
currency=cus.currency,
id=plan_id
)
except Exception as e: # this may fail if the plan already exists
break
# create the subscription
sub = stripe.Subscription.create(
customer="cus_xxx",
items=[
{
"plan": plan_id, # this will either be the `basic-plan` or `basic-plan-{currency}
},
]
)

Related

How to charge existing customers for a products?

If you know Audible, that's how my service works. You can have subscriptions which you get credits for but you can also just buy single items right away (if you want).
Subscriptions work for me but what I can't get my head around is how I can charge an existing customer, using his default payment method, on a single item. Let's stick to Audible.
A user wants to buy a single audio-track.
I though I can:
Create a Product for this track (setting a name and an image-url)
Create or re-use a Price and set the charge-amount as stated in my database
Somehow create an Invoice or Charge for this Price/Product and move one
However, I just don't quite get how to do that.
Looking at the docs of Invoice, it appears to me that I am not able to add a single product or price and let Stripe automatically charge the customer.
I thought it would look something like this:
public void buyProduct(String productId, Customer customer) {
InvoiceCreateParams.builder()
.setCustomer(customer.getId())
.setDefaultPaymentMethod(customer.getPaymentMethod())
.setAutoAdvance(true)
.setCollectionMethod(CollectionMethod.CHARGE_AUTOMATICALLY)
// Add product/price here ?
.build();
// ...
}
So, what is the simplest way to charge a customer for a product?
Update
I noticed that an InvoiceItem can take a Invoice ID.
Is the following correct (in principal)?
Setting autoAdvance to true and CHARGE_AUTOMATICALLY as collection-method, will the user charged correctly as I intend to using the code below?
public void createInvoice() throws StripeException {
String customerId = null;
String paymentMethodId = null;
String priceId = null;
boolean chargeAutomatically = true;
InvoiceCreateParams invoiceCreateParams = InvoiceCreateParams.builder()
.setCustomer(customerId)
.setDefaultPaymentMethod(paymentMethodId)
.setAutoAdvance(chargeAutomatically)
.setCollectionMethod(CollectionMethod.CHARGE_AUTOMATICALLY)
.build();
Invoice invoice = Invoice.create(invoiceCreateParams);
InvoiceItemCreateParams invoiceItemCreateParams = InvoiceItemCreateParams.builder()
.setCustomer(customerId)
.setPrice(priceId)
.setInvoice(invoice.getId())
.build();
InvoiceItem invoiceItem = InvoiceItem.create(invoiceItemCreateParams);
}
It feels weird to create an invoice at first, and set everything up for charging a customer immediatelly, and only after having done so, set the actual item that the user wants to buy.
You should take a look at this: https://stripe.com/docs/billing/invoices/sending#one-off
First, you'll want to create an Invoice Item using the Price and Customer ID (no need to create the invoice first). You can create as many Invoice Items as you want, depending on how many things you want to charge your customer for. Then you can create an Invoice which will automatically pick up all the pending Invoice Items for a given Customer.

How to insert Adjustment record with Contract API

I'm trying to insert an adjustment record via the SOAP API using the following code.
Dim NewAdjustment As Adjustment = New Adjustment With {
.ExternalRef = New StringValue With {.Value = "TEST1234"},
.Description = New StringValue With {.Value = "1234TEST"},
.[Date] = New DateTimeValue With {.Value = "12/20/2018"},
.Details = {New AdjustmentDetail With {
.BranchID = New StringValue With {.Value = "PRODWHOLE"},
.InventoryID = New StringValue With {.Value = "18r.5"},
.WarehouseID = New StringValue With {.Value = "RETAIL"},
.Qty = New DecimalValue With {.Value = 100}
}}
}
Dim InsertAdjustment As Adjustment = CType(soapClient.Put(NewAdjustment), Adjustment)
I get an error px.data.pcexception: Error: 'Branch' cannot be empty. Error: 'Post Period' cannot be empty. Error Inserting 'Receipt' record raised at least one error.
I'm guessing I need to fill those values but I'm not sure how to do that. I see them in the table but not the API interface. I'm new to Acumatica, so I'm guessing this is just something I'm missing.
Thanks in advance.
I have never seen the usage of the Date property as [Date], but that does not mean it will not work. The Posting period is defaulted based on the value of the date property. Make sure that the December 2018 posting period is open on the company that you are logged into with the API. I have seen this error from time to time when the accounting department does not open the period in a timely fashion.
The BranchID is defaulted based on the login parameters of the soapClient. One thing to be aware of is that your API login user needs to have permissions to the BranchID being used, or you will definitely get an error about the Branch being invalid.
Depending on the Inventory costing methodology used by your company, Inventory Adjustments might require that they be processed against an inventory Receipt. This can be tricky to figure out what to do, especially if you have never received anything for this Item in a new implementation, and you want to increase inventory levels. For positive Adjustments in your business case, you might want to consider creating Inventory Receipts instead of Adjustments. The entity is very similar to the Adjustments. For negative Adjustments you might want to consider using Inventory Issues which is again, quite similar.
If you decide to use adjustments, you will have to search the Inventory Receipts for an appopriate Receipt number to use when populating the transaction details. One for each line you insert.

How can bypass the credit limit while creating invoice or saleorder in Netsuite using SuiteTalk Webservice?

I am using Netsuite SuiteTalk web service since 3-4 months I felt comfortable to use it. now, i have issues i want to create saleorder/invoice in netsuite using SuiteTalk but i am unable to do that because everytime i am getting error of credit limit i.e customer invoice amount is more than their credit limit. it's O.K, but as long as i am sending payments too with the same webservice request.
I would appreciate if someone or Netsuite people can help me to bypass credit limit while creating invoice.
please have a look suitetalk c# code.
Invoice inv = new Invoice();
inv.entity = new RecordRef() { internalId = 25, type = RecordType.customer, typeSpecified = true };
inv.tranDate = new DateTime(2018,9,18);
inv.memo = "Test Memo";
inv.department = new RecordRef() { internalId = 10, type = RecordType.department, typeSpecified = true };
inv.location = new RecordRef() { internalId = 16, type = RecordType.location, typeSpecified = true };
InvoiceItemList itemList = new InvoiceItemList();
InvoiceItem[] items = new InvoiceItem[1];
// invoice items
InvoiceItem item = new InvoiceItem();
item.item = new RecordRef() { internalId = 12510 };
item.rate = 2.65;
item.amount = 265.00;
item.quantity = 100;
items[0] = item;
itemList.item = items;
inv.itemList = itemList;
inv.amountPaid = 180;
inv.amountPaidSpecified = true;
inv.onCreditHold = "true";
WriteResponse writeRes = ns.Service.add(inv);
Try below solution
Go to -> Setup -> Accounting -> Accounting Preferences
In General tab account Receivable section
See that CUSTOMER CREDIT LIMIT HANDLING field. choose appropriate value based on your situation.
Ignore – Select this method to allow sales orders and invoices to be entered without a warning for a customer that is at or above their credit limit.
Warn Only – Select this method to generate a warning when a sales order or invoice is being entered that puts the customer at or above their credit limit. You can choose to enter or cancel the transaction once the warning has appeared.
Enforce Holds – Select this method to block the entry of a sales order or invoice that puts the customer at or above their credit limit. This method also blocks the addition of items to existing orders for customers at or above their credit limit.
I have found the best solution, in order to avoid credit limit while creating invoice we can create Payment as PaymentItem and then we need to add in invoice.

Acumatica Web API Apply Discounts

I am trying to get a way to obtain the discount code from the web service API, i.e would there be a function call that could tell me which discount code to apply?
I am otherwise attempting to retrieve the discount codes but they can be by Item or By Item Price Class and Customer etc etc which is making the code longer than expected.
Hopeing there is a "GetBestDiscount" facility in the API that could help me?
Thanks,
G
At this moment Acumatica Discount Engine is deactivated for any Web Service call. Due to this fact, entering an order line without any discount will not populate the discount code.
However, at Acumatica University there is the GetSalesPrice.zip customization package made specifically to retrieving the price of an Item for a Customer (attached to the I200 Screen-Based Web Services 5.3 and the I210 Contract-Based Web Services 5.3 sources).
Sample call for Screen-Based API:
Content getSalesPriceSchema = context.GetSchema();
var commands = new Command[]
{
new Value
{
Value = customer,
LinkedCommand =getSalesPriceSchema.RequiredInputParameters.Customer
},
new Value
{
Value = inventoryID,
LinkedCommand =getSalesPriceSchema.RequiredInputParameters.InventoryID
},
getSalesPriceSchema.OutputPrice.Price
};
Content price = context.Submit(commands)[0];
Sample call for Contract-Based API:
GetSalesPriceInquiry priceToBeGet = new GetSalesPriceInquiry
{
Customer = new StringValue { Value = customer },
InventoryID = new StringValue { Value = inventoryID }
};
GetSalesPriceInquiry stockItemPrice = (GetSalesPriceInquiry)soapClient.Put(priceToBeGet);
I tried creating a temporary Sales order line via API Order Entry Screen without saving it as Gabriel suggestion.
I can retrieve the set price no problems but the Discount Percentage and Discount Code is not returned.
The discount percentage returned is zero and the discount Code is blank.
This is because the Acumatica Discount Engine is deactivated for any Web Service call I guess.
Any reason why the Acumatica Discount Engine is deactivated for any Web Service calls?
There is no such API, however you could use the sales order entry screen API to create a temporary sales order, add one line to it and retrieve the set price or discount without saving the order. This will be the most accurate information, since discounts and price can also depend on the date, quantity and also on other products being ordered at the same time.

Updating sharepoint item multi lookup field via odata

I need some help sorting out some syntax for an update to a list item in sharepoint from an application. Here's a rundown on the situation :
There are two lists within this sp site. One list is a products list, and the second list is a pricing. The way these lists are setup however are a 1 to many scheme. One product can have many pricing records. The product then has a column against it that is a look up field that supports multiple values.
Using REST and oData I can query and get the pricing information easily enough now, but my problem is when I need to update the products record to add a price.
with regular lookup fields I normally just set the ID property for the object, then call the update and savechanges methods for that list. With the pricing column however supporting multiple records there is no ID to set, and the field is an array of sorts. Adding the pricing object (list item) and updating and savechanges doesn't actually save. No errors are thrown but the then when viewing the list it isn't actually saving.
How can I add a price lookup to my Product?
I wrote a small method to query through each price and add it's initial price to the product below for testing :
InventoryCatalogDataContext dc = new InventoryCatalogDataContext(_pushinTinSvc);
dc.Credentials = CredentialCache.DefaultCredentials;
List<PricingItem> pricing = (from q in dc.Pricing
select q).ToList<PricingItem>();
foreach (PricingItem price in pricing)
{
var query = (DataServiceQuery<ProductsItem>)
dc.Products
.Expand("Pricing")
.Where(p => p.Id.Equals(price.StockCodeId));
List<ProductsItem> prods = query.ToList<ProductsItem>();
ProductsItem product = prods[0];
product.Pricing.Add(price);
dc.UpdateObject(product);
}
try
{
dc.SaveChanges();
}
catch (Exception ex)
{
string stopHere = ex.Message;
}
I'm not sure if I'm doing something wrong or if this is a bug. If I inspect the item after the SaveChanges, the item still has the pricing item lookup attached, showing a count of 1. At the end of the code block, if I re-query for the product, at that point it even still has the pricing attached. But once the method finishes and returns to the UI, the pricing is no longer attached, the fields are empty when you look at the list in sharepoint, but the version does increment. So I'm a little lost...

Resources