migrate to gtea from bistbucket

This commit is contained in:
2026-03-15 17:08:23 +07:00
commit 129ca2260c
3716 changed files with 566316 additions and 0 deletions

View File

@@ -0,0 +1,632 @@
<?php
// payment methods
const PAYMENT_METHODS = [
['key' => 'ssl_commerz', 'value' => 'SSLCOMMERZ'],
['key' => 'stripe', 'value' => 'Stripe'],
['key' => 'paypal', 'value' => 'PayPal'],
['key' => 'razor_pay', 'value' => 'Razor Pay'],
['key' => 'paystack', 'value' => 'Paystack'],
['key' => 'senang_pay', 'value' => 'Senang Pay'],
['key' => 'paymob_accept', 'value' => 'Paymob Accept'],
['key' => 'flutterwave', 'value' => 'Flutter Wave'],
['key' => 'paytm', 'value' => 'Paytm'],
['key' => 'paytabs', 'value' => 'Pay Tabs'],
['key' => 'liqpay', 'value' => 'Liq Pay'],
['key' => 'mercadopago', 'value' => 'Mercadopago'],
['key' => 'bkash', 'value' => 'Bkash'],
['key' => 'fatoorah', 'value' => 'Fatoorah'],
['key' => 'xendit', 'value' => 'Xendit'],
['key' => 'amazon_pay', 'value' => 'Amazon Pay'],
['key' => 'iyzi_pay', 'value' => 'Iyzi Pay'],
['key' => 'hyper_pay', 'value' => 'Hyper Pay'],
['key' => 'foloosi', 'value' => 'Foloosi'],
['key' => 'ccavenue', 'value' => 'CC Avenue'],
['key' => 'pvit', 'value' => 'Pvit'],
['key' => 'moncash', 'value' => 'Moncash'],
['key' => 'thawani', 'value' => 'Thawani'],
['key' => 'tap', 'value' => 'Tap Payment'],
['key' => 'viva_wallet', 'value' => 'Viva Wallet'],
['key' => 'hubtel', 'value' => 'Hubtel'],
['key' => 'maxicash', 'value' => 'Maxicash'],
['key' => 'esewa', 'value' => 'Esewa'],
['key' => 'swish', 'value' => 'Swish'],
['key' => 'momo', 'value' => 'Momo'],
['key' => 'payfast', 'value' => 'Pay Fast'],
['key' => 'worldpay', 'value' => 'World Pay'],
['key' => 'sixcash', 'value' => 'Six Cash'],
];
// currencies
const CURRENCIES = [
['code' => 'AED', 'symbol' => 'د.إ', 'name' => 'UAE dirham'],
['code' => 'AFN', 'symbol' => 'Afs', 'name' => 'Afghan afghani'],
['code' => 'ALL', 'symbol' => 'L', 'name' => 'Albanian lek'],
['code' => 'AMD', 'symbol' => 'AMD', 'name' => 'Armenian dram'],
['code' => 'ANG', 'symbol' => 'NAƒ', 'name' => 'Netherlands Antillean gulden'],
['code' => 'AOA', 'symbol' => 'Kz', 'name' => 'Angolan kwanza'],
['code' => 'ARS', 'symbol' => '$', 'name' => 'Argentine peso'],
['code' => 'AUD', 'symbol' => '$', 'name' => 'Australian dollar'],
['code' => 'AWG', 'symbol' => 'ƒ', 'name' => 'Aruban florin'],
['code' => 'AZN', 'symbol' => 'AZN', 'name' => 'Azerbaijani manat'],
['code' => 'BAM', 'symbol' => 'KM', 'name' => 'Bosnia and Herzegovina konvertibilna marka'],
['code' => 'BBD', 'symbol' => 'Bds$', 'name' => 'Barbadian dollar'],
['code' => 'BDT', 'symbol' => '৳', 'name' => 'Bangladeshi taka'],
['code' => 'BGN', 'symbol' => 'BGN', 'name' => 'Bulgarian lev'],
['code' => 'BHD', 'symbol' => '.د.ب', 'name' => 'Bahraini dinar'],
['code' => 'BIF', 'symbol' => 'FBu', 'name' => 'Burundi franc'],
['code' => 'BMD', 'symbol' => 'BD$', 'name' => 'Bermudian dollar'],
['code' => 'BND', 'symbol' => 'B$', 'name' => 'Brunei dollar'],
['code' => 'BOB', 'symbol' => 'Bs.', 'name' => 'Bolivian boliviano'],
['code' => 'BRL', 'symbol' => 'R$', 'name' => 'Brazilian real'],
['code' => 'BSD', 'symbol' => 'B$', 'name' => 'Bahamian dollar'],
['code' => 'BTN', 'symbol' => 'Nu.', 'name' => 'Bhutanese ngultrum'],
['code' => 'BWP', 'symbol' => 'P', 'name' => 'Botswana pula'],
['code' => 'BYR', 'symbol' => 'Br', 'name' => 'Belarusian ruble'],
['code' => 'BZD', 'symbol' => 'BZ$', 'name' => 'Belize dollar'],
['code' => 'CAD', 'symbol' => '$CA', 'name' => 'Canadian dollar'],
['code' => 'CDF', 'symbol' => 'F', 'name' => 'Congolese franc'],
['code' => 'CHF', 'symbol' => 'Fr.', 'name' => 'Swiss franc'],
['code' => 'CLP', 'symbol' => '$', 'name' => 'Chilean peso'],
['code' => 'CNY', 'symbol' => '¥', 'name' => 'Chinese/Yuan renminbi'],
['code' => 'COP', 'symbol' => 'Col$', 'name' => 'Colombian peso'],
['code' => 'CRC', 'symbol' => '₡', 'name' => 'Costa Rican colon'],
['code' => 'CUC', 'symbol' => '$', 'name' => 'Cuban peso'],
['code' => 'CVE', 'symbol' => 'Esc', 'name' => 'Cape Verdean escudo'],
['code' => 'CZK', 'symbol' => 'Kč', 'name' => 'Czech koruna'],
['code' => 'DJF', 'symbol' => 'Fdj', 'name' => 'Djiboutian franc'],
['code' => 'DKK', 'symbol' => 'Kr', 'name' => 'Danish krone'],
['code' => 'DOP', 'symbol' => 'RD$', 'name' => 'Dominican peso'],
['code' => 'DZD', 'symbol' => 'دج', 'name' => 'Algerian dinar'],
['code' => 'EEK', 'symbol' => 'KR', 'name' => 'Estonian kroon'],
['code' => 'EGP', 'symbol' => 'e£', 'name' => 'Egyptian pound'],
['code' => 'ERN', 'symbol' => 'Nfa', 'name' => 'Eritrean nakfa'],
['code' => 'ETB', 'symbol' => 'Br', 'name' => 'Ethiopian birr'],
['code' => 'EUR', 'symbol' => '€', 'name' => 'European Euro'],
['code' => 'FJD', 'symbol' => 'FJ$', 'name' => 'Fijian dollar'],
['code' => 'FKP', 'symbol' => '£', 'name' => 'Falkland Islands pound'],
['code' => 'GBP', 'symbol' => '£', 'name' => 'British pound'],
['code' => 'GEL', 'symbol' => 'GEL', 'name' => 'Georgian lari'],
['code' => 'GHS', 'symbol' => 'GH¢', 'name' => 'Ghanaian cedi'],
['code' => 'GIP', 'symbol' => '£', 'name' => 'Gibraltar pound'],
['code' => 'GMD', 'symbol' => 'D', 'name' => 'Gambian dalasi'],
['code' => 'GNF', 'symbol' => 'FG', 'name' => 'Guinean franc'],
['code' => 'GQE', 'symbol' => 'F', 'name' => 'Equatorial Guinean XXXXX'],
['code' => 'GTQ', 'symbol' => 'Q', 'name' => 'Guatemalan quetzal'],
['code' => 'GYD', 'symbol' => 'GY$', 'name' => 'Guyanese dollar'],
['code' => 'HKD', 'symbol' => 'HK$', 'name' => 'Hong Kong dollar'],
['code' => 'HNL', 'symbol' => 'L', 'name' => 'Honduran lempira'],
['code' => 'HRK', 'symbol' => 'kn', 'name' => 'Croatian kuna'],
['code' => 'HTG', 'symbol' => 'G', 'name' => 'Haitian gourde'],
['code' => 'HUF', 'symbol' => 'Ft', 'name' => 'Hungarian forint'],
['code' => 'IDR', 'symbol' => 'Rp', 'name' => 'Indonesian rupiah'],
['code' => 'ILS', 'symbol' => '₪', 'name' => 'Israeli new sheqel'],
['code' => 'INR', 'symbol' => '₹', 'name' => 'Indian rupee'],
['code' => 'IQD', 'symbol' => 'ع.د', 'name' => 'Iraqi dinar'],
['code' => 'IRR', 'symbol' => 'IRR', 'name' => 'Iranian rial'],
['code' => 'ISK', 'symbol' => 'kr', 'name' => "Icelandic kr\u00f3na"],
['code' => 'JMD', 'symbol' => 'J$', 'name' => 'Jamaican dollar'],
['code' => 'JOD', 'symbol' => 'JOD', 'name' => 'Jordanian dinar'],
['code' => 'JPY', 'symbol' => '¥', 'name' => 'Japanese yen'],
['code' => 'KES', 'symbol' => 'KSh', 'name' => 'Kenyan shilling'],
['code' => 'KGS', 'symbol' => 'Лв', 'name' => 'Kyrgyzstani som'],
['code' => 'KHR', 'symbol' => '៛', 'name' => 'Cambodian riel'],
['code' => 'KMF', 'symbol' => 'KMF', 'name' => 'Comorian franc'],
['code' => 'KPW', 'symbol' => 'W', 'name' => 'North Korean won'],
['code' => 'KRW', 'symbol' => 'W', 'name' => 'South Korean won'],
['code' => 'KWD', 'symbol' => 'KWD', 'name' => 'Kuwaiti dinar'],
['code' => 'KYD', 'symbol' => 'KY$', 'name' => 'Cayman Islands dollar'],
['code' => 'KZT', 'symbol' => 'T', 'name' => 'Kazakhstani tenge'],
['code' => 'LAK', 'symbol' => 'KN', 'name' => 'Lao kip'],
['code' => 'LBP', 'symbol' => '.ل.ل', 'name' => 'Lebanese lira'],
['code' => 'LKR', 'symbol' => 'Rs', 'name' => 'Sri Lankan rupee'],
['code' => 'LRD', 'symbol' => 'L$', 'name' => 'Liberian dollar'],
['code' => 'LSL', 'symbol' => 'M', 'name' => 'Lesotho loti'],
['code' => 'LTL', 'symbol' => 'Lt', 'name' => 'Lithuanian litas'],
['code' => 'LVL', 'symbol' => 'Ls', 'name' => 'Latvian lats'],
['code' => 'LYD', 'symbol' => 'LD', 'name' => 'Libyan dinar'],
['code' => 'MAD', 'symbol' => 'MAD', 'name' => 'Morocodean dirham'],
['code' => 'MDL', 'symbol' => 'MDL', 'name' => 'Moldovan leu'],
['code' => 'MGA', 'symbol' => 'FMG', 'name' => 'Malagasy ariary'],
['code' => 'MKD', 'symbol' => 'MKD', 'name' => 'Macedonian denar'],
['code' => 'MMK', 'symbol' => 'K', 'name' => 'Myanma kyat'],
['code' => 'MNT', 'symbol' => '₮', 'name' => 'Mongolian tugrik'],
['code' => 'MOP', 'symbol' => 'P', 'name' => 'Macanese pataca'],
['code' => 'MRO', 'symbol' => 'UM', 'name' => 'Mauritanian ouguiya'],
['code' => 'MUR', 'symbol' => 'Rs', 'name' => 'Mauritian rupee'],
['code' => 'MVR', 'symbol' => 'Rf', 'name' => 'Maldivian rufiyaa'],
['code' => 'MWK', 'symbol' => 'MK', 'name' => 'Malawian kwacha'],
['code' => 'MXN', 'symbol' => '$', 'name' => 'Mexican peso'],
['code' => 'MYR', 'symbol' => 'RM', 'name' => 'Malaysian ringgit'],
['code' => 'MZM', 'symbol' => 'MTn', 'name' => 'Mozambican metical'],
['code' => 'NAD', 'symbol' => 'N$', 'name' => 'Namibian dollar'],
['code' => 'NGN', 'symbol' => '₦', 'name' => 'Nigerian naira'],
['code' => 'NIO', 'symbol' => 'C$', 'name' => "Nicaraguan c\u00f3rdoba"],
['code' => 'NOK', 'symbol' => 'kr', 'name' => 'Norwegian krone'],
['code' => 'NPR', 'symbol' => 'NRs', 'name' => 'Nepalese rupee'],
['code' => 'NZD', 'symbol' => 'NZ$', 'name' => 'New Zealand dollar'],
['code' => 'OMR', 'symbol' => 'OMR', 'name' => 'Omani rial'],
['code' => 'PAB', 'symbol' => 'B/.', 'name' => 'Panamanian balboa'],
['code' => 'PEN', 'symbol' => 'S/.', 'name' => 'Peruvian nuevo sol'],
['code' => 'PGK', 'symbol' => 'K', 'name' => 'Papua New Guinean kina'],
['code' => 'PHP', 'symbol' => '₱', 'name' => 'Philippine peso'],
['code' => 'PKR', 'symbol' => 'Rs.', 'name' => 'Pakistani rupee'],
['code' => 'PLN', 'symbol' => 'zł', 'name' => 'Polish zloty'],
['code' => 'PYG', 'symbol' => '₲', 'name' => 'Paraguayan guarani'],
['code' => 'QAR', 'symbol' => 'QR', 'name' => 'Qatari riyal'],
['code' => 'RON', 'symbol' => 'L', 'name' => 'Romanian leu'],
['code' => 'RSD', 'symbol' => 'din.', 'name' => 'Serbian dinar'],
['code' => 'RUB', 'symbol' => 'R', 'name' => 'Russian ruble'],
['code' => 'SAR', 'symbol' => 'SR', 'name' => 'Saudi riyal'],
['code' => 'SBD', 'symbol' => 'SI$', 'name' => 'Solomon Islands dollar'],
['code' => 'SCR', 'symbol' => 'SR', 'name' => 'Seychellois rupee'],
['code' => 'SDG', 'symbol' => 'SDG', 'name' => 'Sudanese pound'],
['code' => 'SEK', 'symbol' => 'kr', 'name' => 'Swedish krona'],
['code' => 'SGD', 'symbol' => 'S$', 'name' => 'Singapore dollar'],
['code' => 'SHP', 'symbol' => '£', 'name' => 'Saint Helena pound'],
['code' => 'SLL', 'symbol' => 'Le', 'name' => 'Sierra Leonean leone'],
['code' => 'SOS', 'symbol' => 'Sh.', 'name' => 'Somali shilling'],
['code' => 'SRD', 'symbol' => '$', 'name' => 'Surinamese dollar'],
['code' => 'SYP', 'symbol' => 'LS', 'name' => 'Syrian pound'],
['code' => 'SZL', 'symbol' => 'E', 'name' => 'Swazi lilangeni'],
['code' => 'THB', 'symbol' => '฿', 'name' => 'Thai baht'],
['code' => 'TJS', 'symbol' => 'TJS', 'name' => 'Tajikistani somoni'],
['code' => 'TMT', 'symbol' => 'm', 'name' => 'Turkmen manat'],
['code' => 'TND', 'symbol' => 'DT', 'name' => 'Tunisian dinar'],
['code' => 'TRY', 'symbol' => 'TRY', 'name' => 'Turkish new lira'],
['code' => 'TTD', 'symbol' => 'TT$', 'name' => 'Trinidad and Tobago dollar'],
['code' => 'TWD', 'symbol' => 'NT$', 'name' => 'New Taiwan dollar'],
['code' => 'TZS', 'symbol' => 'TZS', 'name' => 'Tanzanian shilling'],
['code' => 'UAH', 'symbol' => 'UAH', 'name' => 'Ukrainian hryvnia'],
['code' => 'UGX', 'symbol' => 'USh', 'name' => 'Ugandan shilling'],
['code' => 'USD', 'symbol' => '$', 'name' => 'United States dollar'],
['code' => 'UYU', 'symbol' => '$U', 'name' => 'Uruguayan peso'],
['code' => 'UZS', 'symbol' => 'UZS', 'name' => 'Uzbekistani som'],
['code' => 'VEB', 'symbol' => 'Bs', 'name' => 'Venezuelan bolivar'],
['code' => 'VND', 'symbol' => '₫', 'name' => 'Vietnamese dong'],
['code' => 'VUV', 'symbol' => 'VT', 'name' => 'Vanuatu vatu'],
['code' => 'WST', 'symbol' => 'WS$', 'name' => 'Samoan tala'],
['code' => 'XAF', 'symbol' => 'F', 'name' => 'Central African CFA franc'],
['code' => 'XCD', 'symbol' => 'EC$', 'name' => 'East Caribbean dollar'],
['code' => 'XDR', 'symbol' => 'SDR', 'name' => 'Special Drawing Rights'],
['code' => 'XOF', 'symbol' => 'F.', 'name' => 'West African CFA franc'],
['code' => 'XPF', 'symbol' => 'F', 'name' => 'CFP franc'],
['code' => 'YER', 'symbol' => 'YER', 'name' => 'Yemeni rial'],
['code' => 'ZAR', 'symbol' => 'R', 'name' => 'South African rand'],
['code' => 'ZMK', 'symbol' => 'ZK', 'name' => 'Zambian kwacha'],
['code' => 'ZWR', 'symbol' => 'Z$', 'name' => 'Zimbabwean dollar'],
];
// countries
const COUNTRIES = [
['name' => 'Afghanistan', 'code' => 'AF'],
['name' => 'Åland Islands', 'code' => 'AX'],
['name' => 'Albania', 'code' => 'AL'],
['name' => 'Algeria', 'code' => 'DZ'],
['name' => 'American Samoa', 'code' => 'AS'],
['name' => 'AndorrA', 'code' => 'AD'],
['name' => 'Angola', 'code' => 'AO'],
['name' => 'Anguilla', 'code' => 'AI'],
['name' => 'Antarctica', 'code' => 'AQ'],
['name' => 'Antigua and Barbuda', 'code' => 'AG'],
['name' => 'Argentina', 'code' => 'AR'],
['name' => 'Armenia', 'code' => 'AM'],
['name' => 'Aruba', 'code' => 'AW'],
['name' => 'Australia', 'code' => 'AU'],
['name' => 'Austria', 'code' => 'AT'],
['name' => 'Azerbaijan', 'code' => 'AZ'],
['name' => 'Bahamas', 'code' => 'BS'],
['name' => 'Bahrain', 'code' => 'BH'],
['name' => 'Bangladesh', 'code' => 'BD'],
['name' => 'Barbados', 'code' => 'BB'],
['name' => 'Belarus', 'code' => 'BY'],
['name' => 'Belgium', 'code' => 'BE'],
['name' => 'Belize', 'code' => 'BZ'],
['name' => 'Benin', 'code' => 'BJ'],
['name' => 'Bermuda', 'code' => 'BM'],
['name' => 'Bhutan', 'code' => 'BT'],
['name' => 'Bolivia', 'code' => 'BO'],
['name' => 'Bosnia and Herzegovina', 'code' => 'BA'],
['name' => 'Botswana', 'code' => 'BW'],
['name' => 'Bouvet Island', 'code' => 'BV'],
['name' => 'Brazil', 'code' => 'BR'],
['name' => 'British Indian Ocean Territory', 'code' => 'IO'],
['name' => 'Brunei Darussalam', 'code' => 'BN'],
['name' => 'Bulgaria', 'code' => 'BG'],
['name' => 'Burkina Faso', 'code' => 'BF'],
['name' => 'Burundi', 'code' => 'BI'],
['name' => 'Cambodia', 'code' => 'KH'],
['name' => 'Cameroon', 'code' => 'CM'],
['name' => 'Canada', 'code' => 'CA'],
['name' => 'Cape Verde', 'code' => 'CV'],
['name' => 'Cayman Islands', 'code' => 'KY'],
['name' => 'Central African Republic', 'code' => 'CF'],
['name' => 'Chad', 'code' => 'TD'],
['name' => 'Chile', 'code' => 'CL'],
['name' => 'China', 'code' => 'CN'],
['name' => 'Christmas Island', 'code' => 'CX'],
['name' => 'Cocos (Keeling) Islands', 'code' => 'CC'],
['name' => 'Colombia', 'code' => 'CO'],
['name' => 'Comoros', 'code' => 'KM'],
['name' => 'Congo', 'code' => 'CG'],
['name' => 'Congo, The Democratic Republic of the', 'code' => 'CD'],
['name' => 'Cook Islands', 'code' => 'CK'],
['name' => 'Costa Rica', 'code' => 'CR'],
['name' => 'Cote D\'Ivoire', 'code' => 'CI'],
['name' => 'Croatia', 'code' => 'HR'],
['name' => 'Cuba', 'code' => 'CU'],
['name' => 'Cyprus', 'code' => 'CY'],
['name' => 'Czech Republic', 'code' => 'CZ'],
['name' => 'Denmark', 'code' => 'DK'],
['name' => 'Djibouti', 'code' => 'DJ'],
['name' => 'Dominica', 'code' => 'DM'],
['name' => 'Dominican Republic', 'code' => 'DO'],
['name' => 'Ecuador', 'code' => 'EC'],
['name' => 'Egypt', 'code' => 'EG'],
['name' => 'El Salvador', 'code' => 'SV'],
['name' => 'Equatorial Guinea', 'code' => 'GQ'],
['name' => 'Eritrea', 'code' => 'ER'],
['name' => 'Estonia', 'code' => 'EE'],
['name' => 'Ethiopia', 'code' => 'ET'],
['name' => 'Falkland Islands (Malvinas)', 'code' => 'FK'],
['name' => 'Faroe Islands', 'code' => 'FO'],
['name' => 'Fiji', 'code' => 'FJ'],
['name' => 'Finland', 'code' => 'FI'],
['name' => 'France', 'code' => 'FR'],
['name' => 'French Guiana', 'code' => 'GF'],
['name' => 'French Polynesia', 'code' => 'PF'],
['name' => 'French Southern Territories', 'code' => 'TF'],
['name' => 'Gabon', 'code' => 'GA'],
['name' => 'Gambia', 'code' => 'GM'],
['name' => 'Georgia', 'code' => 'GE'],
['name' => 'Germany', 'code' => 'DE'],
['name' => 'Ghana', 'code' => 'GH'],
['name' => 'Gibraltar', 'code' => 'GI'],
['name' => 'Greece', 'code' => 'GR'],
['name' => 'Greenland', 'code' => 'GL'],
['name' => 'Grenada', 'code' => 'GD'],
['name' => 'Guadeloupe', 'code' => 'GP'],
['name' => 'Guam', 'code' => 'GU'],
['name' => 'Guatemala', 'code' => 'GT'],
['name' => 'Guernsey', 'code' => 'GG'],
['name' => 'Guinea', 'code' => 'GN'],
['name' => 'Guinea-Bissau', 'code' => 'GW'],
['name' => 'Guyana', 'code' => 'GY'],
['name' => 'Haiti', 'code' => 'HT'],
['name' => 'Heard Island and Mcdonald Islands', 'code' => 'HM'],
['name' => 'Holy See (Vatican City State)', 'code' => 'VA'],
['name' => 'Honduras', 'code' => 'HN'],
['name' => 'Hong Kong', 'code' => 'HK'],
['name' => 'Hungary', 'code' => 'HU'],
['name' => 'Iceland', 'code' => 'IS'],
['name' => 'India', 'code' => 'IN'],
['name' => 'Indonesia', 'code' => 'ID'],
['name' => 'Iran, Islamic Republic Of', 'code' => 'IR'],
['name' => 'Iraq', 'code' => 'IQ'],
['name' => 'Ireland', 'code' => 'IE'],
['name' => 'Isle of Man', 'code' => 'IM'],
['name' => 'Israel', 'code' => 'IL'],
['name' => 'Italy', 'code' => 'IT'],
['name' => 'Jamaica', 'code' => 'JM'],
['name' => 'Japan', 'code' => 'JP'],
['name' => 'Jersey', 'code' => 'JE'],
['name' => 'Jordan', 'code' => 'JO'],
['name' => 'Kazakhstan', 'code' => 'KZ'],
['name' => 'Kenya', 'code' => 'KE'],
['name' => 'Kiribati', 'code' => 'KI'],
['name' => 'Korea, Democratic People\'S Republic of', 'code' => 'KP'],
['name' => 'Korea, Republic of', 'code' => 'KR'],
['name' => 'Kuwait', 'code' => 'KW'],
['name' => 'Kyrgyzstan', 'code' => 'KG'],
['name' => 'Lao People\'S Democratic Republic', 'code' => 'LA'],
['name' => 'Latvia', 'code' => 'LV'],
['name' => 'Lebanon', 'code' => 'LB'],
['name' => 'Lesotho', 'code' => 'LS'],
['name' => 'Liberia', 'code' => 'LR'],
['name' => 'Libyan Arab Jamahiriya', 'code' => 'LY'],
['name' => 'Liechtenstein', 'code' => 'LI'],
['name' => 'Lithuania', 'code' => 'LT'],
['name' => 'Luxembourg', 'code' => 'LU'],
['name' => 'Macao', 'code' => 'MO'],
['name' => 'Macedonia, The Former Yugoslav Republic of', 'code' => 'MK'],
['name' => 'Madagascar', 'code' => 'MG'],
['name' => 'Malawi', 'code' => 'MW'],
['name' => 'Malaysia', 'code' => 'MY'],
['name' => 'Maldives', 'code' => 'MV'],
['name' => 'Mali', 'code' => 'ML'],
['name' => 'Malta', 'code' => 'MT'],
['name' => 'Marshall Islands', 'code' => 'MH'],
['name' => 'Martinique', 'code' => 'MQ'],
['name' => 'Mauritania', 'code' => 'MR'],
['name' => 'Mauritius', 'code' => 'MU'],
['name' => 'Mayotte', 'code' => 'YT'],
['name' => 'Mexico', 'code' => 'MX'],
['name' => 'Micronesia, Federated States of', 'code' => 'FM'],
['name' => 'Moldova, Republic of', 'code' => 'MD'],
['name' => 'Monaco', 'code' => 'MC'],
['name' => 'Mongolia', 'code' => 'MN'],
['name' => 'Montserrat', 'code' => 'MS'],
['name' => 'Morocco', 'code' => 'MA'],
['name' => 'Mozambique', 'code' => 'MZ'],
['name' => 'Myanmar', 'code' => 'MM'],
['name' => 'Namibia', 'code' => 'NA'],
['name' => 'Nauru', 'code' => 'NR'],
['name' => 'Nepal', 'code' => 'NP'],
['name' => 'Netherlands', 'code' => 'NL'],
['name' => 'Netherlands Antilles', 'code' => 'AN'],
['name' => 'New Caledonia', 'code' => 'NC'],
['name' => 'New Zealand', 'code' => 'NZ'],
['name' => 'Nicaragua', 'code' => 'NI'],
['name' => 'Niger', 'code' => 'NE'],
['name' => 'Nigeria', 'code' => 'NG'],
['name' => 'Niue', 'code' => 'NU'],
['name' => 'Norfolk Island', 'code' => 'NF'],
['name' => 'Northern Mariana Islands', 'code' => 'MP'],
['name' => 'Norway', 'code' => 'NO'],
['name' => 'Oman', 'code' => 'OM'],
['name' => 'Pakistan', 'code' => 'PK'],
['name' => 'Palau', 'code' => 'PW'],
['name' => 'Palestinian Territory, Occupied', 'code' => 'PS'],
['name' => 'Panama', 'code' => 'PA'],
['name' => 'Papua New Guinea', 'code' => 'PG'],
['name' => 'Paraguay', 'code' => 'PY'],
['name' => 'Peru', 'code' => 'PE'],
['name' => 'Philippines', 'code' => 'PH'],
['name' => 'Pitcairn', 'code' => 'PN'],
['name' => 'Poland', 'code' => 'PL'],
['name' => 'Portugal', 'code' => 'PT'],
['name' => 'Puerto Rico', 'code' => 'PR'],
['name' => 'Qatar', 'code' => 'QA'],
['name' => 'Reunion', 'code' => 'RE'],
['name' => 'Romania', 'code' => 'RO'],
['name' => 'Russian Federation', 'code' => 'RU'],
['name' => 'RWANDA', 'code' => 'RW'],
['name' => 'Saint Helena', 'code' => 'SH'],
['name' => 'Saint Kitts and Nevis', 'code' => 'KN'],
['name' => 'Saint Lucia', 'code' => 'LC'],
['name' => 'Saint Pierre and Miquelon', 'code' => 'PM'],
['name' => 'Saint Vincent and the Grenadines', 'code' => 'VC'],
['name' => 'Samoa', 'code' => 'WS'],
['name' => 'San Marino', 'code' => 'SM'],
['name' => 'Sao Tome and Principe', 'code' => 'ST'],
['name' => 'Saudi Arabia', 'code' => 'SA'],
['name' => 'Senegal', 'code' => 'SN'],
['name' => 'Serbia', 'code' => 'RS'],
['name' => 'Montenegro', 'code' => 'ME'],
['name' => 'Seychelles', 'code' => 'SC'],
['name' => 'Sierra Leone', 'code' => 'SL'],
['name' => 'Singapore', 'code' => 'SG'],
['name' => 'Slovakia', 'code' => 'SK'],
['name' => 'Slovenia', 'code' => 'SI'],
['name' => 'Solomon Islands', 'code' => 'SB'],
['name' => 'Somalia', 'code' => 'SO'],
['name' => 'South Africa', 'code' => 'ZA'],
['name' => 'South Georgia and the South Sandwich Islands', 'code' => 'GS'],
['name' => 'Spain', 'code' => 'ES'],
['name' => 'Sri Lanka', 'code' => 'LK'],
['name' => 'Sudan', 'code' => 'SD'],
['name' => 'Suriname', 'code' => 'SR'],
['name' => 'Svalbard and Jan Mayen', 'code' => 'SJ'],
['name' => 'Swaziland', 'code' => 'SZ'],
['name' => 'Sweden', 'code' => 'SE'],
['name' => 'Switzerland', 'code' => 'CH'],
['name' => 'Syrian Arab Republic', 'code' => 'SY'],
['name' => 'Taiwan, Province of China', 'code' => 'TW'],
['name' => 'Tajikistan', 'code' => 'TJ'],
['name' => 'Tanzania, United Republic of', 'code' => 'TZ'],
['name' => 'Thailand', 'code' => 'TH'],
['name' => 'Timor-Leste', 'code' => 'TL'],
['name' => 'Togo', 'code' => 'TG'],
['name' => 'Tokelau', 'code' => 'TK'],
['name' => 'Tonga', 'code' => 'TO'],
['name' => 'Trinidad and Tobago', 'code' => 'TT'],
['name' => 'Tunisia', 'code' => 'TN'],
['name' => 'Turkey', 'code' => 'TR'],
['name' => 'Turkmenistan', 'code' => 'TM'],
['name' => 'Turks and Caicos Islands', 'code' => 'TC'],
['name' => 'Tuvalu', 'code' => 'TV'],
['name' => 'Uganda', 'code' => 'UG'],
['name' => 'Ukraine', 'code' => 'UA'],
['name' => 'United Arab Emirates', 'code' => 'AE'],
['name' => 'United Kingdom', 'code' => 'GB'],
['name' => 'United States', 'code' => 'US'],
['name' => 'United States Minor Outlying Islands', 'code' => 'UM'],
['name' => 'Uruguay', 'code' => 'UY'],
['name' => 'Uzbekistan', 'code' => 'UZ'],
['name' => 'Vanuatu', 'code' => 'VU'],
['name' => 'Venezuela', 'code' => 'VE'],
['name' => 'Viet Nam', 'code' => 'VN'],
['name' => 'Virgin Islands, British', 'code' => 'VG'],
['name' => 'Virgin Islands, U.S.', 'code' => 'VI'],
['name' => 'Wallis and Futuna', 'code' => 'WF'],
['name' => 'Western Sahara', 'code' => 'EH'],
['name' => 'Yemen', 'code' => 'YE'],
['name' => 'Zambia', 'code' => 'ZM'],
['name' => 'Zimbabwe', 'code' => 'ZW'],
];
// languages
const LANGUAGES = [
['code' => 'ab', 'name' => 'Abkhaz', 'nativeName' => 'аҧсуа'],
['code' => 'aa', 'name' => 'Afar', 'nativeName' => 'Afaraf'],
['code' => 'af', 'name' => 'Afrikaans', 'nativeName' => 'Afrikaans'],
['code' => 'ak', 'name' => 'Akan', 'nativeName' => 'Akan'],
['code' => 'sq', 'name' => 'Albanian', 'nativeName' => 'Shqip'],
['code' => 'am', 'name' => 'Amharic', 'nativeName' => 'አማርኛ'],
['code' => 'ar', 'name' => 'Arabic', 'nativeName' => 'العربية'],
['code' => 'an', 'name' => 'Aragonese', 'nativeName' => 'Aragonés'],
['code' => 'hy', 'name' => 'Armenian', 'nativeName' => 'Հայերեն'],
['code' => 'as', 'name' => 'Assamese', 'nativeName' => 'অসমীয়া'],
['code' => 'av', 'name' => 'Avaric', 'nativeName' => 'авар мацӀ, магӀарул мацӀ'],
['code' => 'ae', 'name' => 'Avestan', 'nativeName' => 'avesta'],
['code' => 'ay', 'name' => 'Aymara', 'nativeName' => 'aymar aru'],
['code' => 'az', 'name' => 'Azerbaijani', 'nativeName' => 'azərbaycan dili'],
['code' => 'bm', 'name' => 'Bambara', 'nativeName' => 'bamanankan'],
['code' => 'ba', 'name' => 'Bashkir', 'nativeName' => 'башҡорт теле'],
['code' => 'eu', 'name' => 'Basque', 'nativeName' => 'euskara, euskera'],
['code' => 'be', 'name' => 'Belarusian', 'nativeName' => 'Беларуская'],
['code' => 'bn', 'name' => 'Bengali', 'nativeName' => 'বাংলা'],
['code' => 'bh', 'name' => 'Bihari', 'nativeName' => 'भोजपुरी'],
['code' => 'bi', 'name' => 'Bislama', 'nativeName' => 'Bislama'],
['code' => 'bs', 'name' => 'Bosnian', 'nativeName' => 'bosanski jezik'],
['code' => 'br', 'name' => 'Breton', 'nativeName' => 'brezhoneg'],
['code' => 'bg', 'name' => 'Bulgarian', 'nativeName' => 'български език'],
['code' => 'my', 'name' => 'Burmese', 'nativeName' => 'ဗမာစာ'],
['code' => 'ca', 'name' => 'Catalan; Valencian', 'nativeName' => 'Català'],
['code' => 'ch', 'name' => 'Chamorro', 'nativeName' => 'Chamoru'],
['code' => 'ce', 'name' => 'Chechen', 'nativeName' => 'нохчийн мотт'],
['code' => 'ny', 'name' => 'Chichewa; Chewa; Nyanja', 'nativeName' => 'chiCheŵa, chinyanja'],
['code' => 'zh', 'name' => 'Chinese', 'nativeName' => '中文 (Zhōngwén), 汉语, 漢語'],
['code' => 'cv', 'name' => 'Chuvash', 'nativeName' => 'чӑваш чӗлхи'],
['code' => 'kw', 'name' => 'Cornish', 'nativeName' => 'Kernewek'],
['code' => 'co', 'name' => 'Corsican', 'nativeName' => 'corsu, lingua corsa'],
['code' => 'cr', 'name' => 'Cree', 'nativeName' => 'ᓀᐦᐃᔭᐍᐏᐣ'],
['code' => 'hr', 'name' => 'Croatian', 'nativeName' => 'hrvatski'],
['code' => 'cs', 'name' => 'Czech', 'nativeName' => 'česky, čeština'],
['code' => 'da', 'name' => 'Danish', 'nativeName' => 'dansk'],
['code' => 'dv', 'name' => 'Divehi; Dhivehi; Maldivian;', 'nativeName' => 'ދިވެހި'],
['code' => 'nl', 'name' => 'Dutch', 'nativeName' => 'Nederlands, Vlaams'],
['code' => 'en', 'name' => 'English', 'nativeName' => 'English'],
['code' => 'eo', 'name' => 'Esperanto', 'nativeName' => 'Esperanto'],
['code' => 'et', 'name' => 'Estonian', 'nativeName' => 'eesti, eesti keel'],
['code' => 'ee', 'name' => 'Ewe', 'nativeName' => 'Eʋegbe'],
['code' => 'fo', 'name' => 'Faroese', 'nativeName' => 'føroyskt'],
['code' => 'fj', 'name' => 'Fijian', 'nativeName' => 'vosa Vakaviti'],
['code' => 'fi', 'name' => 'Finnish', 'nativeName' => 'suomi, suomen kieli'],
['code' => 'fr', 'name' => 'French', 'nativeName' => 'français, langue française'],
['code' => 'ff', 'name' => 'Fula; Fulah; Pulaar; Pular', 'nativeName' => 'Fulfulde, Pulaar, Pular'],
['code' => 'gl', 'name' => 'Galician', 'nativeName' => 'Galego'],
['code' => 'ka', 'name' => 'Georgian', 'nativeName' => 'ქართული'],
['code' => 'de', 'name' => 'German', 'nativeName' => 'Deutsch'],
['code' => 'el', 'name' => 'Greek, Modern', 'nativeName' => 'Ελληνικά'],
['code' => 'gn', 'name' => 'Guaraní', 'nativeName' => 'Avañeẽ'],
['code' => 'gu', 'name' => 'Gujarati', 'nativeName' => 'ગુજરાતી'],
['code' => 'ht', 'name' => 'Haitian; Haitian Creole', 'nativeName' => 'Kreyòl ayisyen'],
['code' => 'ha', 'name' => 'Hausa', 'nativeName' => 'Hausa, هَوُسَ'],
['code' => 'he', 'name' => 'Hebrew (modern)', 'nativeName' => 'עברית'],
['code' => 'hz', 'name' => 'Herero', 'nativeName' => 'Otjiherero'],
['code' => 'hi', 'name' => 'Hindi', 'nativeName' => 'हिन्दी, हिंदी'],
['code' => 'ho', 'name' => 'Hiri Motu', 'nativeName' => 'Hiri Motu'],
['code' => 'hu', 'name' => 'Hungarian', 'nativeName' => 'Magyar'],
['code' => 'ia', 'name' => 'Interlingua', 'nativeName' => 'Interlingua'],
['code' => 'id', 'name' => 'Indonesian', 'nativeName' => 'Bahasa Indonesia'],
['code' => 'ie', 'name' => 'Interlingue', 'nativeName' => 'Originally called Occidental; then Interlingue after WWII'],
['code' => 'ga', 'name' => 'Irish', 'nativeName' => 'Gaeilge'],
['code' => 'ig', 'name' => 'Igbo', 'nativeName' => 'Asụsụ Igbo'],
['code' => 'ik', 'name' => 'Inupiaq', 'nativeName' => 'Iñupiaq, Iñupiatun'],
['code' => 'io', 'name' => 'Ido', 'nativeName' => 'Ido'],
['code' => 'is', 'name' => 'Icelandic', 'nativeName' => 'Íslenska'],
['code' => 'it', 'name' => 'Italian', 'nativeName' => 'Italiano'],
['code' => 'iu', 'name' => 'Inuktitut', 'nativeName' => 'ᐃᓄᒃᑎᑐᑦ'],
['code' => 'ja', 'name' => 'Japanese', 'nativeName' => '日本語 (にほんご/にっぽんご)'],
['code' => 'jv', 'name' => 'Javanese', 'nativeName' => 'basa Jawa'],
['code' => 'kl', 'name' => 'Kalaallisut, Greenlandic', 'nativeName' => 'kalaallisut, kalaallit oqaasii'],
['code' => 'kn', 'name' => 'Kannada', 'nativeName' => 'ಕನ್ನಡ'],
['code' => 'kr', 'name' => 'Kanuri', 'nativeName' => 'Kanuri'],
['code' => 'ks', 'name' => 'Kashmiri', 'nativeName' => 'कश्मीरी, كشميري‎'],
['code' => 'kk', 'name' => 'Kazakh', 'nativeName' => 'Қазақ тілі'],
['code' => 'km', 'name' => 'Khmer', 'nativeName' => 'ភាសាខ្មែរ'],
['code' => 'ki', 'name' => 'Kikuyu, Gikuyu', 'nativeName' => 'Gĩkũyũ'],
['code' => 'rw', 'name' => 'Kinyarwanda', 'nativeName' => 'Ikinyarwanda'],
['code' => 'ky', 'name' => 'Kirghiz, Kyrgyz', 'nativeName' => 'кыргыз тили'],
['code' => 'kv', 'name' => 'Komi', 'nativeName' => 'коми кыв'],
['code' => 'kg', 'name' => 'Kongo', 'nativeName' => 'KiKongo'],
['code' => 'ko', 'name' => 'Korean', 'nativeName' => '한국어 (韓國語), 조선말 (朝鮮語)'],
['code' => 'ku', 'name' => 'Kurdish', 'nativeName' => 'Kurdî, كوردی‎'],
['code' => 'kj', 'name' => 'Kwanyama, Kuanyama', 'nativeName' => 'Kuanyama'],
['code' => 'la', 'name' => 'Latin', 'nativeName' => 'latine, lingua latina'],
['code' => 'lb', 'name' => 'Luxembourgish, Letzeburgesch', 'nativeName' => 'Lëtzebuergesch'],
['code' => 'lg', 'name' => 'Luganda', 'nativeName' => 'Luganda'],
['code' => 'li', 'name' => 'Limburgish, Limburgan, Limburger', 'nativeName' => 'Limburgs'],
['code' => 'ln', 'name' => 'Lingala', 'nativeName' => 'Lingála'],
['code' => 'lo', 'name' => 'Lao', 'nativeName' => 'ພາສາລາວ'],
['code' => 'lt', 'name' => 'Lithuanian', 'nativeName' => 'lietuvių kalba'],
['code' => 'lu', 'name' => 'Luba-Katanga', 'nativeName' => ''],
['code' => 'lv', 'name' => 'Latvian', 'nativeName' => 'latviešu valoda'],
['code' => 'gv', 'name' => 'Manx', 'nativeName' => 'Gaelg, Gailck'],
['code' => 'mk', 'name' => 'Macedonian', 'nativeName' => 'македонски јазик'],
['code' => 'mg', 'name' => 'Malagasy', 'nativeName' => 'Malagasy fiteny'],
['code' => 'ms', 'name' => 'Malay', 'nativeName' => 'bahasa Melayu, بهاس ملايو‎'],
['code' => 'ml', 'name' => 'Malayalam', 'nativeName' => 'മലയാളം'],
['code' => 'mt', 'name' => 'Maltese', 'nativeName' => 'Malti'],
['code' => 'mi', 'name' => 'Māori', 'nativeName' => 'te reo Māori'],
['code' => 'mr', 'name' => 'Marathi (Marāṭhī)', 'nativeName' => 'मराठी'],
['code' => 'mh', 'name' => 'Marshallese', 'nativeName' => 'Kajin M̧ajeļ'],
['code' => 'mn', 'name' => 'Mongolian', 'nativeName' => 'монгол'],
['code' => 'na', 'name' => 'Nauru', 'nativeName' => 'Ekakairũ Naoero'],
['code' => 'nv', 'name' => 'Navajo, Navaho', 'nativeName' => 'Diné bizaad, Dinékʼehǰí'],
['code' => 'nb', 'name' => 'Norwegian Bokmål', 'nativeName' => 'Norsk bokmål'],
['code' => 'nd', 'name' => 'North Ndebele', 'nativeName' => 'isiNdebele'],
['code' => 'ne', 'name' => 'Nepali', 'nativeName' => 'नेपाली'],
['code' => 'ng', 'name' => 'Ndonga', 'nativeName' => 'Owambo'],
['code' => 'nn', 'name' => 'Norwegian Nynorsk', 'nativeName' => 'Norsk nynorsk'],
['code' => 'no', 'name' => 'Norwegian', 'nativeName' => 'Norsk'],
['code' => 'ii', 'name' => 'Nuosu', 'nativeName' => 'ꆈꌠ꒿ Nuosuhxop'],
['code' => 'nr', 'name' => 'South Ndebele', 'nativeName' => 'isiNdebele'],
['code' => 'oc', 'name' => 'Occitan', 'nativeName' => 'Occitan'],
['code' => 'oj', 'name' => 'Ojibwe, Ojibwa', 'nativeName' => 'ᐊᓂᔑᓈᐯᒧᐎᓐ'],
['code' => 'cu', 'name' => 'Old Church Slavonic, Church Slavic, Church Slavonic, Old Bulgarian, Old Slavonic', 'nativeName' => 'ѩзыкъ словѣньскъ'],
['code' => 'om', 'name' => 'Oromo', 'nativeName' => 'Afaan Oromoo'],
['code' => 'or', 'name' => 'Oriya', 'nativeName' => 'ଓଡ଼ିଆ'],
['code' => 'os', 'name' => 'Ossetian, Ossetic', 'nativeName' => 'ирон æвзаг'],
['code' => 'pa', 'name' => 'Panjabi, Punjabi', 'nativeName' => 'ਪੰਜਾਬੀ, پنجابی‎'],
['code' => 'pi', 'name' => 'Pāli', 'nativeName' => 'पाऴि'],
['code' => 'fa', 'name' => 'Persian', 'nativeName' => 'فارسی'],
['code' => 'pl', 'name' => 'Polish', 'nativeName' => 'polski'],
['code' => 'ps', 'name' => 'Pashto, Pushto', 'nativeName' => 'پښتو'],
['code' => 'pt', 'name' => 'Portuguese', 'nativeName' => 'Português'],
['code' => 'qu', 'name' => 'Quechua', 'nativeName' => 'Runa Simi, Kichwa'],
['code' => 'rm', 'name' => 'Romansh', 'nativeName' => 'rumantsch grischun'],
['code' => 'rn', 'name' => 'Kirundi', 'nativeName' => 'kiRundi'],
['code' => 'ro', 'name' => 'Romanian, Moldavian, Moldovan', 'nativeName' => 'română'],
['code' => 'ru', 'name' => 'Russian', 'nativeName' => 'русский язык'],
['code' => 'sa', 'name' => 'Sanskrit (Saṁskṛta)', 'nativeName' => 'संस्कृतम्'],
['code' => 'sc', 'name' => 'Sardinian', 'nativeName' => 'sardu'],
['code' => 'sd', 'name' => 'Sindhi', 'nativeName' => 'सिन्धी, سنڌي، سندھی‎'],
['code' => 'se', 'name' => 'Northern Sami', 'nativeName' => 'Davvisámegiella'],
['code' => 'sm', 'name' => 'Samoan', 'nativeName' => 'gagana faa Samoa'],
['code' => 'sg', 'name' => 'Sango', 'nativeName' => 'yângâ tî sängö'],
['code' => 'sr', 'name' => 'Serbian', 'nativeName' => 'српски језик'],
['code' => 'gd', 'name' => 'Scottish Gaelic; Gaelic', 'nativeName' => 'Gàidhlig'],
['code' => 'sn', 'name' => 'Shona', 'nativeName' => 'chiShona'],
['code' => 'si', 'name' => 'Sinhala, Sinhalese', 'nativeName' => 'සිංහල'],
['code' => 'sk', 'name' => 'Slovak', 'nativeName' => 'slovenčina'],
['code' => 'sl', 'name' => 'Slovene', 'nativeName' => 'slovenščina'],
['code' => 'so', 'name' => 'Somali', 'nativeName' => 'Soomaaliga, af Soomaali'],
['code' => 'st', 'name' => 'Southern Sotho', 'nativeName' => 'Sesotho'],
['code' => 'es', 'name' => 'Spanish; Castilian', 'nativeName' => 'español, castellano'],
['code' => 'su', 'name' => 'Sundanese', 'nativeName' => 'Basa Sunda'],
['code' => 'sw', 'name' => 'Swahili', 'nativeName' => 'Kiswahili'],
['code' => 'ss', 'name' => 'Swati', 'nativeName' => 'SiSwati'],
['code' => 'sv', 'name' => 'Swedish', 'nativeName' => 'svenska'],
['code' => 'ta', 'name' => 'Tamil', 'nativeName' => 'தமிழ்'],
['code' => 'te', 'name' => 'Telugu', 'nativeName' => 'తెలుగు'],
['code' => 'tg', 'name' => 'Tajik', 'nativeName' => 'тоҷикӣ, toğikī, تاجیکی‎'],
['code' => 'th', 'name' => 'Thai', 'nativeName' => 'ไทย'],
['code' => 'ti', 'name' => 'Tigrinya', 'nativeName' => 'ትግርኛ'],
['code' => 'bo', 'name' => 'Tibetan Standard, Tibetan, Central', 'nativeName' => 'བོད་ཡིག'],
['code' => 'tk', 'name' => 'Turkmen', 'nativeName' => 'Türkmen, Түркмен'],
['code' => 'tl', 'name' => 'Tagalog', 'nativeName' => 'Wikang Tagalog, ᜏᜒᜃᜅ᜔ ᜆᜄᜎᜓᜄ᜔'],
['code' => 'tn', 'name' => 'Tswana', 'nativeName' => 'Setswana'],
['code' => 'to', 'name' => 'Tonga (Tonga Islands)', 'nativeName' => 'faka Tonga'],
['code' => 'tr', 'name' => 'Turkish', 'nativeName' => 'Türkçe'],
['code' => 'ts', 'name' => 'Tsonga', 'nativeName' => 'Xitsonga'],
['code' => 'tt', 'name' => 'Tatar', 'nativeName' => 'татарча, tatarça, تاتارچا‎'],
['code' => 'tw', 'name' => 'Twi', 'nativeName' => 'Twi'],
['code' => 'ty', 'name' => 'Tahitian', 'nativeName' => 'Reo Tahiti'],
['code' => 'ug', 'name' => 'Uighur, Uyghur', 'nativeName' => 'Uyƣurqə, ئۇيغۇرچە‎'],
['code' => 'uk', 'name' => 'Ukrainian', 'nativeName' => 'українська'],
['code' => 'ur', 'name' => 'Urdu', 'nativeName' => 'اردو'],
['code' => 'uz', 'name' => 'Uzbek', 'nativeName' => 'zbek, Ўзбек, أۇزبېك‎'],
['code' => 've', 'name' => 'Venda', 'nativeName' => 'Tshivenḓa'],
['code' => 'vi', 'name' => 'Vietnamese', 'nativeName' => 'Tiếng Việt'],
['code' => 'vo', 'name' => 'Volapük', 'nativeName' => 'Volapük'],
['code' => 'wa', 'name' => 'Walloon', 'nativeName' => 'Walon'],
['code' => 'cy', 'name' => 'Welsh', 'nativeName' => 'Cymraeg'],
['code' => 'wo', 'name' => 'Wolof', 'nativeName' => 'Wollof'],
['code' => 'fy', 'name' => 'Western Frisian', 'nativeName' => 'Frysk'],
['code' => 'xh', 'name' => 'Xhosa', 'nativeName' => 'isiXhosa'],
['code' => 'yi', 'name' => 'Yiddish', 'nativeName' => 'ייִדיש'],
['code' => 'yo', 'name' => 'Yoruba', 'nativeName' => 'Yorùbá'],
['code' => 'za', 'name' => 'Zhuang, Chuang', 'nativeName' => 'Saɯ cueŋƅ, Saw cuengh'],
];

