ASP.NET MVC C# PayPal Rest API - UNAUTHORIZED_PAYMENT - c#

I'm trying to integrate the paypal rest api to my web application. After digging through all available sources I'm stuck.
I'm using the paypal rest api example from here:
GitHub-PayPal-DotNet-Sample
I updated the nuget to the latest sdk version and replaced the cliendId and secret with my own live keys.
Now my problem is, always I choose "credit_card" I get an 401 error response:
{
"name": "UNAUTHORIZED_PAYMENT",
"message": "Unauthorized payment",
"information_link": "https://developer.paypal.com/webapps/developer/docs/api/#UNAUTHORIZED_PAYMENT",
"debug_id": "1d25a990be5db"
}
I set the currency to "CHF" (application runs in Switzerland) and the amount to "0.05" for testing purposes. I also retrieve a valid access token!
Tried various credit cards some belongs to my merchant account some not, still the same error.
With the option "paypal" it seems to work, but I want to offer credit cards directly within the application.
Is something not available in Switzerland? Any suggestions for this problem? Did I overlook something?
Thanks in advance!
Sample Code:
Payment pay = null;
Amount amount = new Amount();
amount.currency = "CHF";
amount.total = "0.05";
Transaction transaction = new Transaction();
transaction.amount = amount;
transaction.description = orderDescription;
List<Transaction> transactions = new List<Transaction>();
transactions.Add(transaction);
FundingInstrument fundingInstrument = new FundingInstrument();
CreditCardToken creditCardToken = new CreditCardToken();
creditCardToken.credit_card_id = GetSignedInUserCreditCardID(email);
fundingInstrument.credit_card_token = creditCardToken;
List<FundingInstrument> fundingInstrumentList = new List<FundingInstrument>();
fundingInstrumentList.Add(fundingInstrument);
Payer payer = new Payer();
payer.funding_instruments = fundingInstrumentList;
payer.payment_method = paymntMethod.ToString(); //credit_card
Payment pyment = new Payment();
pyment.intent = "sale";
pyment.payer = payer;
pyment.transactions = transactions;
pay = pyment.Create(AccessToken);
return pay;

Per this Direct card payment is only supported in the US, UK (look at the page for further requirements for UK).

Related

Expanding a Source object in a Stripe API call to StripeBalenceService doesn't return any customer info

I'm making a c# call to the Stripe.net API to fetch a balance history for a connected account. I'm trying to expand on the balance transaction object to see where the charge is coming from (ex. the customer who made the charge) as all the charges to connected accounts on my platform are from charge objects with a destination property to the connected account.
Here is my code and a screenshot of what the expanded source looks like, but think I should see a charge id or a customer or something refering me to the initial customer somewhere, but I don't...
var balanceService = new StripeBalanceService();
balanceService.ExpandSource = true;
var list = new List <string> () {
"data.source.source_transfer"
};
StripeList <StripeBalanceTransaction> balanceTransactions
= balanceService.List(
new StripeBalanceTransactionListOptions() {
Limit = 20,
Type = "payment",
Expand = list
},
new StripeRequestOptions() {
StripeConnectAccountId = accountId
}
);
foreach(var transaction in balanceTransactions) {
var test = transaction;
}
I feel like I should see a charge id (ex. ch_xxx) or a Customer value (which is null) all I see of any relevance is a payment id (ex. py_xxx)
It is possible to get the charge object(ch_xxx), it is just a little involved!
As you are using destination charges, the charge(ch_xxx) takes place on the platform account, and then a transfer(tr_xxx) is made to the connected account. That transfer creates a payment(py_xxx) on the connected account, which results in a balance transaction(txn_xxx).
As your code expands the source of those balance transactions, you get the payment(py_xxx). The payment is equivalent to a charge, so it has a source_transfer field. You can expand this field also! This will give you the transfer object(tr_xxx). Finally, the transfer has a source_transaction field, and this can be exapanded to give the original charge(ch_xxx)!
Putting that all together, you will want to expand on "data.source.source_transfer.source_transaction".
If you use a Stripe library in a dynamic language you can see this in action ... unfortunately, stripe-dotnet has an open issue right now which means that you can not do this directly. Instead, you will need to make the API calls manually by calling the various Retrieve functions on the IDs, instead of doing a single expansion. It would look something like this:
var paymentId = transaction.Source.Id;
var chargeService = new StripeChargeService();
var payment = chargeService.Get(
paymentId,
new StripeRequestOptions()
{
StripeConnectAccountId = accountId
}
);
var transferService = new StripeTransferService();
transferService.ExpandSourceTransaction = true;
var transfer = transferService.Get(payment.SourceTransferId);
var charge = transfer.SourceTransaction;
Console.WriteLine(charge.Id);

