From 28b67aa366d3ae74239c0a14eb88aee4c3b4ed23 Mon Sep 17 00:00:00 2001 From: iBNu Maksum Date: Wed, 14 Dec 2022 15:42:51 +0700 Subject: [PATCH] Created Payment Gateway Plugin (markdown) --- Payment-Gateway-Plugin.md | 221 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 Payment-Gateway-Plugin.md diff --git a/Payment-Gateway-Plugin.md b/Payment-Gateway-Plugin.md new file mode 100644 index 0000000..3ea5822 --- /dev/null +++ b/Payment-Gateway-Plugin.md @@ -0,0 +1,221 @@ +You can add your own payment gateway + +all plugin put in system/paymentgateway/**paymentGatewayName**.php + +And put the interface in system/paymentgateway/ui/**paymentGatewayName**.tpl + +The filename will be the start of php function +only one PHP inside folder paymentgateway + +Sample code for [xendit](https://github.com/hotspotbilling/phpnuxbill-xendit) + +```php + +assign('_title', 'Xendit - Payment Gateway - ' . $config['CompanyName']); + //other file for supporting payment gateway if needed + $ui->assign('channels', json_decode(file_get_contents('system/paymentgateway/channel_xendit.json'), true)); + // file inside system/paymentgateway/ui/xendit.tpl + $ui->display('xendit.tpl'); +} + +// required, this will executed when admin save configuration +function xendit_save_config() +{ + global $admin, $_L; + $xendit_secret_key = _post('xendit_secret_key'); + $xendit_verification_token = _post('xendit_verification_token'); + $d = ORM::for_table('tbl_appconfig')->where('setting', 'xendit_secret_key')->find_one(); + if ($d) { + $d->value = $xendit_secret_key; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'xendit_secret_key'; + $d->value = $xendit_secret_key; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'xendit_verification_token')->find_one(); + if ($d) { + $d->value = $xendit_verification_token; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'xendit_verification_token'; + $d->value = $xendit_verification_token; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'xendit_channel')->find_one(); + if ($d) { + $d->value = implode(',', $_POST['xendit_channel']); + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'xendit_channel'; + $d->value = implode(',', $_POST['xendit_channel']); + $d->save(); + } + + _log('[' . $admin['username'] . ']: Xendit ' . $_L['Settings_Saved_Successfully'], 'Admin', $admin['id']); + + r2(U . 'paymentgateway/xendit', 's', $_L['Settings_Saved_Successfully']); +} + +// required, this will executed when customer click to buy Plan +function xendit_create_transaction($trx, $user) +{ + global $config; + $json = [ + 'external_id' => $trx['id'], + 'amount' => $trx['price'], + 'description' => $trx['plan_name'], + 'customer' => [ + 'mobile_number' => $user['phonenumber'], + ], + 'customer_notification_preference' => [ + 'invoice_created' => ['whatsapp', 'sms'], + 'invoice_reminder' => ['whatsapp', 'sms'], + 'invoice_paid' => ['whatsapp', 'sms'], + 'invoice_expired' => ['whatsapp', 'sms'] + ], + 'payment_methods ' => explode(',', $config['xendit_channel']), + 'success_redirect_url' => U . 'order/view/' . $trx['id'] . '/check', + 'failure_redirect_url' => U . 'order/view/' . $trx['id'] . '/check' + ]; + + $result = json_decode(Http::postJsonData(xendit_get_server() . 'invoices', $json, ['Authorization: Basic ' . base64_encode($config['xendit_secret_key'] . ':')]), true); + if (!$result['id']) { + r2(U . 'order/package', 'e', Lang::T("Failed to create transaction.")); + } + $d = ORM::for_table('tbl_payment_gateway') + ->where('username', $user['username']) + ->where('status', 1) + ->find_one(); + $d->gateway_trx_id = $result['id']; + $d->pg_url_payment = $result['invoice_url']; + $d->pg_request = json_encode($result); + $d->expired_date = date('Y-m-d H:i:s', strtotime($result['expiry_date'])); + $d->save(); + // you can redirect user directly to payment page + header('Location: ' . $result['invoice_url']); + exit(); + // or redirect to transaction page + r2(U . "order/view/" . $trx['id'], 's', Lang::T("Transaction has been created.")); +} + +// required, this will executed when customer click check payment, or redirect from +function xendit_get_status($trx, $user) +{ + global $config; + /** + Check status of payment when user request it, this can be run on User page or admin page + System will send Transaction result from tbl_paymentgateway and user data + you can save directly payment status success or failed to table + + example depend on payment gateway result + */ + $result = json_decode(Http::getData(xendit_get_server() . 'invoices/' . $trx['gateway_trx_id'], [ + 'Authorization: Basic ' . base64_encode($config['xendit_secret_key'] . ':') + ]), true); + + if ($trx['status'] == 2) { + // Already paid + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Transaction has been paid..")); + }else if ($result['status'] == 'PENDING') { + r2(U . "order/view/" . $trx['id'], 'w', Lang::T("Transaction still unpaid.")); + } else if (in_array($result['status'], ['PAID', 'SETTLED'])) { + // activate plane for user + if (!Package::rechargeUser($user['id'], $trx['routers'], $trx['plan_id'], $trx['gateway'], $result['payment_channel'])) { + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Failed to activate your Package, try again later.")); + } + // save result json to table for audit + $trx->pg_paid_response = json_encode($result); + + $trx->payment_method = $result['payment_method']; + $trx->payment_channel = $result['payment_channel']; + $trx->paid_date = date('Y-m-d H:i:s', strtotime($result['updated'])); + // change status to paid + $trx->status = 2; + $trx->save(); + + r2(U . "order/view/" . $trx['id'], 's', Lang::T("Transaction has been paid.")); + } else if ($result['status'] == 'EXPIRED') { + // save result json to table for audit + $trx->pg_paid_response = json_encode($result); + $trx->status = 3; + $trx->save(); + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Transaction expired.")); + }else{ + sendTelegram("xendit_get_status: unknown result\n\n".json_encode($result, JSON_PRETTY_PRINT)); + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Unknown Command.")); + } +} + + +// This will executed when Payment Gateway send payment notification +// not required, user can manually check payment status, some server inside local network, so payment gateway caanot send notification +// but you can send notification to another server for your processing to telegram or email +function xendit_payment_notification() +{ + global $config; + // Process POST data from payment gateway + $data = json_decode(file_get_contents('php://input')); + $trx = ORM::for_table('tbl_payment_gateway')->where('gateway_trx_id',$data->id)->find_one(); + if(empty($trx)){ + echo "FAILED"; + } + + $result = json_decode(Http::getData(xendit_get_server() . 'invoices/' . $trx['gateway_trx_id'], [ + 'Authorization: Basic ' . base64_encode($config['xendit_secret_key'] . ':') + ]), true); + if (in_array($result['status'], ['PAID', 'SETTLED'])) { + // activate plane for user + if (!Package::rechargeUser($user['id'], $trx['routers'], $trx['plan_id'], $trx['gateway'], $result['payment_channel'])) { + echo "FAILED"; + } + // save result json to table for audit + $trx->pg_paid_response = json_encode($result); + + $trx->payment_method = $result['payment_method']; + $trx->payment_channel = $result['payment_channel']; + $trx->paid_date = date('Y-m-d H:i:s', strtotime($result['updated'])); + // change status to paid + $trx->status = 2; + $trx->save(); + echo "SUCCESS"; + } else if ($result['status'] == 'EXPIRED') { + // save result json to table for audit + $trx->pg_paid_response = json_encode($result); + $trx->status = 3; + $trx->save(); + echo "SUCCESS"; + }else{ + sendTelegram("xendit_get_status: unknown result\n\n".json_encode($result, JSON_PRETTY_PRINT)); + echo "FAILED"; + } +} + +``` \ No newline at end of file