Stripe.net - Try to charge on behalf - c#

I try to use Stripe to charge on behalf of someone. I did the connect part with success, but I tried to create a token/charge after that and it doesn't work.
Some info on parameters used in the code:
"acct_158fBBAOizDDfp9B" - Get from the Connect user;
WebConfig.AppSettings.StripeClientId - My client Id get from Stripe
dashboard;
WebConfig.AppSettings.StripeSecretApiKey - My Stripe
Secret API Key;
"sk_test_5E9d7UHs9CVa3Ansop2JzIxI" - Private API key
get from Connect user.
Here is my code:
StripeRequestOptions requestOptions = new StripeRequestOptions();
requestOptions.StripeConnectAccountId = "acct_158fBBAOizDDfp9B";
var myToken = new StripeTokenCreateOptions();
myToken.Card = new StripeCreditCardOptions()
{
// set these properties if passing full card details (do not
// set these properties if you set TokenId)
Number = "4242424242424242",
ExpirationYear = "2022",
ExpirationMonth = "10",
AddressCountry = "US", // optional
AddressLine1 = "24 Beef Flank St", // optional
AddressLine2 = "Apt 24", // optional
AddressCity = "Biggie Smalls", // optional
AddressState = "NC", // optional
AddressZip = "27617", // optional
Name = "Joe Meatballs", // optional
Cvc = "1223" // optional
};
// set this property if using a customer (stripe connect only)
myToken.CustomerId = WebConfig.AppSettings.StripeClientId; // My client ID get from Stripe dashboard.
//var tokenService = new StripeTokenService(WebConfig.AppSettings.StripeSecretApiKey);
var tokenService = new StripeTokenService("sk_test_5E9d7UHs9CVa3Ansop2JzIxI");
StripeToken stripeToken = tokenService.Create(myToken, requestOptions);
I've got a «You must pass a valid card ID for this customer.» error.

A couple things:
Since you're using Stripe Connect, you can only create tokens using Stripe.js or Stripe Checkout, your server should never have access to the card info. Also I don't know why you're setting the token's customerId to a client id, clients are not customers.
Also the API key should be your API key, since you're using the Stripe account header, the option is either (your API key and the account id of the connected account) or (access token). This is discussed in the authentication portion of the Stripe Connect documentation.

Related

Stripe API - Search Based on Metadata

I have an application that uses a deep integration with Stripe. My platform is occasionally charging the connected accounts and I am storing information about these charges in the metadata of the charge itself.
I want to display this information back to the connected account so I am using the Charge Service to list charges. However I want to filter that list based on some metadata key/value pair so that I don't have to list all of the charges each time, for every connected account.
Is there a clever way of doing this?
Filtering based on metadata is not supported.
Since you are doing this across Connected accounts, a better approach would be to store the Charge ID and metadata on your end so that you don't have to list and paginate through charges, looking for particular metadata.
Stripe recently added Search API that allows search by metadata. Currently, it does not have .NET / C# integration but you can query using HTTP call directly:
Example from their docs:
curl https://api.stripe.com/v1/search/charges \
-u sk_test_daHanKyJOCiXCeBsa65biLML00wylimZ8S: \
--data-urlencode "query=metadata['key']:'value'" \
-H "Stripe-Version: 2020-08-27;search_api_beta=v1" \
-G
I was able to accomplish this with the "TransferGroup" property of the ChargeCreateOptions object. I basically set the TransferGroup property to a unique value for each connected account which I can then query later.
CREATE THE CHARGE
//THERE IS NO ID IN THE REQUEST OPTIONS BECAUSE
//WE ARE USING THE PLATFORM
var requestOptions = new RequestOptions()
{
ApiKey = {API Key}
};
//CHARGE OPTIONS
var chargeOptions = new ChargeCreateOptions
{
Amount = {AMOUNT},
Currency = "usd",
Description = $"Platform Charge",
SourceId = {StripeId},
Metadata = {MetaData},
TransferGroup = {Unique String For Each Connected Account}
};
//CREAT AND RETURN THE CHARGE
var chargeService = new ChargeService();
return chargeService.Create(chargeOptions, requestOptions);
QUERY THE PLATFORM CHARGES BASED ON TRANSFER GROUP
public List<Charge> StripePlatformCharges(string apiKey, int days, string transferGroup)
{
try
{
RequestOptions requestOptions = new RequestOptions()
{
ApiKey = apiKey
};
ChargeListOptions chargeListOptions = new ChargeListOptions()
{
CreatedRange = new DateRangeOptions()
{
GreaterThanOrEqual = DateTime.Now.AddDays(-days)
},
TransferGroup = transferGroup
};
ChargeService chargeService = new ChargeService();
return chargeService.List(chargeListOptions, requestOptions).ToList();
}
catch (Exception ex)
{
throw new Exception("Error getting stripe charges from the platform", ex);
}
}
Stripe recently released a Search API which offers filtering by metadata for certain resources including charges. The documentation is at https://stripe.com/docs/search