View File

@@ -0,0 +1,17 @@
<?php
use Illuminate\Support\Facades\DB;
if (! function_exists('configSettings')) {
function configSettings($key, $settingsType)
{
try {
$config = DB::table('settings')->where('key_name', $key)
->where('settings_type', $settingsType)->first();
} catch (Exception $exception) {
return null;
}
return (isset($config)) ? $config : null;
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace Modules\Gateways\Library;
class Payer
{
private $name;
private $email;
private $phone;
private $address;
public function __construct($name, $email, $phone, $address)
{
$this->name = $name;
$this->email = $email;
$this->phone = $phone;
$this->address = $address;
}
public function getName()
{
return $this->name;
}
public function getEmail()
{
return $this->email;
}
public function getPhone()
{
return $this->phone;
}
public function getAddress()
{
return $this->address;
}
public function information(): array
{
return [
'name' => $this->getName(),
'email' => $this->getEmail(),
'phone' => $this->getPhone(),
'address' => $this->getAddress(),
];
}
}

View File

@@ -0,0 +1,98 @@
<?php
namespace Modules\Gateways\Library;
class Payment
{
private $hook;
private $currencyCode;
private $paymentMethod;
private $payerId;
private $receiverId;
private $additionalData;
private $paymentAmount;
private $externalRedirectLink;
private $attribute;
private $attributeId;
private $paymentPlatform;
public function __construct($hook, $currencyCode, $paymentMethod, $paymentPlatform, $payerId = null, $receiverId = null, $additionalData = [], $paymentAmount = 0, $externalRedirectLink = null, $attribute = null, $attributeId = null)
{
$this->hook = $hook;
$this->currencyCode = $currencyCode;
$this->paymentMethod = $paymentMethod;
$this->payerId = $payerId;
$this->receiverId = $receiverId;
$this->additionalData = $additionalData;
$this->paymentAmount = $paymentAmount;
$this->externalRedirectLink = $externalRedirectLink;
$this->attribute = $attribute;
$this->attributeId = $attributeId;
$this->paymentPlatform = $paymentPlatform;
}
public function getHook()
{
return $this->hook;
}
public function getCurrencyCode()
{
return $this->currencyCode;
}
public function getPaymentMethod()
{
return $this->paymentMethod;
}
public function getPayerId()
{
return $this->payerId;
}
public function getReceiverId()
{
return $this->receiverId;
}
public function getAdditionalData()
{
return $this->additionalData;
}
public function getPaymentAmount()
{
return $this->paymentAmount;
}
public function getExternalRedirectLink()
{
return $this->externalRedirectLink;
}
public function getAttribute()
{
return $this->attribute;
}
public function getAttributeId()
{
return $this->attributeId;
}
public function getPaymentPlatForm()
{
return $this->paymentPlatform;
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace Modules\Gateways\Library;
class Receiver
{
private $name;
private $image;
public function __construct($name, $image)
{
$this->name = $name;
$this->image = $image;
}
public function getName()
{
return $this->name;
}
public function getImage()
{
return $this->image;
}
public function information(): array
{
return [
'name' => $this->getName(),
'image' => $this->getImage(),
];
}
}

View File

@@ -0,0 +1,176 @@
<?php
namespace Modules\Gateways\Http\Controllers\API;
use App\Http\Controllers\Controller;
use App\Traits\Authenticatable;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Modules\Authentication\Models\SAASSetting;
use Modules\Authentication\Models\Setting;
use Modules\Gateways\Models\PaymentRequest;
class PaymentController extends Controller
{
use Authenticatable;
public function index(Request $request): JsonResponse
{
$paymentMethods = Setting::where('type', PAYMENT_CONFIG)
->where('restaurant_id', $this->getCurrentRestaurantId())
->where('status', '1')
->get();
return $this->responseSuccess($paymentMethods, 'Payment methods list fetched successfully.');
}
public function saasIndex(Request $request): JsonResponse
{
$paymentMethods = SAASSetting::where('type', PAYMENT_CONFIG)->where('status', '1')->get();
return $this->responseSuccess($paymentMethods, 'Payment methods list fetched successfully.');
}
public function update(Request $request, $settingId): JsonResponse
{
$setting = Setting::findOrFail($settingId);
$setting->update([
'payment_info' => $request->payment_info,
'mode' => $request->mode ?? 'test',
'status' => $request->status ?? '1',
'updated_at' => now(),
]);
return $this->responseSuccess($setting, 'Payment method credentials update successfully.');
}
public function statusUpdate($paymentId)
{
$setting = Setting::findOrFail($paymentId);
$setting->update([
'status' => $setting->status === '1' ? '0' : '1',
'updated_at' => now(),
]);
return $this->responseSuccess($setting, 'Payment method status updated successfully.');
}
public function saasUpdate(Request $request, $settingId): JsonResponse
{
$setting = SAASSetting::findOrFail($settingId);
$setting->update([
'payment_info' => $request->payment_info,
'mode' => $request->mode ?? 'test',
'status' => $request->status ?? '1',
'updated_at' => now(),
]);
return $this->responseSuccess($setting, 'Payment method credentials update successfully.');
}
public function saasStatusUpdate($paymentId)
{
$setting = SAASSetting::findOrFail($paymentId);
$setting->update([
'status' => $setting->status === '1' ? '0' : '1',
'updated_at' => now(),
]);
return $this->responseSuccess($setting, 'SAAS Payment method status updated successfully.');
}
public function payment(Request $request): JsonResponse
{
// Validate request
$validator = Validator::make($request->all(), [
'payment_method' => 'required|string',
'payment_type' => 'required|string',
'amount' => 'required|numeric|min:0',
'currency' => 'required|string',
'name' => 'nullable|string',
'phone' => 'required|string',
'email' => 'nullable|string',
'package_id' => 'nullable|string',
'notes' => 'nullable|string',
]);
if ($validator->fails()) {
return response()->json([
'status' => 'fail',
'message' => $validator->errors()->first(),
], 400);
}
$paymentMethod = strtolower($request->payment_method);
$amount = $request->amount;
$currencyCode = $request->currency ?? 'USD'; // Set your default currency or fetch dynamically
$payment = new PaymentRequest;
$payment->restaurant_id = $this->getCurrentRestaurantId();
$payment->payment_amount = $amount;
$payment->currency_code = $currencyCode;
$payment->payment_method = $paymentMethod;
$payment->payment_type = $request->payment_type;
$payment->name = $request->name ?? null;
$payment->phone = $request->phone ?? null;
$payment->email = $request->email ?? null;
$payment->package_id = $request->package_id ?? null;
$payment->notes = $request->notes ?? null;
$payment->gateway_callback_url = $request->gateway_callback_url ?? null;
$payment->external_redirect_link = $request->external_redirect_link ?? null;
$payment->success_hook = $request->success_hook ?? null;
$payment->failure_hook = $request->failure_hook ?? null;
$payment->payment_platform = $request->payment_platform ?? null;
$payment->save();
$paymentUrl = $this->generatePaymentUrl($payment);
if (! $paymentUrl) {
return response()->json([
'status' => 'fail',
'message' => 'Invalid payment method.',
], 400);
}
return response()->json([
'status' => 'success',
'payment_url' => $paymentUrl,
]);
}
private function generatePaymentUrl(PaymentRequest $payment)
{
$routes = [
'ssl_commerz' => 'payment/sslcommerz/pay',
'stripe' => 'payment/stripe/pay',
'paymob_accept' => 'payment/paymob/pay',
'flutterwave' => 'payment/flutterwave-v3/pay',
'paytm' => 'payment/paytm/pay',
'paypal' => 'payment/paypal/pay',
'paytabs' => 'payment/paytabs/pay',
'liqpay' => 'payment/liqpay/pay',
'razor_pay' => 'payment/razor-pay/pay',
'senang_pay' => 'payment/senang-pay/pay',
'mercadopago' => 'payment/mercadopago/pay',
'bkash' => 'payment/bkash/make-payment',
'paystack' => 'payment/paystack/pay',
];
if (array_key_exists($payment->payment_method, $routes)) {
return url("{$routes[$payment->payment_method]}?payment_id={$payment->id}");
}
return false;
}
public function success(Request $request): JsonResponse
{
return response()->json(['message' => 'Payment succeeded'], 200);
}
public function fail(): JsonResponse
{
return response()->json(['message' => 'Payment failed'], 403);
}
}

View File

@@ -0,0 +1,194 @@
<?php
namespace Modules\Gateways\Http\Controllers\AdditionalClasses;
use stdClass;
use Symfony\Component\Process\Exception\InvalidArgumentException;
/**
* Payment method liqpay process
*
* @author Liqpay <support@liqpay.ua>
*/
class LiqPay
{
const CURRENCY_EUR = 'EUR';
const CURRENCY_USD = 'USD';
const CURRENCY_UAH = 'UAH';
const CURRENCY_RUB = 'RUB';
const CURRENCY_RUR = 'RUR';
private $_api_url = 'https://www.liqpay.ua/api/';
private $_checkout_url = 'https://www.liqpay.ua/api/3/checkout';
protected $_supportedCurrencies = [
self::CURRENCY_EUR,
self::CURRENCY_USD,
self::CURRENCY_UAH,
self::CURRENCY_RUB,
self::CURRENCY_RUR,
];
private $_public_key;
private $_private_key;
/**
* Constructor.
*
* @param string|null $api_url (optional)
*
* @throws InvalidArgumentException
*/
public function __construct(string $public_key, string $private_key, ?string $api_url = null)
{
if (empty($public_key)) {
throw new InvalidArgumentException('public_key is empty');
}
if (empty($private_key)) {
throw new InvalidArgumentException('private_key is empty');
}
$this->_public_key = $public_key;
$this->_private_key = $private_key;
if ($api_url !== null) {
$this->_api_url = $api_url;
}
}
/**
* Call API
*/
public function api(string $path, array $params = [], int $timeout = 5): stdClass
{
if (! isset($params['version'])) {
throw new InvalidArgumentException('version is null');
}
$url = $this->_api_url.$path;
$public_key = $this->_public_key;
$private_key = $this->_private_key;
$data = $this->encode_params(array_merge(compact('public_key'), $params));
$signature = $this->str_to_sign($private_key.$data.$private_key);
$postfields = http_build_query([
'data' => $data,
'signature' => $signature,
]);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
$this->_server_response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return json_decode($server_output);
}
/**
* cnb_form
*
*
*
* @throws InvalidArgumentException
*/
public function cnb_form(array $params): string
{
$language = 'en';
if (isset($params['language']) && $params['language'] == 'en') {
$language = 'en';
}
$params = $this->cnb_params($params);
$data = $this->encode_params($params);
$signature = $this->cnb_signature($params);
return sprintf(
'
<form method="POST" action="%s" accept-charset="utf-8">
%s
%s
<input type="image" src="//static.liqpay.ua/buttons/p1%s.radius.png" name="btn_text" />
</form>
',
$this->_checkout_url,
sprintf('<input type="hidden" name="%s" value="%s" />', 'data', $data),
sprintf('<input type="hidden" name="%s" value="%s" />', 'signature', $signature),
$language
);
}
/**
* cnb_signature
*/
public function cnb_signature(array $params): string
{
$params = $this->cnb_params($params);
$private_key = $this->_private_key;
$json = $this->encode_params($params);
$signature = $this->str_to_sign($private_key.$json.$private_key);
return $signature;
}
/**
* cnb_params
*
*
* @return array $params
*/
private function cnb_params(array $params): array
{
$params['public_key'] = $this->_public_key;
if (! isset($params['version'])) {
throw new InvalidArgumentException('version is null');
}
if (! isset($params['amount'])) {
throw new InvalidArgumentException('amount is null');
}
if (! isset($params['currency'])) {
throw new InvalidArgumentException('currency is null');
}
if (! in_array($params['currency'], $this->_supportedCurrencies)) {
throw new InvalidArgumentException('currency is not supported');
}
if ($params['currency'] == self::CURRENCY_RUR) {
$params['currency'] = self::CURRENCY_RUB;
}
if (! isset($params['description'])) {
throw new InvalidArgumentException('description is null');
}
return $params;
}
/**
* encode_params
*/
private function encode_params(array $params): string
{
return base64_encode(json_encode($params));
}
/**
* str_to_sign
*/
public function str_to_sign(string $str): string
{
return base64_encode(sha1($str, 1));
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace Modules\Gateways\Http\Controllers\AdditionalClasses;
use App\Traits\PaymentProcess;
use Modules\Gateways\Models\PaymentRequest;
class Paytabs
{
use PaymentProcess;
private mixed $config_values;
private $payment;
public function __construct()
{
$paymentId = request()->query('payment_id');
$payment = PaymentRequest::where(['id' => $paymentId])->first();
$config = $this->paymentConfig('paytabs', PAYMENT_CONFIG, $payment);
if (! is_null($config) && $config->mode == 'live') {
$this->config_values = json_decode($config->live_values);
} elseif (! is_null($config) && $config->mode == 'test') {
$this->config_values = json_decode($config->test_values);
}
}
public function send_api_request($request_url, $data, $request_method = null)
{
$data['profile_id'] = $this->config_values->profile_id;
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $this->config_values->base_url.'/'.$request_url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_CUSTOMREQUEST => isset($request_method) ? $request_method : 'POST',
CURLOPT_POSTFIELDS => json_encode($data, true),
CURLOPT_HTTPHEADER => [
'authorization:'.$this->config_values->server_key,
'Content-Type:application/json',
],
]);
$response = json_decode(curl_exec($curl), true);
curl_close($curl);
return $response;
}
public function is_valid_redirect($post_values): bool
{
$serverKey = $this->config_values->server_key;
$requestSignature = $post_values['signature'];
unset($post_values['signature']);
$fields = array_filter($post_values);
ksort($fields);
$query = http_build_query($fields);
$signature = hash_hmac('sha256', $query, $serverKey);
if (hash_equals($signature, $requestSignature) === true) {
return true;
} else {
return false;
}
}
}

View File

@@ -0,0 +1,189 @@
<?php
namespace Modules\Gateways\Http\Controllers\WEB;
use App\Http\Controllers\Controller;
use App\Traits\PaymentProcess;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Modules\Authentication\Models\User;
use Modules\Gateways\Models\PaymentRequest;
class BkashPaymentController extends Controller
{
use PaymentProcess;
private mixed $config_values;
private string $base_url;
private $app_key;
private $app_secret;
private $username;
private $password;
private PaymentRequest $payment;
private User $user;
public function __construct(PaymentRequest $payment, User $user)
{
$paymentId = request()->query('payment_id');
$payment = PaymentRequest::where(['id' => $paymentId])->first();
$config = $this->paymentConfig('bkash', PAYMENT_CONFIG, $payment);
$this->config_values = $config->payment_info;
if ($config) {
$this->app_key = $this->config_values['app_key'];
$this->app_secret = $this->config_values['app_secret'];
$this->username = $this->config_values['username'];
$this->password = $this->config_values['password'];
$this->base_url = ($config->mode == 'live') ? 'https://tokenized.pay.bka.sh/v1.2.0-beta' : 'https://tokenized.sandbox.bka.sh/v1.2.0-beta';
}
$this->payment = $payment;
$this->user = $user;
}
public function getToken()
{
$post_token = [
'app_key' => $this->app_key,
'app_secret' => $this->app_secret,
];
$url = curl_init($this->base_url.'/tokenized/checkout/token/grant');
$post_token_json = json_encode($post_token);
$header = [
'Content-Type:application/json',
'username:'.$this->username,
'password:'.$this->password,
];
curl_setopt($url, CURLOPT_HTTPHEADER, $header);
curl_setopt($url, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($url, CURLOPT_RETURNTRANSFER, true);
curl_setopt($url, CURLOPT_POSTFIELDS, $post_token_json);
curl_setopt($url, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($url, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
$resultdata = curl_exec($url);
curl_close($url);
return json_decode($resultdata, true);
}
public function make_tokenize_payment(Request $request): JsonResponse|RedirectResponse
{
$validator = Validator::make($request->all(), [
'payment_id' => 'required',
]);
if ($validator->fails()) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_400, null, $this->errorProcessor($validator)), 400);
}
$data = $this->payment::where(['id' => $request['payment_id']])->where(['is_paid' => 0])->first();
if (! isset($data)) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
$response = self::getToken();
$auth = $response['id_token'];
session()->put('token', $auth);
$callbackURL = route('bkash.callback', ['payment_id' => $request['payment_id'], 'token' => $auth]);
$requestbody = [
'mode' => '0011',
'amount' => round($data->payment_amount, 2),
'currency' => 'BDT',
'intent' => 'sale',
'payerReference' => $data->phone,
'merchantInvoiceNumber' => 'invoice_'.Str::random('15'),
'callbackURL' => $callbackURL,
];
$url = curl_init($this->base_url.'/tokenized/checkout/create');
$requestbodyJson = json_encode($requestbody);
$header = [
'Content-Type:application/json',
'Authorization:'.$auth,
'X-APP-Key:'.$this->app_key,
];
curl_setopt($url, CURLOPT_HTTPHEADER, $header);
curl_setopt($url, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($url, CURLOPT_RETURNTRANSFER, true);
curl_setopt($url, CURLOPT_POSTFIELDS, $requestbodyJson);
curl_setopt($url, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($url, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
$resultdata = curl_exec($url);
curl_close($url);
$obj = json_decode($resultdata);
return redirect()->away($obj->{'bkashURL'});
}
public function callback(Request $request): \Illuminate\Foundation\Application|JsonResponse|Redirector|RedirectResponse|Application
{
$paymentID = $_GET['paymentID'];
$auth = $_GET['token'];
$request_body = [
'paymentID' => $paymentID,
];
$url = curl_init($this->base_url.'/tokenized/checkout/execute');
$request_body_json = json_encode($request_body);
$header = [
'Content-Type:application/json',
'Authorization:'.$auth,
'X-APP-Key:'.$this->app_key,
];
curl_setopt($url, CURLOPT_HTTPHEADER, $header);
curl_setopt($url, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($url, CURLOPT_RETURNTRANSFER, true);
curl_setopt($url, CURLOPT_POSTFIELDS, $request_body_json);
curl_setopt($url, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($url, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
$resultdata = curl_exec($url);
curl_close($url);
$obj = json_decode($resultdata);
if ($obj->statusCode == '0000') {
$this->payment::where(['id' => $request['payment_id']])->update([
'payment_method' => 'bkash',
'is_paid' => 1,
'transaction_id' => $obj->trxID ?? null,
]);
$data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($data) && function_exists($data->hook)) {
call_user_func($data->hook, $data);
}
return $this->paymentResponse($data, 'success');
} else {
$payment_data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($payment_data) && function_exists($payment_data->hook)) {
call_user_func($payment_data->hook, $payment_data);
}
return $this->paymentResponse($payment_data, 'fail');
}
}
}

View File

@@ -0,0 +1,159 @@
<?php
namespace Modules\Gateways\Http\Controllers\WEB;
use App\Http\Controllers\Controller;
use App\Traits\PaymentProcess;
use Illuminate\Foundation\Application;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Validator;
use Modules\Authentication\Models\User;
use Modules\Gateways\Models\PaymentRequest;
class FlutterwaveV3Controller extends Controller
{
use PaymentProcess;
private mixed $config_values;
private PaymentRequest $payment;
private User $user;
public function __construct(PaymentRequest $payment, User $user)
{
$paymentId = request()->query('payment_id');
$payment = PaymentRequest::where(['id' => $paymentId])->first();
$config = $this->paymentConfig('flutterwave', PAYMENT_CONFIG, $payment);
$this->config_values = $config->payment_info;
$this->payment = $payment;
$this->user = $user;
}
public function initialize(Request $request): JsonResponse|string|RedirectResponse
{
$validator = Validator::make($request->all(), [
'payment_id' => 'required',
]);
if ($validator->fails()) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_400, null, $this->errorProcessor($validator)), 400);
}
$data = $this->payment::where(['id' => $request['payment_id']])->where(['is_paid' => 0])->first();
if (! isset($data)) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
if ($data['additional_data'] != null) {
$business = json_decode($data['additional_data']);
$business_name = $business->business_name ?? 'my_business';
} else {
$business_name = 'my_business';
}
$request = [
'tx_ref' => time(),
'amount' => $data->payment_amount,
'currency' => $data->currency_code ?? 'NGN',
'payment_options' => 'card',
'redirect_url' => route('flutterwave-v3.callback', ['payment_id' => $data->id]),
'customer' => [
'email' => $data->email,
'name' => $data->name,
],
'meta' => [
'price' => $data->payment_amount,
],
'customizations' => [
'title' => $business_name,
'description' => $data->id,
],
];
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => 'https://api.flutterwave.com/v3/payments',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => json_encode($request),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.$this->config_values['secret_key'],
'Content-Type: application/json',
],
]);
$response = curl_exec($curl);
curl_close($curl);
$res = json_decode($response);
if ($res->status == 'success') {
return redirect()->away($res->data->link);
}
return 'We can not process your payment';
}
public function callback(Request $request): Application|JsonResponse|Redirector|\Illuminate\Contracts\Foundation\Application|RedirectResponse
{
if ($request['status'] == 'successful') {
$txid = $request['transaction_id'];
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.flutterwave.com/v3/transactions/{$txid}/verify",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer '.$this->config_values['secret_key'],
],
]);
$response = curl_exec($curl);
curl_close($curl);
$res = json_decode($response);
if ($res->status) {
$amountPaid = $res->data->charged_amount;
$amountToPay = $res->data->meta->price;
if ($amountPaid >= $amountToPay) {
$this->payment::where(['id' => $request['payment_id']])->update([
'payment_method' => 'flutterwave',
'is_paid' => 1,
'transaction_id' => $txid,
]);
$data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($data) && function_exists($data->hook)) {
call_user_func($data->hook, $data);
}
return $this->paymentResponse($data, 'success');
}
}
}
$payment_data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($payment_data) && function_exists($payment_data->hook)) {
call_user_func($payment_data->hook, $payment_data);
}
return $this->paymentResponse($payment_data, 'fail');
}
}

