Search for existing answers to your product and support questions.
Familiarize yourself with our support site and learn best practices in working with our team.
Manage Service Requests, View and update service requests submitted by you and others in your organization.
Submit a new issue to our technical support team.
Oracle B2C Service insights from our Technical Support team subject matter experts
Browse resources to assist you in launching your implementation and ensure a successful go-live.
Access your OCI account.
Find product documentation for supported versions of B2C and documentation libraries for related service solutions.
You will have the tools to improve your customers' experience when you learn about all the things our products can do.
Find links for API documentation, Custom Processes, Customer Portal, and Agent Browser UI Extensibility Framework.
Explore how accelerators are designed to demonstrate how an integration scenario could be built using the public integration and extension capabilities of the Oracle B2C Service.
Prepare for a successful transition by reviewing upcoming release changes and enhancements.
Explore webinars, events, and feature kits to learn about B2C Service features, functionality, and best practices from the technical experts.
Oracle MyLearn offers a portfolio of free and paid subscription-based learning resources to help you gain valuable skills, accelerate cloud adoption, increase productivity, and transform your business.
Empower your team with the skills to implement, configure, manage, and use your applications with Customer Experience Cloud Training.
Our goal is to facilitate a friendly, supportive environment where members can easily collaborate with each other on solutions and best practices.
Ask and answer questions specific to B2C.
This is an exciting resource intended to help with your Oracle Service Cloud Analytics.
Share product improvement ideas and enhancement requests with Oracle Development, while collaborating with other Oracle customers and partners.
Update your phone number, email notification preferences, and severity 1 and severity 2 contact preferences.
View the contact managers within your organization.
Find contact information of the Technical Account Manager (TAM) and Client Success Manager (CSM) for your organization.
Learn how to leverage the OCI API Gateway and OCI Functions to build a better custom API solution for B2C Service.
Oracle B2C Service extensibility is improving by leveraging capabilities of Oracle Cloud Infrastructure (OCI). The suite of tools that OCI provides allows you to build new customizations in much more flexible ways than previously possible with Oracle B2C Service extensibility. In this guide, we will explore using the OCI API Gateway and OCI Functions as a replacement for providing custom API endpoints using custom scripts or Customer Portal. Oracle B2C Service customers need custom API endpoints to extend Oracle B2C Service capabilities in circumstances where an external service needs to call Oracle B2C Service but cannot use the REST APIs. Typically, these are external webhooks that need to call Oracle B2C Service such as those provided by SMS and telephony vendors.
Historically, customers have used php scripts to provide custom API endpoints in Oracle B2C Service.
These scripts, while convenient to implement on the Oracle B2C Service platform, require the implementer be aware of the security and scaling implications that are introduced with these types of scripts. It has never been a best practice to implement a customization like this, however, alternatives were also difficult to implement. Until now!
The OCI API Gateway service provides solutions to all of the issues that a custom API implemented in custom scripts introduce, namely authentication & authorization, rate limiting, scalability, and monitoring.
For this post, we will use an example organization that needs to implement an API that can receive a webhook from an SMS service for the creation of service incidents via SMS. To keep the example simple, any inbound SMS will create a new incident, but the business logic could be updated as needed to account for incident updates or other Oracle B2C Service data operations.
The solution is comprised of the following components from OCI:
Be sure to review the pricing documentation for OCI to plan the cost for your OCI usage. You can use the cost estimator to estimate your usage costs.
The following diagram demonstrates the end-to-end flow that this example process will demonstrate:
The following diagram demonstrates where the different components in this solution reside and how they communicate with each other.
The implementation for this effort will be delivered entirely using tools in Oracle Cloud Infrastructure; customizing Oracle B2C Service is not required for this type of solution! The only details needed from Oracle B2C Service will be a service account for integration with the Oracle B2C Service REST APIs.
The implementation will be completed in the following steps:
Be sure that you have the following items available to you before you begin:
In order to deliver a generic example in this guide, the following payload will be the assumed payload provided by the SMS provider. You will need to update the expected payload in your implementation based on the information provided by your SMS vendor.
{ "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "api_version": "2010-04-01", "body": "McAvoy or Stewart? These timelines can get so confusing.", "date_created": "Thu, 30 Jul 2015 20:12:31 +0000", "date_sent": "Thu, 30 Jul 2015 20:12:33 +0000", "date_updated": "Thu, 30 Jul 2015 20:12:33 +0000", "direction": "outbound-api", "error_code": null, "error_message": null, "from": "+15017122661", "messaging_service_sid": "MGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "num_media": "0", "num_segments": "1", "price": null, "price_unit": null, "sid": "SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "status": "sent", "subresource_uris": { "media": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages/SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Media.json" }, "to": "+15558675310", "uri": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages/SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.json" }
This guide comes with a python file that provides the business logic that will consume the webhook payload above and create a Oracle B2C Service incident. It can act as the foundation of a similar implementation based on your own business requirements.
Note: Prerequisites to this section are reviewing the F(n) project documentation for function development and local testing and OCI Functions for cloud deployment. This section will not go into the implementation process of a function since the product documentation supplies that information already.
One of the benefits of using OCI Functions is that you can manage environment variables for your functions so that you do not need to hard-code variables like integration details. Also, there is the added benefit of storing secret data in the secure OCI vault service so that environment variables that need to be secured, such as usernames and passwords, are completely isolated from the function script.
The example below demonstrates getting the required environment variables for integration with a Oracle B2C Service site. The variables are stored at the function’s application so that they can be shared across all functions in the application.
When the function is run in OCI, the script expects that the username and password variables be retrieved from Vault, so we use the OCID of the secrets that represent those variables from setting up the secrets (see OCI Vault for more information). When run locally (for testing), the function expects that the variables are available as regular function configurations.
# Params that will be assigned based on where this function is running username = None password = None # Get environment vars from F(n) hostname = os.getenv("b2cservice_hostname") # If the function is running in OCI, then retrieve secrets from vault if 'oci' in app_id: #logging.getLogger().debug("Using OCI config settings") username_ocid = os.getenv("b2cservice_username_ocid") password_ocid = os.getenv("b2cservice_password_ocid") # By default this will hit the auth service in the region the instance is running. signer = oci.auth.signers.get_resource_principals_signer() # Get instance principal context secret_client = oci.secrets.SecretsClient(config={}, signer=signer) # Get B2CService Credentials from Vault username = read_secret_value(secret_client, username_ocid) password = read_secret_value(secret_client, password_ocid) # else, if running locally, then use env params else: #logging.getLogger().debug("Using local config settings") username = os.getenv("b2cservice_username") password = os.getenv("b2cservice_password")
Load the data into a variable from the function’s data parameter. This process is similar for any function that will have data posted to it.
# Parse Webhook Body try: webhook_data_str = data.getvalue().decode('utf-8') #logging.getLogger().debug(webhook_data_str) webhook_data = json.loads(webhook_data_str)
Next, we will call a few convenience methods in sequence to perform the following steps:
if 'body' in webhook_data: sms_body = webhook_data['body'] sms_from = webhook_data['from'] sms_to = webhook_data['to'] # Check to see if there is a contact with the "to" phone number contact_id = get_contact_by_mobile(osvc_client, sms_from) # If no contact was returned, then create one if contact_id == None: contact_id = create_contact_from_sms(osvc_client, sms_from) # Create an incident from the inbound thread new_incident = create_incident_from_sms(osvc_client, contact_id, webhook_data)
The first call to `get_contact_by_mobile` will query the contact by phone number. If there is no result, then `None` is returned and we know that we need to create a new contact.
def get_contact_by_mobile(osvc_client, number) : contact_results = osvc_client.get("/services/rest/connect/latest/contacts?q=phones.number = '{}'".format(number)) logging.getLogger().debug(json.dumps(contact_results, indent=3)) if 'items' in contact_results and len(contact_results['items']) > 0 and 'id' in contact_results['items'][0]: return contact_results['items'][0]['id'] return None
If required, we call `create_contact_from_sms`, which will create a new contact record with the phone number used to generate the SMS message.
def create_contact_from_sms(osvc_client, number): contact = { "name": { "first": "SMS", "last": "User" } } create_result = osvc_client.post("/services/rest/connect/latest/contacts", json.dumps(contact)) if id in create_result and create_result['id'] != None: contact_id = create_result['id'] new_phone = { "number": number, "phoneType": { "lookupName": "Mobile Phone" } } osvc_client.post("/services/rest/connect/latest/contacts/{}/phones".format(contact_id), json.dumps(new_phone)) return contact_id else: raise Exception(create_result)
Lastly, we call `create_incident_from_sms` passing in the contact and SMS data to create the incident and incident thread as mentioned above.
def create_incident_from_sms(osvc_client, contact_id, webhook_data): subject = webhook_data['body'] new_incident = { "subject": subject, "primaryContact": { "id": contact_id } } create_result = osvc_client.post("/services/rest/connect/latest/incidents", json.dumps(new_incident)) if 'id' in create_result and create_result['id'] > 0: incident_id = create_result['id'] # save the SMS body as a note to the incident for record keeping new_thread = { "text": json.dumps(webhook_data, indent=2), "entryType": { "lookupName": "Note" }, "contentType": { "lookupName": "text/plain" } } logging.getLogger().debug(json.dumps(new_thread, indent=3)) osvc_client.post("/services/rest/connect/latest/incidents/{}/threads".format(incident_id), json.dumps(new_thread)) return create_result else: logging.getLogger().error("Could not get incident ID from create results") raise Exception(create_result)
Now that we understand the business logic of our function’s script, we can test it locally using the F(n) CLI. This document does not explore how to deploy a function to the local F(n) service, but that is covered by the F(n) documentation. In summary, follow these steps:
Assuming you have configured your function properly, you should see a success message once your functions finishes the invoke routine. And, there will be a new incident in Oracle B2C Service where you can verify that the script worked as expected.
Request
echo -n '{"account_sid":"ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","api_version":"2010-04-01", "body":"McAvoy or Stewart? These timelines can get so confusing.", "date_created":"Thu, 30 Jul 2015 20:12:31 +0000","date_sent":"Thu, 30 Jul 2015 20:12:33 +0000","date_updated":"Thu, 30 Jul 2015 20:12:33 +0000","direction":"outbound-api", "error_code":null,"error_message":null,"from":"+13365550622","messaging_service_sid": "MGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","num_media":"0","num_segments":"1","price":null, "price_unit":null,"sid":"SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","status":"sent","subresource_uris": {"media":"/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages/ SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Media.json"},"to":"+15558675310","uri":"/2010-04-01/ Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages/SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.json"}' | fn invoke osvc-webhooks sms-to-incident
Response
HTTP/1.1 200 OK Content-Length: 22 Content-Type: application/json Date: Tue, 15 Sep 2020 14:49:00 GMT Fn-Call-Id: 01EJ93TYPANG8G00GZJ0000021 Fn-Fdk-Version: fdk-python/0.1.18 {"message": "success"} {"message": "success"}
Publishing a function to OCI is like publishing it locally, but there are a few differences that the documentation outlines as you move from your local testing to OCI. Namely, you will need to account for the required attributes, such as your function’s VCN subnet attribute, that need to be added when deploying to OCI.
Follow the processes outlined in the OCI Functions documentation to deploy your application and function to OCI. Be sure to also setup the Vault secrets for the Oracle B2C Service Username and Password as the script expects those variables to be secured by Vault. Testing your function in OCI may still be performed via the command line tools in order to verify that it is working as expected. You only need to start testing HTTP posts after the next section is complete.
It’s time to create and expose an HTTP endpoint that a webhook can call in order to post data to your newly created function. We will walk through the high-level configuration steps in this guide, but refer to the API Gateway documentation for more detailed instructions for implementation.
Navigate to Developer Services > API Gateway in the OCI console.
Ensure that you are in the same compartment as your function. Click “Create Gateway” to create a new API Gateway in the same compartment as our function. Then, fill out the fields in the form that is presented. You will need to be sure to use a public subnet so that your gateway is exposed to the public internet. The gateway may take a few minutes to be created.
Once the gateway is created, click on the “Deployments” link under “Resources” on the left side of the page. Then, click “Create Deployment”.
The next few steps will determine how your exposed REST endpoints will work. Use best-practices or required implementation paradigms for CORS support, etc. established by your organization. And, ensure that you are using an authorization mechanism so that your endpoint is not freely exposed to the public internet.
Create the basic information first. The “Path Prefix” field is the root of your API. You should name it something common to all the endpoints that will be below it.
Setup an authentication type to secure your endpoint. In the case of an SMS provider, it’s likely that you would implement a custom authorizer function to verify the sending IP address in order to validate the request; many SMS providers don’t directly authenticate with webhook endpoints. In cases like this, the ability to leverage custom functions means that you can create any mechanism required to authenticate based on your integrator’s capabilities. Of course, you can use an identify provider, like IDCS, for OAuth, JWT, and SAML authentication solutions.
It’s also a good idea to setup CORS and rate limiting policies as per the requirements of your implementation.
Click “next” and review your API Gateway deployment. Then, click “create”.
Your changes will deploy within your gateway. It may take a few minutes to provision.
Once deployed, it’s time to test your API call from the public internet. We can use cURL from our shell to test.
Note: You may need to update your authorizer function to allow requests from your IP address or the proper parameters based on how that authorizer function was implemented.
curl -X "POST" "https://<gatewayid>.apigateway.us-ashburn-1.oci.customer-oci.com/webhooks/sms-to-incident" \ -H 'Content-Type: application/json; charset=utf-8' \ -d $'{ "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "api_version": "2010-04-01", "body": "McAvoy or Stewart? These timelines can get so confusing.", "date_created": "Thu, 30 Jul 2015 20:12:31 +0000", "date_sent": "Thu, 30 Jul 2015 20:12:33 +0000", "date_updated": "Thu, 30 Jul 2015 20:12:33 +0000", "direction": "outbound-api", "error_code": null, "error_message": null, "from": "+13365550652", "messaging_service_sid": "MGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "num_media": "0", "num_segments": "1", "price": null, "price_unit": null, "sid": "SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "status": "sent", "subresource_uris": { "media": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages/SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Media.json" }, "to": "+15558675310", "uri": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages/SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.json" }'
If your configuration is correct, then you should see a reply from your function that the result was a success! Next, check to ensure that your test created an incident in Oracle B2C Service. If so, then you should be ready to connect your SMS provider’s webhooks to your new HTTP endpoint.
You should now be able to create a custom HTTP endpoint using OCI API Gateway for custom API endpoints that you need for Oracle B2C Service. This approach allows you to build and scale your custom API needs in a secure and supported fashion.