Vendre à un client existant
La documentation suivante décrit la mise en place, via API, d'une vente à un client existant uniquement. La vente à des personnes inconnues du club, par exemple sur un portail non connecté, suit un process spécifique.
INFO
Retrouvez ce scenario dans les collections Bruno disponibles ici : Vendre à un client existant
CAUTION
Il est primmordial de vous être familiarisé avec les termes définis dans le glossaire avant de lire cette documentation.
WARNING
Dans le cas d’une intégration avec un prestataire de paiement, il est important d’effectuer cette action uniquement lorsque celui-ci a validé le paiement (et non ajouter des intentions de paiement).
Macro process de vente
Le processus de vente à un contact existant s'articule comme suit :
- Connaître le contact
- Récupérer le catalogue correspondant au contact
- Vendre un ou plusieurs produits au contact
- Vérifier la validité de la vente
- Valider la vente et enregistrer le paiement
Connaître le contact
Plusieurs informations relatives au contact ciblé par la vente sont à récolter en amont de celle-ci. Ces informations serviront ensuite lors de la récupération du catalogue.
Récupérer les mots clés du contact
Les tags sont listés sous forme de tableau dans la description d'un objet contact, dans la propriété tags
.
GET `/{clientToken}/contacts/{contactId}`
GET `/demoapi/contacts/1234`
{
"@context":"/clienttoken/contexts/Contact",
"@id":"/clienttoken/contacts/1234",
"@type":"http://schema.org/Person",
"number":"4110012692",
// ...
"tags":[ // <-- liste des mots clés de l'utilisateur
{
"@id":"/clienttoken/contact_tags/416202",
"@type":"ContactTag",
"name":"abonnement", // <-- mot clé #1
"validFrom":"2019-05-07",
"validThrough":"2019-06-07"
},
{
"@id":"/clienttoken/contact_tags/416245",
"@type":"ContactTag",
"name":"vip", // <-- mot clé #2
"validFrom":"2019-05-07",
"validThrough":"2019-06-07"
}
],
// ...
}
Récupérer le montant de dette du client
WARNING
Si un client est en dette, il est fort probable que la vente d'un produit lui soit refusée, surtout s'il s'agît d'un produit d'abonnement
Il est donc impératif que vous vous assuriez avant toute chose que le contact ne soit pas endetté.
Et s'il l'est, de l'inviter à clôturer sa dette avant de pouvoir aller plus loin (cf. documentation dédiée)
GET `/{clientToken}/stats/accounts/contacts/:contactId`
GET `/demoapi/stats/accounts/contacts/1234`
{
// ...
"totalRealDebt": 10000, // <-- la valeur de la dette actuelle du contact
// ...
}
Récupérer le catalogue du contact
Avant de commencer une vente il est nécessaire de lister les produits que le contact va pouvoir acheter. Pour cela, on va interroger l’api en lui fournissant le contexte de la vente.
GET /{clientToken}/products
paramètre | description | exemple |
---|---|---|
context[channel] | Canal de vente, valeurs autorisées club , web , terminal . Le catalogue peut varier selon le canal de vente. | web |
context[club] | Club lieu de la vente. Le catalogue peut varier selon le club de vente. | /clientToken/clubs/123 |
context[contactTag] | Les mots clés du contact. Le catalogue peut varier selon les mots clés (exemple : 'VIP' ou 'étudiants'). | nomdutag |
context[debt] | Il s'agit de la dette du client (en centimes), certains clubs restreignent les offres pour les clients ayant une dette trop élevée. | 600 |
context[date] | Date souhaitée de l'achat. Certains produits ne sont pas disponibles tout au long de l'année (les promotions de la rentrée par exemple). | 2019-04-15 |
type | La catégorie du produit. Il est possible de filtrer par catégorie. Valeurs autorisées subscription , subscription_option , badge , counter , package , countermark ,test_session , regular | subscription voir les correspondances de catégories ci après |
page | Numéro de page. La réponse comportant 30 résultats, celle ci peut être paginée. | 1 |
GET /{clientToken}/products?context[channel]=club&context[club]=/{clientToken}/clubs/123&context[contactTag][]=tag-1&context[contactTag][]=tag-2&context[contactId]=/{clientToken}/contacts/123&context[debt]=0&context[date]=2019-04-02&type=badge&page=1
Catégories de produits
Voici les catégories existantes :
subscription
: les produits "abonnements"subscription_option
: les produits "options d'abonnement"badge
: les produits "badges"counter
: les produits "carnets de séances"package
: les produits de formules packagéescountermark
: les produits "contremarque"test_session
: les produits "séance d'essai"regular
: les produits "boutique"
Vendre un ou plusieurs produits au contact
Pour commencer une vente il faut d'abord créer le panier qui accueillera les articles que l'on souhaite vendre. Lors de cette création seules quelques infos sommaires sont nécessaires :
- Le contact à qui la vente est faite (
contactId
) - Le club dans lequel la vente est faite (
clubId
,clubCode
)
A cela s'ajouteront des informations non obligatoires à la création, mais que vous devrez renseigner avant la validation finale. Ces informations serviront à la facturation :
- Les informations supplémentaires du contact (
contactFamilyName
,contactGivenName
,contactNumber
) - Son adresse (
address
)
Création de la vente
Les informations requises dans la requête :
paramètre | description | exemple |
---|---|---|
contactId | Identifiant du contact ciblé par la vente. Il s'agit d'une IRI et non d'un simple identifiant numérique | /{clientToken}/contacts/12345 |
contactFamilyName | Nom de famille du contact. | Doe |
contactGivenName | Prénom du contact. | John |
contactNumber | Numéro du contact. | 423456 |
clubId | Identifiant du club sous forme d'IRI | /{clientToken}/clubs/1 |
clubCode | Code du club | ABCDE |
address[addressCountry] | Pays | France |
address[addressLocality] | Ville | La Madeleine |
address[postalCode] | Code postal | 59110 |
address[streetAddress] | Adresse | 41 rue du Général de Gaulle |
POST `/{clientToken}/sales`
curl --location --globoff '/demoapi/sales' \
--data '{
"contactId": "/demoapi/contacts/1",
"contactFamilyName": "Doe",
"contactGivenName": "John",
"contactNumber": "1",
"clubId": "/demoapi/clubs/1",
"clubCode": "ABCDE",
"address": {
"addressCountry": "France",
"addressLocality": "La Madeleine",
"postalCode": "59110",
"streetAddress": "41 Rue du Général de Gaulle"
}
}'
{
"@context":"/clientToken/contexts/Sale",
"@id":"/clientToken/sales/373969", // <-- identifiant du panier
"@type":"Sale",
// ...
}
Ajouter un article au panier
Quelques précisions d'importance avant d'ajouter un article au panier.
Les comportements
Comme toute API de vente, nous avons donc un catalogue composé de produits et un panier composé d'articles. Par dessus ces notions classiques se trouvent les comportements (behaviors
). Ce sont eux qui sont responsables du métier du fitness et des incidences liées aux achats des divers produits (ajouter un abonnement, créditer des séances ...).
Parmi ces comportements, certains impliquent des précisions de la part de l'acheteur (par exemple, acheter un abonnement nécessite une date de début) et d'autres ne nécessitent aucune précision (par exemple, acheter une gourde ou une serviette ne souffre d'aucune interrogation).
Référrez vous à la documentation dédiée aux comportements de produit.
Vendre un produit
Pour vendre un produit, il faut donc ajouter celui-ci au panier. Vous aurez donc besoin de l'identifiant du panier précédemment créé. Se reporter à la création du panier.
D'autre part, selon les comportements associés au produit vous devrez fournir les précisions attendues. Ajouter un article au panier passe donc toujours par le même point d'API, seuls les paramètres varient en fonction des comportements.
POST /{clientToken}/sales/{saleId}/articles
paramètre | description | exemple |
---|---|---|
offerId | Identifiant de l'offre du produit que l'on souhaite vendre. Il s'agit d'une IRI et non d'un simple identifiant numérique | /{clientToken}/offers/4321 |
implementation | (optionnel) précisions liées au comportement du produit ajouté. Voir ci après pour les différents formats attendus | |
implementations | (optionnel) précisions liées aux multiples comportements du produit dans le cas de packages. Voir ci après pour les différents formats attendus |
Vérifiez la validité de la vente
Il se peut que certains produits de la vente ne soient pas compatibles avec le contact. Par exemple une offre avec une restriction d'âge contredite par la date de naissance. L'ajout sur la vente n'est pas empêché, puisque vous pourriez vouloir modifier le contact en aval. Néanmoins si vous ne vérifiez pas l'intégrité de la vente avant de la soumettre vous risquez des erreurs.
WARNING: Attention : Régler (via un paiement) une vente incompatible, va encaisser l'argent sur le compte du client - la vente ne sera pas réglée (ventilée) : Ce sera au club de venir refaire la vente et d'y ventiler le paiement.
GET /{client_token}/sales/{id}/check
Cet endpoint renvoie
204
La vente est valide
400
La vente contient des erreurs
404
Identifiant de la vente incorrect / vente introuvable
Valider la vente et enregistrer le paiement
Afin de valider une vente vous pouvez, au choix :
- Ajouter le paiement
- Différer le paiement de la vente
Connaître la caisse et le montant à encaisser
Avant d'enregistrer un paiement, quelques informations à récolter :
- montant à encaisser
- caisse sur laquelle enregistrer le paiement
Pour cela il suffit d'interroger notre panier.
GET /{clientToken}/sales/{saleId}
paramètre | description | exemple |
---|---|---|
saleId | Identifiant du panier | 456 |
Exemple de requête
GET /{clientToken}/sales/1
{
// ...
"checkoutId": "/clientToken/checkouts/1234", // <-- identifiant de la caisse
"totalTI": 1100, // <-- montant à encaisser en centimes
// ...
}
Valider la vente en lui ajoutant un paiement
WARNING
Attention, ces appels permettent de créer des paiments dans l'application, il est donc important de comprendre qu'à chaque appel, un paiment est créé, avec les liaisons comptables derrière.
Pour une vente de 50€, si 2 appels à l'API "ajout d'un paiement" de 50€ sont faits, le client aura un trop perçu de 50€ qui pourra servir à régler d'autres achats, même si le client n'a pas réellement payé 100€. Il est important de bien sécuriser ces appels.
Lors de l'ajout d'un paiement, plusieurs informations sont nécessaires :
- Le contact à l'origine du paiement (
contactId
,contactFamilyName
,contactGivenName
,contactNumber
) - Le club dans lequel le paiement est fait (
clubId
,clubCode
,checkout
) - Le montant du paiement (
amount
) - Le moyen de paiement, parmi :
CBWeb
, pour un paiement CB en lignecash
, pour un paiement en liquidecheque
, pour un paiement en chèquecard
, pour un paiement en CB sur place
POST /{clientToken}/sales/{saleId}/payments
paramètre | description | exemple |
---|---|---|
contactId | Identifiant du contact effectuant le paiement | /{clientToken}/contacts/456 |
contactFamilyName | Nom de famille du contact effectuant le paiement | Doe |
contactGivenName | Prénom du contact effectuant le paiement | John |
contactNumber | Numéro du contact effectuant le paiement | 98765 |
amount | Montant du paiement en centimes | 4995 |
mean | Moyen de paiement | CBWeb |
clubId | Identifiant du club sous forme d'IRI | /{clientToken}/clubs/1 |
clubCode | Code du club | ABCDE |
checkout | Identifiant de caisse du club sous forme d'IRI | /{clientToken}/checkouts/2 |
paymentCards | Détail des paiements par carte uniquement dans le cas d'un mean=card | |
paymentCards[][amount] | Montant du paiement par carte en centimes (uniquement smean=card ) | 4995 |
paymentCards[][network] | Réseau bancaire parmi CBGroup , AmEx , Payline et `External(uniquement si | mean=card ) |
cheques | Détail des paiements par chèques uniquement dans le cas d'un mean=cheque | |
cheques[][amount] | Montant du chèque en centimes (uniquement si mean=cheque ) | 4995 |
cheques[][bank] | Nom de la banque (uniquement si mean=cheque ) | Banque populaire |
cheques[][code] | Numéro du chèque (uniquement si mean=cheque ) | 1234567890 |
cheques[][depositDesiredDate] | Date de dépôt souhaitée (uniquement si mean=cheque ) 2019-01-31 | |
cheques[][owner] | Nom du titulaire du chèque (uniquement si mean=cheque ) | John Doe |
Exemple d'un paiement Web
curl '/{clientToken}/sales/1/payments'
{
"contactId": "/{clientToken}/contacts/1",
"contactFamilyName": "Doe",
"contactGivenName": "John",
"contactNumber": "1",
"amount": 5000,
"mean": "CBWeb",
"clubId": "/{clientToken}/clubs/1",
"clubCode": "AA1",
"checkout": "/{clientToken}/checkouts/1"
}
{
"contactId": "/{clientToken}/contacts/1",
"contactFamilyName": "Doe",
"contactGivenName": "John",
"contactNumber": "1",
"amount": 5000,
"mean": "card",
"clubId": "/{clientToken}/clubs/1",
"clubCode": "AA1",
"checkout": "/{clientToken}/checkouts/1",
"paymentCards": [
{
"amount": 5000,
"network": "CBGroup",
}
]
}
{
"contactId": "/{clientToken}/contacts/1",
"contactFamilyName": "Doe",
"contactGivenName": "John",
"contactNumber": "1",
"amount": 5000,
"mean": "cheque",
"clubId": "/{clientToken}/clubs/1",
"clubCode": "AA1",
"checkout": "/{clientToken}/checkouts/1",
"cheques": [ // A remplir uniquement pour les paiements en chèques
{
"amount": 5000,
"bank": "Crédit du nord",
"code": "1234567890",
"depositDesiredDate": "2019-04-15",
"owner": "John Doe"
}
]
}
Valider la vente en différant le paiement
Il est permis de valider une vente en différant le paiement. Le contact sera redevable des montants de la vente avant la date indiquée.
paramètre | description | exemple |
---|---|---|
date | Date à compter de laquelle le paiement sera considéré "en retard" | 2019-02-28 |
POST `/{clientToken}/sales/{saleId}/postpone_due`
{
"date": "2019-02-28"
}
Valider la vente sans paiement / Produits offerts
Si - et seulement si - vous veniez à créer une vente d'un montant nul (0€, produit gratuit)
Vous pouvez alors terminer la vente en lui appliquant une transition de validation
`POST /{client_token}/sales/{id}/transitions`
{
"transition": "validate"
}
La vente se retrouvera alors enregistrée, et les (potentiels) comportements de produits joués.