View File

@@ -0,0 +1,84 @@
<?php
namespace Modules\Gateways\Http\Controllers\WEB;
use App\Http\Controllers\Controller;
use App\Traits\PaymentProcess;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Str;
use Modules\Gateways\Http\Controllers\AdditionalClasses\LiqPay;
use Modules\Gateways\Models\PaymentRequest;
class LiqPayController extends Controller
{
use PaymentProcess;
private PaymentRequest $payment;
public function __construct(PaymentRequest $payment)
{
$this->payment = $payment;
}
public function payment(Request $request): JsonResponse|string|RedirectResponse
{
$paymentId = request()->query('payment_id');
$payment = PaymentRequest::where(['id' => $paymentId])->first();
try {
$config = $this->paymentConfig('liqpay', PAYMENT_CONFIG, $payment);
$values = $config->payment_info;
$tran = Str::random(6).'-'.rand(1, 1000);
$data = $this->payment::where(['id' => $request['payment_id']])->where(['is_paid' => 0])->first();
if (! isset($data)) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
$public_key = $values['public_key'];
$private_key = $values['private_key'];
$liqpay = new LiqPay($public_key, $private_key);
$html = $liqpay->cnb_form([
'action' => 'pay',
'amount' => round($data->payment_amount, 2),
'currency' => $data->currency_code, // USD
'description' => 'Transaction ID: '.$tran,
'order_id' => $data->attribute_id,
'result_url' => route('liqpay.callback', ['payment_id' => $data->id]),
'server_url' => route('liqpay.callback', ['payment_id' => $data->id]),
'version' => '3',
]);
return $html;
} catch (\Exception $ex) {
return back();
}
}
public function callback(Request $request): JsonResponse|Redirector|RedirectResponse|Application
{
if ($request['status'] == 'success') {
$this->payment::where(['id' => $request['payment_id']])->update([
'payment_method' => 'liqpay',
'is_paid' => 1,
'transaction_id' => $request['transaction_id'],
]);
$data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($data) && function_exists($data->hook)) {
call_user_func($data->hook, $data);
}
return $this->paymentResponse($data, 'success');
}
$payment_data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($payment_data) && function_exists($payment_data->hook)) {
call_user_func($payment_data->hook, $payment_data);
}
return $this->paymentResponse($payment_data, 'fail');
}
}

