Code Monkey home page Code Monkey logo

azure-api-management-monetization's Introduction

Azure API Management - Monetization

Purpose and scope

This is a demo project providing two working examples of how to integrate Azure API Management (APIM) with payment providers - one based on integration with Stripe, the other with Adyen.

The objective is to show how you can enable consumers to discover an API that you wish to make public, enter their payment details, activate their subscription and trigger automated payment based on their usage of the API.

To use this demo, you will need to deploy the solution into your own Azure subscription and to set up your own Stripe / Adyen account. This is not a managed service - you will be responsible for managing the resources that are deployed on Azure, adapting the solution to meet your specific use case and keeping the solution up to date.

Table of contents

Document Purpose
Monetization with Azure API Management Makes recommendations about how to design a successful monetization strategy for your API.
How API Management supports monetization Provides an overview of the API Management features that can be used to accelerate and de-risk API monetization.
How to implement monetization with Azure API Management and Stripe Describes how the Stripe integration has been implemented and the user flow through the solution.
Deploy demo with Stripe End to end deployment steps to implement the demo project with Stripe as payment provider.
How to implement monetization with Azure API Management and Adyen Describes how the Adyen integration has been implemented and the user flow through the solution.
Deploy demo with Adyen End to end deployment steps to implement the demo project with Adyen as payment provider.
Deployment details Details the resources that are deployed and the approach taken to script the deployment.
Advanced steps Details of advanced steps to modify the infrastructure templates and run the billing app locally.

Steps to follow

Follow these steps to implement the demo project:

  1. Read Monetization with Azure API Management to get background about designing a successful monetization strategy.

  2. Read How API Management supports monetization to understand how APIM supports implementation of a monetization strategy.

  3. Choose the payment provider you want to implement - either Stripe or Adyen.

  4. Read the overview: either How to implement monetization with Azure API Management and Stripe or How to implement monetization with Azure API Management and Adyen to understand more about Stripe / Adyen, how they integrate with APIM, the architecture adopted and the consumer flow through the solution.

  5. Follow the deployment instructions in either Deploy demo with Stripe or Deploy demo with Adyen to set up the pre-requisites, deploy the resources onto Azure and complete remaining steps post deployment to implement the demo project.

  6. Reference Deployment details to get more detail about the resources that are being deployed and how this has been scripted.

  7. Reference Advanced steps if you want to modify the infrastructure templates or run the billing app locally.

Architecture

The following diagram illustrates the high level architecture this demo has adopted to integrate API Management with a payment provider, showing the components of the solution across APIM, the Billing App (both hosted on Azure) and the payment provider. It also highlights the major integration flows between components, including the interactions between the API Consumer (both developer and application) and the solution:

Monetization with Stripe

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.

When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

Trademarks

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.

azure-api-management-monetization's People

Contributors

dependabot[bot] avatar dlepow avatar howardvanrooijen avatar johndowns avatar jvr2022 avatar miaojiang avatar microsoft-github-operations[bot] avatar microsoftopensource avatar mikebudzynski avatar mikeevanslarah avatar smartitect avatar tamarafmsft avatar tomkerkhove avatar v-hhunter avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

azure-api-management-monetization's Issues

stripeinitialization.ps1

Getting error when applying this:
$monetizationModels = Invoke-WebRequest -Uri $ApimGatewayUrl/billing/monetizationModels -Headers @{"Ocp-Apim-Subscription-Key"=$ApimSubscriptionKey} | ConvertFrom-Json
-or-
$apimProducts = Invoke-WebRequest -Uri $ApimGatewayUrl/billing/products -Headers @{"Ocp-Apim-Subscription-Key"=$ApimSubscriptionKey} | ConvertFrom-Json

Response status code does not indicate success: 301 (Moved Permanently)

Purpose of Reader Role Assigned to API Management Service besides the Service Principal Contributor Role

The API Management is given Reader Role. What is the purpose of this role and where it is used.

