AuthorizationException while sending a payment request with braintree on Sandbox - c#

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.

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

CyberSource Simple Order API Capture PayPal transaction

I'm attempting to capture a PayPal transaction that has been authorized using the PayPal button. I'm trying to use CyberSource Simple Order API to do this. I have the only 3 pieces of information that seem to come back from the PayPal button are: payerID, paymentID and paymentToken. I've tried a few ways of handing this off to the Simple Order API, but always get a 102 code with the DECLINE message in the response. Cybersource's logging system indicates this is because The following request field(s) is either invalid or missing: request_token.
Do I need to conduct the whole transaction - authorize and capture - via cybersource? Or what is the way I can take the paypal-generated button and authorize a transaction, then capture it via CyberSource?
Here's my code snippet for the CyberSource SOAPI request:
RequestMessage request = new RequestMessage
{
merchantID = WebConfigurationManager.AppSettings["cybs.merchantID"]
, payPalDoCaptureService = new PayPalDoCaptureService {
run = "true"
, invoiceNumber = orders
, paypalAuthorizationId = authId
, paypalAuthorizationRequestToken = requestToken
, completeType = "Complete" }
, clientApplication = "MyClient Application"
, clientApplicationVersion = "2.0"
, clientApplicationUser = userName
, clientEnvironment = WebConfigurationManager.AppSettings["Tier"]
, merchantReferenceCode = orders
, customerID = OrderConstants.CustomerNumber
, merchantDefinedData = new MerchantDefinedData { field1 = "Customer #: " + OrderConstants.CustomerNumber, field2 = orders }
, purchaseTotals = new PurchaseTotals { currency = "usd", grandTotalAmount = total, taxAmount = taxtotal }
, item = items.ToArray()
};
ReplyMessage reply = new ReplyMessage();
try
{
reply = SoapClient.RunTransaction(request);
}
catch (Exception ex)
{
reply.decision = "SYSTEM ERROR";
reply.additionalData = string.Format("Error processing request. Exception message: {0}", ex.Message);
}
Have you tried setting up your request like this? Pay no attention to the values I used, but I am looking at the example in the docs (Example 21 Request for payPalDoCaptureService). You'll need to ctrl+f to find it.
RequestMessage request = new RequestMessage
{
payPalDoCaptureService_run=true
, merchantID = WebConfigurationManager.AppSettings["cybs.merchantID"]
, merchantReferenceCode = HTNsubscription9647
, purchaseTotals = new PurchaseTotals { currency = "usd", grandTotalAmount = total, taxAmount = taxtotal }
, payPalDoCaptureService = new PayPalDoCaptureService
{
run = "true"
, invoiceNumber = orders
, paypalAuthorizationId = authId
, paypalAuthorizationRequestID = authReqId
, paypalAuthorizationRequestToken = requestToken
, completeType = "Complete"
}
}
I did end up solving this problem. My question involving whether I needed to employ CyberSource from end-to-end was the correct path. Eventually I figured out - after talking for days with CyberSource support - that I needed to use their "Set Service" in a WebApi method to generate the PayPal "token" and give that to the PayPal button via ajax within the javascript that generates the button. I also had to dig deep into their and PayPal's documentation and to figure out how to make that work because it wasn't super clear initially. At any rate, once I did the Set service, I gathered the information in the response from CyberSource, along with the PayPal token, and send that along to a Get Details service call (also CyberSource). Finally that information is given to a combined Do Sale and Do Capture service call and the funds are captured. The button only allowed a user to log into their PayPal account and verify they wanted to continue with the transaction.
CyberSource's documentation is a little lacking in clarity with regards to this, and they link to a deprecated set of PayPal documentation, which doesn't make anything easier.
As the error says you have git invalid data, please check the reply fields invalidField_0 through invalidField_N for
the invalid fields.
I hope these Requesting the Authorization Service samples will help

Stripe.net - Try to charge on behalf

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.

PayPal Adaptive Payments - retrieving sender's billing address via IPN / API?

I'm using the Adaptive Payments API to redirect the user from my web-site to a PayPal page to finish the payment. I've hooked this up with a 3rd party Invoicing service which listens via IPN.
For some reason, the Billing Address does not appear in the IPN data, and so does not appear on the invoice. Is there any flag I need to pass to the Adaptive Payments API to tell it to pass along the Billing Address?
Here's how I'm currently using the API:
var receiverList = new ReceiverList
{
receiver = new List<Receiver>
{
new Receiver(purchase.TotalPrice)
{
email = _configurationReader.GetStringValue("PayPalEmail")
}
},
};
var envelope = new RequestEnvelope("en_US");
var payRequest = new PayRequest(envelope, ActionType.Pay.GetApiString(), cancelUrl, CurrencyCode.USDollar.GetApiString(), receiverList, returnUrl);
var service = new AdaptivePaymentsService();
var response = service.Pay(payRequest);
purchase.PayPalPaymentId = response.payKey;
return CreatePayPalRedirectUrl(response);
PayPal does not send billing addresses to sellers. That's one of the advantages for buyers using the system...they don't have to share any billing info with all the different sellers they buy from.
The only address you would ever get from PayPal (in an API response, IPN notification, etc.) would be a shipping address, and that would only be provided if included in the original transaction.

Categories