How to create a direct charge by using a shared customer?

I am attempting to create a direct charge to a connected account from my platform. I have been advised by Stripe support to do this by using a shared customer, however that has just created more issues.
The code itself is very simple, if it worked. It updates the platform customer with the src_... token provided by an iOS app. This works. It then attempts to create a shared customer using the StripeTokenService(). This does not work, despite following the documentation to the letter. The error I receive is:
You provided a customer without specifying a source. The default source of the customer is a source and cannot be shared from existing customers.
I can see no method of providing a source to the shared customer in the Stripe .Net SDK. All I can provide is a Card or BankAccount, neither of which I want to do as the API should remain agnostic of sensitive user information.
What exactly am I doing wrong here?
StripeConfiguration.SetApiKey(Settings.Stripe.SecretKey);
var businessRequestOptions = new StripeRequestOptions { StripeConnectAccountId = businessOwner.StripeAccountId };
var customerService = new StripeCustomerService();
customerService.Update(userDetail.StripeCustomerId, new StripeCustomerUpdateOptions
{
SourceToken = stripeToken // = 'src_...'
});
var tokenService = new StripeTokenService();
// this is the call that generates the error I mentioned above \/ \/
var token = tokenService.Create(new StripeTokenCreateOptions
{
CustomerId = userDetail.StripeCustomerId // = 'cus_...'
}, businessRequestOptions);
// create a direct charge to the business account (taking out application fee)
var chargeService = new StripeChargeService();
var stripeCharge = chargeService.Create(new StripeChargeCreateOptions
{
Amount = Convert.ToInt32(fee),
Currency = currency,
Description = $"Payment to {businessOwner.BusinessName} through Service X",
ApplicationFee = applicationFee,
SourceTokenOrExistingSourceId = token.Id, // use shared customerId here
}, businessRequestOptions);
When using Sources you have to use a different approach which is documented here: https://stripe.com/docs/sources/connect#shared-card-sources
The idea is that you are going to "clone" the Source from the platform to the connected account. This is done using the original_source when creating a new Source. You will then get a new Source object with a different id src_XXXX that you can then charge directly on the connected account.

Creating Subscription payments using PayPal SDK with .NET