resource apimManagedIdentityReaderRole 'Microsoft.Authorization/roleAssignments@2020-10-01-preview' = {
 scope: resourceGroup()
 name: guid(apiManagementService.id, readerRoleId)
 properties: {
   roleDefinitionId: readerRoleId
   principalId: apiManagementService.identity.principalId
 }
}

Asking this question because there is already a Service Principal which is given Contributor Role. The Billing web app authenticates to the API Management management API using this service principal to create/update the API Management subscription after checkout using APIM API's

resource servicePrincipalContributorRole 'Microsoft.Authorization/roleAssignments@2020-10-01-preview' = {
  name: guid(resourceGroup().id, servicePrincipalObjectId, contributorRoleId)
  scope: resourceGroup()
  properties: {
    roleDefinitionId: contributorRoleId
    principalId: servicePrincipalObjectId
  }
}

Validation on subscription name form

Hi,
There's no validation on the form when creating a subscription and allows an empty subscription name. However, this creates an issue and does not allow the successful subscription creation on the APIM. Can this be rectified, please?

When running Stripe Initialization Script, it says "Resource group not found"

I know it is because the resource group is under a specific subscription. I tried switching to that by saying "Select-AzSubscription -SubscriptionName '' but I still get the same error.

Here is the error:

Error:
(ResourceGroupNotFound) Resource group '[REDACTED RESOURCE GROUP NAME]' could not be found.
Code: ResourceGroupNotFound
Message: Resource group '[REDACTED RESOURCE GROUP NAME]' could not be found.

Could we instead have the subscription key also be added as a parameter for the script? This would make sure the resource group can be found. Just an idea, but would love any help.

Infinite loop in Stripe billing service

startingAfter = stripeSubscription.id;

if (usageUnits === 0) {
return;
}

Hello, Looks like there's a bug in the stripeBillingService where the startingAfter = stripeSubscription.id never runs if usageUnits is 0 in the lines preceding. That line is critical to retrieve the next page of subscriptions from Stripe

This then a never ending loop. I think the startingAfter = stripeSubscription.id should be right at the beginning of the stripeSubscriptionListResponse.data.forEach function

Plan to have the Billing Web App code updated

I am looking into integrating Azure API management with Stripe for Monetizing API's in our Organization. Is there any plans to update the billing web app code with latest Azure REST API's and libraries. Like I stumbled into @azure/ms-rest-nodeauth is deprecated and should be replaced with @azure/identity
I do not have developers who can take this up.
It will be really helpful if this code is updated with instructions to use it with existing Azure APIM which has Azure AD and B2C users and not use the Authentication (Sign-in & Sign-up) delegation but only use the product subscription delegation.

App service failed to pull Docker image

Thanks for this demo app.

However the Billing app can't be deployed on my App Service:

Got this from the Docker logs

2021-11-14T16:52:54.689Z INFO - Pulling image: ghcr.io/microsoft/azure-api-management-monetization/app:latest
2021-11-14T16:52:56.888Z ERROR - DockerApiException: Docker API responded with status code=InternalServerError, response={"message":"Get https://ghcr.io/v2/microsoft/azure-api-management-monetization/app/manifests/latest: unauthorized"}
2021-11-14T16:52:56.890Z ERROR - Pull image threw Exception: Input string was not in a correct format.
2021-11-14T16:52:56.892Z INFO - Pulling image from Docker hub: ghcr.io/microsoft/azure-api-management-monetization/app:latest
2021-11-14T16:52:57.608Z ERROR - DockerApiException: Docker API responded with status code=InternalServerError, response={"message":"Get https://ghcr.io/v2/microsoft/azure-api-management-monetization/app/manifests/latest: unauthorized"}
2021-11-14T16:52:57.614Z WARN - Image pull failed. Defaulting to local copy if present.
2021-11-14T16:52:57.617Z ERROR - Image pull failed: Verify docker image configuration and credentials (if using private repository)
2021-11-14T16:52:57.624Z INFO - Stopping site yukiapimpaymentproviderdemo because it failed during startup.

TypeScript errors in app build

Following errors when running npm run build:

