PaymentControlPlugin how to configure

394 views
Skip to first unread message

ggra...@gmail.com

unread,
Apr 15, 2016, 11:05:37 AM4/15/16
to Kill Bill users mailing-list
Hey there,

i cloned the hello-world-payment-api-plugin and exchanged the PaymentPluginApi interface with the PaymentControlApi Interface and excluded the servlet registration.

1. I can mvn clean isntall and upload the plugin.jar into /var/lib/killbill/bundles/plugins/java/payment-control-plugin/0.0.1/payment-control-plugin-0.0.1.jar

2. The next i did is altering the sha1.yml File and added

"PAYMENT-CONTROL":{
"plugin_name":"payment-control-plugin",
"language":"java",
"group_id":"org.kill-bill.billing.plugin.java",
"artifact_id":"payment-control-plugin",
"packaging":"jar",
"classifier":null,
"version":"0.0.1"
}

When i restart killbill i only see the follwoing log:

2016-04-15 15:02:04,333 [Thread-6] INFO o.k.b.p.j.p.0.0.1 - BundleEvent RESOLVED
2016-04-15 15:02:04,336 [Thread-6] INFO o.k.b.p.j.p.0.0.1 - OSGI bundle = org.kill-bill.billing.plugin.java.payment-control-plugin recieved START command
2016-04-15 15:02:04,365 [localhost-startStop-1] INFO o.k.b.p.p.DefaultPaymentProviderPluginRegistry - DefaultPaymentControlProviderPluginRegistry registering service payment-control-plugin
2016-04-15 15:02:04,368 [Thread-6] INFO o.k.b.p.j.p.0.0.1 - [[org.killbill.billing.plugin.netstream.PaymentControlPluginApi]]ServiceEvent REGISTERED
2016-04-15 15:02:04,368 [localhost-startStop-1] INFO o.killbill.billing.osgi.FileInstall - Starting bundle file:/var/lib/killbill/bundles/plugins/java/analytics-plugin/3.0.1/analytics-plugin-3.0.1.jar
2016-04-15 15:02:04,369 [Thread-6] INFO o.k.b.p.j.p.0.0.1 - BundleEvent STARTED

when i make a payment, i receive the event after the strip plugin processed the payment:

2016-04-15 15:04:05,473 [Thread-6] INFO o.k.b.p.j.p.0.0.1 - Received event PAYMENT_SUCCESS for object id f541755a-dbf9-470b-8492-421e7c2dcfaf of type PAYMENT


But i dont receive calls belonging to the PaymentControlPlugin.

Am i missing sth....??? Im running Killbill 0.16.0 in a docker contsainer

Thx in advance and if u have any questions let me know

stephane brossier

unread,
Apr 15, 2016, 2:21:10 PM4/15/16
to ggra...@gmail.com, Kill Bill users mailing-list
On Fri, Apr 15, 2016 at 8:05 AM, <ggra...@gmail.com> wrote:
Hey there,

i cloned the hello-world-payment-api-plugin and exchanged the PaymentPluginApi interface with the PaymentControlApi Interface and excluded the servlet registration.


Are you talking about this repo


1. I can mvn clean isntall and upload the plugin.jar into /var/lib/killbill/bundles/plugins/java/payment-control-plugin/0.0.1/payment-control-plugin-0.0.1.jar


I am guessing your system property 'org.killbill.osgi.bundle.install.dir' points to  '/var/lib/killbill/bundles/' (not the default value) ?

If this is the case, what you did is correct, and your plugin should be detected when KB starts (and started).




2. The next i did is altering the sha1.yml File and added

"PAYMENT-CONTROL":{
      "plugin_name":"payment-control-plugin",
      "language":"java",
      "group_id":"org.kill-bill.billing.plugin.java",
      "artifact_id":"payment-control-plugin",
      "packaging":"jar",
      "classifier":null,
      "version":"0.0.1"
   }



You don't need to touch anything by hand. Those files `sha1.yml` (and `plugin_identifiers.json`) are managed by KPM (for installation, ...). If you don't install using KPM and do an installation by hand things should work. This is not the recommended way but this is a fine way when you are in that dev/test stage.


 

When i restart killbill i only see the follwoing log:

2016-04-15 15:02:04,333 [Thread-6] INFO  o.k.b.p.j.p.0.0.1 - BundleEvent RESOLVED
2016-04-15 15:02:04,336 [Thread-6] INFO  o.k.b.p.j.p.0.0.1 - OSGI bundle = org.kill-bill.billing.plugin.java.payment-control-plugin recieved START command
2016-04-15 15:02:04,365 [localhost-startStop-1] INFO  o.k.b.p.p.DefaultPaymentProviderPluginRegistry - DefaultPaymentControlProviderPluginRegistry registering service payment-control-plugin
2016-04-15 15:02:04,368 [Thread-6] INFO  o.k.b.p.j.p.0.0.1 - [[org.killbill.billing.plugin.netstream.PaymentControlPluginApi]]ServiceEvent REGISTERED
2016-04-15 15:02:04,368 [localhost-startStop-1] INFO  o.killbill.billing.osgi.FileInstall - Starting bundle file:/var/lib/killbill/bundles/plugins/java/analytics-plugin/3.0.1/analytics-plugin-3.0.1.jar
2016-04-15 15:02:04,369 [Thread-6] INFO  o.k.b.p.j.p.0.0.1 - BundleEvent STARTED

when i make a payment, i receive the event after the strip plugin processed the payment:

2016-04-15 15:04:05,473 [Thread-6] INFO  o.k.b.p.j.p.0.0.1 - Received event PAYMENT_SUCCESS for object id f541755a-dbf9-470b-8492-421e7c2dcfaf of type PAYMENT





Are you sure 'org.killbill.osgi.bundle.install.dir' points to  '/var/lib/killbill/bundles/' ? Do you also have analytics plugin installed there? 


 

But i dont receive calls belonging to the PaymentControlPlugin.




Which calls do you expect to see? What are you trying to do? Did you read the PaymentControlPlugin doc?


 
Am i missing sth....??? Im running Killbill 0.16.0 in a docker contsainer

Thx in advance and if u have any questions let me know

--
You received this message because you are subscribed to the Google Groups "Kill Bill users mailing-list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to killbilling-us...@googlegroups.com.
To post to this group, send email to killbill...@googlegroups.com.
Visit this group at https://groups.google.com/group/killbilling-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/killbilling-users/3fd6d5f5-9091-466f-a2a5-150e6825a578%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

ggra...@gmail.com

unread,
Apr 18, 2016, 3:12:29 AM4/18/16
to Kill Bill users mailing-list, ggra...@gmail.com
Am Freitag, 15. April 2016 20:21:10 UTC+2 schrieb stephane brossier:
> On Fri, Apr 15, 2016 at 8:05 AM, <ggra...@gmail.com> wrote:
> Hey there,
>
>
>
> i cloned the hello-world-payment-api-plugin and exchanged the PaymentPluginApi interface with the PaymentControlApi Interface and excluded the servlet registration.
>
>
>
>
>
> Are you talking about this repo? 

Yes, thats exactly the example project i started from, but ive no intention to write a PaymentPlugin but a PaymentControlPlugin to revoke a payment before it got processed by the payment providers

>
>
>
>
> 1. I can mvn clean isntall and upload the plugin.jar into /var/lib/killbill/bundles/plugins/java/payment-control-plugin/0.0.1/payment-control-plugin-0.0.1.jar
>
>
>
>
>
> I am guessing your system property 'org.killbill.osgi.bundle.install.dir' points to  '/var/lib/killbill/bundles/' (not the default value) ?

yes thats true

>
>
> If this is the case, what you did is correct, and your plugin should be detected when KB starts (and started).
>
>
>
> 2. The next i did is altering the sha1.yml File and added
>
>
>
> "PAYMENT-CONTROL":{
>
>       "plugin_name":"payment-control-plugin",
>
>       "language":"java",
>
>       "group_id":"org.kill-bill.billing.plugin.java",
>
>       "artifact_id":"payment-control-plugin",
>
>       "packaging":"jar",
>
>       "classifier":null,
>
>       "version":"0.0.1"
>
>    }
>
>
> You don't need to touch anything by hand. Those files `sha1.yml` (and `plugin_identifiers.json`) are managed by KPM (for installation, ...). If you don't install using KPM and do an installation by hand things should work. This is not the recommended way but this is a fine way when you are in that dev/test stage.