Secure Stripe Payment

I'm running a Stripe test payment on an ASP Net site. When the user is ready to pay they are FORWARDED to their gateway to collect card details.
Once they complete a successful payment they are returned to the success URL i set with the {SESSION_ID} variable alongside the URL i.e. www.example.com/success?session_id{Session_ID}.
I then process the payment by getting the session first
StripeConfiguration.ApiKey = "sk_test_123";
var service = new SessionService();
Checkout.Session sess service.Get("cs_test_4561");
I then find the payment from my database using the session id i saved and passed when the user checked out.
My concern is that through a web sniffer tool the Session ID can be picked up and you can pass that manually to the successURL.
I can add HTTPS to the site but is there anything else i could do to make this a little more difficult i.e. expire the Session ID after some time or have a value from Strip to confirm the payment is successful?
Edit 1:
My code behind to set the SessionCreateOptions
var options = new SessionCreateOptions
{
PaymentMethodTypes = new List<string> { "card", },
LineItems = GetItems(),
SuccessUrl = "www.example.com/success?session_id={CHECKOUT_SESSION_ID}",
CancelUrl = "www.example.com/cancel",
PaymentIntentData = new SessionPaymentIntentDataOptions
{
Metadata = new Dictionary<string, string>{
{"orderID","123"}
}
},
Mode="payment",
};
var service = new SessionService();
Session session = service.Create(options);
When the user is returned back to the success page, i run this code to get the session i run the above code to get the Session but payment_intent is null if i type sess.PaymentIntent
When you retrieve the CheckoutSession by its id, you should check its payment_intent to verify that it shows status: succeeded. That shows that the payment went through without issue.
More details on the entire process here:
https://stripe.com/docs/payments/checkout/fulfillment

How to pass PayPal send invoice reminder value using c#..? (PayPal Invoicing API)

I'm integrating PayPal Send Invoice Reminder through PayPal Invoicing API.
Here is my code,
sandbox url
var sandbox = "https://api.sandbox.paypal.com/v1/invoicing/invoices/";
notification object,
var notification = new Notification
{
subject = "Payment Reminder",
note = "This is a reminder that payment is due on " + InvoiceDueDate,
send_to_merchant = true
};
Invoice Id and Generated Access Token,
var invoice_id = "your invoice id";
var access_token = "your generated access token";
PayPal Send Reminder Api needed above values for Send Reminder Task but how to get response using above values and also how to pass these values(parameters) to rest API of PayPal.
Thanks, Kaushik.
Send Reminder PayPal Example:

Charging customer on behalf of shopkeeper using Stripe Connect?

