Code the EGW API library: add credits; redeem credits; webhook processing Move EGW webhook processing in the slave servers /* "game_id":"", // optional? "game_name":"", // optional? "game_username":"" // optional? game_id game_name used to form response text message, should be looked up from the dbase tables, not supplied by the caller. game_username -------------------------------------------------------------------------------- NOT USED ep_main . ember_games 1 record int 2 game_name varchar(30) -------------------------------------------------------------------------------- ep_main . egw_games 1 record Primary int 2 game_name varchar(30) you would think this would include a game_id -------------------------------------------------------------------------------- questions: 1) In the emberpayRfP api, I am trying to understand why the gaming parameters (game_id, game_distributor_id, game_name, game_username) are optional on the input. It looks to me that they would be absolutely required for this system, but the existing code is written to allow them to be omitted. A: required (as needed?) 2) Where do game_id values originate? who/what generates them? --are game_id values unique to the distributor, (same game from two different distributors would have different game_id's) --or are game_id values unique to the EGW api definitions (directly/indirectly from the game vendors) --or are we generating them as globally unique values? A: game_id values are given to us by the distributor when we onboard them, and their games B: Until I get the complete Spec from EGW, I am not 100% sure. I believe a game_id is the same for all distributors in ep_main.channel_partner_games, what is the difference between partner_id and game_distributor_id? player games? which games or distributors is the player signed up for? */ ================================================================================ Guide to EGW data values ================================================================================ "operator_wallet_id": "1231", "operator_wallet_id" – is the merchants/game operators id in your system. This can be what ever you want it to be. *** use partner_id (channel_partner_id, distributor_id) "player_wallet_id": "123", "player_wallet_id" is the players operators id in your system. This can be whatever you want it to be. *** use subscribers.card_number "operator_game_id": 42, "operator_game_id” is our internal id for each merchants/game operators game platform they have registered. We will provide this to you. *** comes from player game registration process "player_game_user_id": 123 "player_game_user_id" is the players login id for the game platform they selected. The player will provide this to you and you will in turn provide to us. *** comes from player game registration process "operator_id": "0f6d7d8a-7e9a-4d95-9f73-5f7d9b8327a1", identifies distributor/channel partner in egw system "payment_provider_id": "ember", "amount": "10.00", embrpay.net/textalerts_api/process_distributor_redemption_response.php line 62 in the spreadsheet -- duh -------------------------------------------------------------------------------- subscribed_games -- games to which a player is subscribed. record int table record id group_number varchar(10) communities table key -- varchar(10) there subscriber_id int subscribers table key -- local player id phone_number varchar(20) subscribers table key -- local player id -- length changed from 16 to 20 partner_id varchar(20) partner_id of channel partner -- local distributor_id (new column) game_distributor_id varchar(20) egw operator_id - this is passed in through the sigup link/qrcode comes from gaming company originally assuming that egw uses the same code internally and that this is their operator_id (IS THIS A VALID ASSUMPTION) game_id varchar(20) egw operator_game_id game_name varchar(50) egw display_name game_username varchar(20) egw player_game_user_id -- comes from user input game_password varchar(20) password for game account access, comes from user input (possible addition?) created datetime -------------------------------------------------------------------------------- channel_partner_games ​ record int group_number varchar(10) communities table key -- varchar(10) there partner_id varchar(20) game_distributor_id varchar(20) game_id varchar(20) game_name varchar(50) enable_ledger_deposit char(1) enable_ledger_redeem char(1) created datetime -------------------------------------------------------------------------------- Wait for Trice webhooks to determine outcome of RfP (actually, no. respond in sync, or async mode) If RfP is successful rfp webhook status == completed for emberRfp (source == 'E') { If "enable_ledger_deposit" = "Y" for that game Ember uses the EGW API to load game credits Record EGW session_id found in API response Wait for EGW webhook with session_id Message both the Player and Distributor "Payment was made and credits were added" Else, we message the Distributor to add credits manually Message both the Player and Distributor } Else if RfP fails emberRfpFailure - trice sendRFP call returns error emberRfpFailure - trice sendRFP webhooks report failure { Message both the Player and Distributor with failure message } -------------------------------------------------------------------------------- Files changed: redeemEmberpayPlayer.php emberpayRfP.php process_distributor_redemption_response.php redeemEmberpayPlayer --> send sms message --> distributorYesResponse --> rtpSend --> rtpSuccess --> egw->redeem --> egwRedeemSuccess / egwRedeemFailure distributorNoResponse distributorTimeoutResponse 05/18/2026 16:43:12 EDT - 68.132.120.2 - 2161035 - SendRequest: json_response = '{"account_number":"2610568277","business":{"address":{"city":"Tampa","country":"US","line1":"3140 N Armenia Ave","line2":"STE 2","state":"FL","zip":"33607"},"business_dba":"Future 6","business_name":"Future 6 Helping Hand Fund","formation_state":"FL","phone":{"country_code":"1","number":"8135395564"},"tax_id_provided":true,"verification":{}},"business_profile":{"estimated_monthly_volumes_provided":true,"naics":"813410","name":"Future 6","product_description":"distribution of payments","url":"https:\\/\\/www.f6helpinghand.org\\/"},"business_type":"company","capabilities":{"aggregator":"inactive","monit… 21:05:38.930189","email":"info@f6helpinghand.org","hold_details":null,"id":"88007eb2-5dc4-11f0-a3a9-a2cf1d3a5109","individual":null,"ip_address_allow_list":["44.241.134.243","44.195.133.182","44.226.114.221"],"notes":[],"status":"ok","tos_acceptance":null,"updated":"2025-07-22 18:18:56.797052","verified_for":[{"bank_id":"gnb","bank_name":"Great North Bank","verified":"2025-07-22 18:18:56"}]}' 05/18/2026 16:43:10 EDT - 68.132.120.2 - 2161035 - TriceApi ( array ( 'groupId' => '2', 'selectorId' => '22', 'merchantId' => '', 'gateway_code' => '15', 'gateway_name' => 'trice', 'gateway_mode' => 'live', 'gateway_services' => 'rtp', 'record_id' => '34', 'country_code' => 'US', 'currency_code' => 'USD', 'account_id' => '14cc2d6c-007e-11f1-a666-875524d58a6f', 'client_id' => '88fa3f88-5dc4-11f0-aeba-df3ceec389bf', 'client_secret' => 'f7t33E6E8wDJztcf', 'access_token' => 'eyJraWQiOiJhMmNiNzUxZi00MjdiLTQ4MmQtYTg0MS1jMjVkYTg5OWViMDciLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJjbGllbnQ6ODhmYTNmODgtNWRjNC0xMWYwLWFlYmEtZGYzY2VlYzM4OWJmIiwiYXVkIjoiaHR0cHM6Ly9hcGkudHJpY2UuY28iLCJhY2NvdW50SWQiOiI4ODAwN2ViMi01ZGM0LTExZjAtYTNhOS1hMmNmMWQzYTUxMDkiLCJuYmYiOjE3NzEwMTY2ODQsInNjb3BlIjpbInJ0cC5yZnBfc2VuZGVyIiwicnRwLnNlbmRlciJdLCJpc3MiOiJodHRwczovL2FwaS50cmljZS5jby9hdXRoL3YxIiwiZXhwIjoxNzcxMDQ1NDg0LCJpYXQiOjE3NzEwMTY2ODQsImp0aSI6IjE3YTE4ZGUyLWZmOWMtNGQ1ZS04MzY1LTg0NmY4YjA2YWVmYiJ9.rFihi5BVEK8QtDA_5gyeo0o4kNeyOB5oviG2hJjPKTu7u9bC0y8UQid5biS9IKgh3FdkoQr-kOxqctTcrCg3sWZ4gBlChzZ9jsnMEDNdwkdtFjh346ncwBf8Do0cHYn2VTfdLNd0UmHxh-O5ee383qz_kaRzQACUDWXDDMfjyZ6IZCjPpSHpiuvxK1ObAoqoa71c-IqE-Tdf3PLJWFRlH1DhpZ10G-AAoMfUybUld8Ageu1oQ2D19hR5E9adKfZuR80zMRqnn0I-JRX-vWVzhWqW8M9CBMubzUeGjjbPvPJXIdpAQVN-ITtAU1zrCy2lNtecLfO0meL3NGqBHrL5-Q', 'token_type' => 'Bearer', 'expires_at' => '1771045483', 'value_1' => '', 'value_2' => '', 'value_3' => '', 'value_4' => '', 'value_5' => '', ) ) createOperator 05/19/2026 15:54:00 EDT - 74.110.227.200 - post response decoded = array ( 'operator_id' => '29de67f1-f666-4aba-ad9f-6b4c13f754a2', 'username' => 'operator_test_01', ) Step 1: You send a Operator registration request and we create an Operator. Step 2: We send a email to Operator to login and setup an operator games. Each game got a game_id. Please use predefined Operator id: 73b83a81-0293-45ae-99ba-bdd7f3555aa4 we already setup all games for it. 05/20/2026 09:47:54 EDT - 74.110.227.200 - get response decoded = array ( 0 => array ( 'game_id' => 'c054e606-8778-49d7-b519-edfccb899b25', 'name' => 'Dragon City', 'game_pos_url_box' => 'https://pos.goldendragon.city/login/9521499', 'status' => 'active', ), 1 => array ( 'game_id' => '2f4776d5-a091-4058-a13f-42e715f00ca8', 'name' => 'Fortune 2 go', 'game_pos_url_box' => 'https://pos2.fortune2go20.com/pos/index-fortune2go.html?k=undefined', 'status' => 'active', ), 2 => array ( 'game_id' => '92d9a074-3a27-463a-9255-b8ba671df802', 'name' => 'Golden Dragon', 'game_pos_url_box' => 'https://pos.goldendragoncity.com/pos/2636393', 'status' => 'active', ), 3 => array ( 'game_id' => '822b6efa-1e8c-466f-a8a8-a850512784cb', 'name' => 'Magic City', 'game_pos_url_box' => 'https://pos.magiccity777.com/pos/login', 'status' => 'active', ), 4 => array ( 'game_id' => 'e3d253f9-903d-4f1b-aeb4-5063697eff51', 'name' => 'River Sweeps', 'game_pos_url_box' => 'https://river-pay.com/office/login', 'status' => 'active', ), 5 => array ( 'game_id' => '184aee6c-deca-4de1-bcee-fdc8af792cc1', 'name' => 'Ultra Panda', 'game_pos_url_box' => 'https://ht.ultrapanda.mobi/', 'status' => 'active', ), ) payment_tracking_2 -- copy structure only payment_rules_2 -- copied structure and data payment_fraud_events_2 -- copy structure only // E-817a7ccfeb9741e9aaeaabd5a178d275 // 1) transaction data is stored after success/failure intiation of rtp/rfp transaction. // in case of success, stores initial success. webhooks use reference_number to find transaction and update status // 2) when the rfp request is declined via the bank app, no transactions occur, so no transaction table entries are inserted // 3) last successful transactions were run 05/22/2026 ================================================================================================================================================================ from may 20 message to dan They (egw) is telling me that we have to create a new operator (distributor) by calling the egw api. were you aware of that? I was under the impression that we would not need to call any "create" type api, that all the id's were pre-created and supplied externally through links or qr codes. So, apparently the call to egw CreateOperator has to be done during your onboarding process. Do you want to point me to where this is, or should I give you the code that needs to be inserted there? is there a document that describes the sequence of events necessary to onboard a new distributor, or generally the CRUD of distributors? same for game id's? I am getting conflicting information. ----------------- to bhup on june 1 Hello, do you have any sort of specification or written description of how a customer (player or distributor) enters this system? I have not seen a detailed description, so I am trying to determine exactly what information is passed to us initially (first contact). Does it come through the app you are building, or through a QR code, a link or what? Is it from a distributor or player or both? Anything would be helpful. ----------------- asked Melissa Hi Tom, we don't have a Testflight for EmberPay because we're not submitting apps to the app stores but I do have a wireframe. I'll send it to you now (stored in egwapi folder) ---------------- You might also want to check out pwa.emberpay.net/gaming It's probably more up to date than even the wireframe is because we added some fields to both the Registration form as well as the Payment Information form https://pwa.emberpay.net/gaming?folder=gaming&r=GAM-AF1-2 You can use that link to register Thanks! ------------------ Currently we offer 6 game platforms (Golden Dragon Mobi, Golden Dragon City, Magic City, Fortune 2 Go, River Sweeps and Ultra Panda) that operators can use. When we onboard a processor like Ember, Ember tells us which platforms they want to offer their customers. [tk notes: Ember selects from list, creating a list of available games for this *application*. This is distinct from distributor/operator games (channel_partner_games) or player games (subscribed_games). The list is accessed via egwapi->getAvailableGames(), Get all games assigned to the authenticated processor (Ember)] We then set this up in our backend. At this point, Ember will follow the steps int he EGW API documentation (v4 sent earlier) to onboard the operators. Step 1 Get Available Games for Authenticated Processor, is where you pull the latest list of games you want to offer. We do this so if you add/delete a game platform you want to offer all your operators will be updated. Step 1 -- Get Available Games get response decoded = array ( 0 => array ( 'game_id' => 'c054e606-8778-49d7-b519-edfccb899b25', 'name' => 'Dragon City', 'game_pos_url_box' => 'https://pos.goldendragon.city/login/9521499', 'status' => 'active', ), ... Step 2 -- Create Operator Account createOperator { string $username "username": "Assigned by Processor", string $email "email": "operator_demo_02@example.com", string $business_name "business_name": "Example Operator", string $contact_first_name "contact_first_name": "John", string $contact_last_name "contact_last_name": "Doe", string $address "address": "221B Baker Street, London", string $contact_phone "contact_phone": "9195551212", string $operator_site_url "operator_site_url": "https://operator.example.com" } response: 201 The HTTP 201 Created status code is a success response indicating that a client's request was successfully fulfilled and resulted in the creation of one or more new resources on the server. { "operator_id": "0f6d7d8a-7e9a-4d95-9f73-5f7d9b8327a1", "username": "operator_demo_02" } As I suspected, we do need to create the operators via the egwapi. The following is a brief summary of the first part of the process. ** denotes action points Step 1 When Ember sets up with EGW, you have an assigned list of games which is available through the egwapi via getAvailableGames. Step 2 Ember then onboards a new distributor/operator by creating a new operator via the egwapi createOperator. The arguments for that operation are: string $username "username": "Assigned by Processor", string $email "email": "operator_demo_02@example.com", string $business_name "business_name": "Example Operator", string $contact_first_name "contact_first_name": "John", string $contact_last_name "contact_last_name": "Doe", string $address "address": "221B Baker Street, London", string $contact_phone "contact_phone": "9195551212", string $operator_site_url "operator_site_url": "https://operator.example.com" This data must be collected from the distributor during the onboarding process. I am inquiring with egw about duplicate detection for username, email, phone, etc. now. ** Will we need to supply CRUD for distributors? (ui and api interfaces to update and delete existing distributors) Step 3 Add games to distributor. Use Ember available games list to add new games to distributor created above. Assuming automatic addition of all available games. (allow choice? charge per game?) ** Do we need to have CRUD for distributor games as well? If fixed list, then no. ** What if available games list for Ember changes? Update all distributors? Players? Notifications? operator_wallet_id` (string, required) payment provider wallet id - id provided by payment provider (Payment Processor) numbenclature: operator == payment provider == distributor from operator: create operator username - from distrib - how distributor logs into GD email, etc site_url = what is this? where does it come from? createOperatorGame username password kiosk from operator drawer from operator (1-5) station always blank order always zero publish_site ==> comes from available games list, status = active player_game_user_id is "mobile id" createOperator username = partner_id AVAILABLE games ==> ep_main.egw_games add these from getavailablegames 'game_id' => '184aee6c-deca-4de1-bcee-fdc8af792cc1', 'name' => 'Ultra Panda', 'game_pos_url_box' => 'https://ht.ultrapanda.mobi/', 'status' => 'active', --------------------------------------------------------- add fields to ep_main.channel_partner_games username password kiosk from operator drawer from operator (1-5) (all from distributor onboarding new section) createOperatorGames --------------------------------------------------------- edit_channel_partner.php onboard_channel_partner.php The output of this is the partner_id if (emberPay) { $payload = [ 'username' => $row['partner_id'], // Assigned by Processor 'email' => $row['contactEmail'], // operator_demo_02@example.com", 'business_name' => $row['legalName'], // Example Operator 'contact_first_name' => $row['contactFirstName'], // "John" 'contact_last_name' => $row['contactLastName'], // "Doe" 'address' => $row['address1'].($row['address2'])?(', '.$row['address2']):''; // "221B Baker Street, London" 'contact_phone' => $row['contactPhone'], // "9195551212" 'operator_site_url' => $row['operator_site_url']; // "https://operator.example.com" ]; createOperator( $payload ); input is username --> partner_id output is operator_id } ================================================== I will fix it in the database, manually for transactions that occurred after 4/14 ================================================== each distributor / channel_partner / operator game has these fields FROM EGWAPI getActiveGames(): "game_id": "6d882f16-477f-42d5-86a9-1780b851b589", "name": "Golden Dragon Mobi", "game_pos_url_box": "https://pos.goldendragoncity.com/pos/kiosk#", "status": "active" from table ep_main . channel_partner_games 1 record Primary int 2 group_number Index varchar(10) 3 partner_id Index varchar(20) 4 game_distributor_id varchar(40) // game_operator_id 5 game_id varchar(20) 6 game_name varchar(50) NEW game_pos_url_box varchar(200) NEW game_status varchar(8) 7 enable_ledger_deposit char(1) 8 enable_ledger_redeem char(1) 9 created datetime ALTER TABLE `channel_partner_games` ADD `game_pos_url_box` VARCHAR(200) NOT NULL AFTER `game_name`, ADD `game_status` VARCHAR(8) NOT NULL AFTER `game_pos_url_box`; "operator_site_url": "https://operator.example.com" -- supplied by distributor during onboarding, used in egwapi::createOperator channel_partners_* operator_site_url ALTER TABLE `channel_partners_1` ADD `operator_site_url` VARCHAR(200) NOT NULL AFTER `enable_game_list`; ALTER TABLE `channel_partners_2` ADD `operator_site_url` VARCHAR(200) NOT NULL AFTER `enable_game_list`; { "game_id": "73b83a81-0293-45ae-99ba-bdd7f3555aa4", "display_name": "Golden Dragon", "pos_username": "cashier", "pos_password": "password", "publish_site": true, "drawer": "1", "kiosk_number": " 9628449", "station_number": , "order": 0, "pos_category": "dragon" } list of available games list = getAvailableGames() foreach( $gameList as $game ) { // do not list games already in cp games if (has_game($game->id)) continue; show option $game->id $game->name } [select game to add] [Add Game] games list game_name game_id oprator_game_id status url [enable/disable] [remove] -------------------------------------------------------------------------------- Hello all, I am at the point where I need the operator management api endpoints we discussed last week. Simply put, I cannot create the operators if I cannot manage what is in the system. Here are my suggestions: 1) getOperators() -- returns array of operator information for all operators created by the authenticated processor. defaults to active operators only, but should have option for listing all or disabled as well. Pagination will become a necessity here quickly. 2) getOperator() -- returns a single operator by username, email or phone, according the the argument array provided. Important: are we normalizing phone numbers or accepting them freeform? Ember uses the ISO standard format. 3) updateOperator() -- updates a single operator by username, email or phone, according the the argument array provided. each uses this common data structure @param string $operator_id @param string $username @param string $email @param string $business_name @param string $contact_first_name @param string $contact_last_name @param string $address @param string $contact_phone @param string $operator_site_url -------------------------------------------------------------------------------- I am stalled working on the partners/egw interface (creating operators and games). egw has not provided the tools to get the job done, and they keep either refusing to create the interfaces I need or putting it off until 'next week.' We know that means 'next month'. I will keep working on the ui, and use this as a test case for when the api is unreachable or malfunctions. --------------------------------------------------------------------------------