View File

@@ -0,0 +1,102 @@
<?php
namespace Modules\Gateways\Http\Controllers\WEB;
use App\Http\Controllers\Controller;
use App\Traits\PaymentProcess;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Foundation\Application;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Validator;
use MercadoPago\Payer;
use MercadoPago\Payment;
use MercadoPago\SDK;
use Modules\Authentication\Models\User;
use Modules\Gateways\Models\PaymentRequest;
class MercadoPagoController extends Controller
{
use PaymentProcess;
private PaymentRequest $paymentRequest;
private mixed $config;
private User $user;
public function __construct(PaymentRequest $paymentRequest, User $user)
{
$paymentId = request()->query('payment_id');
$payment = PaymentRequest::where(['id' => $paymentId])->first();
$config = $this->paymentConfig('mercadopago', PAYMENT_CONFIG, $payment);
$config = $this->config->value;
$this->paymentRequest = $paymentRequest;
$this->user = $user;
}
public function index(Request $request): View|Application|Factory|JsonResponse|\Illuminate\Contracts\Foundation\Application
{
$validator = Validator::make($request->all(), [
'payment_id' => 'required',
]);
if ($validator->fails()) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_400, null, $this->errorProcessor($validator)), 400);
}
$data = $this->paymentRequest::where(['id' => $request['payment_id']])->where(['is_paid' => 0])->first();
if (! isset($data)) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
$config = $this->config;
return view('Gateways::payment.payment-view-marcedo-pogo', compact('config', 'data'));
}
public function make_payment(Request $request): Application|JsonResponse|Redirector|\Illuminate\Contracts\Foundation\Application|RedirectResponse
{
SDK::setAccessToken($this->config->access_token);
$payment = new Payment;
$payment->transaction_amount = (float) $request['transactionAmount'];
$payment->token = $request['token'];
$payment->description = $request['description'];
$payment->installments = (int) $request['installments'];
$payment->payment_method_id = $request['paymentMethodId'];
$payment->issuer_id = (int) $request['issuer'];
$payer = new Payer;
$payer->email = $request['payer']['email'];
$payer->identification = [
'type' => $request['payer']['identification']['type'],
'number' => $request['payer']['identification']['number'],
];
$payment->payer = $payer;
$payment->save();
if ($payment->status == 'approved') {
$this->paymentRequest::where(['id' => $request['payment_id']])->update([
'payment_method' => 'mercadopago',
'is_paid' => 1,
'transaction_id' => $payment->id,
]);
$data = $this->paymentRequest::where(['id' => $request['payment_id']])->first();
if (isset($data) && function_exists($data->hook)) {
call_user_func($data->hook, $data);
}
return $this->paymentResponse($data, 'success');
}
$payment_data = $this->paymentRequest::where(['id' => $request['payment_id']])->first();
if (isset($payment_data) && function_exists($payment_data->hook)) {
call_user_func($payment_data->hook, $payment_data);
}
return $this->paymentResponse($payment_data, 'fail');
}
}