ok, so i should not configure this by hand. and as i havent installed the jar with KPM it will be generate automatically the sha1 file?

Another Question, how can i install my own cusom killbill osgi plugin with KPM? is there a tutorial or so?

>
>
>
> When i restart killbill i only see the follwoing log:
>
>
>
> 2016-04-15 15:02:04,333 [Thread-6] INFO  o.k.b.p.j.p.0.0.1 - BundleEvent RESOLVED
>
> 2016-04-15 15:02:04,336 [Thread-6] INFO  o.k.b.p.j.p.0.0.1 - OSGI bundle = org.kill-bill.billing.plugin.java.payment-control-plugin recieved START command
>
> 2016-04-15 15:02:04,365 [localhost-startStop-1] INFO  o.k.b.p.p.DefaultPaymentProviderPluginRegistry - DefaultPaymentControlProviderPluginRegistry registering service payment-control-plugin
>
> 2016-04-15 15:02:04,368 [Thread-6] INFO  o.k.b.p.j.p.0.0.1 - [[org.killbill.billing.plugin.netstream.PaymentControlPluginApi]]ServiceEvent REGISTERED
>
> 2016-04-15 15:02:04,368 [localhost-startStop-1] INFO  o.killbill.billing.osgi.FileInstall - Starting bundle file:/var/lib/killbill/bundles/plugins/java/analytics-plugin/3.0.1/analytics-plugin-3.0.1.jar
>
> 2016-04-15 15:02:04,369 [Thread-6] INFO  o.k.b.p.j.p.0.0.1 - BundleEvent STARTED
>
>
>
> when i make a payment, i receive the event after the stripe plugin processed the payment:
>
>
>
> 2016-04-15 15:04:05,473 [Thread-6] INFO  o.k.b.p.j.p.0.0.1 - Received event PAYMENT_SUCCESS for object id f541755a-dbf9-470b-8492-421e7c2dcfaf of type PAYMENT
>
>
>
>
>
>
>
>
>
>
>
> Are you sure 'org.killbill.osgi.bundle.install.dir' points to  '/var/lib/killbill/bundles/' ? Do you also have analytics plugin installed there? 
>
yes it points to  '/var/lib/killbill/bundles/' and we also have a analytics-plugin installed

tomcat7@f3e747379388:/var/lib/killbill/bundles/plugins/java$ ls -lah
total 16K
drwxr-xr-x. 4 tomcat7 tomcat7 4.0K Apr 15 14:07 .
drwxr-xr-x. 4 tomcat7 tomcat7 4.0K Apr 15 14:14 ..
drwxr-xr-x. 3 tomcat7 tomcat7 4.0K Apr 15 15:01 analytics-plugin
drwxr-xr-x. 3 tomcat7 tomcat7 4.0K Apr 15 14:07 payment-control-plugin


>
>
>  
>
>
> But i dont receive calls belonging to the PaymentControlPlugin.
>
>
>
>
>
>
>
>
>
> Which calls do you expect to see? What are you trying to do? Did you read the PaymentControlPlugin doc?


1. What i do...

Postman Get:
{{baseURLKillBill}}/accounts/7c37b24a-6c24-463f-b8c9-0fd7e55daa0c/payments

Body: {"transactionType":"PURCHASE","amount":"10","currency":"USD"}

1.1 What i expect at the time after i executed the payment request

I expect that the PaymentControlPluginApi.priorCall(...) gets invoked, so that i can control the payment before it got processed by the PaymentPlugin (Stripe) and i can revoke it if needed... therefore the next calls onSuccessCall or onFailureCall should also be visible somewhere...


Here are some gist's of the project
-> Activator
-> https://gist.github.com/ProjektBaguette/c36410c446484bbc6499eb67e6b4c88c

-> PaymentControlPlugin
-> https://gist.github.com/ProjektBaguette/87dbdab7bfa66800b4e25ec9f5a9c2d4



And another big question for me, as i cant really determine how to configure the plugin with an external config file? where to place it and so on, i cant find a proper tutorial. is it the plugin_identifiers.json yout talked about above in the text???