I am developing this using ASP.NET and i have used Stripe.NET dll, according to the documentation I had linked up my shopkeeper stripe account with me and got the access code.
Now i have confusion about my customer, he should be added as customer in shopkeeper's stripe account or just his account is linked up with my Stripe account as Shopkeepers.
Can anyone please explain, how it will work ?
var stripeService = new StripeChargeService(sellerStore.StripeMerchantAccessToken); //The token returned from the above method
var stripeChargeOption = new StripeChargeCreateOptions() {
AmountInCents = amountInCents,
Currency = "usd",
CustomerId = buyerPaymentInfo.StripeCustomerToken,
Description = "Locabal",
ApplicationFeeInCents = locabalsCut
};
var response = stripeService.Create(stripeChargeOption);
buyerPaymentInfo.StripeCustomerToken will be Access code or it will be the customer registered in Suppliers account ?
I want to charge customer using his Credit Card
Your help will be highly appreciated.
As per my understanding of Stripe API, you should create a customer in your account and use customer ID which starts with "cus_" in the charge.
If you look at following stripe.net discussion you will see how to create a customer and use it in your charge.
https://github.com/jaymedavis/stripe.net/pull/43#issuecomment-30345043
//This is what we do to create a long-term customer in our system
//user is a user object unique to our system. We save it in our database
//stripeToken is what is generated by the Javascript on the page
var stripeService = new stripeCustomerService(ConfigurationManager.AppSettings["StripeSecret"]);
var stripeTokenOptions = new StripeCustomerCreateOptions { TokenId = stripeToken };
var response = stripeService.Create(stripeTokenOptions);
if (user.PaymentInfo == null)
{
PaymentInfo paymentInfo = new PaymentInfo
{
StripeCustomerToken = response.Id
};
user.PaymentInfo = paymentInfo;
}
else
{
user.PaymentInfo.StripeCustomerToken = response.Id;
}

AuthorizationException while sending a payment request with braintree on Sandbox

No matter what I do I'm always getting the same AuthorizationException for the following request on sandbox with valid keys:
REQUEST:
{"CreditCard":
{
"CVV":"123",
"ExpirationMonth":"10",
"ExpirationYear":"2016",
"Number":"4111 1111 1111 1111"
},
"Amount":195.000000,
"OrderId":"bb461ebb-b894-4716-9ea2-7317f9e8c8d9",
"MerchantAccountId":"xxxxx",
"TaxAmount":0,
"Type":{},
"CustomFields":
{
"correlation_id":"bb461ebb-b894-4716-9ea2-7317f9e8c8d9"
},
"Options":
{
"StoreInVault":true,
"SubmitForSettlement":true
},
"CustomerId":"2012f124-2f00-477f-85fb-f6bc3f5fe275"
}
Here's the code that I'm using to create this request:
var request = new TransactionRequest
{
OrderId = message.Id.ToString(),
Amount = message.Amount,
CustomerId = message.CustomerId.ToString(),
MerchantAccountId = message.MerchantAccountId,
Options = new TransactionOptionsRequest
{
SubmitForSettlement = message.SubmitForSettlement
}
};
string expirationMonth = message.ExpirationMonth.GetValueOrDefault().ToString(CultureInfo.InvariantCulture);
string expirationYear = message.ExpirationYear.GetValueOrDefault().ToString(CultureInfo.InvariantCulture);
request.CreditCard = new TransactionCreditCardRequest
{
Token = message.CreditCardId.ToString(),
CardholderName = message.CardholderName,
Number = message.CardNumber,
ExpirationMonth = expirationMonth,
ExpirationYear = expirationYear,
CVV = message.CVV
};
request.Options.StoreInVault = true;
var result = _gateway.Transaction.Sale(request);
What I'm missing?
I work at Braintree. If you have any other questions, feel free to contact our support team directly.
This error can happen when you're attempting to use a merchant account that your user doesn't have access to. In this case, the merchant account ID you're passing (which you X'd out above) doesn't exist.
Take a look at our support pages for more information on merchant account IDs:
Merchant Account ID
With Braintree, you can have multiple merchant accounts processing via the same single gateway account. You could have multiple locations, multiple businesses, and multiple currencies all setup and processing under one single account. This makes it easy to keep track of all of your processing with unified reporting and access and can even save you money.
You can find the values for all merchant accounts in your gateway account by following these steps:
Log in to the Control Panel
Navigate to Settings -> Processing
Scroll to the bottom of the page to find the section labeled Merchant Accounts
If I only have a single merchant account, do I still need to send this value with API requests?
No, this is an optional value with all API requests that support it. If you only have a single merchant account, there's no need to include this value. If you have more than one merchant account you can specify which merchant account should be used with each API request. If you omit this value, all requests will automatically be routed through your default account.

Categories