View File

@@ -0,0 +1,289 @@
<?php
namespace Modules\Gateways\Http\Controllers\WEB;
use App\Http\Controllers\Controller;
use App\Traits\PaymentProcess;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Modules\Authentication\Models\User;
use Modules\Gateways\Models\PaymentRequest;
class PaymobController extends Controller
{
use PaymentProcess;
private mixed $config_values;
private PaymentRequest $payment;
private User $user;
private string $base_url;
private array $supportedCountries = [
'egypt' => 'https://accept.paymob.com',
'PAK' => 'https://pakistan.paymob.com',
'KSA' => 'https://ksa.paymob.com',
'oman' => 'https://oman.paymob.com',
'UAE' => 'https://uae.paymob.com',
];
private string $defaultBaseUrl = 'https://accept.paymob.com';
public function __construct(PaymentRequest $payment, User $user)
{
$paymentId = request()->query('payment_id');
$payment = PaymentRequest::where(['id' => $paymentId])->first();
$config = $this->paymentConfig('paymob_accept', PAYMENT_CONFIG, $payment);
$values = $config->payment_info;
$this->payment = $payment;
$this->user = $user;
$country = $this->config_values['supported_country'];
if (array_key_exists($country, $this->supportedCountries)) {
$this->base_url = $this->supportedCountries[$country];
} else {
$this->base_url = $this->defaultBaseUrl;
}
}
protected function cURL($url, $json)
{
$ch = curl_init($url);
$headers = [];
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($json));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$output = curl_exec($ch);
curl_close($ch);
return json_decode($output);
}
public function credit(Request $request): JsonResponse|RedirectResponse
{
$validator = Validator::make($request->all(), [
'payment_id' => 'required',
]);
if ($validator->fails()) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_400, null, $this->errorProcessor($validator)), 400);
}
$paymentData = $this->payment::where(['id' => $request['payment_id']])->where(['is_paid' => 0])->first();
if (! isset($paymentData)) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
session()->put('payment_id', $paymentData->id);
if ($paymentData['additional_data'] != null) {
$business = json_decode($paymentData['additional_data']);
$business_name = $business->business_name ?? 'my_business';
} else {
$business_name = 'my_business';
}
$payer = json_decode($paymentData['payer_information']);
$url = $this->base_url.'/v1/intention/';
$config = $this->config_values;
$token = $config['secret_key']; // secret key
// Data for the request
$integration_id = (int) $config['integration_id'];
$data = [
'amount' => round($paymentData->payment_amount * 100),
'currency' => $paymentData->currency_code,
'payment_methods' => [$integration_id], // integration id will be integer
'items' => [
[
'name' => 'payable amount',
'amount' => round($paymentData->payment_amount * 100),
'description' => 'payable amount',
'quantity' => 1,
],
],
'billing_data' => [
'apartment' => 'N/A',
'email' => ! empty($payer->email) ? $payer->email : 'test@gmail.com',
'floor' => 'N/A',
'first_name' => ! empty($payer->name) ? $payer->name : 'rashed',
'street' => 'N/A',
'building' => 'N/A',
'phone_number' => ! empty($payer->phone) ? $payer->phone : '0182780000000',
'shipping_method' => 'PKG',
'postal_code' => 'N/A',
'city' => 'N/A',
'country' => 'N/A',
'last_name' => ! empty($payer->name) ? $payer->name : 'rashed',
'state' => 'N/A',
],
'special_reference' => time(),
'customer' => [
'first_name' => ! empty($payer->name) ? $payer->name : 'rashed',
'last_name' => ! empty($payer->name) ? $payer->name : 'rashed',
'email' => ! empty($payer->email) ? $payer->email : 'test@gmail.com',
'extras' => [
're' => '22',
],
],
'extras' => [
'ee' => 22,
],
'redirection_url' => route('paymob.callback'),
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Token '.$token,
'Content-Type: application/json',
]);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
$result = json_decode($response, true);
if (! isset($result['client_secret'])) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
$secret_key = $result['client_secret'];
curl_close($ch);
$publicKey = $config['public_key'];
$urlRedirect = $this->base_url."/unifiedcheckout/?publicKey=$publicKey&clientSecret=$secret_key";
return redirect()->to($urlRedirect);
}
public function createOrder($token, $paymentData, $business_name)
{
$items[] = [
'name' => $business_name,
'amount_cents' => round($paymentData->payment_amount * 100),
'description' => 'payment ID :'.$paymentData->id,
'quantity' => 1,
];
$data = [
'auth_token' => $token,
'delivery_needed' => 'false',
'amount_cents' => round($paymentData->payment_amount * 100),
'currency' => $paymentData->currency_code,
'items' => $items,
];
return $this->cURL(
$this->base_url.'/api/ecommerce/orders',
$data
);
}
public function getPaymentToken($order, $token, $paymentData, $payer)
{
$value = $paymentData->payment_amount;
$billingData = [
'apartment' => 'N/A',
'email' => ! empty($payer->email) ? $payer->email : 'test@gmail.com',
'floor' => 'N/A',
'first_name' => ! empty($payer->name) ? $payer->name : 'rashed',
'street' => 'N/A',
'building' => 'N/A',
'phone_number' => ! empty($payer->phone) ? $payer->phone : '0182780000000',
'shipping_method' => 'PKG',
'postal_code' => 'N/A',
'city' => 'N/A',
'country' => 'N/A',
'last_name' => ! empty($payer->name) ? $payer->name : 'rashed',
'state' => 'N/A',
];
$data = [
'auth_token' => $token,
'amount_cents' => round($value * 100),
'expiration' => 3600,
'order_id' => $order->id,
'billing_data' => $billingData,
'currency' => $paymentData->currency_code,
'integration_id' => is_array($this->config_values) ? $this->config_values['integration_id'] : $this->config_values->integration_id,
];
$response = $this->cURL(
$this->base_url.'/api/acceptance/payment_keys',
$data
);
return $response->token;
}
public function callback(Request $request)
{
$data = $request->all();
ksort($data);
$hmac = $data['hmac'];
$array = [
'amount_cents',
'created_at',
'currency',
'error_occured',
'has_parent_transaction',
'id',
'integration_id',
'is_3d_secure',
'is_auth',
'is_capture',
'is_refunded',
'is_standalone_payment',
'is_voided',
'order',
'owner',
'pending',
'source_data_pan',
'source_data_sub_type',
'source_data_type',
'success',
];
$connectedString = '';
foreach ($data as $key => $element) {
if (in_array($key, $array)) {
$connectedString .= $element;
}
}
$secret = is_array($this->config_values) ? $this->config_values['hmac'] : $this->config_values->hmac;
$hased = hash_hmac('sha512', $connectedString, $secret);
if ($hased == $hmac && $data['success'] === 'true') {
$this->payment::where(['id' => session('payment_id')])->update([
'payment_method' => 'paymob',
'is_paid' => 1,
'transaction_id' => session('payment_id'),
]);
$paymentData = $this->payment::where(['id' => session('payment_id')])->first();
if (isset($paymentData) && function_exists($paymentData->success_hook)) {
call_user_func($paymentData->hook, $paymentData);
}
return $this->paymentResponse($paymentData, 'success');
}
$paymentData = $this->payment::where(['id' => session('payment_id')])->first();
if (isset($paymentData) && function_exists($paymentData->failure_hook)) {
call_user_func($paymentData->hook, $paymentData);
}
return $this->paymentResponse($paymentData, 'fail');
}
}

View File

@@ -0,0 +1,203 @@
<?php
namespace Modules\Gateways\Http\Controllers\WEB;
use App\Http\Controllers\Controller;
use App\Traits\PaymentProcess;
use Illuminate\Foundation\Application;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Modules\Gateways\Models\PaymentRequest;
class PaypalPaymentController extends Controller
{
use PaymentProcess;
private mixed $config_values;
private string $base_url;
private PaymentRequest $payment;
public function __construct(PaymentRequest $payment)
{
$paymentId = request()->query('payment_id');
$payment = PaymentRequest::where(['id' => $paymentId])->first();
$config = $this->paymentConfig('paypal', PAYMENT_CONFIG, $payment);
$values = $config->payment_info;
if ($config) {
$this->base_url = ($config->mode == 'test') ? 'https://api-m.sandbox.paypal.com' : 'https://api-m.paypal.com';
}
$this->payment = $payment;
}
public function token(): bool|string
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->base_url.'/v1/oauth2/token');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'grant_type=client_credentials');
curl_setopt($ch, CURLOPT_USERPWD, $this->config_values['client_id'].':'.$this->config_values['client_secret']);
$headers = [];
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$accessToken = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:'.curl_error($ch);
}
curl_close($ch);
return $accessToken;
}
/**
* Responds with a welcome message with instructions
*/
public function payment(Request $request): JsonResponse|RedirectResponse
{
$validator = Validator::make($request->all(), [
'payment_id' => 'required',
]);
if ($validator->fails()) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_400, null, $this->errorProcessor($validator)), 400);
}
$data = $this->payment::where(['id' => $request['payment_id']])->where(['is_paid' => 0])->first();
if (! isset($data)) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
if ($data['additional_data'] != null) {
$business = json_decode($data['additional_data']);
$business_name = $business->business_name ?? 'my_business';
} else {
$business_name = 'my_business';
}
$accessToken = json_decode($this->token(), true);
if (isset($accessToken['access_token'])) {
$accessToken = $accessToken['access_token'];
$payment_data = [];
$payment_data['purchase_units'] = [
[
'reference_id' => $data->id,
'name' => $business_name,
'desc' => 'payment ID :'.$data->id,
'amount' => [
'currency_code' => $data->currency_code ?? 'USD',
'value' => number_format($data->payment_amount, 2),
],
],
];
$payment_data['invoice_id'] = $data->id;
$payment_data['invoice_description'] = "Order #{$payment_data['invoice_id']} Invoice";
$payment_data['total'] = round($data->payment_amount, 2);
$payment_data['intent'] = 'CAPTURE';
$payment_data['application_context'] = [
'return_url' => route('paypal.success', ['payment_id' => $data->id]),
'cancel_url' => route('paypal.cancel', ['payment_id' => $data->id]),
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->base_url.'/v2/checkout/orders');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payment_data));
$headers = [];
$headers[] = 'Content-Type: application/json';
$headers[] = "Authorization: Bearer $accessToken";
$headers[] = 'Paypal-Request-Id:'.Str::uuid();
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:'.curl_error($ch);
}
curl_close($ch);
} else {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
$response = json_decode($response);
$links = $response->links;
return Redirect::away($links[1]->href);
}
/**
* Responds with a welcome message with instructions
*/
public function cancel(Request $request): Application|JsonResponse|Redirector|\Illuminate\Contracts\Foundation\Application|RedirectResponse
{
$data = $this->payment::where(['id' => $request['payment_id']])->first();
return $this->paymentResponse($data, 'cancel');
}
/**
* Responds with a welcome message with instructions
*/
public function success(Request $request): Application|JsonResponse|Redirector|\Illuminate\Contracts\Foundation\Application|RedirectResponse
{
$accessToken = json_decode($this->token(), true);
$accessToken = $accessToken['access_token'];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->base_url."/v2/checkout/orders/{$request->token}/capture");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
$headers = [];
$headers[] = 'Content-Type: application/json';
$headers[] = "Authorization: Bearer $accessToken";
$headers[] = 'Paypal-Request-Id:'.Str::uuid();
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:'.curl_error($ch);
}
curl_close($ch);
$response = json_decode($result);
if ($response->status === 'COMPLETED') {
$this->payment::where(['id' => $request['payment_id']])->update([
'payment_method' => 'paypal',
'is_paid' => 1,
'transaction_id' => $response->id,
]);
$data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($data) && function_exists($data->hook)) {
call_user_func($data->hook, $data);
}
return $this->paymentResponse($data, 'success');
}
$payment_data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($payment_data) && function_exists($payment_data->hook)) {
call_user_func($payment_data->hook, $payment_data);
}
return $this->paymentResponse($payment_data, 'fail');
}
}

View File

@@ -0,0 +1,99 @@
<?php
namespace Modules\Gateways\Http\Controllers\WEB;
use App\Http\Controllers\Controller;
use App\Traits\PaymentProcess;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Foundation\Application;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Validator;
use Modules\Authentication\Models\User;
use Modules\Gateways\Models\PaymentRequest;
use Unicodeveloper\Paystack\Facades\Paystack;
class PaystackController extends Controller
{
use PaymentProcess;
private PaymentRequest $payment;
private User $user;
public function __construct(PaymentRequest $payment, User $user)
{
$paymentId = request()->query('payment_id');
$payment = PaymentRequest::where(['id' => $paymentId])->first();
$config = $this->paymentConfig('paystack', PAYMENT_CONFIG, $payment);
$values = $config->payment_info;
if ($values) {
$config = [
'publicKey' => env('PAYSTACK_PUBLIC_KEY', $values['public_key']),
'secretKey' => env('PAYSTACK_SECRET_KEY', $values['secret_key']),
'paymentUrl' => env('PAYSTACK_PAYMENT_URL', 'https://api.paystack.co'),
'merchantEmail' => env('MERCHANT_EMAIL', $values['merchant_email']),
];
Config::set('paystack', $config);
}
$this->payment = $payment;
$this->user = $user;
}
public function index(Request $request): View|Application|Factory|JsonResponse|\Illuminate\Contracts\Foundation\Application
{
$validator = Validator::make($request->all(), [
'payment_id' => 'required',
]);
if ($validator->fails()) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_400, null, $this->errorProcessor($validator)), 400);
}
$data = $this->payment::where(['id' => $request['payment_id']])->where(['is_paid' => 0])->first();
if (! isset($data)) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
$reference = Paystack::genTranxRef();
return view('Gateways::payment.paystack', compact('data', 'reference'));
}
public function redirectToGateway(Request $request)
{
return Paystack::getAuthorizationUrl()->redirectNow();
}
public function handleGatewayCallback(Request $request): Application|JsonResponse|Redirector|\Illuminate\Contracts\Foundation\Application|RedirectResponse
{
$paymentDetails = Paystack::getPaymentData();
if ($paymentDetails['status'] == true) {
$this->payment::where(['attribute_id' => $paymentDetails['data']['orderID']])->update([
'payment_method' => 'paystack',
'is_paid' => 1,
'transaction_id' => $request['trxref'],
]);
$data = $this->payment::where(['attribute_id' => $paymentDetails['data']['orderID']])->first();
if (isset($data) && function_exists($data->hook)) {
call_user_func($data->hook, $data);
}
return $this->paymentResponse($data, 'success');
}
$payment_data = $this->payment::where(['attribute_id' => $paymentDetails['data']['orderID']])->first();
if (isset($payment_data) && function_exists($payment_data->hook)) {
call_user_func($payment_data->hook, $payment_data);
}
return $this->paymentResponse($payment_data, 'fail');
}
}

View File