#10 7.556 src/services/apimService.ts(133,34): error TS2339: Property 'id' does not exist on type 'unknown'.
#10 7.557 src/services/monetizationService.ts(14,54): error TS2339: Property 'find' does not exist on type 'unknown'.

Billing Portal Update

Hello, are there any plans to upgrade the Billing Portal App?

Using the current version seems is now broken and does not work. I am able to get the products registered but upon trying to Subscribe, users get a white screen like if its having issues with the Stripe checkout sessions, packages seem to be outdated, typscript errors.

Has anyone been able to get this workin recently?

Best way to implement a free trial

I'm looking to use Stripe and APIM together, but would like to be able to offer a free trial prior to payment. Is there a recommended pattern for setting this up with APIM/Stripe?

Blocking issues

In README :
deploy.ps1 -TenantId "" -SubscriptionId "" -ResourceGroupName "apimmonetization" -ResourceGroupLocation "uksouth" --ArtifactStorageAccountName "" => single dash, not double dash like this : -ArtifactStorageAccountName

In appservice.bicep and main.bicep :
Default App Service Plan SKU is put to F1 which doesn’t allow “Always on” hosting. Had to change to P1V3 to deploy the Web App.

For some reason the deployment only works if parameters appServiceName and apimServiceName have the same value. Otherwise it fails. Didn’t have the time to investigate why.

General feedback

  1. There isn't a particular recommended doc sequence. We should make it clear in the readme.md or somewhere else.
  2. "How to think about monetization", this is a good overview. I'd remove "Azure API Management" from the title since this is actually the content of the other doc.
  3. "How to monetize with APIM", consider adding a simplified high level architecture diagram showing the relationship of APIM, billing portal, and payment provider. (this diagram can be much simpler than the stripe and adyen specific image)
  4. "Deployment and initiation guide" - this is where I got lost, especially with the overlap and cross-ref to the project README. Also, I think the intent is to have steps how to create the APIM service and billing portal, without a lot of payment provider detail. Unfortunately, customer has to decide on a payment provider first, and it was confusing to me to read Stripe and Adyen details without having introduced them first. One option is to carve out common prerequisite steps as an include that can be used in either the Stripe or Adyen specific docs which follow.
  5. Stripe and Adyen specific doc - For the Consumer Flow sections, consider adding a few screens or code snippets, otherwise it's a wall of text.
  6. Some required files might be missing? I didn't find any generated JSON templates in the project folder. Didn't find apiConfiguration/config.yaml, etc.
  7. I noticed several broken doc links.

Feedback on readme.md

  1. Make it very explicit that this is a demo, and that customers will have to deploy this, keep up-to-date with any changes you publish, and also maintain their own infrastructure and Stripe accounts – i.e. clarify that this is not a managed service.
  2. The readme.md doc should serve as an introduction and table-of-content that links to relevant docs. At the moment it feels like it jumps straight into the details and I had a hard time understanding the big picture. I know there’s some of this in the API Subscription doc but I think a high-level overview in the readme would be worthwhile.

Feedback on Dev experience

A few thing I think we should fix/add:

  • Mention NodeJS as a pre-requisite, and provide a link to download.
  • We should add the CLI version (2.21.0+) which we know for sure will work with the script. Also mention "az upgrade".
  • We should add references to docs for each CLI command.
  • Deploy to Azure button doesn't work as-is (we need to check how to make it work after forking).
  • Typo: --ArtifactStorageAccountName "" (should be one dash).
  • Links to docs for "API Management", "App Service", "Web App for Containers", "Service Principal RBAC".
  • Mention that you need to rename "main.parameters.template.json" to "main.parameters.json"
  • Also, we need example values for each parameter in "main.parameters.json".
  • In "main.parameters.json" // The client secret for the service principal": rename "secret" to "password" (the idea is to match wording to avoid unnecessary confusion):
{
  "appId": "…",
  "displayName": "alzaslon-sp",
  "name": http://alzaslon-sp,
  "password": "…",
  "tenant": "…"
}
  • In "main.parameters.json" property "stripeApiKey" matches to "Initialization Key" or "App key"?
  • We need to tell where to get those in Stripe:
        "checkoutSuccessfulUrl": {
            "value": ""
        },
        "checkoutCancelledUrl": {
            "value": ""
        }