I have found this code on the following website:
https://devtools-paypal.com/guide/recurring_payment_ec/dotnet?interactive=ON&env=sandbox
The code is as follows:
SetExpressCheckoutRequestDetailsType ecDetails = new SetExpressCheckoutRequestDetailsType();
ecDetails.ReturnURL = "https://devtools-paypal.com/guide/recurring_payment_ec/dotnet?success=true";
ecDetails.CancelURL = "https://devtools-paypal.com/guide/recurring_payment_ec/dotnet?cancel=true";
ecDetails.PaymentDetails = paymentDetails;
BillingCodeType billingCodeType = (BillingCodeType)EnumUtils.GetValue("RecurringPayments", typeof(BillingCodeType));
BillingAgreementDetailsType baType = new BillingAgreementDetailsType(billingCodeType);
baType.BillingAgreementDescription = "recurringbilling";
ecDetails.BillingAgreementDetails.Add(baType);
SetExpressCheckoutRequestType request = new SetExpressCheckoutRequestType();
request.Version = "104.0";
request.SetExpressCheckoutRequestDetails = ecDetails;
SetExpressCheckoutReq wrapper = new SetExpressCheckoutReq();
wrapper.SetExpressCheckoutRequest = request;
Dictionary<string, string> sdkConfig = new Dictionary<string, string>();
sdkConfig.Add("mode", "sandbox");
sdkConfig.Add("account1.apiUsername", "jb-us-seller_api1.paypal.com");
sdkConfig.Add("account1.apiPassword", "WX4WTU3S8MY44S7F");
sdkConfig.Add("account1.apiSignature", "AFcWxV21C7fd0v3bYYYRCpSSRl31A7yDhhsPUU2XhtMoZXsWHFxu-RWy");
PayPalAPIInterfaceServiceService service = new PayPalAPIInterfaceServiceService(sdkConfig);
SetExpressCheckoutResponseType setECResponse = service.SetExpressCheckout(wrapper);
This first part of the code is responsible for creating a PayPal billing agreement on basis which is specified in the parameters of the code.
The call then at the end returns a string as following:
https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-4SD42613U5111594L
This takes the user to the paypal site to confirm the billing agreement and the user is then returned to my website.
Then to create a recurring payments profile associated with the billing agreement, which was created using the SetExpressCheckout call, make a CreateRecurringPaymentsProfile API call with the token you got in SetExpressCheckout API response and the billingAgreementDescription used in SetExpressCheckout API request.
The code looks as following:
CreateRecurringPaymentsProfileRequestType createRPProfileRequest = new CreateRecurringPaymentsProfileRequestType();
CreateRecurringPaymentsProfileRequestDetailsType createRPProfileRequestDetails = new CreateRecurringPaymentsProfileRequestDetailsType();
createRPProfileRequestDetails.Token = "EC-4SD42613U5111594L";
createRPProfileRequest.CreateRecurringPaymentsProfileRequestDetails = createRPProfileRequestDetails;
RecurringPaymentsProfileDetailsType profileDetails = new RecurringPaymentsProfileDetailsType("2016-010-31T00:00:00:000Z");
profileDetails.RecurringPaymentsProfileDetails = profileDetails;
int frequency = 10;
BasicAmountType paymentAmount = new BasicAmountType((CurrencyCodeType)EnumUtils.GetValue("USD", typeof(CurrencyCodeType)), "1.0");
BillingPeriodType period = (BillingPeriodType)EnumUtils.GetValue("Day", typeof(BillingPeriodType));
BillingPeriodDetailsType paymentPeriod = new BillingPeriodDetailsType(period, frequency, paymentAmount);
ScheduleDetailsType scheduleDetails = new ScheduleDetailsType();
scheduleDetails.Description = "recurringbilling";
scheduleDetails.PaymentPeriod = paymentPeriod;
profileDetails.ScheduleDetails = scheduleDetails;
CreateRecurringPaymentsProfileReq createRPProfileReq = new CreateRecurringPaymentsProfileReq();
createRPProfileReq.CreateRecurringPaymentsProfileRequest = createRPProfileRequest;
Dictionary<string, string> sdkConfig = new Dictionary<string, string>();
sdkConfig.Add("mode", "sandbox");
sdkConfig.Add("account1.apiUsername", "jb-us-seller_api1.paypal.com");
sdkConfig.Add("account1.apiPassword", "WX4WTU3S8MY44S7F");
sdkConfig.Add("account1.apiSignature", "AFcWxV21C7fd0v3bYYYRCpSSRl31A7yDhhsPUU2XhtMoZXsWHFxu-RWy");
PayPalAPIInterfaceServiceService service = new PayPalAPIInterfaceServiceService(sdkConfig);
CreateRecurringPaymentsProfileResponseType createRPProfileResponse = service.CreateRecurringPaymentsProfile(createRPProfileReq);
A response will be returned containing PROFILEID and ACK values:
PROFILEID=I-0H1CDRF2NEWB&PROFILESTATUS=ActiveProfile&TIMESTAMP=2016-10-31T15:56:13Z&CORRELATIONID=a5fcc91e86a24&ACK=Success&VERSION=104.0&BUILD=24616352
Once that is finished, I store hte ProfileID parameter into my DB so that I can handle the subscriptions for the future...
My question here is: how do I manage the subscriptions on monthly/yearly basis (depending how the user decides that he will pay monthly or yearly)?
There are couple of scenarios here that I'm thinking of:
What if user cancels the billing agreement via paypal ? Should I then check the subscription status upon every user login ?
Billing on the PayPal's side is probably done automatically , or do I have to create a payment request somehow every 1 month / 1 year in order to charge the user for using premium services on my website???
This is all still very confusing for me since I'm encountering this sort of problem for the first time since I started to do coding...
Can someone help me out?

