Regarding PlayFab and OAuth.
- Twitch version example is broken. I think I could get it to work by doing some steps manually so will have to experiment with that more later.
- PlayFab doesn’t have Twitter OAuth which I wish it did have.
- Facebook OAuth seems straight forward. However it requires business verification stuff I think which I don’t have setup for Pixcade, I might be wrong, need to test and see.
- Google OAuth also is straight forward. In the case of Google OAuth is it’s annoying to setup custom support e-mail addresses to show, I’m not atm sure how to do that for Pixcade without paying money which is annoying.
I’m not going to mess with OAuth more for now though but maybe after the gamejam I’ll add more of the others, it’s nice that you can add others after. Using e-mail + password will be what I do use along with a guess account system that gives them an incentive to upgrade to a full account.
While doing some research on PlayFab again I looked at AdVenture Capitalist again and am surprised to learn that they did not use PlayFab for saving / syncing user data… this seems like a mistake. But they did get value out of it. PlayFab has some features which can help you improve monetization clearly.
I posted on the Coil receipt validation Github page and also learned some more about it
https://github.com/coilhq/receipt-verifier/pull/19
https://github.com/coilhq/receipt-verifier/issues/20
sabinebertram there mentioned this which should be able to be used to at least test receipt verification I think, but it is not suitable for production. I still want an EZ solution too and I think if that group can make one it will help with adoption.
https://ilp-torrent.sabinebertram.com/verifier-app/
Testing PayPal HTML5 payments via PlayFab is next on my todo list for this. I want to test doing
- Full version unlock IAP
- Disable ads IAP (ads also disable when buying anything else? I’m sure a CloudScript could be setup to do that)
- Refresh energy IAP
- Buy currency IAP
PlayFab has features which can help setup all of these. The full version unlock and disable adds would maybe be adding things to the user’s inventory, refresh energy would be a currency (you can setup currencies which auto regenerate over time, and still allow buying more of it to go above the max), and buying currency would just be like buying gold/gems.
I’ll be testing PlayFab’s coupon system for all of the IAP stuff too.
For Web Monetization until we have reliable receipt verification I think I will do only two things:
- Disable ads (which means buying the IAP is not required)
- Flat %/X bonus to things, so like it could mean earing more XP or more gold as a bonus thanks to having WM enabled
Once receipt verification is in place I will want to test having a currency be granted in accordance (with a multiplier to incentivize it) with the amount of value being paid through WM. So it can be kind of like a pseudo paid subscription with passive trickle value as you play.
PlayFab doesn’t support PayPal sandbox? https://community.playfab.com/questions/5228/having-issues-with-playfab-and-paypal-only-in-the.html
Hit a dead end with implementing PayPal
PlayFab not authorized to perform actions on given PayPal account.
I did setup the permissions but it did not help.
Next, set up the third-party permissions in PayPal so that we can act on your behalf. For live payments, set your account to allow “billing_api1.playfab.com” to process Express Checkout payments.
Here is the very ugly test code so far
function init(self)
local loginRequest = {
-- https://api.playfab.com/Documentation/Client/method/LoginWithCustomID
CustomId = "TestCustomId",
CreateAccount = true
}
PlayFabClientApi.LoginWithCustomID(loginRequest,
function(result)
print("Login Successful: " .. result.PlayFabId)
local account_info_request = {}
print(PlayFabClientApi.GetAccountInfo(account_info_request,
function(result)
pprint(result.AccountInfo)
print("UID:" .. result.AccountInfo.PlayFabId)
local start_purchase_request = {
Items = {
{ItemId = "test-item-one-cent", Quantity = 1, Annotation = "Purchased via in-game store"}
}
}
PlayFabClientApi.StartPurchase(start_purchase_request,
function(result)
pprint(result)
local purchase_request = {
OrderId = result.OrderId,
ProviderName = "PayPal",
Currency = "RM"
}
PlayFabClientApi.PayForPurchase(purchase_request, function(result) pprint(result) end, function(error) pprint(error) end)
end,
function(error) pprint(error) end)
end,
function(error)
pprint(error)
end))
end,
function(error)
print("Login Failed: " .. error.errorMessage)
end)
end
For me this ends in
{ --[[000002CBF87A5800]]
error = "FailedByPaymentProvider",
errorCode = 1015,
code = 400,
status = "BadRequest",
errorDetails = { --[[000002CBF87A5AB0]]
ProviderOrderId = { } --[[000002CBF87A5D80]],
ProviderErrorCode = { --[[000002CBF87A5B00]]
1 = "1"
},
ProviderErrorDetails = { } --[[000002CBF87A5CC0]],
ProviderErrorMessage = { --[[000002CBF87A5BD0]]
1 = "Error: 10002 - Authentication/Authorization Failed"
}
},
errorMessage = "PlayFab not authorized to perform actions on given PayPal account."
}
Maybe someone else can experiment with that, or if they already have it working give notes on what was done differently.
I cannot appear to be able to delete the option for PlayFab no matter where I look to see if redoing it helps
I tried setting the Real Money price to 100 instead of 1 and did not help.
Found where to remove the PlayFab option
https://www.paypal.com/businessmanage/credentials/apiaccess
Manage API Permissions
billing_api1.playfab.com
Although I removed it without checking the permissions it had listed.
Added it again with the 2 express payment options and it didn’t work still. Tried giving it way more permissions and it still is not working. Possibly it’s a delay thing so I’ll try again later after it has time to decide to work or not.
Success! So maybe when I added their id before I forgot to add the right permissions related to express cart. I also tried redoing the addon on PlayFab so that might have helped to refresh it.
DEBUG:SCRIPT:
{
OrderId = "XXXXXXXXXXXXXX",
Status = "Init",
PurchasePrice = 100,
PurchaseCurrency = "RM",
ProviderData = "XXXXXXXXXXXXXX",
PurchaseConfirmationPageURL = "https://www.paypal.com/webscr?cmd=_express-checkout&useraction=commit&token=XXXXXXXXXXXXXX",
VirtualCurrency = { } ,
CreditApplied = 0,
VCAmount = { }
}
https://docs.microsoft.com/en-us/gaming/playfab/features/commerce/economy/non-receipt-payment-processing
I believe this should also work to allow doing IAPs within desktop games. You would open the PurchaseConfirmationPageURL with sys.open_url() wait for user to finish transaction, and then wait on PlayFab to confirm it’s finished. Would need to test to be sure.
Yes! It can be done on desktop games too not just HTML5 I tested the entire flow.
{
PurchaseDate = "2020-10-27T05:37:03.88Z",
Items = {
1 = {
Annotation = "Purchased via in-game store",
DisplayName = "Test Item 0.10 USD",
PurchaseDate = "2020-10-27T05:37:03.88Z",
UnitPrice = 10,
UnitCurrency = "RM",
CatalogVersion = "Tests",
ItemClass = "test",
ItemInstanceId = "XXXXXXXXXXX",
ItemId = "test-item-one-cent"
}
},
OrderId = "XXXXXXXXXXX"
}
Fun fact: PayPal takes everything from micro payments like ones at $0.10 there might be some setup you can go through where they don’t do that though it’s not this one.
I refunded the 10cents after we tested.
Based on these fees it seems like even charging $1 for something is a dumb idea, better to go higher if you have give the value to the player where they feel it’s worth the price.
At the moment I’m confused as to where the PayPal Transaction ID is on the PlayFab side after a purchase is made. Need to test this more to see which IDs line up.
Another thing I need to test is the return link from PayPal / setup the flow for it to be nice.
Current ugly test code
function init(self)
local loginRequest = {
-- https://api.playfab.com/Documentation/Client/method/LoginWithCustomID
CustomId = "TestCustomId",
CreateAccount = true
}
PlayFabClientApi.LoginWithCustomID(loginRequest,
function(result)
print("Login Successful: " .. result.PlayFabId)
local account_info_request = {}
print(PlayFabClientApi.GetAccountInfo(account_info_request,
function(result)
pprint(result.AccountInfo)
print("UID:" .. result.AccountInfo.PlayFabId)
local start_purchase_request = {
Items = {
{ItemId = "test-item-one-cent", Quantity = 1, Annotation = "Purchased via in-game store"}
}
}
PlayFabClientApi.StartPurchase(start_purchase_request,
function(result)
pprint(result)
local purchase_request = {
OrderId = result.OrderId,
ProviderName = "PayPal",
Currency = "RM"
}
PlayFabClientApi.PayForPurchase(purchase_request,
function(result)
pprint(result)
-- repeat checking purchase
sys.open_url(result.PurchaseConfirmationPageURL)
timer.delay(10, true, function(self, handle, time_elapsed)
local confirm_purchase_request = {
OrderId = result.OrderId
}
PlayFabClientApi.ConfirmPurchase(confirm_purchase_request,
function(result)
pprint(result)
if result.PurchaseDate then
print("Purchase went through fully!")
end
end,
function(error)
pprint(error)
end)
end)
end,
function(error) pprint(error) end)
end,
function(error) pprint(error) end)
end,
function(error)
pprint(error)
end))
end,
function(error)
print("Login Failed: " .. error.errorMessage)
end)
end
There are a bunch of transaction states and they will need to be handled properly. I’d guess it may be possible to run different CloudScripts when transaction state changes to decide what to do, like what to do when handling a refund or chargeback if you want to do that automatically.