@@ -0,0 +1,142 @@
<?php
namespace Modules\Gateways\Http\Controllers\WEB;
use App\Http\Controllers\Controller;
use App\Traits\PaymentProcess;
use Illuminate\Foundation\Application;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Validator;
use Modules\Authentication\Models\User;
use Modules\Gateways\Http\Controllers\AdditionalClasses\Paytabs;
use Modules\Gateways\Models\PaymentRequest;
class PaytabsController extends Controller
{
use PaymentProcess;
private PaymentRequest $payment;
private User $user;
public function __construct(PaymentRequest $payment, User $user)
{
$this->payment = $payment;
$this->user = $user;
}
public function payment(Request $request)
{
$paymentId = request()->query('payment_id');
$payment = PaymentRequest::where(['id' => $paymentId])->first();
$validator = Validator::make($request->all(), [
'payment_id' => 'required',
]);
if ($validator->fails()) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_400, null, $this->errorProcessor($validator)), 400);
}
$payment_data = $this->payment::where(['id' => $request['payment_id']])->where(['is_paid' => 0])->first();
if (! isset($payment_data)) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
$payer = json_decode($payment_data['payer_information']);
$plugin = new Paytabs;
$request_url = 'payment/request';
$data = [
'tran_type' => 'sale',
'tran_class' => 'ecom',
'cart_id' => $payment_data->id,
'cart_currency' => $payment_data->currency_code ?? 'USD',
'cart_amount' => number_format($payment_data->payment_amount, 2),
'cart_description' => 'products',
'paypage_lang' => 'en',
'callback' => route('paytabs.callback', ['payment_id' => $payment_data->id]),
'return' => route('paytabs.callback', ['payment_id' => $payment_data->id]),
'customer_details' => [
'name' => $payer->name,
'email' => $payer->email,
'phone' => $payer->phone ?? '000000',
'street1' => 'N/A',
'city' => 'N/A',
'state' => 'N/A',
'country' => 'N/A',
'zip' => '00000',
],
'shipping_details' => [
'name' => 'N/A',
'email' => 'N/A',
'phone' => 'N/A',
'street1' => 'N/A',
'city' => 'N/A',
'state' => 'N/A',
'country' => 'N/A',
'zip' => '0000',
],
'user_defined' => [
'udf9' => 'UDF9',
'udf3' => 'UDF3',
],
];
$page = $plugin->send_api_request($request_url, $data);
if (! isset($page['redirect_url'])) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
header('Location:'.$page['redirect_url']); /* Redirect browser */
exit();
}
public function callback(Request $request): Application|JsonResponse|Redirector|\Illuminate\Contracts\Foundation\Application|RedirectResponse
{
$plugin = new Paytabs;
$response_data = $_POST;
$transRef = filter_input(INPUT_POST, 'tranRef');
if (! $transRef) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
$is_valid = $plugin->is_valid_redirect($response_data);
if (! $is_valid) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
$request_url = 'payment/query';
$data = [
'tran_ref' => $transRef,
];
$verify_result = $plugin->send_api_request($request_url, $data);
$is_success = $verify_result['payment_result']['response_status'] === 'A';
if ($is_success) {
$this->payment::where(['id' => $request['payment_id']])->update([
'payment_method' => 'paytabs',
'is_paid' => 1,
'transaction_id' => $transRef,
]);
$payment_data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($payment_data) && function_exists($payment_data->hook)) {
call_user_func($payment_data->hook, $payment_data);
}
return $this->paymentResponse($payment_data, 'success');
}
$payment_data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($payment_data) && function_exists($payment_data->hook)) {
call_user_func($payment_data->hook, $payment_data);
}
return $this->paymentResponse($payment_data, 'fail');
}
public function response(): JsonResponse
{
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_200), 200);
}
}

View File

@@ -0,0 +1,262 @@
<?php
namespace Modules\Gateways\Http\Controllers\WEB;
use App\Http\Controllers\Controller;
use App\Traits\PaymentProcess;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Validator;
use Modules\Authentication\Models\User;
use Modules\Gateways\Models\PaymentRequest;
class PaytmController extends Controller
{
use PaymentProcess;
private PaymentRequest $payment;
private User $user;
public function __construct(PaymentRequest $payment, User $user)
{
$paymentId = request()->query('payment_id');
$payment = PaymentRequest::where(['id' => $paymentId])->first();
$config = $this->paymentConfig('paytm', PAYMENT_CONFIG, $payment);
$paytm = $config->value;
if (isset($paytm)) {
$PAYTM_STATUS_QUERY_NEW_URL = 'https://securegw-stage.paytm.in/merchant-status/getTxnStatus';
$PAYTM_TXN_URL = 'https://securegw-stage.paytm.in/theia/processTransaction';
if ($config->mode == 'live') {
$PAYTM_STATUS_QUERY_NEW_URL = 'https://securegw.paytm.in/merchant-status/getTxnStatus';
$PAYTM_TXN_URL = 'https://securegw.paytm.in/theia/processTransaction';
}
$config = [
'PAYTM_ENVIRONMENT' => (env('APP_MODE') == 'live') ? 'PROD' : 'TEST',
'PAYTM_MERCHANT_KEY' => env('PAYTM_MERCHANT_KEY', $paytm['merchant_key']),
'PAYTM_MERCHANT_MID' => env('PAYTM_MERCHANT_MID', $paytm['merchant_id']),
'PAYTM_MERCHANT_WEBSITE' => env('PAYTM_MERCHANT_WEBSITE', $paytm['merchant_website_link']),
'PAYTM_REFUND_URL' => env('PAYTM_REFUND_URL', $paytm['refund_url'] ?? ''),
'PAYTM_STATUS_QUERY_URL' => env('PAYTM_STATUS_QUERY_URL', $PAYTM_STATUS_QUERY_NEW_URL),
'PAYTM_STATUS_QUERY_NEW_URL' => env('PAYTM_STATUS_QUERY_NEW_URL', $PAYTM_STATUS_QUERY_NEW_URL),
'PAYTM_TXN_URL' => env('PAYTM_TXN_URL', $PAYTM_TXN_URL),
];
Config::set('paytm_config', $config);
}
$this->payment = $payment;
$this->user = $user;
}
public function encrypt_e($input, $ky): bool|string
{
$key = html_entity_decode($ky);
$iv = '@@@@&&&&####$$$$';
$data = openssl_encrypt($input, 'AES-128-CBC', $key, 0, $iv);
return $data;
}
public function decrypt_e($crypt, $ky): bool|string
{
$key = html_entity_decode($ky);
$iv = '@@@@&&&&####$$$$';
$data = openssl_decrypt($crypt, 'AES-128-CBC', $key, 0, $iv);
return $data;
}
public function generateSalt_e($length): string
{
$random = '';
srand((float) microtime() * 1000000);
$data = 'AbcDE123IJKLMN67QRSTUVWXYZ';
$data .= 'aBCdefghijklmn123opq45rs67tuv89wxyz';
$data .= '0FGH45OP89';
for ($i = 0; $i < $length; $i++) {
$random .= substr($data, (rand() % (strlen($data))), 1);
}
return $random;
}
public function checkString_e($value)
{
if ($value == 'null') {
$value = '';
}
return $value;
}
public function getChecksumFromArray($arrayList, $key, $sort = 1): bool|string
{
if ($sort != 0) {
ksort($arrayList);
}
$str = $this->getArray2Str($arrayList);
$salt = $this->generateSalt_e(4);
$finalString = $str.'|'.$salt;
$hash = hash('sha256', $finalString);
$hashString = $hash.$salt;
$checksum = $this->encrypt_e($hashString, $key);
return $checksum;
}
public function verifychecksum_e($arrayList, $key, $checksumvalue): string
{
$arrayList = $this->removeCheckSumParam($arrayList);
ksort($arrayList);
$str = $this->getArray2StrForVerify($arrayList);
$paytm_hash = $this->decrypt_e($checksumvalue, $key);
$salt = substr($paytm_hash, -4);
$finalString = $str.'|'.$salt;
$website_hash = hash('sha256', $finalString);
$website_hash .= $salt;
if ($website_hash == $paytm_hash) {
$validFlag = 'TRUE';
} else {
$validFlag = 'FALSE';
}
return $validFlag;
}
public function getArray2Str($arrayList): string
{
$findme = 'REFUND';
$findmepipe = '|';
$paramStr = '';
$flag = 1;
foreach ($arrayList as $key => $value) {
$pos = strpos($value, $findme);
$pospipe = strpos($value, $findmepipe);
if ($pos !== false || $pospipe !== false) {
continue;
}
if ($flag) {
$paramStr .= $this->checkString_e($value);
$flag = 0;
} else {
$paramStr .= '|'.$this->checkString_e($value);
}
}
return $paramStr;
}
public function getArray2StrForVerify($arrayList): string
{
$paramStr = '';
$flag = 1;
foreach ($arrayList as $key => $value) {
if ($flag) {
$paramStr .= $this->checkString_e($value);
$flag = 0;
} else {
$paramStr .= '|'.$this->checkString_e($value);
}
}
return $paramStr;
}
public function removeCheckSumParam($arrayList)
{
if (isset($arrayList['CHECKSUMHASH'])) {
unset($arrayList['CHECKSUMHASH']);
}
return $arrayList;
}
public function payment(Request $request): View|Factory|JsonResponse|Application
{
$validator = Validator::make($request->all(), [
'payment_id' => 'required',
]);
if ($validator->fails()) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_400, null, $this->errorProcessor($validator)), 400);
}
$data = $this->payment::where(['id' => $request['payment_id']])->where(['is_paid' => 0])->first();
if (! isset($data)) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
$paramList = [];
$ORDER_ID = time();
$INDUSTRY_TYPE_ID = $request['INDUSTRY_TYPE_ID'];
$CHANNEL_ID = $request['CHANNEL_ID'];
$TXN_AMOUNT = round($data->payment_amount, 2);
$paramList['MID'] = Config::get('paytm_config.PAYTM_MERCHANT_MID');
$paramList['ORDER_ID'] = $ORDER_ID;
$paramList['CUST_ID'] = $data['payer_id'];
$paramList['INDUSTRY_TYPE_ID'] = $INDUSTRY_TYPE_ID;
$paramList['CHANNEL_ID'] = $CHANNEL_ID;
$paramList['TXN_AMOUNT'] = $TXN_AMOUNT;
$paramList['WEBSITE'] = Config::get('paytm_config.PAYTM_MERCHANT_WEBSITE');
$paramList['CALLBACK_URL'] = route('paytm.response', ['payment_id' => $data->id]);
$paramList['MSISDN'] = $data->phone;
$paramList['EMAIL'] = $data->email;
$paramList['VERIFIED_BY'] = 'EMAIL';
$paramList['IS_USER_VERIFIED'] = 'YES';
$checkSum = $this->getChecksumFromArray($paramList, Config::get('paytm_config.PAYTM_MERCHANT_KEY'));
return view('payment.paytm', compact('checkSum', 'paramList'));
}
public function callback(Request $request): JsonResponse|Redirector|RedirectResponse|Application
{
$paramList = $_POST;
$paytmChecksum = isset($_POST['CHECKSUMHASH']) ? $_POST['CHECKSUMHASH'] : '';
$isValidChecksum = $this->verifychecksum_e($paramList, Config::get('paytm_config.PAYTM_MERCHANT_KEY'), $paytmChecksum); // will return TRUE or FALSE string.
if ($isValidChecksum == 'TRUE') {
if ($request['STATUS'] == 'TXN_SUCCESS') {
$this->payment::where(['id' => $request['payment_id']])->update([
'payment_method' => 'paytm',
'is_paid' => 1,
'transaction_id' => $request['TXNID'],
]);
$data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($data) && function_exists($data->hook)) {
call_user_func($data->hook, $data);
}
return $this->paymentResponse($data, 'success');
}
}
$payment_data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($payment_data) && function_exists($payment_data->hook)) {
call_user_func($payment_data->hook, $payment_data);
}
return $this->paymentResponse($payment_data, 'fail');
}
}

View File

@@ -0,0 +1,128 @@
<?php
namespace Modules\Gateways\Http\Controllers\WEB;
use App\Http\Controllers\Controller;
use App\Traits\PaymentProcess;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Foundation\Application;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Validator;
use Modules\Gateways\Models\PaymentRequest;
use SimpleXMLElement;
class PvitController extends Controller
{
use PaymentProcess;
private mixed $config_values;
private $mc_tel_merchant;
private $access_token;
private $mc_merchant_code;
private PaymentRequest $payment;
public function __construct(PaymentRequest $payment)
{
$paymentId = request()->query('payment_id');
$payment = PaymentRequest::where(['id' => $paymentId])->first();
$config = $this->paymentConfig('pvit', PAYMENT_CONFIG, $payment);
$this->config_values = $config->payment_info;
if ($config) {
$this->mc_tel_merchant = $this->config_values['mc_tel_merchant'];
$this->access_token = $this->config_values['access_token'];
$this->mc_merchant_code = $this->config_values['mc_merchant_code'];
}
$this->payment = $payment;
}
public function payment(Request $req): View|Application|Factory|JsonResponse|\Illuminate\Contracts\Foundation\Application
{
$validator = Validator::make($req->all(), [
'payment_id' => 'required',
]);
if ($validator->fails()) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_400, null, $this->errorProcessor($validator)), 400);
}
$payment_data = $this->payment::where(['id' => $req['payment_id']])->where(['is_paid' => 0])->first();
if (! isset($payment_data)) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
$config_val = $this->config_values;
return view('Gateways::payment.pvit', compact(['payment_data', 'config_val']));
}
public function callBack(Request $request): Application|JsonResponse|Redirector|\Illuminate\Contracts\Foundation\Application|RedirectResponse
{
if ($request->ref || $request->statut) {
if ($request->statut == 200) {
$this->payment::where(['id' => $request['payment_id']])->update([
'payment_method' => 'pvit',
'is_paid' => 1,
'transaction_id' => $request->ref ?? $request['payment_id'],
]);
$data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($data) && function_exists($data->hook)) {
call_user_func($data->hook, $data);
}
return $this->paymentResponse($data, 'success');
}
$payment_data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($payment_data) && function_exists($payment_data->hook)) {
call_user_func($payment_data->hook, $payment_data);
}
return $this->paymentResponse($payment_data, 'fail');
}
$data = $this->payment::where(['id' => $request['payment_id']])->first();
$data_received = file_get_contents('php://input');
$data_received_xml = json_decode(json_encode(new SimpleXMLElement($data_received)), true);
if (isset($data_received_xml['NUM_TRANSACTION']) && isset($data_received_xml['STATUT'])) {
if ($data_received_xml['STATUT'] == 200) {
$this->payment::where(['id' => $request['payment_id']])->update([
'payment_method' => 'pvit',
'is_paid' => 1,
'transaction_id' => $data_received_xml['NUM_TRANSACTION'],
]);
$data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($data) && function_exists($data->hook)) {
call_user_func($data->hook, $data);
}
return $this->paymentResponse($data, 'success');
}
if (isset($data) && function_exists($data->hook)) {
call_user_func($data->hook, $data);
}
return $this->paymentResponse($data, 'fail');
}
if (isset($data) && function_exists($data->hook)) {
call_user_func($data->hook, $data);
}
return $this->paymentResponse($data, 'fail');
}
}

View File

@@ -0,0 +1,130 @@
<?php
namespace Modules\Gateways\Http\Controllers\WEB;
use App\Traits\PaymentProcess;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Validator;
use Modules\Authentication\Models\User;
use Modules\Gateways\Models\PaymentRequest;
use Razorpay\Api\Api;
class RazorPayController extends Controller
{
use PaymentProcess;
private PaymentRequest $payment;
private $user;
public function __construct(PaymentRequest $payment, User $user)
{
$paymentId = request()->query('payment_id');
$payment = PaymentRequest::where(['id' => $paymentId])->first();
$config = $this->paymentConfig('razor_pay', PAYMENT_CONFIG, $payment);
$razor = $config->payment_info;
if ($razor) {
$config = [
'api_key' => $razor['api_key'],
'api_secret' => $razor['api_secret'],
];
Config::set('razor_config', $config);
}
$this->payment = $payment;
$this->user = $user;
}
public function index(Request $request): View|Factory|JsonResponse|Application
{
$validator = Validator::make($request->all(), [
'payment_id' => 'required',
]);
if ($validator->fails()) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_400, null, $this->errorProcessor($validator)), 400);
}
$data = $this->payment::where(['id' => $request['payment_id']])->where(['is_paid' => 0])->first();
if (! isset($data)) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
if ($data['additional_data'] != null) {
$business = json_decode($data['additional_data']);
$business_name = $business->business_name ?? 'my_business';
$business_logo = $business->business_logo ?? url('/');
} else {
$business_name = 'my_business';
$business_logo = url('/');
}
return view('payment.razor-pay', compact('data', 'business_logo', 'business_name'));
}
public function payment(Request $request): JsonResponse|Redirector|RedirectResponse|Application
{
$input = $request->all();
$api = new Api(config('razor_config.api_key'), config('razor_config.api_secret'));
$input['razorpay_payment_id'] = '7c5e8410-92b2-43a8-b27c-4fd4ea930d6c';
$payment = $api->payment->fetch($input['razorpay_payment_id']);
if (count($input) && ! empty($input['razorpay_payment_id'])) {
$response = $api->payment->fetch($input['razorpay_payment_id'])->capture(['amount' => $payment['amount'] - $payment['fee']]);
$this->payment::where(['id' => $request['payment_id']])->update([
'payment_method' => 'razor_pay',
'is_paid' => 1,
'transaction_id' => $input['razorpay_payment_id'],
]);
$data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($data) && function_exists($data->success_hook)) {
call_user_func($data->success_hook, $data);
}
return $this->paymentResponse($data, 'success');
}
$payment_data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($payment_data) && function_exists($payment_data->failure_hook)) {
call_user_func($payment_data->failure_hook, $payment_data);
}
return $this->paymentResponse($payment_data, 'fail');
}
public function callback(Request $request): JsonResponse|Redirector|RedirectResponse|Application
{
$input = $request->all();
$data_id = base64_decode($request?->payment_data);
$payment_data = $this->payment::where(['id' => $data_id])->first();
if (count($input) && ! empty($input['razorpay_payment_id'])) {
if (isset($payment_data) && function_exists($payment_data->success_hook)) {
$payment_data->payment_method = 'razor_pay';
$payment_data->is_paid = 1;
$payment_data->transaction_id = $input['razorpay_payment_id'];
$payment_data->save();
call_user_func($payment_data->success_hook, $payment_data);
return $this->paymentResponse($payment_data, 'success');
}
}
return $this->paymentResponse($payment_data, 'fail');
}
public function cancel(Request $request): JsonResponse|Redirector|RedirectResponse|Application
{
$payment_data = $this->payment::where(['id' => $request['payment_id']])->first();
return $this->paymentResponse($payment_data, 'fail');
}
}

View File