Thank you for your patience and if you can see anything im doing wrong let me know, im trying to find it out in the meanwhile :-D

ggra...@gmail.com

unread,
Apr 18, 2016, 10:39:43 AM4/18/16
to Kill Bill users mailing-list, ggra...@gmail.com
ok i found a solution to my problem :-D

I missunderstood the part in the documentation which explains how to specify the order of several payment-control-plugins.

There are as u stated 2 solutions:

After i added at the API level the queryParam {killbillUrl}account/userid/payments?controlPluginName=payment-control-plugin

or i specified in /etc/killbill/killbill.properties the system property variable org.killbill.payment.invoice.plugin=payment-control-plugin

Now i finally get the expected behaviour :-)

stephane brossier

unread,
Apr 18, 2016, 12:35:52 PM4/18/16
to giuliano grassi, Kill Bill users mailing-list
[...]

On Mon, Apr 18, 2016 at 7:39 AM, <ggra...@gmail.com> wrote:
ok i found a solution to my problem :-D


Great!  Did you solve all your issues or are there any remaining things to discuss?

Stéphane
 

ggra...@gmail.com

unread,
Apr 19, 2016, 8:18:14 AM4/19/16
to Kill Bill users mailing-list, ggra...@gmail.com
Now i have no issues anymore, but there are still some uncertainties about what are the proper ways to configure the plugins in a multi-tenancy environement

i want to configure different properties for each tenant, therefore i can sent
curl -v \
-X POST \
-u admin:password \
-H 'X-Killbill-ApiKey: devKey' \
-H 'X-Killbill-ApiSecret: devSecret' \
-H 'X-Killbill-CreatedBy: admin' \
-H 'Content-Type: text/plain' \
-d 'com.mycompany.killbill.plugins.paymentControl.url=http://172.17.0.3:8082' \
http://127.0.0.1:8080/1.0/kb/tenants/uploadPluginConfig/payment-control-plugin


I cant find a way to check the plugin config on the API for the affected tenant, is there a possibility?

My problem here:
I doesnt get the appropriate values back in the PaymentControlPlugin from what i configured with the above POST call to uploadPluginConfig for a certain tenant. If i add the config props to /etc/killbill/killbill.properties as global configs it works, but if i set the conf values per tenant with the api call it doesnt. Also if i upload a config file over KAUI with the same configs sepcified as in the API call, the received configs in the Plugin are not set.

Am i missing here sth...

>
> Stéphane
>  

stephane brossier

unread,
Apr 19, 2016, 12:09:15 PM4/19/16
to giuliano grassi, Kill Bill users mailing-list
On Tue, Apr 19, 2016 at 5:18 AM, <ggra...@gmail.com> wrote:
Am Montag, 18. April 2016 18:35:52 UTC+2 schrieb stephane brossier:
> [...]
>
>
> On Mon, Apr 18, 2016 at 7:39 AM,  <ggra...@gmail.com> wrote:
> ok i found a solution to my problem :-D
>
>
>
>
>
> Great!  Did you solve all your issues or are there any remaining things to discuss?

Now i have no issues anymore, but there are still some uncertainties about what are the proper ways to configure the plugins in a multi-tenancy environement

i want to configure different properties for each tenant, therefore i can sent
curl -v \
     -X POST \
     -u admin:password \
     -H 'X-Killbill-ApiKey: devKey' \
     -H 'X-Killbill-ApiSecret: devSecret' \
     -H 'X-Killbill-CreatedBy: admin' \
     -H 'Content-Type: text/plain' \
     -d 'com.mycompany.killbill.plugins.paymentControl.url=http://172.17.0.3:8082' \
     http://127.0.0.1:8080/1.0/kb/tenants/uploadPluginConfig/payment-control-plugin


This is indeed the correct way, but your have to make sure your plugin listens to the property changes when they occur: The system will emit some bus events `TENANT_CONFIG_CHANGE` and `TENANT_CONFIG_DELETION` when some of the per-tenant plugin properties are uploaded. One way could be to reuse the java plugin framework we wrote and which already does the work for you (the listener can be found here). The Adyen plugin is also an example of such plugin we write and that inherits the framework and you can see an example in the AdyenConfigurationHandler class




