I am trying to provide Google payment service using nestjs.
const GoogleReceiptVerify = require('google-play-billing-validator');
...
constructor(
grv = new GoogleReceiptVerify({
email: myClientMail,
key: myClientSecret,
});
)
...
async googleValide(body){
const data = Buffer.from(messageData, 'base64').toString('utf8');
const jsonData = JSON.parse(data);
const receipt = {
packageName: jsonData.packageName,
productId: jsonData.subscriptionNotification.subscriptionId,
purchaseToken: jsonData.subscriptionNotification.purchaseToken,
};
const promiseData = await grv.verifySub(receipt);
const payload = promiseData.payload;
}
Above is my code.
When user pays for a subscription, user get the exact price.
However, when upgrade, user will see the price of subscription product, not the actual payment amount.
I wonder how to check the actual amount paid, not the price of the subscription product.
curreny : 'USD',
actualAmount : '1.5'
The payment receipt received by e-mail will indicate the actual payment price.
Related
I've been using Stripe. When checkout X will create a Payment Intent every time a customer arrives on the checkout. This will result into an "Incomplete" payment.
I integrete STRIPE in my .Net Core application. Here the code below :
public void Pay(CardInfo cardInfo, double amount)
{
StripeConfiguration.ApiKey = _paramList["secretKey"];
State = PaymentState.Pending;
try
{
var options = new SessionCreateOptions
{
Mode = "payment",
SuccessUrl = "https://example.com/success",
CancelUrl = "https://example.com/cancel",
Customer = cardInfo.Owner,
CustomerEmail = cardInfo.ParamList["email"],
PaymentMethodTypes = new List<string>
{
"card",
},
LineItems = new List<SessionLineItemOptions>
{
new SessionLineItemOptions
{
Amount = Convert.ToInt64(amount.ToString().Replace(",","")),
Currency = "eur",
Quantity = 1,
Name = _paramList["account"]
},
},
};
var service = new SessionService();
service.Create(options);
State = PaymentState.Accepted;
}
catch (StripeException error)
{
State = PaymentState.Error;
PaymentReturn = error.Message;
Logger.Write(string.Format("Error STRIPE payment status {0} : ",PaymentReturn));
}
}
In my form payment, I'm not using stripe form but I've created one and I retrieve all information that I need (Card Number, CVV, Expiration, Email and Amount)
When using Stripe Checkout, a PaymentIntent is created under the hood to support the SCA compliant payment. If the session is not completed, the PaymentIntent will remain in state incomplete. This. part is entirely normal.
Integrating with Stripe using a checkout session, but not redirecting to the Stripe hosted Checkout is not a supported integration. If you would like to support handling the card fields yourself, then an integration using Stripe.js and Elements is the best way forward [1]. If you would like to continue using Stripe Checkout as it offers so much functionality out of the box, then once the session is created, you should use redirectToCheckout() from Stripe.js [2] to send the user to Stripe Checkout.
[1] https://stripe.com/docs/payments/accept-a-payment?integration=elements
[2] https://stripe.com/docs/payments/accept-a-payment#redirect-customers
I am implementing apple pay onto our website. I do not have a macOS device and am using windows visual studios / mvcnet. I have done all the merchantID and certification stuff and configured it on the windows machine. I am using Apple Pay JS and on the step where the payment sheet is opened with session.begin(). I use an ajax call to retrieve a merchantSession, which I believe it does successfully because the object consumed by session.completeMerchantValidation(merchantSession) contains an epochnumber, expiration time and the site name. However, immediately after completeMerchantValidation, the oncancel event is fired, and I get a red alert saying "Payment not completed".
I need help with how to proceed from here, I read somewhere online that the domain on where I am testing needs to be a registered merchant domain. For example, when I test the functionality of the button, I need to be on www.mySite.com, where I have mySite.com registered as a domain. Can someone confirm if this is true.. because I am accessing the site from my iOS devices through local IP address. If that is not true, any help proceeding from where I am would be helpful.
function StartPaySession() {
var lineItems = [
{
label: 'Shipping',
amount: '0.00',
}
];
var shippingMethods = [
{
label: 'Free Shipping',
amount: '0.00',
identifier: 'free',
detail: 'Delivers in five business days',
},
{
label: 'Express Shipping',
amount: '5.00',
identifier: 'express',
detail: 'Delivers in two business days',
}
];
var total = {
label: 'Apple Pay Example',
amount: '8.99',
};
var paymentData = {
countryCode: 'US',
currencyCode: 'USD',
shippingMethods: shippingMethods,
lineItems: lineItems,
total: total,
supportedNetworks: ['amex', 'discover', 'masterCard', 'visa'],
merchantCapabilities: ['supports3DS'],
requiredShippingContactFields: ['postalAddress', 'email'],
};
var paySession = new ApplePaySession(2, paymentData);
paySession.onvalidatemerchant = function (event) {
var validationData = { ValidationUrl: event.validationURL };
$.ajax({
url: '/orders/cart/startapplepaysession',
method: "POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(validationData)
}).then(function (merchantSession) {
paySession.completeMerchantValidation(merchantSession);
alert("end = " + window.location.host);
}, function (error) {
alert("merchant validation unsuccessful: " + JSON.stringify(error));
paySession.abort();
});
};
paySession.onpaymentmethodselected = function (event) {
alert("1");
paySession.completePaymentMethodSelection(total, lineItems);
};
paySession.onshippingcontactselected = function (event) {
alert("2");
paySession.completeShippingContactSelection(ApplePaySession.STATUS_SUCCESS, shippingMethods, total, lineItems);
};
paySession.onshippingmethodselected = function (event) {
alert("3");
paySession.completeShippingMethodSelection(ApplePaySession.STATUS_SUCCESS, total, lineItems);
}
paySession.onpaymentauthorized = function (event) {
var token = event.payment.token;
alert("payment authorization | token = " + token);
paySession.completePayment(ApplePaySession.STATUS_SUCCESS);
}
paySession.oncancel = function (event) {
alert("payment cancel error " + event);
}
paySession.begin();
};
You are creating the Apple pay session at the wrong place.You need to create it from server side not on the client side.
These links might help requesting apple pay payment session, complete merchant validation
Steps are discussed here:on validate merchant
This is an old question, but thought I'd post my experience in case it's relevant. I was seeing the same behavior as described by original poster when testing on my local server, but was able to get payment sheet interactions to work.
What worked for me
Log in to AppleID as a Sandbox Test User
Specify "localhost" as the domain when performing merchant validation, e.g.:
{
"merchantIdentifier": "<your merchant ID>",
"displayName": "<your merchant display name>",
"initiative": "web",
"initiativeContext": "localhost"
}
I have deployed a cloud function to my Firebase In order to use Firebase as my backend server to handle Stripe payment.
The link of the sample Firebase cloud functions i have used: https://github.com/firebase/functions-samples/tree/master/stripe
Here is the function I should trigger when I charge the user in my app
exports.createStripeCharge = functions.database.ref('/stripe_customers/{userId}/charges/{id}').onWrite((event) => {
const val = event.data.val();
if (val === null || val.id || val.error) return null;
return admin.database().ref(`/stripe_customers/${event.params.userId}/customer_id`).once('value').then((snapshot) => {
return snapshot.val();
}).then((customer) => {
const amount = val.amount;
const idempotency_key = event.params.id;
let charge = {amount, currency, customer};
if (val.source !== null) charge.source = val.source;
return stripe.charges.create(charge, {idempotency_key});
}).then((response) => {
return event.data.adminRef.set(response);
}).catch((error) => {
return event.data.adminRef.child('error').set(userFacingMessage(error));
}).then(() => {
return reportError(error, {user: event.params.userId});
});
});
I know that the above function will be triggered when my database changed.
My question is, what is the proper way to pass the Stripe payment detail to my Firebase Database? I am not sure what should I pass to my firebase database after reading the stripe document.
Could anyone help me with this question? Thanks!!
P.S. My developing environment: Objective C, IOS application.
The easiest way is to have your app make an HTTP POST request to an HTTP Firebase function. Your app should already be doing this in order to create the Stripe ephemeral key and you can handle payments in a similar way. After the charge is successful you can save the resulting info to your database.
The function:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const express = require('express');
const bodyParser = require('body-parser');
const stripeApp = express();
stripeApp.use(bodyParser.json());
stripeApp.post('/order', (req, res) => {
const { source } = req.body; // This is the token provided by your app
return stripe.charges.create({...}) // the actual payment
});
exports.stripeAPI = functions.https.onRequest(stripeApp);
Have a took at Stripe's demo iOS app - its swift but it should still make sense in Obj-C world. https://github.com/stripe/stripe-connect-rocketrides/tree/master/ios/RocketRides.
Particularly https://github.com/stripe/stripe-connect-rocketrides/blob/master/ios/RocketRides/MainAPIClient.swift#L39
So the process that works for me is -
1) iOS provides card details to Stripe using native SDK
2) Stripe provides a token which you send it to your Firebase backend
you could store it in stripeTokens/userId/yourToken
3) Firebase cloud function then triggers a function and uses this token to create Stripe customer (See saving for later and Customer)
you could store it in stripe_customers/userId/stripeCustomerId like your example
4) Remember to remove yourToken because it's only valid once
5) finally you can use this stripeCustomerId to make payments
Important concept here is to create a customer and store in your backend for future payments.
Hope this helps.
I am following GitHub code on how to implement push notification based on realtime database triggers.
Here is the code and the link:
https://github.com/firebase/functions-samples/blob/master/fcm-notifications/functions/index.js
/**
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
/**
* Triggers when a user gets a new follower and sends a notification.
*
* Followers add a flag to `/followers/{followedUid}/{followerUid}`.
* Users save their device notification tokens to `/users/{followedUid}/notificationTokens/{notificationToken}`.
*/
exports.sendFollowerNotification = functions.database.ref('/followers/{followedUid}/{followerUid}').onWrite(event => {
const followerUid = event.params.followerUid;
const followedUid = event.params.followedUid;
// If un-follow we exit the function.
if (!event.data.val()) {
return console.log('User ', followerUid, 'un-followed user', followedUid);
}
console.log('We have a new follower UID:', followerUid, 'for user:', followerUid);
// Get the list of device notification tokens.
const getDeviceTokensPromise = admin.database().ref(`/users/${followedUid}/notificationTokens`).once('value');
// Get the follower profile.
const getFollowerProfilePromise = admin.auth().getUser(followerUid);
return Promise.all([getDeviceTokensPromise, getFollowerProfilePromise]).then(results => {
const tokensSnapshot = results[0];
const follower = results[1];
// Check if there are any device tokens.
if (!tokensSnapshot.hasChildren()) {
return console.log('There are no notification tokens to send to.');
}
console.log('There are', tokensSnapshot.numChildren(), 'tokens to send notifications to.');
console.log('Fetched follower profile', follower);
// Notification details.
const payload = {
notification: {
title: 'You have a new follower!',
body: `${follower.displayName} is now following you.`,
icon: follower.photoURL
}
};
// Listing all tokens.
const tokens = Object.keys(tokensSnapshot.val());
// Send notifications to all tokens.
return admin.messaging().sendToDevice(tokens, payload).then(response => {
// For each message check if there was an error.
const tokensToRemove = [];
response.results.forEach((result, index) => {
const error = result.error;
if (error) {
console.error('Failure sending notification to', tokens[index], error);
// Cleanup the tokens who are not registered anymore.
if (error.code === 'messaging/invalid-registration-token' ||
error.code === 'messaging/registration-token-not-registered') {
tokensToRemove.push(tokensSnapshot.ref.child(tokens[index]).remove());
}
}
});
return Promise.all(tokensToRemove);
});
});
});
My silly question, new to Functions and Node, is in this code notifications are sent to all users who tokens are saved, is that correct? and if it is how can I let's say send just to one particular person instead all?
I was thinking of saving token of each user in different nodes (children) so I can pick the one I want to send notification to. Does it work?
Thanks All
This code will send notification to just one user (follower in this example). This user can have multiple tokens, representing multiple devices, and hence the variable name: tokensSnapshot.
What you intend to do is very doable with Cloud Functions. You just have to be careful with paths of your nodes where you save users, or tokens, for instance. Also as Frank van Puffelen suggested, having some acquaintance with Admin SDK (Realtime Database and FCM) will really help you out.
The Stripe is configured with mvc application. but need to send email receipt to customer after successful payment done. If not wrong this can do after webhook event gathered. but couldn't find exact code or api for email payment receipt in c#. any guidelines please.
Edited:
Sorry, I thought someone knew about stripe...
my code is
var myCustomer = new StripeCustomerCreateOptions();
// set these properties if it makes you happy
myCustomer.Email = "email#me.com";
myCustomer.Description = "test: email#me.com";
myCustomer.CardNumber = "4242424242424242";
myCustomer.CardExpirationYear = "2016";
myCustomer.CardExpirationMonth = "10";
myCustomer.CardName = "Red Swan";
myCustomer.CardCvc = "223";
myCustomer.PlanId = "testPremium";
myCustomer.Quantity = 1;
var customerService = new StripeCustomerService();
StripeCustomer stripeCustomer = customerService.Create(myCustomer);
var chargeService = new StripeChargeService();
var stripeCharge = chargeService.Create(myCharge);
This code creates the customer on Stripe as well as performs the payment aganist the plan id that provided... but for sending the mail (generated payment receipt by stripe) to this customer, I need guidelines for code.
I tried for code :
var myCharge = new StripeChargeCreateOptions
{
CustomerId = stripeCustomer.Id,
Currency = "gbp",
Amount=1000,
ReceiptEmail="customer#email.com"
};
var chargeService = new StripeChargeService();
var stripeCharge = chargeService.Create(myCharge);
but not working.