@@ -0,0 +1,83 @@
<?php
namespace Modules\Gateways\Http\Controllers\WEB;
use App\Http\Controllers\Controller;
use App\Traits\PaymentProcess;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Validator;
use Modules\Authentication\Models\User;
use Modules\Gateways\Models\PaymentRequest;
class SenangPayController extends Controller
{
use PaymentProcess;
private mixed $config_values;
private PaymentRequest $payment;
private User $user;
public function __construct(PaymentRequest $payment, User $user)
{
$paymentId = request()->query('payment_id');
$payment = PaymentRequest::where(['id' => $paymentId])->first();
$config = $this->paymentConfig('senang_pay', PAYMENT_CONFIG, $payment);
$this->config_values = $config->payment_info;
$this->payment = $payment;
$this->user = $user;
}
public function index(Request $request): View|Factory|JsonResponse|Application
{
$validator = Validator::make($request->all(), [
'payment_id' => 'required',
]);
if ($validator->fails()) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_400, null, $this->errorProcessor($validator)), 400);
}
$payment_data = $this->payment::where(['id' => $request['payment_id']])->where(['is_paid' => 0])->first();
if (! isset($payment_data)) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
$payer = json_decode($payment_data['payer_information']);
$config = $this->config_values;
session()->put('payment_id', $payment_data->id);
return view('Gateways::payment.senang-pay', compact('payment_data', 'payer', 'config'));
}
public function return_senang_pay(Request $request): JsonResponse|Redirector|RedirectResponse|Application
{
if ($request['status_id'] == 1) {
$this->payment::where(['id' => session()->get('payment_id')])->update([
'payment_method' => 'senang_pay',
'is_paid' => 1,
'transaction_id' => $request['transaction_id'],
]);
$data = $this->payment::where(['id' => session()->get('payment_id')])->first();
if (isset($data) && function_exists($data->hook)) {
call_user_func($data->hook, $data);
}
return $this->paymentResponse($data, 'success');
}
$payment_data = $this->payment::where(['id' => session()->get('payment_id')])->first();
if (isset($payment_data) && function_exists($payment_data->hook)) {
call_user_func($payment_data->hook, $payment_data);
}
return $this->paymentResponse($payment_data, 'fail');
}
}

View File

@@ -0,0 +1,226 @@
<?php
namespace Modules\Gateways\Http\Controllers\WEB;
use App\Http\Controllers\Controller;
use App\Traits\PaymentProcess;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Validator;
use Modules\Authentication\Models\User;
use Modules\Gateways\Models\PaymentRequest;
class SslCommerzPaymentController extends Controller
{
use PaymentProcess;
private $store_id;
private $store_password;
private bool $host;
private string $direct_api_url;
private PaymentRequest $payment;
private $user;
public function __construct(PaymentRequest $payment, User $user)
{
$paymentId = request()->query('payment_id');
$payment = PaymentRequest::where(['id' => $paymentId])->first();
$config = $this->paymentConfig('ssl_commerz', 'payment_config', $payment);
$values = $config->payment_info;
if ($config) {
$this->store_id = $values['store_id'];
$this->store_password = $values['store_password'];
// REQUEST SEND TO SSLCOMMERZ
$this->direct_api_url = 'https://sandbox.sslcommerz.com/gwprocess/v4/api.php';
$this->host = true;
if ($config->mode == 'live') {
$this->direct_api_url = 'https://securepay.sslcommerz.com/gwprocess/v4/api.php';
$this->host = false;
}
}
$this->payment = $payment;
$this->user = $user;
}
public function index(Request $request)
{
$validator = Validator::make($request->all(), [
'payment_id' => 'required',
]);
if ($validator->fails()) {
return response()->json($this->responseFormatter(DEFAULT_400, null, $this->errorProcessor($validator)), 400);
}
$data = $this->payment::where(['id' => $request['payment_id']])->where(['is_paid' => 0])->first();
if (! isset($data)) {
return response()->json($this->responseFormatter(DEFAULT_204), 200);
}
$payment_amount = $data['payment_amount'];
$post_data = [];
$post_data['store_id'] = $this->store_id;
$post_data['store_passwd'] = $this->store_password;
$post_data['total_amount'] = round($payment_amount, 2);
$post_data['currency'] = $data['currency_code'];
$post_data['tran_id'] = uniqid();
$post_data['success_url'] = url('/').'/payment/sslcommerz/success?payment_id='.$data['id'];
$post_data['fail_url'] = url('/').'/payment/sslcommerz/failed?payment_id='.$data['id'];
$post_data['cancel_url'] = url('/').'/payment/sslcommerz/canceled?payment_id='.$data['id'];
// CUSTOMER INFORMATION
$post_data['cus_name'] = $data->name;
$post_data['cus_email'] = $data->email ?? 'customer@gmail.com';
$post_data['cus_add1'] = 'N/A';
$post_data['cus_add2'] = '';
$post_data['cus_city'] = '';
$post_data['cus_state'] = '';
$post_data['cus_postcode'] = '';
$post_data['cus_country'] = '';
$post_data['cus_phone'] = $data->phone ?? '0000000000';
$post_data['cus_fax'] = '';
// SHIPMENT INFORMATION
$post_data['ship_name'] = 'N/A';
$post_data['ship_add1'] = 'N/A';
$post_data['ship_add2'] = 'N/A';
$post_data['ship_city'] = 'N/A';
$post_data['ship_state'] = 'N/A';
$post_data['ship_postcode'] = 'N/A';
$post_data['ship_phone'] = '';
$post_data['ship_country'] = 'N/A';
$post_data['shipping_method'] = 'NO';
$post_data['product_name'] = 'N/A';
$post_data['product_category'] = 'N/A';
$post_data['product_profile'] = 'service';
// OPTIONAL PARAMETERS
$post_data['value_a'] = 'ref001';
$post_data['value_b'] = 'ref002';
$post_data['value_c'] = 'ref003';
$post_data['value_d'] = 'ref004';
$handle = curl_init();
curl_setopt($handle, CURLOPT_URL, $this->direct_api_url);
curl_setopt($handle, CURLOPT_TIMEOUT, 30);
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($handle, CURLOPT_POST, 1);
curl_setopt($handle, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, $this->host); // KEEP IT FALSE IF YOU RUN FROM LOCAL PC
$content = curl_exec($handle);
$code = curl_getinfo($handle, CURLINFO_HTTP_CODE);
if ($code == 200 && ! (curl_errno($handle))) {
curl_close($handle);
$sslcommerzResponse = $content;
} else {
curl_close($handle);
return back();
}
$sslcz = json_decode($sslcommerzResponse, true);
if (isset($sslcz['GatewayPageURL']) && $sslcz['GatewayPageURL'] != '') {
echo "<meta http-equiv='refresh' content='0;url=".$sslcz['GatewayPageURL']."'>";
exit;
} else {
return response()->json($this->responseFormatter(DEFAULT_204), 200);
}
}
// FUNCTION TO CHECK HASH VALUE
protected function SSLCOMMERZ_hash_verify($store_passwd, $post_data)
{
if (isset($post_data) && isset($post_data['verify_sign']) && isset($post_data['verify_key'])) {
// NEW ARRAY DECLARED TO TAKE VALUE OF ALL POST
$pre_define_key = explode(',', $post_data['verify_key']);
$new_data = [];
if (! empty($pre_define_key)) {
foreach ($pre_define_key as $value) {
if (isset($post_data[$value])) {
$new_data[$value] = ($post_data[$value]);
}
}
}
// ADD MD5 OF STORE PASSWORD
$new_data['store_passwd'] = md5($store_passwd);
// SORT THE KEY AS BEFORE
ksort($new_data);
$hash_string = '';
foreach ($new_data as $key => $value) {
$hash_string .= $key.'='.($value).'&';
}
$hash_string = rtrim($hash_string, '&');
if (md5($hash_string) == $post_data['verify_sign']) {
return true;
} else {
$this->error = 'Verification signature not matched';
return false;
}
} else {
$this->error = 'Required data mission. ex: verify_key, verify_sign';
return false;
}
}
public function success(Request $request): JsonResponse|Redirector|RedirectResponse|Application
{
if ($request['status'] == 'VALID' && $this->SSLCOMMERZ_hash_verify($this->store_password, $request)) {
$this->payment::where(['id' => $request['payment_id']])->update([
'payment_method' => 'ssl_commerz',
'is_paid' => 1,
'transaction_id' => $request->input('tran_id'),
]);
$data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($data) && function_exists($data->hook)) {
call_user_func($data->hook, $data);
}
return $this->paymentResponse($data, 'success');
}
$data = $this->payment::where(['id' => $request['payment_id']])->first();
return $this->paymentResponse($data, 'fail');
}
public function failed(Request $request): JsonResponse|Redirector|RedirectResponse|Application
{
$data = $this->payment::where(['id' => $request['payment_id']])->first();
return $this->paymentResponse($data, 'fail');
}
public function canceled(Request $request): JsonResponse|Redirector|RedirectResponse|Application
{
$data = $this->payment::where(['id' => $request['payment_id']])->first();
return $this->paymentResponse($data, 'cancel');
}
}

View File

@@ -0,0 +1,127 @@
<?php
namespace Modules\Gateways\Http\Controllers\WEB;
use App\Traits\PaymentProcess;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Validator;
use Modules\Gateways\Models\PaymentRequest;
use Stripe\Checkout\Session;
use Stripe\Stripe;
class StripePaymentController extends Controller
{
use PaymentProcess;
private $config_values;
private PaymentRequest $payment;
public function __construct(PaymentRequest $payment)
{
// Skip all logic when running in console (artisan)
if (app()->runningInConsole()) {
return;
}
$paymentId = request()->query('payment_id');
$payment = PaymentRequest::find($paymentId);
if (! $payment) {
throw new \Exception('Payment not found!');
}
$config = $this->paymentConfig('stripe', PAYMENT_CONFIG, $payment);
if (! $config) {
throw new \Exception('Stripe payment config not found!');
}
$this->config_values = $config->payment_info;
$this->payment = $payment;
}
public function index(Request $request): View|Factory|JsonResponse|Application
{
$validator = Validator::make($request->all(), [
'payment_id' => 'required',
]);
if ($validator->fails()) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_400, null, $this->errorProcessor($validator)), 400);
}
$data = $this->payment::where(['id' => $request['payment_id']])->where(['is_paid' => 0])->first();
if (! isset($data)) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
$config = $this->config_values;
return view('payment.stripe', compact('data', 'config'));
}
public function payment_process_3d(Request $request): JsonResponse
{
$data = $this->payment::where(['id' => $request['payment_id']])->where(['is_paid' => 0])->first();
if (! isset($data)) {
return response()->json($this->responseFormatter(GATEWAYS_DEFAULT_204), 200);
}
$payment_amount = $data['payment_amount'];
Stripe::setApiKey($this->config_values['api_key']);
header('Content-Type: application/json');
$currency_code = $data->currency_code;
$checkout_session = Session::create([
'payment_method_types' => ['card'],
'line_items' => [[
'price_data' => [
'currency' => $currency_code ?? 'usd',
'unit_amount' => round($payment_amount, 2) * 100,
'product_data' => [
'name' => 'Fees Collection',
],
],
'quantity' => 1,
]],
'mode' => 'payment',
'success_url' => url('/').'/payment/stripe/success?session_id={CHECKOUT_SESSION_ID}&payment_id='.$data->id,
'cancel_url' => url()->previous(),
]);
return response()->json(['id' => $checkout_session->id]);
}
public function success(Request $request)
{
Stripe::setApiKey($this->config_values['api_key']);
$session = Session::retrieve($request->get('session_id'));
if ($session->payment_status == 'paid' && $session->status == 'complete') {
$this->payment::where(['id' => $request['payment_id']])->update([
'payment_method' => 'stripe',
'is_paid' => 1,
'transaction_id' => $session->payment_intent,
]);
$data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($data) && function_exists($data->success_hook)) {
call_user_func($data->success_hook, $data);
}
return $this->paymentResponse($data, 'success');
}
$payment_data = $this->payment::where(['id' => $request['payment_id']])->first();
if (isset($payment_data) && function_exists($payment_data->failure_hook)) {
call_user_func($payment_data->failure_hook, $payment_data);
}
return $this->paymentResponse($payment_data, 'fail');
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Modules\Gateways\Models;
use Illuminate\Database\Eloquent\Model;
class PaymentRequest extends Model
{
protected $fillable = [
'id',
'restaurant_id',
'receiver_id',
'payment_amount',
'gateway_callback_url',
'success_hook',
'failure_hook',
'transaction_id',
'currency_code',
'payment_method',
'payment_type',
'additional_data',
'is_paid',
'payer_information',
'external_redirect_link',
'receiver_information',
'attribute_id',
'package_id',
'notes',
'attribute',
'payment_platform',
];
protected $casts = [
'payer_information' => 'array',
];
}

View File

@@ -0,0 +1,30 @@
<?php
namespace Modules\Gateways\Providers;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event handler mappings for the application.
*
* @var array<string, array<int, string>>
*/
protected $listen = [];
/**
* Indicates if events should be discovered.
*
* @var bool
*/
protected static $shouldDiscoverEvents = true;
/**
* Configure the proper event listeners for email verification.
*/
protected function configureEmailVerification(): void
{
//
}
}

View File

@@ -0,0 +1,135 @@
<?php
namespace Modules\Gateways\Providers;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
use Nwidart\Modules\Traits\PathNamespace;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
class GatewaysServiceProvider extends ServiceProvider
{
use PathNamespace;
protected string $name = 'Gateways';
protected string $nameLower = 'gateways';
/**
* Boot the application events.
*/
public function boot(): void
{
$this->registerCommands();
$this->registerCommandSchedules();
$this->registerTranslations();
$this->registerConfig();
$this->registerViews();
$this->loadMigrationsFrom(module_path($this->name, 'database/migrations'));
}
/**
* Register the service provider.
*/
public function register(): void
{
$this->app->register(EventServiceProvider::class);
$this->app->register(RouteServiceProvider::class);
}
/**
* Register commands in the format of Command::class
*/
protected function registerCommands(): void
{
// $this->commands([]);
}
/**
* Register command Schedules.
*/
protected function registerCommandSchedules(): void
{
// $this->app->booted(function () {
// $schedule = $this->app->make(Schedule::class);
// $schedule->command('inspire')->hourly();
// });
}
/**
* Register translations.
*/
public function registerTranslations(): void
{
$langPath = resource_path('lang/modules/'.$this->nameLower);
if (is_dir($langPath)) {
$this->loadTranslationsFrom($langPath, $this->nameLower);
$this->loadJsonTranslationsFrom($langPath);
} else {
$this->loadTranslationsFrom(module_path($this->name, 'lang'), $this->nameLower);
$this->loadJsonTranslationsFrom(module_path($this->name, 'lang'));
}
}
/**
* Register config.
*/
protected function registerConfig(): void
{
$relativeConfigPath = config('modules.paths.generator.config.path');
$configPath = module_path($this->name, $relativeConfigPath);
if (is_dir($configPath)) {
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($configPath));
foreach ($iterator as $file) {
if ($file->isFile() && $file->getExtension() === 'php') {
$relativePath = str_replace($configPath.DIRECTORY_SEPARATOR, '', $file->getPathname());
$configKey = $this->nameLower.'.'.str_replace([DIRECTORY_SEPARATOR, '.php'], ['.', ''], $relativePath);
$key = ($relativePath === 'config.php') ? $this->nameLower : $configKey;
$this->publishes([$file->getPathname() => config_path($relativePath)], 'config');
$this->mergeConfigFrom($file->getPathname(), $key);
}
}
}
}
/**
* Register views.
*/
public function registerViews(): void
{
$viewPath = resource_path('views/modules/'.$this->nameLower);
$sourcePath = module_path($this->name, 'resources/views');
$this->publishes([$sourcePath => $viewPath], ['views', $this->nameLower.'-module-views']);
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->nameLower);
$componentNamespace = $this->module_namespace($this->name, $this->app_path(config('modules.paths.generator.component-class.path')));
Blade::componentNamespace($componentNamespace, $this->nameLower);
}
/**
* Get the services provided by the provider.
*/
public function provides(): array
{
return [];
}
private function getPublishableViewPaths(): array
{
$paths = [];
foreach (config('view.paths') as $path) {
if (is_dir($path.'/modules/'.$this->nameLower)) {
$paths[] = $path.'/modules/'.$this->nameLower;
}
}
return $paths;
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace Modules\Gateways\Providers;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
protected string $name = 'Gateways';
/**
* Called before routes are registered.
*
* Register any model bindings or pattern based filters.
*/
public function boot(): void
{
parent::boot();
}
/**
* Define the routes for the application.
*/
public function map(): void
{
$this->mapApiRoutes();
$this->mapWebRoutes();
}
/**
* Define the "web" routes for the application.
*
* These routes all receive session state, CSRF protection, etc.
*/
protected function mapWebRoutes(): void
{
Route::middleware('web')->group(module_path($this->name, '/routes/web.php'));
}
/**
* Define the "api" routes for the application.
*
* These routes are typically stateless.
*/
protected function mapApiRoutes(): void
{
Route::middleware('api')->prefix('api')->name('api.')->group(module_path($this->name, '/routes/api.php'));
}
}

View File

@@ -0,0 +1,30 @@
{
"name": "nwidart/gateways",
"description": "",
"authors": [
{
"name": "Nicolas Widart",
"email": "n.widart@gmail.com"
}
],
"extra": {
"laravel": {
"providers": [],
"aliases": {
}
}
},
"autoload": {
"psr-4": {
"Modules\\Gateways\\": "app/",
"Modules\\Gateways\\Database\\Factories\\": "database/factories/",
"Modules\\Gateways\\Database\\Seeders\\": "database/seeders/"
}
},
"autoload-dev": {
"psr-4": {
"Modules\\Gateways\\Tests\\": "tests/"
}
}
}

View File

@@ -0,0 +1,5 @@
<?php
return [
'name' => 'Gateways',
];

View File

@@ -0,0 +1,52 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Modules\Authentication\Models\Restaurant;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('payment_requests', function (Blueprint $table) {
$table->id(); // ✅ REQUIRED (auto increment)
$table->foreignIdFor(Restaurant::class)->constrained('restaurants')->cascadeOnDelete();
$table->string('payer_id', 64)->nullable();
$table->string('receiver_id', 64)->nullable();
$table->decimal('payment_amount', 24, 2)->default(0.00);
$table->string('gateway_callback_url', 191)->nullable();
$table->string('success_hook', 100)->nullable();
$table->string('failure_hook', 100)->nullable();
$table->string('transaction_id', 100)->nullable();
$table->string('currency_code', 20)->default('USD');
$table->string('payment_method', 50)->nullable();
$table->string('payment_type', 50)->nullable();
$table->string('name', 50)->nullable();
$table->string('phone', 25)->nullable();
$table->string('email', 50)->nullable();
$table->unsignedBigInteger('package_id')->nullable();
$table->string('notes', 50)->nullable();
$table->json('additional_data')->nullable();
$table->boolean('is_paid')->default(0);
$table->json('payer_information')->nullable();
$table->string('external_redirect_link', 255)->nullable();
$table->json('receiver_information')->nullable();
$table->string('attribute_id', 64)->nullable();
$table->string('attribute', 255)->nullable();
$table->string('payment_platform', 255)->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('payment_requests');
}
};

View File

@@ -0,0 +1,16 @@
<?php
namespace Modules\Gateways\Database\Seeders;
use Illuminate\Database\Seeder;
class GatewaysDatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$this->call([]);
}
}

View File

@@ -0,0 +1,11 @@
{
"name": "Gateways",
"alias": "gateways",
"description": "",
"keywords": [],
"priority": 0,
"providers": [
"Modules\\Gateways\\Providers\\GatewaysServiceProvider"
],
"files": []
}

View File

@@ -0,0 +1,15 @@
{
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"axios": "^1.1.2",
"laravel-vite-plugin": "^0.7.5",
"sass": "^1.69.5",
"postcss": "^8.3.7",
"vite": "^4.0.0"
}
}