I cant find a way to check the plugin config on the API for the affected tenant, is there a possibility?


The per-tenant plugin properties are stored in the Kill Bill 'tenant_kvs' table. Besides looking at the entries in that table you can also use the endpoint to retrieve such properties:

GET /1.0/kb/tenants/uploadPluginConfig/{plugin_name}


S.

ggra...@gmail.com

unread,
Apr 20, 2016, 11:41:38 AM4/20/16
to Kill Bill users mailing-list, ggra...@gmail.com
ok, good morning...

so now i know how to listen on those changes, but also here i get problems...


after sending a configUpload to the API when i extract the properties.getProperty(PREFIX+"configPath") in (is extending PluginTenantConfigurableConfigurationHandler) PaymentControlConfigurationHandler.createConfigurable(Properties properties) it will return configPath =>
null instead of tenant.conf

but

the properties.toString returns =>
{?org.killbill.billing.plugin.paymentControl.configPath=tenant.conf?}

but it gets read from the /etc/killbill/killbill.properties as expected as default.conf same as tenant.conf.

Why is that? Can you point me to the appropriate part in killbill where you create the Properties received from the uploadConfig API call... or tell me how the propper way will be to handle such a properties object???


Im really short before to extract all configurations from the DB table... :-(

Other questions:
1. As the system properties configuration cannot represent object structures, i first wanted to try it out with yaml configurations, which is somehow not documented at all for a java plugin, not to mention configuration of a java plugin with yaml... therefore i changed and thought to make one path which holds a typesafe config file in the root path...


so my goal is, only read the tenants config path which then gets read into a TypeSafeConfigObject by help of my extended PluginTenantConfigurableConfigurationHandler and im going on from there in the PaymentControlPluginApi.priorCall by requesting the appropriate ConfigObject of the tenant...

Would you consider to go this way?


2. Im loosing very much time with assembling, uploading and restarting of killbill, i cant debug and i need to log as hell... its very tedious, any help?

3. Is there any internal and useful how to, pitfalls document or any representative help i can get about how to create a plugin without bordering you day to day???


Have a nice day






ggra...@gmail.com

unread,
Apr 20, 2016, 2:28:22 PM4/20/16
to Kill Bill users mailing-list, ggra...@gmail.com
So now it gets funny, the config gets loaded as expected, never mind... when i uploaded the config with a ` instead of a ' in the curl statement i cp'd i had got encoding problems

forget point 3, when i find some time ill write a summary and post it to u :-)

points 1-2 are still interesting to get some ideas

stephane brossier

unread,
Apr 20, 2016, 9:15:29 PM4/20/16
to giuliano grassi, Kill Bill users mailing-list
I am lost in that discussion... i don't know (anymore) what you are trying to do, and what is not working?

Let me summarize my thoughts about plugin config properties, maybe this will bring a fresh start...

Plugins have the ability to use per-tenant configuration. Those can be uploaded through KB using specific endpoint (where CONFIG could be key value, json, ... whatever and PLUGIN_NAME the name of your plugin as it appears on the filesystem). See example for Adyen plugin or Cybersource plugin.

# Upload new config
curl -v \
     -X POST \
     -u admin:password \
     -H 'X-Killbill-ApiKey: bob' \
     -H 'X-Killbill-ApiSecret: lazar' \
     -H 'X-Killbill-CreatedBy: admin' \
     -H 'Content-Type: application/json' \
     -d '<CONFIG>' \


# Retrieve config
curl -v \
     -u admin:password \
     -H 'X-Killbill-ApiKey: bob' \
     -H 'X-Killbill-ApiSecret: lazar' \
     -H 'X-Killbill-CreatedBy: admin' \
     -H 'Content-Type: application/json' \

When uploading a new config for a tenant, the system will propagate the info to all the nodes using bus event, which means your plugin needs to listen to those bus events. I mentioned that in my previous email:
 
The system will emit some bus events `TENANT_CONFIG_CHANGE` and `TENANT_CONFIG_DELETION` when some of the per-tenant plugin properties are uploaded. One way could be to reuse the java plugin framework we wrote and which already does the work for you (the listener can be found here). The Adyen plugin is also an example of such plugin we write and that inherits the framework and you can see an example in the AdyenConfigurationHandler class


Please be clear about what's not clear ;-)

 
3. Is there any internal and useful how to, pitfalls document or any representative help i can get about how to create a plugin without bordering you day to day???


Well we are trying our best to write documentation but keep in mind that we have been working on that system for the past 5 years, so this is not always easy to understand what is missing, not clear, ... this is where we need help. It is fine to spend a large amount of time answering your (and others) questions, but we what we ask in return is some help to improve the doc, either through PRs or **precise** gaps in our doc so that at the very worst we can update them and avoid having to repeat the same things every day.


Stéphane


ggra...@gmail.com

unread,
Apr 22, 2016, 5:22:14 AM4/22/16
to Kill Bill users mailing-list, ggra...@gmail.com
Hey Stéphane,

i created an internal Documentation with all points i havent found in a description somewhere, im posting it here, so that maybe someone can profit from this summary.

1. Clone the example Plugin-Project -> https://github.com/killbill/killbill-hello-world-java-plugin

2. Add the Killbill-Plugin-Framework as a dependency -> https://github.com/killbill/killbill-plugin-framework-java

3. In the maven-bundle-plugin add as described in the readme, some imports are used from the plugin-framework, others from the killbill client, if there will occure further ClassNotFoundExceptions -> consult the Pom of the Adyen Plugin, https://github.com/killbill/killbill-adyen-plugin

<configuration>
<instructions>
<Import-Package>
org.killbill.billing.account.api;
org.killbill.billing.catalog.api;
org.killbill.billing.invoice.api;
org.killbill.billing.entitlement.api;
org.killbill.billing.notification.api;
org.killbill.billing.notification.plugin.api;
org.killbill.billing.notification.plugin;
org.killbill.billing.osgi.api;
org.killbill.billing.osgi.api.config;
org.killbill.billing.payment.api;
org.killbill.billing.payment.plugin.api;
org.killbill.billing.control.plugin.api;
org.killbill.billing.tenant.api;
org.killbill.billing.usage.api;
org.killbill.billing.util.api;
org.killbill.billing.currency.plugin.api;
org.killbill.billing.currency.api;
org.killbill.billing.security.api;
javax.net.ssl; <!-- javax._ USED for the import org.killbill.billing.plugin.util.http.HttpClient;.-->
javax.management;
javax.jws;
javax.jws.soap;
javax.annotation;
javax.activation;
javax.xml.soap;
javax.xml.ws;
javax.xml.ws.spi;
javax.xml.ws.handler.soap;
javax.xml.ws.handler;
javax.xml.ws.http;
javax.xml.ws.soap;
javax.xml.ws.wsaddressing;
javax.xml.stream;
javax.xml.stream.events;
javax.xml.stream.util;
javax.xml.bind.annotation.adapters;
javax.xml.bind;
javax.xml.bind.helpers;
javax.xml.bind.annotation;
javax.xml.bind.attachment;
javax.xml.datatype;
javax.xml.namespace;
javax.xml.parsers;
javax.xml.transform;
javax.xml.transform.sax;
javax.xml.transform.dom;
javax.xml.transform.stream;
javax.xml.xpath;
javax.naming.directory;
javax.naming.event;
javax.naming.ldap;
javax.naming.spi;
javax.naming;
version="[0,3)",
*;resolution:=optional
</Import-Package>
</instructions>
</configuration>

4. Add the Guava Dependency which is used from the framework to use a functional programming library from google

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<scope>compile</scope>
</dependency>

5. Assemble the Jar with all dependencies, therefore it is required to add the maven-assembly-plugin and an adequate assembly.xml

5.1. Maven Plugin

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>jar-with-dep</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<finalName>${project.artifactId}-${project.version}</finalName>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/assembly/jar-assembly.xml</descriptor>
</descriptors>
<archive>
<manifestFile>target/classes/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</execution>
</executions>
</plugin>

5.2. Assembly.xml

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>jar-with-dependencies</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>

<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<useProjectAttachments>true</useProjectAttachments>
<useTransitiveDependencies>true</useTransitiveDependencies>
<unpack>true</unpack>
<unpackOptions>
<excludes>
<exclude>META-INF/cxf/**</exclude>
<exclude>javax/xml/**</exclude>
</excludes>
</unpackOptions>
</dependencySet>
</dependencySets>

<fileSets>
<fileSet>
<directory>target/classes/META-INF</directory>
<outputDirectory>META-INF</outputDirectory>
<fileMode>0644</fileMode>
</fileSet>
<fileSet>
<directory>target/classes</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
<fileSet>
<directory>src/main/assembly/cxf</directory>
<outputDirectory>META-INF/cxf</outputDirectory>
<fileMode>0644</fileMode>
</fileSet>
</fileSets>
</assembly>

6. To activate the Plugin in Killbill, you have two options, at least for the PaymentControlPlugin -> this varies i guess from plugin to plugin

6.1. By filling out the Query Param controlPluginName at the API Level when executing a payment -> see http://killbill.io/api/#!/accounts/processPayment
6.2 By setting a globalConfig for killbill you activate this payment-control-plugin for all tenants

//Look at Point 5: Global Configuration
org.killbill.payment.invoice.plugin=payment-control-plugin

7. Probably each Plugin needs some TenantBased Configuration, as Killbill consists of a Cluster full with Nodes, the Nodes need to listen to ConfigurationChange Events invoked by uploading Configurations to the API.

7.1 Global Configurations are stored under

$ vim /etc/killbill/killbill.properties
//Example of one single configuration
com.netstream.ch.killbill.plugins.payment-control-plugin.configFilePath=/var/lib/killbill/bundles/plugins/java/payment-control-plugin/x.y.z/default.conf

//Example of extracting this property in the Plugin
PaymentControlActivator.PROPERTY_PREFIX = "com.netstream.ch.killbill.plugins.payment-control-plugin.";
this.typesafeConfigPath = properties.getProperty(PaymentControlActivator.PROPERTY_PREFIX + "configFilePath");

7.2 As we always have multiple Tenants we need to listen to the Killbill Events sent to the EventBus

7.2.1 Here is a Gist of the Activator:

https://gist.github.com/ProjektBaguette/574bbe16cff9dd3f430cad42e81b743d

- First, we need to override getOSGIKillbillEventHandler and add the ConfigurationHandler to the PluginConfigurationEventHandler
- We need to setDefaultConfigurable -> will load the default.conf as configurable
- We need to add the configurationHandler as reference to our PluginApiImplementation

7.2.2 Here is an example of the ConfigurationHandler which returns the current Configurable cached for the tenant

- First, we need to override createConfigurable which returns an object which gets cached, so we can make there heavy computations like creating Clients or so
https://gist.github.com/ProjektBaguette/74f88b36e3e909de5700da59a0e21681
- As the System Properties can not represent Configurations in an object structure we decided to use TypesafeConfigurations / Lightbend
- Example of how to read a Killbill Property which represents a Filepath to a Typesafe Config File which gets transformed into a config object -> https://gist.github.com/ProjektBaguette/e390f905fe1d1061bda11e5e3c00cf66
- Finally the PluginApiImplementation which requests the TenantsConfiguration by requesting it from the ConfigurationHandler by the current TenantId -> https://gist.github.com/ProjektBaguette/8c01e794955ba0d7b3fef65ac21b1bda

7.3 Upload Tenant Config over API
# Upload new config
curl -v \
-X POST \
-u admin:password \

-H 'X-Killbill-ApiKey: bob' \
-H 'X-Killbill-ApiSecret: lazar' \
-H 'X-Killbill-CreatedBy: admin' \
-H 'Content-Type: application/json' \
-d '<CONFIG>' \
http://host:port/1.0/kb/tenants/uploadPluginConfig/<PLUGIN_NAME>

# Retrieve config
curl -v \
-u admin:password \

-H 'X-Killbill-ApiKey: bob' \
-H 'X-Killbill-ApiSecret: lazar' \
-H 'X-Killbill-CreatedBy: admin' \
-H 'Content-Type: application/json' \
http://host:port/1.0/kb/tenants/uploadPluginConfig/<PLUGIN_NAME>


8. Building the jar and adding it to killbill which is a docker container in our case
$local: mvn clean install
$local: scp target/payment-control-plugin-0.0.1.jar me@dockerHostServer: -> upload to docker host
$local: ssh to dockerHostServer and sudo -i yourself
$dockerHostServer: docker cp /home/chdgrgi9/payment-control-plugin-0.0.1.jar f3e747379388:/var/lib/killbill/bundles/plugins/java/payment-control-plugin/0.0.1/
$dockerHostServer: docker start killbill_0_16_0
$dockerHostServer: docker logs -f=true --tail=1000 killbill_0_16_0


Thank you for your help Stéphane. Hope that that this will help someone.

stephane brossier

unread,
Apr 24, 2016, 4:20:27 PM4/24/16
to giuliano grassi, Kill Bill users mailing-list
Hi there,

Thanks for taking the time to write some instructions. I decided to write a new documentation about plugin development and i would be interested to hear about your feedback. I also updated some other documentation linked from that main doc, and updated our java hello world plugin.

I have a few comments/questions on what you provided.

[...]
I updated our java hello world plugin with all that. It was somehow intentional to not include it by default because a lot of those `Import` packages are actually not needed for the hello world in its current form (same for guava,...). But i guess, if the intent is to provide something that can be cloned it might also make sense to already include a lot of things by default.
I am not clear about that part. Why do you need that?

 
6. To activate the Plugin in Killbill, you have two options, at least for the PaymentControlPlugin -> this varies i guess from plugin to plugin 
6.1. By filling out the Query Param controlPluginName at the API Level when executing a payment -> see http://killbill.io/api/#!/accounts/processPayment
6.2 By setting a globalConfig for killbill you activate this payment-control-plugin for all tenants

//Look at Point 5: Global Configuration
org.killbill.payment.invoice.plugin=payment-control-plugin




I added some documentation for each plugin type to explain the activation mechanism (e.g control plugin activation)


 
7. Probably each Plugin needs some TenantBased Configuration, as Killbill consists of a Cluster  full with Nodes, the Nodes need to listen to ConfigurationChange Events invoked by uploading Configurations to the API.

7.1 Global Configurations are stored under

$ vim /etc/killbill/killbill.properties
//Example of one single configuration
com.netstream.ch.killbill.plugins.payment-control-plugin.configFilePath=/var/lib/killbill/bundles/plugins/java/payment-control-plugin/x.y.z/default.conf

//Example of extracting this property in the Plugin
PaymentControlActivator.PROPERTY_PREFIX = "com.netstream.ch.killbill.plugins.payment-control-plugin.";
this.typesafeConfigPath = properties.getProperty(PaymentControlActivator.PROPERTY_PREFIX + "configFilePath");

I added the documentation about plugin configuration and also updated our hello world plugin to reuse the configuration logic from our java framework.
I believe most of that is now either integrated in our hello world plugin or part of the documentation, but your post is also a good source of info people will be able to find when searching the mailing list.



Thanks,

Stéphane

 

Thank you for your help Stéphane. Hope that that this will help someone.
--
You received this message because you are subscribed to the Google Groups "Kill Bill users mailing-list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to killbilling-us...@googlegroups.com.
To post to this group, send email to killbill...@googlegroups.com.
Visit this group at https://groups.google.com/group/killbilling-users.

ggra...@gmail.com

unread,
Apr 26, 2016, 11:10:34 AM4/26/16
to Kill Bill users mailing-list, ggra...@gmail.com
Am Sonntag, 24. April 2016 22:20:27 UTC+2 schrieb stephane brossier:
> Hi there,
>
>
>
> Thanks for taking the time to write some instructions. I decided to write a new documentation about plugin development and i would be interested to hear about your feedback. I also updated some other documentation linked from that main doc, and updated our java hello world plugin.

thank you alot...
Yes, it def does make sense to include some of the dependencies and the tenantConfigHandler part too, as its much more easier to delete then to add that kind of source if you dont know the principals behind. But with your new doc, i guess its def much more easy to get acquainted with the plugin development.
i had to add that to get a assembled jar with all dependencies, without it, i ran into ClassNotFoundExceptions on some of the Google Guava API's and others...
yes, that was my intention to write it, and for you to have a draft and see where users like me have difficulties.
Reply all
Reply to author
Forward
0 new messages