Pierre was able to help me get the HPP working, but now i'm having issues with notifications and storing payment details.
Prior to generating the HPP link, i create an empty payment method:
curl -v \
-u admin:password \
-H "X-Killbill-ApiKey: bob" \
-H "X-Killbill-ApiSecret: lazar" \
-H "Content-Type: application/json" \
-H "X-Killbill-CreatedBy: admin" \
-X POST \
--data-binary '{
"pluginName": "killbill-adyen",
"pluginInfo": {
"properties": []
}
}' \
"http://127.0.0.1:8080/1.0/kb/accounts/5655bc3f-e347-4cd1-8408-5663cc91be37/paymentMethods?isDefault=true"
I generate the HPP link using the following parameters:
country, recurringType (RECURRING), email, serverURL, resultURL, amount, currency
I'm able to successfully get to the HPP, make a payment, and have it authorized and immediately settled with Adyen.
Both the authorization webhook, and the capture hook, are sent to KillBill through our notification proxy. However, ONLY the Authorization event seems to be logged. The capture event is not recorded for some reason, and so the invoice is never marked as paid.
Here are screenshots:
A few payment attempts, all show 0. --- https://db.tt/RWkszpGQ
Payment details, same for all 3 --- https://db.tt/VYtkmTN1
Charge in Adyen --- https://db.tt/8MDovRaa
By the way, the actual invoice total is 7.42, so i'm not sure why it says 742.
Here are the related server log events:
2016-07-09T22:06:35,574+0000 lvl='INFO', log='AdyenNotificationService', th='catalina-exec-9', xff='', rId='0d5d2ae3-79f9-42f0-9e4a-5942a4eeeec5', aRId='', tRId='1', Handling notification: eventCode='AUTHORISATION', pspReference='8514681019943711', originalReference='null', success='true', reason='2324:1111:08/2018', merchantReference='b390c834-9903-4728-b3b6-9bef9213a697'
2016-07-09T22:06:35,598+0000 lvl='INFO', log='DefaultPaymentApi', th='catalina-exec-9', xff='', rId='0d5d2ae3-79f9-42f0-9e4a-5942a4eeeec5', aRId='1', tRId='1', ENTERING PaymentApi: transactionType='AUTHORIZE', accountId='154d2f1f-14d6-4857-92e2-9905c0e473f5', paymentMethodId='8aedb0c3-4a06-42a2-871d-a3c0f7962669', paymentExternalKey='b390c834-9903-4728-b3b6-9bef9213a697', paymentTransactionExternalKey='b390c834-9903-4728-b3b6-9bef9213a697', amount='742', currency='EUR'
2016-07-09T22:06:35,794+0000 lvl='INFO', log='DefaultPaymentApi', th='catalina-exec-9', xff='', rId='0d5d2ae3-79f9-42f0-9e4a-5942a4eeeec5', aRId='1', tRId='1', EXITING PaymentApi: transactionType='AUTHORIZE', accountId='154d2f1f-14d6-4857-92e2-9905c0e473f5', paymentMethodId='8aedb0c3-4a06-42a2-871d-a3c0f7962669', paymentExternalKey='b390c834-9903-4728-b3b6-9bef9213a697', paymentTransactionExternalKey='b390c834-9903-4728-b3b6-9bef9213a697', paymentId='db66f2f4-6b9c-4689-9f53-8f0bbc8a3ee3', transactionId='965edacb-6fc5-4b88-9379-735f8b2b877c', amount='742.00', currency='EUR', transactionStatus='SUCCESS'
2016-07-09T22:10:57,839+0000 lvl='INFO', log='AdyenNotificationService', th='catalina-exec-9', xff='', rId='3ac4629f-7697-4ae8-ba31-25d84ffc0af4', aRId='', tRId='1', Handling notification: eventCode='CAPTURE', pspReference='8814681022186404', originalReference='8514681019943711', success='true', reason='', merchantReference='b390c834-9903-4728-b3b6-9bef9213a697'
2016-07-09T22:10:57,870+0000 lvl='INFO', log='LoggingFilter', th='catalina-exec-9', xff='', rId='3ac4629f-7697-4ae8-ba31-25d84ffc0af4', aRId='1', tRId='1', 391 * Server out-bound response
391 < 200
391 < Content-Type: application/json
391 < Vary: Accept-Encoding
391 < Content-Encoding: gzip
391 <
And finally, and i'm not sure if the Adyen Plugin is supposed to do this, but it's not storing any data locally. It should store some values to make future payments possible. Is this something that our app needs to do using the API?
I really appreciate any help or pointers you can give me.
Thanks,
Kris
--
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/1b24aa15-9491-4bf1-9230-eff49aa9d44b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
1) The capture responses show as 'pending' initially, and then moves to payment failure. In the zip file i included, you'll see the first database output for notification #3 shows the capture received, and additional data is null. I guess at some point later some processing happens, and the next screenshot shows additional data with the output from adyen. At that point, you'll see the payment has failed in Kaui.
Do I need to build something outside of killbill that will go through and initiate a capture request on all HPP payments so Killbill will get the notification? Or can KillBill be configured to see that initial authorization as a successful payment and allow me to use the auto-capture feature within Adyen?
I see the adyen plugin was updated to use the new adyen key type, sha256, however the merchantSig calculation does not seem to be correct. I looked through the commits for the java adyen plugin, and the only thing that jumped out at me is that it appears the plugin is only hashing specific fields. I do know that the new method requires all submitted fields to be included in the signature.
For my project, it's not an issue as I just included the Adyen ruby gem and generate the signature on the fly, but i'm sure others will have issues with it.def adyen_signature(data)data.delete("merchantSig")data.merge!('sharedSecret' => my_hmac_keyAdyen::Signature.sign(data)end
1) HPP + Server notifications are 90% there! They are processed correctly as purchases (using the authMode=false), however the payment amount isn't actually being applied to anything. Whether it's to the outstanding invoices, or as a credit on the account.
2) On a test using a Maestro card with 3d secure, the manual payment (after the token was synced) failed with an error of "configuration 905 Payment details are not supported". This generates the following killbill error: Error while communicating with the Kill Bill server: Error 500: java.sql.SQLDataException: Data too long for column 'gateway_error_code' at row 1
3) I created a new HPP request using a standard visa card, updated the token in the database, and then tried again. I was able to create a manual payment once, but then all subsequent charges failed....Same error as above in killbill, but in the adyen_responses table, I can see this: "{"exceptionMessage":"validation 803 PaymentDetail not found","exceptionClass":"org.apache.cxf.binding.soap.SoapFault","adyenCallErrorStatus":"RESPONSE_ABOUT_INVALID_REQUEST"}"
On Mon, Jul 11, 2016 at 5:49 PM, Kris Watson <kristia...@gmail.com> wrote:I see the adyen plugin was updated to use the new adyen key type, sha256, however the merchantSig calculation does not seem to be correct. I looked through the commits for the java adyen plugin, and the only thing that jumped out at me is that it appears the plugin is only hashing specific fields. I do know that the new method requires all submitted fields to be included in the signature.Sorry about that - when I merged the PR, I hadn't realized that this would change the default behavior. sha1 is still supported (you can configure it by setting the property org.killbill.billing.plugin.adyen.hmac.algorithm=HmacSHA1).Regarding the errors, I've added Andre, who submitted the PR. Could you provide an example of fields you submit? We could add this as a regression test.
For my project, it's not an issue as I just included the Adyen ruby gem and generate the signature on the fly, but i'm sure others will have issues with it.def adyen_signature(data)data.delete("merchantSig")data.merge!('sharedSecret' => my_hmac_keyAdyen::Signature.sign(data)endFWIW, while this works of course, it's kind of a Kill Bill anti-pattern: one of the goals of the platform is to abstract the gateways from the API user (as much as possible). It's especially important when using advanced functionalities like payment routing (you don't always know against which gateway the payment will be submitted).
1) HPP + Server notifications are 90% there! They are processed correctly as purchases (using the authMode=false), however the payment amount isn't actually being applied to anything. Whether it's to the outstanding invoices, or as a credit on the account.I think I know why but could you describe in more details your scenario, the flow (how does your user tokenize the cart, at what point does he subscribe, what kind of invoice is generated, etc.) and the Kill Bill APIs you are using for this?
2) On a test using a Maestro card with 3d secure, the manual payment (after the token was synced) failed with an error of "configuration 905 Payment details are not supported". This generates the following killbill error: Error while communicating with the Kill Bill server: Error 500: java.sql.SQLDataException: Data too long for column 'gateway_error_code' at row 1Interesting - are you running MySQL in strict mode? We probably never saw it because the column was silently truncated in our tests. Should be fixed by https://github.com/killbill/killbill-adyen-plugin/commit/fa88297067b601fca41207958e8a1e73bcc23733.Regarding the error itself, are you completing the 3D-S flow in one go (buildFormDescriptor -> Adyen HPP -> 3D-S redirect -> Kill Bill/website redirect)? When using the PCI APIs, there is an extra step (extra API call) required to "complete" the 3D-S payment, I'm not familiar how it works with HPP though. Are you sure Adyen sees the payment method as validated?Also, you mention a token - does Adyen let you create a recurring contract with a Maestro card? I don't think you can trigger recurring payments with Maestro unless you are part of MARP.
3) I created a new HPP request using a standard visa card, updated the token in the database, and then tried again. I was able to create a manual payment once, but then all subsequent charges failed....Same error as above in killbill, but in the adyen_responses table, I can see this: "{"exceptionMessage":"validation 803 PaymentDetail not found","exceptionClass":"org.apache.cxf.binding.soap.SoapFault","adyenCallErrorStatus":"RESPONSE_ABOUT_INVALID_REQUEST"}"
So, you can re-use the token once, then it fails? That's odd indeed. Could you share the full Kill Bill logs, including the XML requests to/from Adyen (you can mask the headers, and any sensitive information)?
--Pierre
No problem. Here are all the fields that i'm including to get a correct signature: currencyCode, shopperReference, countryCode, skinCode, merchantReference, shopperEmail, shopper.firstName, merchantAccount, shipBeforeDate, paymentAmount, shopperLocale, sessionValidity, resURL, recurringContract, shopper.lastName
All invoices are generated by a subscription. So a user signs up for a subscription, KillBill generates the invoice, the user views that invoice, and then makes their initial payment through the HPP. Adyen will then send the notification back to KillBill (which works). What isn't clear, is what KillBill does with that payment. It appears that it does not know what invoice should get that payment, but then shouldn't a credit be generated? Right now the payment goes nowhere and can't be used for anything...Perhaps i'm missing something in my HPP request that should tell KillBill what invoice to apply the payment to? If that's not possible, i'm fine with it just generating credits. I'm not sure what you see as the best way for KillBill to handle unknown payments.
In Adyen, it showed the recurring contract & payment...so I think that worked. By the way, we're moving from our own home-grown billing / adyen integration to KillBill, and we would use the following API call to make recurring payments...and it seemed to work fine. Although, offhand, i'm not sure if there are any 3ds customers...
Hi Kris,I'm still parsing the logs to figure out why subsequent requests fail, but here are some partial answers in the meantime.
On Tue, Jul 12, 2016 at 1:00 PM, Kris Watson <kristia...@gmail.com> wrote:No problem. Here are all the fields that i'm including to get a correct signature: currencyCode, shopperReference, countryCode, skinCode, merchantReference, shopperEmail, shopper.firstName, merchantAccount, shipBeforeDate, paymentAmount, shopperLocale, sessionValidity, resURL, recurringContract, shopper.lastNameGreat - I've created https://github.com/killbill/killbill-adyen-plugin/issues/51 for tracking.All invoices are generated by a subscription. So a user signs up for a subscription, KillBill generates the invoice, the user views that invoice, and then makes their initial payment through the HPP. Adyen will then send the notification back to KillBill (which works). What isn't clear, is what KillBill does with that payment. It appears that it does not know what invoice should get that payment, but then shouldn't a credit be generated? Right now the payment goes nowhere and can't be used for anything...Perhaps i'm missing something in my HPP request that should tell KillBill what invoice to apply the payment to? If that's not possible, i'm fine with it just generating credits. I'm not sure what you see as the best way for KillBill to handle unknown payments.The typical Kill Bill flow is:
- Create an account
- Add a default payment method (e.g. tokenize the card in the gateway)
- Add a subscription
Step 3 triggers an invoice and a payment on that default payment method (if the invoice has a positive balance, e.g. if there is no trial period).Because Adyen doesn't let you tokenize outside of a payment call, you could emulate step 2 as an AUTH + VOID operation:
- Create an account
- Add the default payment method:
- Trigger the HPP call to create a recurring contract (AUTH mode - typically for $1)
- Sync the payment method
- VOID the payment
- Add a subscription
Would that work in your environment?
If not, I could add a parameter in the Adyen plugin to link the invoice to that payment. But I'm curious about how you would configure Kill Bill in that scenario: are the accounts in AUTO_PAY_OFF? Otherwise, after the invoice is generated, the first payment will fail (until the user makes the initial payment). This has some potential side effects on entitlement (the user has access to the service for free) and overdue.
About credits: they are really driven by the invoice module (e.g. generated when the user downgrades to a cheaper plan and the change is configured as IMMEDIATE in the catalog). You could indeed add manually some credit to reflect the payment, but that seems error prone (the link invoice-payment should really be handled internally by Kill Bill).
In Adyen, it showed the recurring contract & payment...so I think that worked. By the way, we're moving from our own home-grown billing / adyen integration to KillBill, and we would use the following API call to make recurring payments...and it seemed to work fine. Although, offhand, i'm not sure if there are any 3ds customers...Kill Bill does support one-off payments with 3D-S. In a recurring environment, if the payment method always requires 3D-S, this is more difficult though (since you have to make the user follow the redirect each time). This could be solved by sending the user the invoice (and putting the account into MANUAL_PAY) - we can talk in more details about it when you have that use-case.
--Pierre
Yeah, this flow seems totally doable. The thing I'll need to figure out is how to automate the void process. So a user goes through our order flow, creates their payment through the HPP for $1. Now our app will need to i guess poll KB looking for a $1 payment, and void that? Since the notifications are going to KB, our app won't know if that payment from the Adyen should be voided or not.
Yeah, so it was a bit wonky, but we were using set_auto_pay_off() and remove_auto_invoicing_off() in our app, and storing the state of the payment method (i.e. is it ready to use or not). The above scenario seems much better. ;)
On Wed, Jul 13, 2016 at 11:57 AM, Kris Watson <kristia...@gmail.com> wrote:Yeah, this flow seems totally doable. The thing I'll need to figure out is how to automate the void process. So a user goes through our order flow, creates their payment through the HPP for $1. Now our app will need to i guess poll KB looking for a $1 payment, and void that? Since the notifications are going to KB, our app won't know if that payment from the Adyen should be voided or not.Yes, that's the downside of the asynchronous notifications-based model :(You have several options though, in order of complexity:
- Have your app poll Kill Bill. Maybe in the redirect, after the HPP, you could show a spinner to the user ("Validating payment method") while you poll, void and refresh the payment method (should take a couple of seconds at most)
- Have your app listen to Kill Bill webhooks (you can register your endpoint via POST /1.0/kb/tenants/registerNotificationCallback?cb=http://myapp.com/notify). Upon receiving a PAYMENT_SUCCESS event for a payment method validation call, trigger the void from your app
- Create a notifications plugin (in Ruby or Java) to listen to these events, and trigger the void from the plugin
I'm still parsing the logs to figure out why subsequent requests fail, but here are some partial answers in the meantime.Awesome, I appreciate it!
It seems that you have hardcoded the selectedRecurringDetailReference from the initial transaction. However the selectedRecurringDetailReference can change:
So at the moment of transaction 8514685549750694 you tried it with 8414685480379231 which was already closed.
So in Adyen, a recurring contract can have multiple stored payment options, but i noticed in KB only a single payment token is stored per payment method (adyen_payment_methods). So conceivably, it could be as simple as just using 'LATEST' when passing selectedRecurringDetailReference in your plugin instead of the stored reference?
could you tell me if issue with SHA256 encryption is solved? I found a ticket opened here https://github.com/killbill/killbill-adyen-plugin/issues/51but above you say that in adyen-plugin version 0.5.1 this issue is fixed.I'm asking because I face a problem with merchant signature, and it is calculated different in plugin then in Adyen (HMAC calculation page).