Print Packing Slip "No Address Provided" via REST API C#

Have successfully implemented PayPal.Api.Payments.Payer using:
PayPal.Api.Payments.Address billingAddress = new PayPal.Api.Payments.Address();
...
creditCard.billing_address = billingAddress;
HOWEVER, when I look at the dashboard and go to print packing slip; I see "No Address Provided" and "The sender of this payment is Unregistered".
Does the buyer need to be "registered" with paypal for the shipping information to show up or am I not setting something correctly. I have looked pretty extensively. Billing info is set correctly.
Thank you
Thank you, that worked. Here is my working code for others.
PayPal.Api.Payments.Transaction transaction = new PayPal.Api.Payments.Transaction();
transaction.item_list.shipping_address.city = reader[5].ToString().Trim();
transaction.item_list.shipping_address.line1 = reader[2].ToString().Trim();
transaction.item_list.shipping_address.postal_code = reader[7].ToString().Trim();
transaction.item_list.shipping_address.state = reader[6].ToString().Trim();
transaction.item_list.shipping_address.country_code = reader[20].ToString().Trim();
transaction.amount = amount;
transaction.description = "xxx";
List transactions = new List();
transactions.Add(transaction);
all working now on http://niupure.com
PayPal does not share billing information through transaction details. Because of this, you will need to set the payment.transactions[0].item_list.shipping_address as well as the billing information.

Add a payment using quickbooks API?

I'm using the QBFC13 Library to sync QuickBooks and my .NET app.
But I can't seem to find out how can I add a payment to quickbooks from my app.
I've notice that I have this method:
IPaymentMethodAdd paymentMehtodAddRq = requestMsgSet.AppendPaymentMethodAddRq()
But I don't know how to fill the parameters for it to work.
Can somebody please help me with an example of a simple payment passing the: ClientId and the Amount Paid?
Note: I'm using C#.
This is a 2 step process.
Create a bill
Make the Payment
Create a bill;
IMsgSetRequest requestMsgSet = sessionManager.getMsgSetRequest();
requestMsgSet.Attributes.OnError = ENRqOnError.roeContinue;
IBillAdd addBill = requestMsgSet.AppendBillAddRq();
addBill.VendorRef.FullName.SetValue(vendorName);
addBill.TxnDate.SetValue(DateTime.Now);
addBill.DueDate.SetValue(dueDate);
addBill.APAccountRef.FullName.SetValue(accountPayable);
addBill.Memo.SetValue(accountPayableMemo);
IExpenseLineAdd expenceLineAdd = addBill.ExpenseLineAddList.Append();
expenceLineAdd.AccountRef.FullName.SetValue(accountExpenses);
expenceLineAdd.Amount.SetValue(value);
expenceLineAdd.Memo.SetValue(accountExpensesLineMemo);
IMsgSetResponse responseSet = sessionManager.doRequest(true, ref requestMsgSet)
Make the Payment : You can do the payment using cheque or credit card
Credit Card,
IMsgSetRequest requestMsgSet = sessionManager.getMsgSetRequest();
requestMsgSet.Attributes.OnError = ENRqOnError.roeContinue;
IBillPaymentCreditCardAdd paymentAdd = requestMsgSet.AppendBillPaymentCreditCardAddRq();
paymentAdd.CreditCardAccountRef.FullName.SetValue("CreditCardAccount");
paymentAdd.PayeeEntityRef.FullName.SetValue("TestVendor");
paymentAdd.TxnDate.SetValue(DateTime.Now);
paymentAdd.Memo.SetValue("test payment credit card");
IAppliedToTxnAdd appliedToTxnAdd = paymentAdd.AppliedToTxnAddList.Append();
appliedToTxnAdd.TxnID.SetValue("7D-1509602561");
appliedToTxnAdd.PaymentAmount.SetValue((double)250.00);
IMsgSetResponse responseSet = sessionManager.doRequest(true, ref requestMsgSet)
See the Onscreen Reference Guide included with the SDK that has the available parameters and fields. http://developer-static.intuit.com/qbsdk-current/common/newosr/index.html

Categories