Commerce SDK - React Native
Our Commerce SDK works seamlessly in React Native. You may have noticed it inside Valora, the primary wallet for the Celo Network (seen below).
Doing the same for your mobile app is pretty straightforward and we've outlined the steps below. π
Step 1: Obtain your API Keyβ
To get set up with API Keys please email us at support@bidali.com with your request. We will provide you with API keys for our staging and production environments.
The Commerce URLs to use in the webview will be:
Environment | URL | |
---|---|---|
Staging / Testnet | https://commerce.staging.bidali.com/dapp?key=YOUR_API_KEY | https://docs.bidali.com/commerce/currencies?environment=testnet |
Production / Mainnet | https://commerce.bidali.com/dapp?key=YOUR_API_KEY | https://docs.bidali.com/commerce/currencies |
When specifying the accepted payment options and providing balances, Bidali uses a unique internal identifier named protocol
. You can view the list of supported protocols below.
Environment | URL |
---|---|
Staging / Testnet | https://docs.bidali.com/commerce/currencies?environment=testnet |
Production / Mainnet | https://docs.bidali.com/commerce/currencies |
Step 2: Load the Commerce URL in a WebViewβ
<WebView
ref={webViewRef}
source={{ uri: COMMERCE_URL }}
onMessage={onMessage}
injectedJavaScriptBeforeContentLoaded={initialJavascript} />);
See full sample code below
Valora's integration is slightly different but you can view their open source code to see how it works. It is a good example of how to best to setup and interact with the webview and Bidali from React Native.
Step 3: Add a bidaliProvider
onto the window and specify the paymentCurrencies
that you will be acceptingβ
window.bidaliProvider = {
key: 'YOUR API KEY', // This is provided by Bidali
name: 'YOUR WALLET NAME', // This will be provided by Bidali with your apiKey
paymentCurrencies: ['stellar', 'stellarusdc'],
email: 'test@test.com',
phoneNumber: '15554321234',
balances: {
'stellar': '5',
'usdcstellar': '20'
},
onPaymentRequest: (paymentRequest) => {
var payload = { method: 'onPaymentRequest', data: paymentRequest };
window.ReactNativeWebView.postMessage(JSON.stringify(payload));
},
openUrl: function (url) {
var payload = { method: 'openUrl', data: { url } };
window.ReactNativeWebView.postMessage(JSON.stringify(payload));
}
};
window.bidaliProvider
must have the following properties:
Property | Type | Description |
---|---|---|
name | String | The name of the wallet integrating (Provided by Bidali) |
key | String | This is your Bidali Commerce Publishable Key. The unique and public key that identifies your organization. It looks like pk_viqah4squsnuw6p0e1ue .(Provided by Bidali) |
paymentCurrencies | String[] | Allows you to only show certain cryptocurrencies as payment options. It takes an Array of String s that are the coin protocols (Bidali's unique identifier) |
limitToCountries | String[] | Country codes of the countries to limit the products to, ex: [ "US", "CA" ] |
email | String | Allows us to pre-populate their email, user has to confirm during checkout flow |
phoneNumber | String | Allows us to pre-populate the phone number for mobile topups, the user has the chance to change this |
balances | object | The balances for the allowed currencies, ex. { stellar: '25.2', usdcstellar: '2000' } |
onPaymentRequest | Function | Provide a handler for this function that displays a payment confirmation modal for the user |
openUrl | Function | Opens a URL to our support docs, etc. Ideally should open in an external browser or a new in-app modal browser |
Step 4: Handle onPaymentRequest
β
Add a handler for onPaymentRequest
that shows the user a payment confirmation modal using the information in the paymentRequest
. If an extraId
field is present on the paymentRequest
it must be sent with the transaction (ex. as a memo)
This is what a paymentRequest
looks likeβ
{
amount: '0.0187',
symbol: 'ETH', // This is the payment currency your user chose
protocol: 'ethereum', // This is Bidali's unique identifier for a currency
address: '0x220b48eda85a0a067c769f0442dd2f4e03ba625a',
chargeId: 'vIQ807gvR',
extraId: 'vIQ807gvR'
extraIdName: 'Memo text'
description: '$50 Amazon US',
lineItems: [
{
name: 'Amazon US',
quantity: 1,
amount: '$50 USD',
image: 'https://assets.bidali.com/commerce/brands/amazon-com-us.png'
}
]
}
A paymentRequest
has the following properties:
Property | Type | Description |
---|---|---|
address | String | The address to send to |
amount | String | The amount to send, as a user readable string (ex. "25") |
symbol | String | The symbol of the currency the user has chosen to pay with, ex: BTC , not unique to a currency (for instance USDC ERC20 and USDC on Stellar both have the symbol USDC ) |
protocol | String | The protocol of the currency the user has chosen to pay with, this is unique for each currency. ex: usdcstellar |
description | String | A comma-delimited list of products being purchased. Can be used on your payment approval screen so the user sees what they are approving payment for. Ex: $50 USD Amazon US, 2x $25 USD Apple US |
lineItems | Array | A list of products being purchased. Just like with description , you can use this on your payment approval screen. A line item looks like { name: 'Apple US', quantity: 1, amount: '$5 USD', image: 'https://assets.bidali.com/commerce/brands/apple.png' } |
chargeId | String | The users order reference, helpful to reference the order in the future or if there are any issues. Ex: vIQ807gvR |
extraId | String | The extraId that must be passed for the payment to be credited appropriately to the order. Currently only applicable to currencies on Stellar, Algorand, and Solana networks |
extraIdName | String | The name of the extraId that must be sent with the transaction. Currently only applicable to currencies on Stellar, Algorand, and Solana networks |
Step 5: Notify Bidali of payment statusβ
When the user sends the transaction call window.bidaliProvider.paymentSent()
inside the WebView. If they cancel payment / dismiss the modal then call window.bidaliProvider.paymentCancelled()
Step 6: Update balancesβ
After a user sends a transaction or their balances change, update the balances
object on window.bidaliProvider
by stringifying it and injecting the javascript
useEffect(() => {
webViewRef.current?.injectJavaScript(`
window.bidaliProvider.balances = ${JSON.stringify(balances)}
`)
}, [balances]);
Example codeβ
Hereβs some sample code for React Native that loads the Commerce URL in a react-native-webview, injects javascript that sets window.bidaliProvider
and handles onPaymentRequest
.
Note: Ensure the JS you inject injectedJavaScriptBeforeContentLoaded
ends with true;
as shown below or sometimes there can be silent failures.
import React, { useRef, useState, useEffect } from 'react';
import styled from 'styled-components/native';
import { WebView } from 'react-native-webview';
const Container = styled.SafeAreaView`
flex: 1;
`;
const BidaliScreen = ({ user }) => {
const [ balances, setBalances ] = useState({ stellar: '5.2', usdcstellar: '2000' });
const webViewRef = useRef(null);
const user = {
email: 'test@test.com',
phoneNumber: '15554321234'
};
const onMessage = event => {
const { method, data } = JSON.parse(event.nativeEvent.data);
switch (method) {
case 'onPaymentRequest': {
const {
amount,
address,
symbol,
protocol,
description,
chargeId,
extraId: memo
} = data;
// These 2 callbacks need to be called to notify Bidali of the status of the payment request
// so it can update the WebView accordingly.
const onPaymentSent = () => {
webViewRef.current?.injectJavaScript(`window.bidaliProvider.paymentSent();`);
};
const onPaymentCancelled = () => {
webViewRef.current?.injectJavaScript(`window.bidaliProvider.paymentCancelled();`)
};
if(protocol === 'stellar') {
// Show a native transaction confirmation modal to the user
const result = await sendXLM({ amount, address, symbol, protocol, memo });
if(result.status === 'sent') {
onPaymentSent();
} else if(result.status === 'cancelled') {
onPaymentCancelled();
}
}
break;
}
case 'openUrl': {
const { url } = data;
// Open the URL in an in-app browser or external browser
}
}
};
const initialJavascript = `
window.bidaliProvider = {
name: 'WALLET NAME', // This will be provided by Bidali with your apiKey
paymentCurrencies: ['stellar', 'usdcstellar'],
email: ${user.email ? `'${user.email}'` : null},
phoneNumber: ${user.phoneNumber ? `'${user.phoneNumber}'` : null},
balances: ${JSON.stringify(balances)},
onPaymentRequest: (paymentRequest) => {
var payload = { method: 'onPaymentRequest', data: paymentRequest };
window.ReactNativeWebView.postMessage(JSON.stringify(payload));
},
openUrl: function (url) {
var payload = { method: 'openUrl', data: { url } };
window.ReactNativeWebView.postMessage(JSON.stringify(payload));
}
};
true; // note: this is required, or you'll sometimes get silent failures
`;
useEffect(() => {
webViewRef.current?.injectJavaScript(`
window.bidaliProvider.balances = ${JSON.stringify(balances)}
`)
}, [balances]);
return (<Container>
<WebView
ref={webViewRef}
source={{ uri: 'https://commerce.staging.bidali.com/dapp?key=YOUR_API_KEY' }}
onMessage={onMessage}
injectedJavaScriptBeforeContentLoaded={initialJavascript} />
</Container>);
};
export default BidaliScreen;
Please send any feedback to support@bidali.com