stripe: parameter_unknown - "recurring Received unknown parameter: "recurring. Did you mean recurring?

I followed the stripe-deploy.md step by step, but I see the above error in the product page in stripe. Seems like an obvious typo somewhere. I'm wondering if anyone else has come across this bug and if there is a known fix for it?

some more details:
this seems to be the post body for this endpoint (POST /v1/prices)

{
  ""recurring": {
    "interval": {
      """: "month"
    },
    "usage_type": {
      """: "licensed"
    },
    "interval_count": {
      """: "1"
    }
  },
  "product": ["basic"](https://dashboard.stripe.com/test/products/basic),
  "currency": "usd",
  "unit_amount_decimal": "1495"
}

Thanks

Demo deployment with Stripe: "Invalid Credentials" error message when trying to sign up

I followed all the instructions to deploy this demo, and everything ran successfully. I can see the products information both in APIM and Stripe. When I try to sign up to Developer Portal, I get redirected to the Web App and after entering any type of credentials and hitting the Sign-up button, I always get the "Invalid Credentials" error message

Looking at the Web App logs, I can see a 302 http code when the POST /signUp request is triggered. And this is the response url I get after hitting the Sign-up button:
https://app-apim-monetization.azurewebsites.net/apim-delegation?errorMessage=Invalid%20credentials&returnUrl=%2F&operation=SignUp&salt=DubYQ0sJC%2F8K3sAIc6TBw2PvW%2Bn4Uk4qD9TnZepMikM%3D&sig=0bkL1gQtCrJzqcC5Z7h1Ja1meewi9M%2Bl4ReSkqJhXdb3btZ1%2Bo0EpammjcyhqDiGuPMEvWELhhuX%2F2l0FFF7Sg%3D%3D

Can you please help me get this issue fixed?

Unable to deploy the solution

Unfortunately, I'm unable to deploy the solution, stuck with the following error:

{
    "error":{
        "code":"InvalidTemplate",
        "message":"Deployment template validation failed: 'The template parameters 'checkoutSuccessfulUrl, checkoutCancelledUrl' in the parameters file are not valid; they are not present in the original template and can therefore not be provided at deployment time. The only supported parameters for this template are 'apimServiceName, apimPublisherEmail, apimPublisherName, apimSku, apimSkuCount, appServiceHostingPlanName, appServiceName, appServiceSkuName, appServiceSkuCapacity, paymentProvider, stripeApiKey, stripePublicKey, adyenApiKey, adyenClientKey, adyenMerchantAccount, appServiceContainerImage, appServiceContainerPort, servicePrincipalClientId, servicePrincipalObjectId, servicePrincipalClientSecret, servicePrincipalTenantId, location, artifactsBaseUrl'. Please see https://aka.ms/arm-deploy/#parameter-file for usage details.'.",
        "additionalInfo":[
            {
                "type":"TemplateViolation",
                "info":{
                    "lineNumber":0,
                    "linePosition":0,
                    "path":""
                }
            }
        ]
    }
}

My parameters in the template:

        "checkoutSuccessfulUrl": {
            "value": https://localhost:3000/checkout/success
        },
        "checkoutCancelledUrl": {
            "value": https://localhost:3000/checkout/cancelled
        }

I assume these are webhooks in Stripe, so it would be awesome to provide information (in README file) on them, i.e. where to get those values for local and production environments.

Modify monetizationModels.json post-hoc

Hi!

What's the recommended workflow if one wants to modify a monetization model after the deployment?

E.g. for the Pro product in Stripe, if I go to my Stripe console and modify the quota from 5000 to 10000, do I have to redeploy or will things "just work"?

It seems much more intuitive that the APIM polls Stripe for latest monetization models of the products as opposed to looking into internally cached version of the monetizationModels.json file that was used during the deployment?

The only piece of code that seems to rely on this file is here in stripe.ts:
const pricingModelType = monetizationModel.pricingModelType;
and it looks like the model type is thus the only bit that can't be modified post-hoc?

Or am I misunderstanding something here?

Would be good to have a README that discusses how to modify stuff after the deployment happened which I assume is a very common workflow.

General feedback

  • General feedback
    • Consistently use "monetization" across the repo, currently both monetization and monetisation is used :)
    • I think the flow is still a bit disjoint and might be confusing (I actually got lost). To me a reader should follow the below flow and we need to restructure the content a bit:
      • Start with readme.md to understand the purpose and scope of the repository with a table of content
      • Read the two high-level docs to get an overview
      • Read an overview of integrating APIM with Stripe (i.e., What is Stripe, how Stripe's product map to APIM product, architecture diagram, consumer flow)
      • Ready to deploy the sample, read and complete the pre-requisites
      • Follow instructions to deploy the project
  • In readme.md
    • I suggest providing a full table of contents with purpose of each doc and where to start
    • In the diagram, I suggest change "App Service" to "Billing App" or "Custom Billing App" to be consistent with other diagrams
    • I would suggest moving pre-requisite to stripe-deploy and adyen-deploy to make readme.md concise - readme.md can just cover the purpose of the repo, table of contents. We already have a pre-requisite section in those docs.
  • Adyen and Stripe docs
    • It's unclear what are "pricing model" vs "revenue model". Are they APIM products vs Stripe products? The explanations in the doc did not help.
  • deployment-details.md
    • This doc is in the repo but not referred from any other doc.
  • advanced-steps.md
    • The doc says "If you want to make modifications to the infrastructure templates, you will need to run a build script in order to generate a new ARM template output for deployment." - I am not sure does the build script generate ARM template for APIM? or the Billing Portal? Please expand a little.
  • how-APIM-monetisation.md
    • "Delegation" is a key feature to make the integration possible. I think we should expand on that section a little bit assuming users do not know what "sign up and the subscription stages of the process" means at this point. We touched on that topic a little in the "API Consumption" section.
    • If structure of the repo is updated, then the link in the last sentence of this doc will need to be changed as well.

API version retirements

Hi,
It seems like the Azure Javascript SDK version (7.0.0) being used in this app for ARM API management has been retired.
https://learn.microsoft.com/en-us/azure/api-management/breaking-changes/api-version-retirement-sep-2023?WT.mc_id=Portal-Microsoft_Azure_Expert

I'm getting errors that look like this:

2023-10-23T23:41:17.533579576Z: [ERROR]  (node:1) UnhandledPromiseRejectionWarning: Error: Failed to connect to Management endpoint Port 3443 at endpoint <app_name>.management.azure-api.net for the service.
2023-10-23T23:41:17.533596418Z: [ERROR]      at new RestError (/usr/app/node_modules/@azure/ms-rest-js/dist/msRest.node.js:2469:28)
2023-10-23T23:41:17.533614762Z: [ERROR]      at /usr/app/node_modules/@azure/ms-rest-js/dist/msRest.node.js:3671:37
2023-10-23T23:41:17.533621214Z: [ERROR]      at runMicrotasks (<anonymous>)
2023-10-23T23:41:17.533625974Z: [ERROR]      at processTicksAndRejections (internal/process/task_queues.js:95:5)
2023-10-23T23:41:17.533630712Z: [ERROR]  (node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 455236)

which causes an infinite loop every midnight when attempting to report Stripe billing.

Any assistance would be greatly appreciated.

Unable to initialize Stripe

I'm not able to initialize the Stripe part with the stripeInitialisation.ps1 script
Output is the following:

Stripe CLI already installed.
{
  "error": {
    "code": "parameter_invalid_empty",
    "doc_url": "https://stripe.com/docs/error-codes/parameter-invalid-empty",
    "message": "You passed an empty string for 'id'. We assume empty values are an attempt to unset a parameter; however 'id' cannot be unset. You should remove 'id' from your request or supply a non-empty value.",
    "param": "id",
    "type": "invalid_request_error"
  }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.