authService.tsx 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. import axios from 'axios';
  2. import { Alert } from 'react-native';
  3. import * as SecureStore from 'expo-secure-store';
  4. import { EXPO_PUBLIC_API_URL } from '@env';
  5. import { forgetPasswordFormData } from '../types/signup';
  6. import { CustomerData } from '../types/signUpFormData';
  7. import * as FileSystem from 'expo-file-system';
  8. class AuthenticationService {
  9. private apiUrl: string;
  10. constructor() {
  11. this.apiUrl = EXPO_PUBLIC_API_URL;
  12. if (!this.apiUrl) {
  13. throw new Error('API URL is not defined in environment variables');
  14. }
  15. }
  16. async emailLogin(username: string, password: string, isBinding?: boolean) {
  17. try {
  18. console.log('username in emailLogin auth service', username);
  19. console.log('password in emailLogin auth service', password);
  20. console.log('isBinding in emailLogin auth service', isBinding);
  21. const response = await axios.post(
  22. `${this.apiUrl}/public/client/customer/sign-in`,
  23. {
  24. email: username,
  25. password: password,
  26. isBinding: isBinding
  27. },
  28. {
  29. headers: {
  30. 'Content-Type': 'application/json',
  31. Accept: 'application/json'
  32. }
  33. }
  34. );
  35. if (response.status === 201) {
  36. const token = response.data.accessToken;
  37. await SecureStore.setItemAsync('accessToken', token);
  38. console.log('AccessToken', token);
  39. console.log('Login successful!');
  40. return true;
  41. } else {
  42. console.error('Login failed:', response.status);
  43. return false;
  44. }
  45. } catch (error) {
  46. if (axios.isAxiosError(error)) {
  47. console.error('Login error:', error.response?.data?.message || error.message);
  48. } else {
  49. console.error('An unexpected error occurred:', error);
  50. }
  51. return false;
  52. }
  53. }
  54. async phoneLogin(username: string, password: string, isBinding?: boolean) {
  55. try {
  56. console.log('username', username);
  57. console.log('password', password);
  58. console.log('isBinding', isBinding);
  59. const response = await axios.post(
  60. // `${this.apiUrl}/public/client/customer/sign-in`,
  61. // `${this.apiUrl}/public/client/customer/sign-in`,
  62. `${this.apiUrl}/public/client/customer/phone/sign-in`,
  63. {
  64. phone: username,
  65. password: password,
  66. isBinding: isBinding
  67. },
  68. {
  69. headers: {
  70. 'Content-Type': 'application/json',
  71. Accept: 'application/json'
  72. }
  73. }
  74. );
  75. if (response.status === 201) {
  76. const token = response.data.accessToken;
  77. await SecureStore.setItemAsync('accessToken', token);
  78. console.log('AccessToken', token);
  79. console.log('Login successful!');
  80. return true;
  81. } else {
  82. console.error('Login failed:', response.status);
  83. return false;
  84. }
  85. } catch (error) {
  86. if (axios.isAxiosError(error)) {
  87. console.error('Login error:', error.response?.data?.message || error.message);
  88. } else {
  89. console.error('An unexpected error occurred:', error);
  90. }
  91. return false;
  92. }
  93. }
  94. async logout() {
  95. await SecureStore.deleteItemAsync('accessToken');
  96. console.log('log out successfully, accessToken deleted');
  97. }
  98. //BELOW CODES RELATE TO "SIGN UP"
  99. //BELOW CODES RELATE TO "SIGN UP"
  100. async sendOtpToSignUpEmail(email: string) {
  101. try {
  102. const response = await axios.post(
  103. `${this.apiUrl}/public/client/customer/otp`,
  104. { email: email },
  105. {
  106. headers: {
  107. 'Content-Type': 'application/json',
  108. Accept: 'application/json'
  109. }
  110. }
  111. );
  112. if (response.status === 200 || response.status === 201) {
  113. console.log('OTP sent successfully');
  114. return true;
  115. } else {
  116. console.error('Failed to send OTP:', response.status);
  117. return false;
  118. }
  119. } catch (error) {
  120. if (axios.isAxiosError(error)) {
  121. console.error('Error sending OTP:', error.response?.data?.message || error.message);
  122. } else {
  123. console.error('An unexpected error occurred while sending OTP:', error);
  124. }
  125. return false;
  126. }
  127. }
  128. async uploadUberImage(imageUri: string, customFileName: string) {
  129. try {
  130. const fileInfo = await FileSystem.getInfoAsync(imageUri);
  131. if (!fileInfo.exists) {
  132. throw new Error('File does not exist');
  133. }
  134. const fileExtension = imageUri.split('.').pop().toLowerCase();
  135. const allowedExtensions = ['jpg', 'jpeg', 'png'];
  136. if (!allowedExtensions.includes(fileExtension)) {
  137. throw new Error('只接受jpg,jpeg,png格式的圖片');
  138. }
  139. const formData = new FormData();
  140. const fileName = customFileName || imageUri.split('/').pop();
  141. formData.append('file', {
  142. uri: imageUri,
  143. name: fileName,
  144. type: `image/${fileExtension}`
  145. } as any);
  146. const accessToken = await SecureStore.getItemAsync('accessToken');
  147. const response = await axios.post(`${this.apiUrl}/clients/customer/image?type=uber`, formData, {
  148. headers: {
  149. accept: '*/*',
  150. 'Content-Type': 'multipart/form-data',
  151. Authorization: `Bearer ${accessToken}`
  152. }
  153. });
  154. console.log('Upload response:', response.data);
  155. return response.data;
  156. } catch (error) {
  157. console.error('Error uploading image:', error);
  158. throw error;
  159. }
  160. }
  161. async verifySignUpOtp(
  162. email: string,
  163. code: string,
  164. setScreen: React.Dispatch<React.SetStateAction<number>>,
  165. setError: React.Dispatch<React.SetStateAction<string>>
  166. ) {
  167. try {
  168. const response = await axios.put(
  169. `${this.apiUrl}/public/client/customer/otp`,
  170. { email, code },
  171. {
  172. headers: {
  173. 'Content-Type': 'application/json',
  174. Accept: 'application/json'
  175. }
  176. }
  177. );
  178. if (response.status === 200) {
  179. console.log('OTP verified successfully');
  180. setScreen((currentScreenNumber: number) => currentScreenNumber + 1);
  181. return true;
  182. } else {
  183. console.error('OTP verification failed:', response.status);
  184. setError('OTP驗證碼錯誤');
  185. return false;
  186. }
  187. } catch (error) {
  188. if (axios.isAxiosError(error)) {
  189. console.error('Error verifying OTP:', error.response?.data?.message || error.message);
  190. setError('發生意外錯誤,請確保您輸入的電子郵件正確,並再次確認您的OTP驗證碼是否正確。');
  191. } else {
  192. console.error('An unexpected error occurred while verifying OTP:', error);
  193. setError('發生意外錯誤,請稍後再試');
  194. }
  195. return false;
  196. }
  197. }
  198. async signUp(data: CustomerData) {
  199. try {
  200. const response = await axios.post(`${this.apiUrl}/public/client/customer`, data, {
  201. headers: {
  202. 'Content-Type': 'application/json',
  203. Accept: 'application/json'
  204. }
  205. });
  206. console.log('Signup response.data:', response.data);
  207. console.log('Signup response.status:', response.status);
  208. if (response.status === 200 || response.status === 201) {
  209. console.log('Signup successful');
  210. return true;
  211. } else {
  212. console.error('Signup failed:', response.status);
  213. return false;
  214. }
  215. } catch (error) {
  216. if (axios.isAxiosError(error)) {
  217. console.error('Error signing up:', error.response?.data?.message || error.message);
  218. } else {
  219. console.error('An unexpected error occurred while signing up:', error);
  220. }
  221. return false;
  222. }
  223. }
  224. //BELOW CODES RELATE TO "FORGET PASSWORD"
  225. //BELOW CODES RELATE TO "FORGET PASSWORD"
  226. async sendForgetPasswordOtp(email: string) {
  227. try {
  228. const response = await axios.post(
  229. `${this.apiUrl}/public/client/customer/pw/otp`,
  230. { email },
  231. {
  232. headers: {
  233. 'Content-Type': 'application/json',
  234. Accept: 'application/json'
  235. }
  236. }
  237. );
  238. if (response.status === 200 || response.status === 201) {
  239. console.log('Forget password OTP sent successfully');
  240. return true;
  241. } else {
  242. console.error('Failed to send forget password OTP:', response.status);
  243. return false;
  244. }
  245. } catch (error) {
  246. if (axios.isAxiosError(error)) {
  247. console.error('Error sending forget password OTP:', error.response?.data?.message || error.message);
  248. } else {
  249. console.error('An unexpected error occurred while sending forget password OTP:', error);
  250. }
  251. return false;
  252. }
  253. }
  254. async getVersion() {
  255. try {
  256. const response = await axios.get(`${this.apiUrl}/public/client/app/version`);
  257. return response.data.data;
  258. } catch (error) {
  259. console.error('Error getting version:', error);
  260. return null;
  261. }
  262. }
  263. async verifyingOtpForgetPassword(
  264. email: string,
  265. otp: string,
  266. setForgetPasswordFormData: React.Dispatch<React.SetStateAction<forgetPasswordFormData>>,
  267. setData: React.Dispatch<React.SetStateAction<string>>
  268. ) {
  269. try {
  270. const res = await axios.put(`${this.apiUrl}/public/client/customer/pw/otp`, {
  271. email: email,
  272. code: otp
  273. });
  274. const data = res.data;
  275. setData(data.msg);
  276. console.log(data.msg);
  277. setForgetPasswordFormData((prevFormData) => ({
  278. ...prevFormData,
  279. otpAuthCompleted: true
  280. }));
  281. return true;
  282. } catch (error) {
  283. console.error('Error', error);
  284. return false;
  285. }
  286. }
  287. async changePassword(confirmedNewPassword: string, data: string) {
  288. try {
  289. const res = await axios.put(
  290. `${this.apiUrl}/clients/customer/pw/forget`,
  291. { newPassword: confirmedNewPassword },
  292. {
  293. headers: {
  294. Authorization: `Bearer ${data}`
  295. }
  296. }
  297. );
  298. return true;
  299. } catch (error) {
  300. if (axios.isAxiosError(error)) {
  301. console.error('Error changing password:', error.response?.data?.message || error.message);
  302. } else {
  303. console.error('An unexpected error occurred:', error);
  304. }
  305. }
  306. }
  307. //BELOW CODES RELATE TO "changing account info (such as gender, name)"
  308. //BELOW CODES RELATE TO "changing account info (such as gender, name)"
  309. async changeName(name: string | null, token: string | null): Promise<boolean> {
  310. try {
  311. const res = await axios.put(
  312. `${this.apiUrl}/clients/customer`,
  313. { nickname: name },
  314. {
  315. headers: {
  316. Authorization: `Bearer ${token}`
  317. }
  318. }
  319. );
  320. console.log('Change Name Successfully!');
  321. return true;
  322. } catch (error) {
  323. if (axios.isAxiosError(error)) {
  324. console.error('Error changing name:', error.response?.data?.message);
  325. } else {
  326. console.error('An unexpected error occurred:', error);
  327. }
  328. return false;
  329. }
  330. }
  331. async changePhone(phone: string | null, token: string | null): Promise<boolean> {
  332. try {
  333. const convertPhoneStringToNumber = Number(phone);
  334. const res = await axios.put(
  335. `${this.apiUrl}/clients/customer`,
  336. { phone: convertPhoneStringToNumber },
  337. {
  338. headers: {
  339. Authorization: `Bearer ${token}`
  340. }
  341. }
  342. );
  343. console.log('Change Phone Successfully!');
  344. return true;
  345. } catch (error) {
  346. if (axios.isAxiosError(error)) {
  347. console.error('Error changing phone:', error.response?.data?.message);
  348. } else {
  349. console.error('An unexpected error occurred:', error);
  350. }
  351. return false;
  352. }
  353. }
  354. async changeGender(gender: string | null, token: string | null): Promise<boolean> {
  355. try {
  356. const res = await axios.put(
  357. `${this.apiUrl}/clients/customer`,
  358. { gender: gender },
  359. {
  360. headers: {
  361. Authorization: `Bearer ${token}`
  362. }
  363. }
  364. );
  365. console.log('Change gender Successfully!');
  366. return true;
  367. } catch (error) {
  368. if (axios.isAxiosError(error)) {
  369. console.error('Error changing gender:', error.response?.data?.message);
  370. } else {
  371. console.error('An unexpected error occurred:', error);
  372. }
  373. return false;
  374. }
  375. }
  376. async getUserInfo() {
  377. try {
  378. const response = await axios.get(`${this.apiUrl}/clients/customer`, {
  379. headers: {
  380. Authorization: `Bearer ${await SecureStore.getItemAsync('accessToken')}`
  381. }
  382. });
  383. if (response.status === 200 || response.status === 201) {
  384. // console.log(response);
  385. return response;
  386. } else {
  387. console.log('invalid response');
  388. }
  389. } catch (error) {
  390. console.log(error);
  391. }
  392. }
  393. async deleteAccount(): Promise<boolean> {
  394. try {
  395. const accessToken = await SecureStore.getItemAsync('accessToken');
  396. const response = await axios.delete(`${this.apiUrl}/clients/customer`, {
  397. headers: {
  398. Authorization: `Bearer ${accessToken}`
  399. }
  400. });
  401. if (response.status === 200 || response.status === 201) {
  402. console.log('Account deleted successfully');
  403. return true;
  404. } else {
  405. console.error('Failed to delete account:', response.status);
  406. return false;
  407. }
  408. } catch (error) {
  409. if (axios.isAxiosError(error)) {
  410. console.error('Error deleting account:', error.response?.data?.message || error.message);
  411. } else {
  412. console.error('An unexpected error occurred while deleting account:', error);
  413. }
  414. return false;
  415. }
  416. }
  417. async checkPhoneSame(phoneNumber: string) {
  418. try {
  419. console.log('being checkPhoneSame');
  420. const response = await axios.post(
  421. `${this.apiUrl}/clients/customer/binding/sms`,
  422. {
  423. phone: phoneNumber,
  424. type: 3
  425. },
  426. {
  427. headers: {
  428. Authorization: `Bearer ${await SecureStore.getItemAsync('accessToken')}`
  429. }
  430. }
  431. );
  432. const token = await SecureStore.getItemAsync('accessToken');
  433. console.log('accessToken', token);
  434. console.log('checkPhoneSame response', response.data);
  435. return response.data;
  436. } catch (error) {
  437. console.log(error);
  438. }
  439. }
  440. async confirmBindingPhone(phoneNumber: string, otp: string, notify_session_id: string) {
  441. try {
  442. const response = await axios.put(
  443. `${this.apiUrl}/public/client/customer/phone/otp`,
  444. {
  445. phone: phoneNumber,
  446. code: otp,
  447. notify_session_id: notify_session_id,
  448. type: 3
  449. },
  450. {
  451. headers: {
  452. 'Content-Type': 'application/json',
  453. Accept: 'application/json'
  454. }
  455. }
  456. );
  457. console.log('confirmBindingPhone response', response.data);
  458. return response.data;
  459. } catch (error) {
  460. console.log(error);
  461. }
  462. }
  463. async verifyPhoneOtp(phoneNumber: string, otp: string, notify_session_id: string) {
  464. try {
  465. const response = await axios.put(
  466. `${this.apiUrl}/public/client/customer/phone/otp`,
  467. {
  468. phone: phoneNumber,
  469. code: otp,
  470. notify_session_id: notify_session_id
  471. },
  472. {
  473. headers: {
  474. 'Content-Type': 'application/json',
  475. Accept: '*/*'
  476. }
  477. }
  478. );
  479. console.log('verifyPhoneOtp response:', response.data);
  480. return response.data;
  481. } catch (error) {
  482. if (axios.isAxiosError(error)) {
  483. console.error('Error verifying phone OTP:', error.response?.data || error.message);
  484. throw error;
  485. } else {
  486. console.error('Unexpected error:', error);
  487. throw new Error('Failed to verify phone OTP');
  488. }
  489. }
  490. }
  491. async sendOtpToSignUpPhone(phone: string) {
  492. try {
  493. const response = await axios.post(`${this.apiUrl}/public/client/customer/phone/sms`, {
  494. phone: phone,
  495. type: 1
  496. });
  497. if (response.status === 200 || response.status === 201) {
  498. console.log('OTP sent successfully -- from api sendOtpToSignUpPhone, response:', response);
  499. return true;
  500. } else {
  501. console.error('Failed to send OTP -- from api sendOtpToSignUpPhone.. response:', response);
  502. return false;
  503. }
  504. } catch (error) {
  505. console.log(error);
  506. }
  507. }
  508. }
  509. export const authenticationService = new AuthenticationService();