View File

@@ -0,0 +1,9 @@
@extends('Gateways::layouts.master')
@section('content')
<h1>Hello World</h1>
<p>
This view is loaded from module: {!! config('Gateways.name') !!}
</p>
@endsection

View File

@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Module Gateways</title>
</head>
<body>
@yield('content')
</body>
</html>

View File

@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Configuration</title>
@stack('css')
</head>
<body>
@yield('payment')
<script src="{{asset('public/assets/modules/select2/select2.min.js')}}"></script>
@stack('script_2')
</body>
</html>

View File

@@ -0,0 +1,227 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<title>
@yield('title')
</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css"
href="{{ asset('public/assets/modules/payment/mercado_pogo/css/bootstrap.min.css') }}">
<link rel="stylesheet" type="text/css" href="{{ asset('public/assets/modules/payment/mercado_pogo/css/index.css') }}">
<script src="{{ asset('assets/admin-module/js/jquery-3.6.0.min.js') }}"></script>
<script src="https://sdk.mercadopago.com/js/v2"></script>
</head>
<body>
<main>
<!-- Hidden input to store your integration public key -->
<input type="hidden" id="mercado-pago-public-key" value="{{ $config->public_key }}">
<!-- Payment -->
<section class="payment-form dark">
<div class="container__payment">
<div class="block-heading">
<h2>Card Payment</h2>
<!-- <p>This is an example of a Mercado Pago integration</p> -->
</div>
<div class="form-payment">
<div class="products">
<p class="alert alert-danger d-none" role="alert" id="error_alert"></p>
<div class="total">Amount to be paid {{ $data->currency_code }}<span
class="price">{{ $data->payment_amount }}</span></div>
</div>
<div class="payment-details">
<form id="form-checkout">
<h3 class="title">Buyer Details</h3>
<div class="row">
<div class="form-group col">
<input id="form-checkout__cardholderEmail" name="cardholderEmail" type="email"
class="form-control" />
</div>
</div>
<div class="row">
<div class="form-group col-sm-5">
<select id="form-checkout__identificationType" name="identificationType"
class="form-control"></select>
</div>
<div class="form-group col-sm-7">
<input id="form-checkout__identificationNumber" name="docNumber" type="text"
class="form-control" />
</div>
</div>
<br>
<h3 class="title">Card Details</h3>
<div class="row">
<div class="form-group col-sm-8">
<input id="form-checkout__cardholderName" name="cardholderName" type="text"
class="form-control" />
</div>
<div class="form-group col-sm-4">
<div class="input-group expiration-date">
<input id="form-checkout__cardExpirationMonth" name="cardExpirationMonth"
type="text" class="form-control" />
<span class="date-separator">/</span>
<input id="form-checkout__cardExpirationYear" name="cardExpirationYear"
type="text" class="form-control" />
</div>
</div>
<div class="form-group col-sm-8">
<input id="form-checkout__cardNumber" name="cardNumber" type="text"
class="form-control" />
</div>
<div class="form-group col-sm-4">
<input id="form-checkout__securityCode" name="securityCode" type="text"
class="form-control" />
</div>
<div id="issuerInput" class="form-group col-sm-12 hidden">
<select id="form-checkout__issuer" name="issuer" class="form-control"></select>
</div>
<div class="form-group col-sm-12">
<select id="form-checkout__installments" name="installments" type="text"
class="form-control"></select>
</div>
<div class="form-group col-sm-12">
<br>
<button id="form-checkout__submit" type="submit"
class="btn btn--primary btn-block">Pay</button>
<br>
<p id="loading-message">Loading, please wait...</p>
<br>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
</main>
</body>
<script>
"use strict";
const publicKey = document.getElementById("mercado-pago-public-key").value;
const mercadopago = new MercadoPago(publicKey);
loadCardForm();
function loadCardForm() {
const productCost = '{{ $data->payment_amount }}';
const cardForm = mercadopago.cardForm({
amount: productCost,
autoMount: true,
form: {
id: "form-checkout",
cardholderName: {
id: "form-checkout__cardholderName",
placeholder: "Card holder name",
},
cardholderEmail: {
id: "form-checkout__cardholderEmail",
placeholder: "Card holder email",
},
cardNumber: {
id: "form-checkout__cardNumber",
placeholder: "Card number",
},
cardExpirationMonth: {
id: "form-checkout__cardExpirationMonth",
placeholder: "MM",
},
cardExpirationYear: {
id: "form-checkout__cardExpirationYear",
placeholder: "YY",
},
securityCode: {
id: "form-checkout__securityCode",
placeholder: "Security code",
},
installments: {
id: "form-checkout__installments",
placeholder: "Installments",
},
identificationType: {
id: "form-checkout__identificationType",
},
identificationNumber: {
id: "form-checkout__identificationNumber",
placeholder: "Identification number",
},
issuer: {
id: "form-checkout__issuer",
placeholder: "Issuer",
},
},
callbacks: {
onFormMounted: error => {
if (error)
return console.warn("Form Mounted handling error: ", error);
},
onSubmit: event => {
event.preventDefault();
document.getElementById("loading-message").style.display = "block";
const {
paymentMethodId,
issuerId,
cardholderEmail: email,
amount,
token,
installments,
identificationNumber,
identificationType,
} = cardForm.getCardFormData();
fetch("{{ route('mercadopago.make_payment', ['payment_id' => $data->id]) }}", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-TOKEN": "{{ csrf_token() }}"
},
body: JSON.stringify({
token,
issuerId,
paymentMethodId,
transactionAmount: Number(amount),
installments: Number(installments),
payer: {
email,
identification: {
type: identificationType,
number: identificationNumber,
},
},
}),
})
.then(response => {
return response.json();
})
.then(result => {
if (result.error) {
document.getElementById("loading-message").style.display = "none";
document.getElementById("error_alert").innerText = result.error;
document.getElementById("error_alert").style.display = "block";
return false;
}
location.href = '{{ route('payment-success') }}';
})
.catch(error => {
document.getElementById("loading-message").style.display = "none";
document.getElementById("error_alert").innerHtml = error;
document.getElementById("error_alert").style.display = "block";
});
},
onFetching: (resource) => {
const payButton = document.getElementById("form-checkout__submit");
payButton.setAttribute('disabled', true);
return () => {
payButton.removeAttribute("disabled");
};
},
},
});
}
</script>
</html>

View File

@@ -0,0 +1,38 @@
@extends('payment.layouts.master')
@push('script')
@endpush
@section('content')
<center>
<div class="loader"></div>
</center>
<form method="POST" action="{!! route('paystack.payment', ['token' => $data->id]) !!}" accept-charset="UTF-8" class="form-horizontal" role="form">
@csrf
<div class="row">
<div class="col-md-8 col-md-offset-2">
<input type="hidden" name="email"
value="{{ $payer->email != null ? $payer->email : 'required@email.com' }}">
{{-- required --}}
<input type="hidden" name="orderID" value="{{ $data->attribute_id }}">
<input type="hidden" name="amount" value="{{ $data->payment_amount * 100 }}"> {{-- required in kobo --}}
<input type="hidden" name="quantity" value="1">
<input type="hidden" name="currency" value="{{ $data->currency_code }}">
<input type="hidden" name="metadata" value="{{ json_encode($array = ['key_name' => 'value']) }}">
{{-- For other necessary things you want to add to your payload. it is optional though --}}
<input type="hidden" name="reference" value="{{ $reference }}"> {{-- required --}}
<button class="btn btn-block d-none" id="pay-button" type="submit"></button>
</div>
</div>
</form>
<script type="text/javascript">
"use strict";
document.addEventListener("DOMContentLoaded", function() {
document.getElementById("pay-button").click();
});
</script>
@endsection

View File

@@ -0,0 +1,28 @@
@extends('payment.layouts.master')
@push('script')
@endpush
@section('content')
<center>
<div class="loader"></div>
</center>
<form method="post" action="<?php echo \Illuminate\Support\Facades\Config::get('paytm_config.PAYTM_TXN_URL'); ?>" id="form">
<table border="1">
<tbody>
@foreach ($paramList as $name => $value)
<input type="hidden" name="{{ $name }}" value="{{ $value }}">
@endforeach
<input type="hidden" name="CHECKSUMHASH" value="{{ $checkSum }}">
</tbody>
</table>
</form>
<script type="text/javascript">
"use strict";
document.addEventListener("DOMContentLoaded", function() {
document.getElementById("form").submit();
});
</script>
@endsection

View File

@@ -0,0 +1,51 @@
@extends('payment.layouts.master')
@push('script')
<style>
.razorpay-cancel-button {
border: 1px solid #0000008c;
border-radius: 2px;
margin: 0;
font-size: 14px;
padding: .125rem 1rem;
}
.d-none {
display: none;
}
</style>
@endpush
@section('content')
<center>
<div class="loader"></div>
</center>
<form action="{!! route('razor-pay.payment', ['payment_id' => $data->id]) !!}" id="form" method="POST">
@csrf
<script src="https://checkout.razorpay.com/v1/checkout.js" data-key="{{ config()->get('razor_config.api_key') }}"
data-amount="{{ round($data->payment_amount, 2) * 100 }}"
data-buttontext="Pay {{ round($data->payment_amount, 2) . ' ' . $data->currency_code }}"
data-name="{{ $business_name ?? '' }}" data-description="{{ $data->payment_amount }}"
data-image="{{ $business_logo ?? '' }}" data-prefill.name="{{ $payer->name ?? '' }}"
data-prefill.email="{{ $payer->email ?? '' }}" data-prefill.contact="{{ $payer->phone ?? '' }}"
data-callback_url="{{ route('razor-pay.callback', ['payment_data' => base64_encode($data->id)]) }}"
data-theme.color="#ff7529"></script>
<button class="btn btn-block d-none" id="pay-button" type="submit"></button>
<button class="razorpay-cancel-button" type="button" id="cancel-button" onclick="handleCancel()">Cancel</button>
</form>
@push('script')
<script type="text/javascript">
"use strict";
document.addEventListener("DOMContentLoaded", function() {
document.getElementById("pay-button").click();
});
function handleCancel() {
window.location.href = '{{ route('razor-pay.cancel', ['payment_id' => $data->id]) }}';
}
</script>
@endpush
@endsection

View File

@@ -0,0 +1,35 @@
@extends('payment.layouts.master')
@push('script')
<script src="https://polyfill.io/v3/polyfill.min.js?version=3.52.1&features=fetch"></script>
<script src="https://js.stripe.com/v3/"></script>
@endpush
@section('content')
<center>
<div class="loader"></div>
</center>
<script type="text/javascript">
"use strict";
// Create an instance of the Stripe object with your publishable API key
let stripe = Stripe('{{ $config->published_key }}');
document.addEventListener("DOMContentLoaded", function() {
fetch("{{ url("payment/stripe/token/?payment_id={$data->id}") }}", {
method: "GET",
}).then(function(response) {
return response.text();
}).then(function(session) {
return stripe.redirectToCheckout({
sessionId: JSON.parse(session).id
});
}).then(function(result) {
if (result.error) {
alert(result.error.message);
}
}).catch(function(error) {
console.error("error:", error);
});
});
</script>
@endsection

View File

@@ -0,0 +1,16 @@
<?php
use Illuminate\Support\Facades\Route;
use Modules\Gateways\Http\Controllers\API\PaymentController;
Route::middleware('auth:api')->prefix('v1')->group(function () {
// Digital Payment API
Route::get('digital-payment', [PaymentController::class, 'index']);
Route::put('digital-payment/{settingId}', [PaymentController::class, 'update']);
Route::post('digital-payment', [PaymentController::class, 'payment']);
Route::get('digital-payment-status/{settingId}', [PaymentController::class, 'statusUpdate']);
Route::get('saas-digital-payment', [PaymentController::class, 'saasIndex']);
Route::put('saas-digital-payment/{settingId}', [PaymentController::class, 'saasUpdate']);
Route::get('saas-digital-payment-status/{settingId}', [PaymentController::class, 'saasStatusUpdate']);
});

View File

@@ -0,0 +1,131 @@
<?php
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
use Illuminate\Support\Facades\Route;
use Modules\Gateways\Http\Controllers\API\PaymentController;
use Modules\Gateways\Http\Controllers\WEB\BkashPaymentController;
use Modules\Gateways\Http\Controllers\WEB\FlutterwaveV3Controller;
use Modules\Gateways\Http\Controllers\WEB\LiqPayController;
use Modules\Gateways\Http\Controllers\WEB\MercadoPagoController;
use Modules\Gateways\Http\Controllers\WEB\PaymobController;
use Modules\Gateways\Http\Controllers\WEB\PaypalPaymentController;
use Modules\Gateways\Http\Controllers\WEB\PaystackController;
use Modules\Gateways\Http\Controllers\WEB\PaytabsController;
use Modules\Gateways\Http\Controllers\WEB\PaytmController;
use Modules\Gateways\Http\Controllers\WEB\PvitController;
use Modules\Gateways\Http\Controllers\WEB\RazorPayController;
use Modules\Gateways\Http\Controllers\WEB\SenangPayController;
use Modules\Gateways\Http\Controllers\WEB\SslCommerzPaymentController;
use Modules\Gateways\Http\Controllers\WEB\StripePaymentController;
// Payment API Group
Route::group(['prefix' => 'payment'], function () {
// STRIPE Payment Routes
Route::group(['prefix' => 'stripe', 'as' => 'stripe.'], function () {
Route::get('pay', [StripePaymentController::class, 'index'])->name('pay');
Route::get('token', [StripePaymentController::class, 'payment_process_3d'])->name('token');
Route::get('success', [StripePaymentController::class, 'success'])->name('success');
});
// RAZOR-PAY
Route::group(['prefix' => 'razor-pay', 'as' => 'razor-pay.'], function () {
Route::get('pay', [RazorPayController::class, 'index']);
Route::post('payment', [RazorPayController::class, 'payment'])->name('payment')
->withoutMiddleware([VerifyCsrfToken::class]);
Route::post('callback', [RazorPayController::class, 'callback'])->name('callback')
->withoutMiddleware([VerifyCsrfToken::class]);
Route::any('cancel', [RazorPayController::class, 'cancel'])->name('cancel')
->withoutMiddleware([VerifyCsrfToken::class]);
});
// SSLCOMMERZ
Route::group(['prefix' => 'sslcommerz', 'as' => 'sslcommerz.'], function () {
Route::get('pay', [SslCommerzPaymentController::class, 'index'])->name('pay');
Route::post('success', [SslCommerzPaymentController::class, 'success'])
->withoutMiddleware([VerifyCsrfToken::class]);
Route::post('failed', [SslCommerzPaymentController::class, 'failed'])
->withoutMiddleware([VerifyCsrfToken::class]);
Route::post('canceled', [SslCommerzPaymentController::class, 'canceled'])
->withoutMiddleware([VerifyCsrfToken::class]);
});
// PAYPAL
Route::group(['prefix' => 'paypal', 'as' => 'paypal.'], function () {
Route::get('pay', [PaypalPaymentController::class, 'payment']);
Route::any('success', [PaypalPaymentController::class, 'success'])->name('success')
->withoutMiddleware([VerifyCsrfToken::class]);
Route::any('cancel', [PaypalPaymentController::class, 'cancel'])->name('cancel')
->withoutMiddleware([VerifyCsrfToken::class]);
});
// SENANG-PAY
Route::group(['prefix' => 'senang-pay', 'as' => 'senang-pay.'], function () {
Route::get('pay', [SenangPayController::class, 'index']);
Route::any('callback', [SenangPayController::class, 'return_senang_pay']);
});
// PAYTM
Route::group(['prefix' => 'paytm', 'as' => 'paytm.'], function () {
Route::get('pay', [PaytmController::class, 'payment']);
Route::any('response', [PaytmController::class, 'response'])->name('response');
});
// FLUTTERWAVE
Route::group(['prefix' => 'flutterwave-v3', 'as' => 'flutterwave-v3.'], function () {
Route::get('pay', [FlutterwaveV3Controller::class, 'initialize'])->name('pay');
Route::get('callback', [FlutterwaveV3Controller::class, 'callback'])->name('callback');
});
// PAYSTACK
Route::group(['prefix' => 'paystack', 'as' => 'paystack.'], function () {
Route::get('pay', [PaystackController::class, 'index'])->name('pay');
Route::post('payment', [PaystackController::class, 'redirectToGateway'])->name('payment');
Route::get('callback', [PaystackController::class, 'handleGatewayCallback'])->name('callback');
});
// BKASH
Route::group(['prefix' => 'bkash', 'as' => 'bkash.'], function () {
// Payment Routes for bKash
Route::get('make-payment', [BkashPaymentController::class, 'make_tokenize_payment'])->name('make-payment');
Route::any('callback', [BkashPaymentController::class, 'callback'])->name('callback');
});
// Liqpay
Route::group(['prefix' => 'liqpay', 'as' => 'liqpay.'], function () {
Route::get('payment', [LiqPayController::class, 'payment'])->name('payment');
Route::any('callback', [LiqPayController::class, 'callback'])->name('callback');
});
// MERCADOPAGO
Route::group(['prefix' => 'mercadopago', 'as' => 'mercadopago.'], function () {
Route::get('pay', [MercadoPagoController::class, 'index'])->name('index');
Route::post('make-payment', [MercadoPagoController::class, 'make_payment'])->name('make_payment');
});
// PAYMOB
Route::group(['prefix' => 'paymob', 'as' => 'paymob.'], function () {
Route::any('pay', [PaymobController::class, 'credit'])->name('pay');
Route::any('callback', [PaymobController::class, 'callback'])->name('callback');
});
// PAYTABS
Route::group(['prefix' => 'paytabs', 'as' => 'paytabs.'], function () {
Route::any('pay', [PaytabsController::class, 'payment'])->name('pay');
Route::any('callback', [PaytabsController::class, 'callback'])->name('callback');
Route::any('response', [PaytabsController::class, 'response'])->name('response');
});
// Pvit
Route::group(['prefix' => 'pvit', 'as' => 'pvit.'], function () {
Route::any('pay', [PvitController::class, 'payment'])->name('pay')
->withoutMiddleware([VerifyCsrfToken::class]);
Route::any('callback', [PvitController::class, 'callBack'])->name('callBack')
->withoutMiddleware([VerifyCsrfToken::class]);
});
});
Route::controller(PaymentController::class)->group(function () {
Route::get('web-payment', 'web_payment_success')->name('web-payment-success');
Route::get('payment-success', 'success')->name('payment-success');
Route::get('payment-fail', 'fail')->name('payment-fail');
});

View File

@@ -0,0 +1,21 @@
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
build: {
outDir: '../../public/build-gateways',
emptyOutDir: true,
manifest: true,
},
plugins: [
laravel({
publicDirectory: '../../public',
buildDirectory: 'build-gateways',
input: [
__dirname + '/resources/assets/sass/app.scss',
__dirname + '/resources/assets/js/app.js'
],
refresh: true,
}),
],
});