Integrations
Our modules integrations into your payment phase follow the same pattern :
- create the order
- make your user pay (ex: through in-page widget or redirection)
- check for payment confirmation (widget callback, webhooks)
Getting your credentials
First things first, you will need to safely store your credentials.
A couple of keys will be given to you :
- the secret key : is used on back-end to call our API
- the public key : is used on front-end to load our widget
- the webhook key : a secret key used for webhook signature verification
Those keys are unique to each platform. If you are integrating multiple modules, since a one module is configured by platform, you will have to use the correct ones by module.
Once you are logged into your dashboard, you can find your keys (starting by sk_.. and pk_..) on your platform view > configure button (in the header) > Credentials (bottom of the page).
Attention
Never expose your secrets keys (sk_...). It is meant to be used server side.
One thing to note is that you have on set of credentials by platforms. So if you are integrating multiple sharegroop modules, you should plan to store and retrieve them all.
Create an order
With your secret key, you can now create an order.
The most secure way to create an order, is to simply call POST /orders (cf. API ref.) from your backend when you need to, usually just before arriving on your payment page.
API reference tips : look for the corresponding UX "POST /orders (ux)" api call
Common parameters :
amount | total order amount in currency cents |
trackId | Your internal resource id, so you can match it on your side |
buyer's information |
As we should avoid the user to double input his information. The more you provide, the less we ask the user. If you do not provide the email for example, our UI will ask for it. |
items |
The basket items list :
Required for ux picking , so that buyers can choose the items they want to pay, otherwise the basket is used for display.
|
locale | translations language (for UI and emails) |
notifyUrl | Your https endpoint for webhook notifications (you could use tools like "ngrok" or "webhook.site" on your local dev environment) |
metadata | Your custom data specified in this key value string map. It allows you to pass on data you want to retrieve through ShareGroop. |
see more in the API Reference |
To keep things easy, only amount
is required (except for scoring requirements, see below), other parameters are either optional or default to your platform configuration.
You should refer to your preferred module for specific parameters.
You will then get an order.id
in the response : save it for later operations.
TIP
Implementation note đĄ :
- When ShareGroop is proposed alongside other payment options, a better option is to add an simple API call to your backend. You can then make the call to our api to create the order and get back the order id only when your user chooses our payment facilities. By avoiding creating orders systematically, you will not have unnecessary ShareGroop orders in your data.
- Some parameters will vary depending on your modules. Unless you need to specifically control your module's behavior, we recommend that you only specify
required
module parameters. The order will be created using your platform default configurations : this simplifies your integration, and allow tweaking it without having to change your code.
Front-end only integration
The captain component can be loaded into your page without the need to create an order first via API. This plug & play integration uses the parameters specified to load the Captain component. It only creates the order and transaction after the first payment attempt.
<!--somewhere on your payment page page-->
<div id="sharegroop-captain"></div>
// before the </body> end tag
<script src="https://widget.sandbox.sharegroop.com/widget.js"></script>
<script>
// init and mount the captain component
ShareGroop.initCaptain({
"selector": "#sharegroop-captain", // target element selector
"publicKey": "pk_...", // your public key
"locale": "en",
"order": {
"email": "captain@email.com",
"firstName": "John",
"lastName": "Doe",
"trackId": "TRACK-1",
"amount": 10000, // mandatory, cents
"currency": "EUR",
"items": [ // your order items
{
"trackId": "TRACK-A",
"name": "Product A",
"description": "Description A",
"amount": 10000, // cents
"metadata": {
"key": "value"
}
}
],
"metadata": {
"key1": "value1",
"key2": "value2"
}
},
"events": {
"onValidated": function (data) {
console.log("I've been validated", data);
}
}
}).mount();
// or you can mount it later
// ShareGroop.mount("#your-element-selector");
</script>
When the captain payment is successful, the event onValidated
is fired. Then, it will execute your callback provided with relevant datas as parameter, such as the just created sharegroop order
id. Save it for potential later operations.
// onValidated data object :
{
order: "ord_...", // the sharegroop order id
auth: "auth_...", // the authorization id
status: "authorized" // or "captured" // the authorization status
}
Recommandation
After the payment, you must perform a confirmation check from your backend since payment is coming from the front-end. Either synchronously from onValidated callback redirection, or by waiting for our instant confirmation webhook
TIP
đ Go to Captain reference to get the detailed captain configuration
Scoring
When your platform is set up with financing option, we perform scoring based on the data so that we can refine our risk assessments. The more precise and complete the data is, the greater financing acceptance could be.
Below data should be provided during order creation :
{
// mandatory (will be requested to buyer if not provided) :
"email": "captain@example.com",
"firstName": "John",
"lastName": "Carter",
"billingAddress" : {
"organization": "Company SAS", // default to order.organization
"firstName": "John", // default to order.firstName
"lastName": "Carter", // default to order.lastName
"street1": "1 Rue de Richelieu",
"street2": "Apt. 123",
"city": "Paris",
"zip": "75001",
"country": "FR",
"state": "Ile-de-France"
},
"phone": "+33612345678", // E.164 format (regex: ^\+[1-9]\d{1,13}$)
"civility": "mr", // enum: "mr" (man) or "ms" (women)
"birthDate": 315529200000, // timestamp (in millisecond)
"birthZipCode": "75001", // Must contain 2, 3 or 5 characters ("99" if born outside from the target market, "971" for Gouadeloup, "972" for Martinique)
"items": [ // Mandatory, add an item for each product sold
{
"name": "Product A",
"amount": 2200, // should be : total of items (so unit price * quantity)
"category": "Category A", // your product main category name
"shippingMethod": "UPS",
"quantity": 1 // total of units for this item
},
{
"name": "Product B",
"amount": 10000,
"category": "Category B",
"shippingMethod": "DHL",
"quantity": 2
},
{ // Travel specifics
"name": "Product Travel", // ex: a flight ticket
"amount": 100000,
"category": "Category B",
"quantity": 1,
"travel": {
"departureDate": 1641769200000, // timestamp epoch ms
"departureCompany": "AF", // IATA 2-letter code
"departureAirport": "CDG", // IATA 3-letter code
"destinationAirport": "JFK", // IATA 3-letter code
"destinationCountryCode": "US", // max 2 characters (ISO Alpha-2)
"returnDate": 1642633200000, // timestamp epoch ms
"ticketType": "twoWay", // ["unknown", "oneWay", "twoWay", "multiple"]
"ticketClass": "economy", // ["unknown", "economy", "premiumEconomy", "business", "first", "others"]
"ticketIsUpdatable": true, // can the ticket be modified/canceled
"travelersCount": 2, // number of travelers related to this item
"travelerIsBuyer": true, // does the bank card holder participate in travel ("true", "false")
"passportsExpirationDates": [1750543200000, 1783807200000, ...], // travelers passport expiration date (timestamp epoch ms)
"luggageSupplement": "Extra 20kg", // max 30 characters
"insurance": "Travel Plus Insurance" // complementary insurance type chosen by travelers (max 30 chars)
},
{ // Rental specifics
"name": "Product Rental",
"amount": 10000,
"category": "Category B",
"quantity": 2,
"rental": {
"company": "Hilton New York", // Hotel name, hotel chain name, etc. (max 50 chars)
"destination": "New York City", // Destination city name (max 50 chars)
"roomsNumber": 2, // number of rooms
"nightsNumber": 4 // number of nights
}
}
],
// optional :
"birthCity" : "Paris",
"birthCountry" : "FR",
"birthState": "Ile-de-France",
"isPro": true,
"organization": "Company SAS",
"siren": "732829320",
"shippingAddress" : { // optional (default to billingAddress if can not be provided)
"organization": "Company SAS",
"firstName": "John",
"lastName": "Carter",
"street1": "1 Rue de Richelieu",
"street2": "Apt. 123",
"city": "Paris",
"zip": "75001",
"country": "FR",
"state": "Ile-de-France"
},
"session": { // automatically detected if not provided
"ip": "127.0.0.1",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:78.0) Gecko/20100101 Firefox/78.0",
"channel": "web" // enum: web, mobile, pos, call
}
}
Some of those data are also used in context of the PSD2 requirements that can help avoiding strong authentication.
In addition, other data correlated to your sector of activity may be required too (e.g : travel, rental). Those would be covered during the qualification phase with your assigned Success Manager.
We recommend that you provide the data you have already collected in your checkout flow, so that we do not ask them again to the user.
In-page widget
For a smoother user experience, it is common practice to avoid redirecting the user to an external party. To achieve this, you can use our embedded frames loaded in your own pages via our javascript widget.
Captain component
Having created an order, you can now load the captain component on your payment page using the order id.
Note : In a split payment, we call Captain the first buyer initializing a group purchase.
<!--somewhere on your payment page page-->
<div id="sharegroop-captain"></div>
// before the </body> end tag
<script src="https://widget.sandbox.sharegroop.com/widget.js"></script>
<script>
// init and mount the captain component
ShareGroop.initCaptain({
"selector": "#sharegroop-captain", // target element selector
"publicKey": "pk_...", // your public key
"orderId": "ord_...", // the order id
"events": {
"onReady": function () {
console.log("I'm ready");
},
"onValidated": function (data) {
console.log("I've been validated, let's go to your next step !");
}
}
}).mount();
// or you can mount it later
// ShareGroop.mount(".optional-el-selector");
</script>
TIP
Our components are fully responsive and handle the frame height resizing so you should not force the parent container element to a fixed height.
âšī¸ Our components kick off a secure handshake and loads our content that confirms the handshake.
The onValidated
event is triggered when the captain payment is confirmed. This will execute the associated javascript callback so you can perform your next action such as submit a form or go to your confirmation page.
TIP
đ Go to Captain reference to get the detailed configuration
Link component
Whenever you need to display the ShareGroop link, you can load the link component using the order id, usually on your payment confirmation page.
It loads our UI showing the due date, and allows the user to easily copy the link or directly share it on the most common social group discussion channels.
<!--somewhere on your confirmation page-->
<div id="sharegroop-link"></div>
// before the </body> end tag
<script src="https://widget.sandbox.sharegroop.com/widget.js"></script>
<script>
// init and mount the captain component
ShareGroop.initLink({
"selector": "#sharegroop-link", // target element selector
"publicKey": "pk_...", // your public key
"orderId": "ord_...", // the order id
"events": {
"onReady": function () {
console.log("I'm ready");
}
}
});
</script>
âšī¸ note that the sharegroop.com script loaded is the same as the captain one. Your user already has it cached.
TIP
đ Go to Link reference to get the detailed configuration
Hosted page redirection
If for some reason you do not desire to benefit from an in-page user experience, you can redirect your user to our hosted payment page instead.
The redirectUrl
is the url you need to redirect your user to. It is provided in the POST Order response body.
During your order creation, you only need to specify a few urls (https mandatory), that will be https GET requested :
successUrl
: Once the user payment is successful and the order is confirmed, the user will be redirected to yourorder.successUrl
if specifiedcancelUrl
: when the user clicks on "cancel and return to the shop" link, usually to choose another payment method
After the payment, double check for confirmation
From your backend, after captain payment has been validated,
you should double check the order for :
status
=confirmed
orcompleted
amount
= your desired order total amount (if front-end integration)- (and of course that your own url & order handles multiple load properly)
Synchronously : by calling GET /orders/:id
Asynchronously : by receiving our Webhooks
And that's it folks đ !
What's next ?
You can :
- handle our Webhooks for deeper integration.
- manage your order via our API (ex: Refunds)
- check our Reportings for reconciliations matters
Testing
The following will work only on ShareGroop sandbox.
You can use the following test cards during test payments phases :
Brand | Number | cvv | date |
---|---|---|---|
Visa | 4242 4242 4242 4242 | 100 | 01/99 |
Mastercard | 5436 0310 3060 6378 | 257 | 01/99 |
AMEX | 3782 822463 10005 | 1000 | 01/99 |
TIP
đ Gateway-router : If your integration is using your own payment provider, you must directly use test cards provided in its documentation. Above cards will not work.
Customizations
We can customize the UI logo, colors & wording to match your brand identity.
Customization needs are usually covered during the qualification phase with your assigned Success Manager, where we also look at your complete checkout funnel and can make some proposals on how to fit your new module in it for optimized results.
Ask our support@sharegroop.com.
Multi Modules integration
Depending on the Organization structure and on your front-end integration constraints, you may have multiple Platforms & Modules at your disposal.
1 - Multi sharegroop credentials
According to your Organization setup,
- you may have multiple Platforms (resource starting with
pl_...
) - you may have multiple Modules (resource starting with
md_...
listed in your platform's configuration page)
Platforms are defined depending on your UX and routing needs during the implementation phase (it could represent multiple stores, markets, countries, websites).
Modules are defined depending on what experience you want to propose to your users during payment.
You will have a set of credentials by platform you will need to store & use (public key, secret api key, webhook secret key).
We recommend that you use the corresponding sharegroop
platformId
as unique key to retrieve them on your system.
2 - Multi modules UX
Our Payment UX (widget or redirection) can be loaded, either :
- by specifiying 0 module : the default platform configuration takes over.
- by specifiying more than 1 module : the UX shows a list of module to choose. The module UX changes with the user choice.
- by specifiying 1 module : the UX does not show a list of module. It shows the module UX directly.
A default choices of module can be defined on your platform(s), so that it applied for every Order creation.
And you can also define the module choices to propose, and override module configurations following this reference
The choice list can be customized as follows :
- Name
- Description
- Image
- Position priority in the list
If your Platform does not have Modules linked to it (check in Dashboard > Platform > Configuration). It means that your Platforms have been configured directly as a Module. If you are not sure, ask support@sharegroop.com
3 - Multi widget instances
If you opt for the in-page widget integration : to allow multiple instances to load properly, you should retain in a map the widget instance returned when initialized.
// You can load your page with required module values, such as the module public key
var sgWidgets = [
'single': {
'publicKey': 'pk_test_single',
'selector':
'loaded': false,
...
}:
'split': {
'publicKey': 'pk_test_split',
'loaded': false,
...
}:
'multi': {
'publicKey': 'pk_test_multi',
'loaded': false,
...
}:
];
// Once your UI defines the correct "module" to load,
// simply retain the module widget JS instance into the map
// ex: var module = "split";
var selectedModule = sgWidgets[module];
var selectedModule.instance = ShareGroop.initCaptain({
'selector': selectedModule.selector, // the matching module target element selector
'publicKey': selectedModule.publicKey, // the matching module public key
'events': {
'onReady': function () {
selectedModule.loaded = true;
},
...
}
...
}).mount();
// Then you can retrieve the correct instance from your JS map,
// when "module" variable changes depending on your UI upates
sgWidgets[module]['instance'].pay();
4 - Retrieving the correct webhook key for signature verification (or any other parameters your specify from the notification url)
To handle our webhooks events signature verification, you will also need the corresponding platform keys.
- If you saved the
orderId
(and maybeorder.platformId
) during the payment, you could easily retrieve the matchingwebhookSecretKey
from our event body, and then treat the webhook - Or you can also define
order.notifyUrl
before the payment with any query string parameter that would help your webhook processing. Such ashttps://myendpoint.com/what-ever?a-key=a-value
(ex: you can put?platformId=sg-platform-id
). We will POST to your notify url with all parameters.
Notification urls can also be configured at platform level, and will be used by default for all its orders (in
Platform > Configuration > Url notification webhook
)
See webhooks
Integration features
The following sections expose various integration features helping for the integration into your existing flow.
You should read Get started before.
External call to action
If you wish to use our component with your own call to action (your payment button), simply add cta: false
in the component config to hide the payment button inside the widget. Call .pay()
method to trigger ShareGroop's form validation and payment.
You can find a full working demo here illustrating how to use your own call to action with our widget here.
Here is an example :
<!--somewhere on your payment page page-->
<div id="sharegroop-captain"></div>
<!--your page call to action to trigger payment-->
<div id="my-cta"></div>
var sg = ShareGroop.initCaptain({
"selector": "#sharegroop-captain",
"publicKey": "pk_...",
"locale": "en",
"cta": false, // hide sharegroop cta
"orderId": "ord_...",
"events": {
"onInvalid": function () {
// triggered when widget form is not valid yet to trigger payment
console.log("[demo] event invalid");
},
"onValid": function () {
// triggered when widget form is ready to be submitted for payment
console.log("[demo] event valid");
},
"onError": function () {
// triggered on payment error
console.log("[demo] event error");
},
"onValidated": function (data) {
// handle in page payment success behavior
console.log("[demo] event validated", JSON.stringify(data, null, 2));
},
}
}).mount();
// trigger sharegroop payment from you call to action
var cta = document.getElementById("my-cta");
cta.addEventListener("click", function (e) {
e.preventDefault();
sg.pay();
});
To support external call to action behaviors,
couples events are at your disposal :
onValid
: this event is fired when the widget form becomes valid, meaning it is ready to trigger the payment. You can use this callback to interact with your existing page from validation implementation, or directly call the .pay() to trigger the payment.onInvalid
: this event is fired when the widget form is marked as not valid after you called .pay(). Payment will not be triggered until form is valid.
and the
.pay()
method allows you to trigger the same behavior our widget call to action does. It will first trigger the widget's form validation :- If the form is valid, it proceeds to payment, which leads to
onValidated
oronError
events. - If not, payment is not triggered,
onInvalid
event is fired and inputs in cause are marked to the end-user.
- If the form is valid, it proceeds to payment, which leads to
TIP
đ Depending on your call to action form validation strategy, you usually can let your CTA clickable and perform validation on the fly, but can also disable your CTA until the form is valid. Both can be supported using the above mechanisms.
Check-out a simple demo here here.
Two-phase commit
According to your internal processes, you may have the need to confirm or not an order before finalizing it.
This feature is particularly useful :
- if you have your internal services telling you that you can not honor the order anymore
- if you can only honor part of the Order (e.g: a lack of stock)
Two-phase commit is an integration feature which allows you to approve or cancel an order before ShareGroop can proceed to the order completion (e.g : capturing authorized payments, sending webhooks order.completed).
This feature can be activated by default on your platform, or by specifying directly order.tpc: true
during order creation.
Once an order has been initiated with two-phase commit. You can commit to the order any time until its completion using POST /orders/:id/commit.
With two-phase commit, before we start your order completion process :
- if the order is supposed to be canceled (e.g: mode
standard
, due date reached but not fully paid) :
it will be cancelled as expected - no action is expected on your side. - if the order is supposed to be completed (e.g: mode
direct
and due date reached), and you did not already commit :
we will put it in stand-by instead of completing it, and wait for your commitment (order.status: pendingCommit
).
Then, you will receive a webhook notificationorder.pendingCommit
so you can commit (or eventually cancel) the order.
However, if you did commit before this point, the pendingCommit status is being skipped and the order enters the completion process as non two-phase commit integration.
WARNING
âŗ If you do not commit before 6 days from its creation, your order will be canceled automatically even though it was supposed to be completed
Two-phase commit flow :
- You create an Order with
tpc: true
- Your Customer complete the UX, your order is
confirmed
- When you can commit, you call POST /orders/commit, it will then be able to proceed to your Order next step (trigger captures, order.completed)
- You can also commit a lower order amount than the initial one you wanted your user to pay : we will do the recalculations to capture accordingly.
- Approaching 6 days, if you still did not commit, we put the order in
pendingCommit
status and send a last webhook "order.pendingCommit" so you know you should commit before Order cancels for non commitment.
Two-phase commit with Installment or Pay later with financing :
If you commit with a lower amount (or cancel) an order for which you have been financed. The amount financed will be retained on the next payouts.
And deadlines amount will be re-calculated depending on the committed amount, as described in Installments Cancellations.