Browse Source

update pay

warrior 2 months ago
parent
commit
74ef494bd5

+ 0 - 1
projects/live-app/src/app/components/pay-comp/pay-comp.component.html

@@ -11,7 +11,6 @@
         <ion-icon name="close-outline"></ion-icon>
       </div>
       @if (!codeLink) {
-
       <div class="pay-title">支付订单</div>
       <div class="pay-num">¥{{ price || 0 }}</div>
       <div class="options">

+ 135 - 59
projects/live-app/src/app/components/pay-comp/pay-comp.component.ts

@@ -4,6 +4,7 @@ import { AlertController, IonicModule, ToastController } from '@ionic/angular';
 import { ActivatedRoute } from '@angular/router';
 import { AccountService } from '../../../services/account.service';
 import { HttpClient } from '@angular/common/http';
+import * as Parse from 'parse';
 declare var wx: any;
 
 @Component({
@@ -15,12 +16,20 @@ declare var wx: any;
 })
 export class PayCompComponent implements OnInit {
   @Input('price') price!: number;
-  @Input('tradeNo') tradeNo: string = 'C20241215050401'; //支付单号
-  @Output() onChange: EventEmitter<any> = new EventEmitter<any>();
+  @Input('gid') gid: string | undefined;
+  @Input('orderType') orderType!: string; //订单类型
+  @Input('tradeNo') tradeNo: string | undefined; //支付单号
+  @Input('title') title: string = '会员购买';
+
+  @Output() payResult: EventEmitter<any> = new EventEmitter<any>();
+
+  @Input('orderId') orderId?: string;
   isOpen: boolean = true; //打开弹窗
   checkpay: string = 'wxpay';
   userAgent?: string; //获取当前浏览器环境
-  codeLink?:string
+  codeLink?: string;
+  user: Parse.Object = Parse.User.current()!;
+  timer: any; //定时查询
 
   constructor(
     private accServ: AccountService,
@@ -45,17 +54,35 @@ export class PayCompComponent implements OnInit {
     this.checkpay = val;
     console.log(val);
   }
-  async showCodeModal(type: string) {
-    switch (type) {
-      case 'wxpay':
-        this.openWxPay();
-        break;
-      default:
-        break;
-    }
-  }
+  // async showCodeModal(type: string) {
+  //   if (!this.tradeNo) {
+  //     this.tradeNo = this.accServ.setTradeNo();
+  //   } else {
+  //     this.orderId = await this.getOrder();
+  //     if(this.orderType == 'service' && !this.orderId){
+  //       this.tradeNo = this.accServ.setTradeNo();
+  //     }
+  //   }
+  //   console.log(this.tradeNo);
+  //   switch (type) {
+  //     case 'wxpay':
+  //       this.openWxPay();
+  //       break;
+  //     default:
+  //       break;
+  //   }
+  // }
   /* 校验支付方式 */
-  openWxPay() {
+  async openWxPay() {
+    if (!this.tradeNo) {
+      this.tradeNo = this.accServ.setTradeNo();
+    } else {
+      this.orderId = await this.getOrder();
+      if(this.orderType == 'service' && !this.orderId){
+        this.tradeNo = this.accServ.setTradeNo();
+      }
+    }
+    console.log(this.tradeNo);
     let ua = navigator.userAgent.toLowerCase();
     let isWeixin = ua.indexOf('micromessenger') != -1;
     if (isWeixin) {
@@ -65,63 +92,25 @@ export class PayCompComponent implements OnInit {
       this.wxPay();
     }
   }
-  /* pc端支付 */
-  async wxPay() {
-    this.tradeNo = this.accServ.setTradeNo();
-    // this.navCtrl.navigateRoot('account/payment');
-    //console.log(this.company, this.tradeNo);
-    let params = {
-      company: this.accServ.company,
-      out_trade_no: this.tradeNo,
-      total_fee: this.price,
-      body: '充值',
-    };
-    try {
-      let _this = this;
-      Parse.Cloud.run('pay_code2', params).then(async (res) => {
-        let nonce_str = res.nonce_str;
-        let codeLink = res.code_url[0];
-        console.log(codeLink);
-        // let order = await this.accServ.setOrder('service', {
-        //   out_trade_no: this.tradeNo,
-        //   payType: 'wxpay-pc',
-        //   total_fee: this.price,
-        //   code: codeLink,
-        // });
-        // window.open(
-        //   `${location.protocol}//${location.host}/account/payment/${order.objectId}/${nonce_str}`
-        // );
-        this.isOpen = false;
-      });
-    } catch (error) {
-      alert(error);
-    }
-  }
   isDisabled: boolean = false; //防抖
 
-  /* h5环境 */
+  /* 微信浏览器H5环境 */
   async wxPayH5() {
     if (this.isDisabled) return;
     try {
       this.isDisabled = true;
-      this.tradeNo = this.accServ.setTradeNo();
-      //console.log(this.company, this.tradeNo);
       let wechat = Parse.User.current()?.get('wechat');
       let openid =
-        localStorage.getItem('openid') || wechat['wxb4193c93ae9aa696']?.openid;
+        localStorage.getItem('openid') || wechat['wx86a6c35812a41d41']?.openid;
       if (openid) {
+        await this.getOrderId();
         let params = {
           company: this.accServ.company,
           out_trade_no: this.tradeNo,
           total_fee: +this.price,
           openid: openid,
-          appid: 'wxb4193c93ae9aa696',
+          appid: 'wx86a6c35812a41d41',
         };
-        await this.accServ.setOrder('service', {
-          out_trade_no: this.tradeNo,
-          payType: 'wxpay-h5',
-          total_fee: this.price,
-        });
         let _this = this;
         this.http
           .post(`https://server.fmode.cn/api/wxpay/neworder`, params)
@@ -141,10 +130,16 @@ export class PayCompComponent implements OnInit {
                     nonce_str: payinfo.nonceStr,
                     company: this.accServ.company,
                   };
-
-                  // this.accServ.saveAccountLog(info, _this.order.objectId, _this.company, _this.message);
+                  if (this.orderId) {
+                    this.accServ.updateAccountLog(info, this.orderId);
+                  }
                   _this.toast('支付成功', 'success');
                   _this.isOpen = false;
+                  _this.payResult.emit({
+                    code: 200,
+                    tradeNo: this.tradeNo,
+                    type: this.checkpay,
+                  });
                 }
               },
             });
@@ -186,14 +181,95 @@ export class PayCompComponent implements OnInit {
       alert.present();
     }
   }
-
+  /* 浏览器二维码支付 */
+  async wxPay() {
+    let params = {
+      company: this.accServ.company,
+      out_trade_no: this.tradeNo,
+      total_fee: this.price,
+      body: 'title',
+    };
+    Parse.Cloud.run('pay_code2', params)
+      .then(async (res) => {
+        let nonce_str = res.nonce_str;
+        let codeLink = res.code_url[0];
+        console.log(codeLink);
+        await this.getOrderId();
+        this.updateOrder(nonce_str)
+        this.isOpen = false;
+      })
+      .catch((err) => {
+        this.isDisabled = false;
+        this.toast(err.message, 'danger');
+      });
+  }
+/* 关闭支付弹窗 */
   onClose() {
     this.isOpen = false;
     const result = {
       code: 0,
+      tradeNo: this.tradeNo,
       type: this.checkpay,
     };
-    this.onChange.emit(result);
+    this.payResult.emit(result);
+  }
+
+  async getOrderId() {
+    if (this.orderType == 'service' && !this.orderId && this.gid) {
+      let resulte = await this.accServ.setOrder({
+        type: 'service',
+        gid: this.gid,
+        price: this.price,
+        total_fee: this.price,
+        tradeNo: this.tradeNo!,
+        out_trade_no: this.tradeNo!,
+        payType: 'wxpay',
+      });
+      console.log(resulte);
+      if (resulte?.id) {
+        this.orderId = resulte.id;
+      }
+    }
+  }
+  updateOrder(nonce_str:string) {
+    // 定时查询订单支付状态
+    let that = this;
+    that.timer = setInterval(() => {
+      let info = {
+        out_trade_no: that.tradeNo,
+        nonce_str: nonce_str,
+        company: this.accServ.company,
+      };
+      // console.log(info);
+      Parse.Cloud.run("order_status2", info)
+        .then(async (res) => {
+          // console.log(res);
+          if (res.status && res.status[0] == "SUCCESS") {
+            clearInterval(that.timer);
+            if (this.orderId) {
+              this.accServ.updateAccountLog(info, this.orderId);
+            }
+            that.toast("支付成功",'success');
+            that.isOpen = false;
+            that.payResult.emit({
+              code: 200,
+              tradeNo: this.tradeNo,
+              type: this.checkpay,
+            });
+          }
+        })
+        .catch((err) => {});
+    }, 3000);
+  }
+
+  async getOrder(): Promise<string | undefined> {
+    let query = new Parse.Query('Order');
+    query.notEqualTo('isDeleted', true);
+    query.equalTo('status', '100');
+    query.equalTo('orderNum', this.tradeNo);
+    query.select('objectId');
+    let res = await query.first();
+    return res?.id;
   }
   async toast(text: string, type?: string) {
     const toast = await this.toastController.create({

+ 7 - 11
projects/live-app/src/modules/account/recharge/recharge.component.html

@@ -1,12 +1,10 @@
-<nav title="余额充值"></nav>
-<div class="top">
-  <!-- <div class="head">
-		<ion-icon name="chevron-back-outline" style="width: 24px;height: 24px;color:#fff; position: fixed;
-    top: 15px;
-    left: 10px;" (click)="back()"></ion-icon>
-		<div class="name">余额充值</div>
-	</div> -->
-
+<nav title="充值"></nav>
+<div class="recharge-content">
+  <div class="options">
+    @for (val of options; track $index) {
+    <div class="select" (click)="onChange(val)">{{ val }}</div>
+    }
+  </div>
   <div class="li">
     <input
       type="number"
@@ -19,9 +17,7 @@
     />
   </div>
 
-  <!--<div class="confirm" (click)="updataOrder()">充值</div>-->
   <div class="confirm" (click)="showPay()">充值</div>
-
   <ion-alert
     [isOpen]="modal"
     trigger="present-alert"

+ 10 - 11
projects/live-app/src/modules/account/recharge/recharge.component.scss

@@ -1,21 +1,20 @@
-.top {
+.recharge-content {
 	background-image: url("https://file-cloud.fmode.cn/uiZD6NisQm/20220831/g1bkbm102855.png");
 	background-repeat: no-repeat;
 	background-position: center top;
 	background-size: 100% 100%;
 	height: 100%;
-	padding-top: 80px;
+	padding-top: 10px;
 	width: 100%;
 	text-align: center;
-
-
-	.head {
-		padding: 15px 5px;
-		background: #292B2A;
-
-		.name {
-			color: #fff;
-			text-align: center;
+	.options{
+		display: grid;
+		grid-template-columns: repeat(4, 1fr);
+		grid-gap: 10px;
+		padding: 6px;
+		.select{
+			padding: 10px 0;
+			border: 1px solid;
 		}
 	}
 

+ 292 - 266
projects/live-app/src/modules/account/recharge/recharge.component.ts

@@ -1,35 +1,35 @@
 import { Component, OnInit } from '@angular/core';
 import { FormsModule } from '@angular/forms';
-import * as Parse from "parse";
-import { HttpClient } from "@angular/common/http";
-import { Router } from "@angular/router";
-import { catchError } from "rxjs/operators";
-import { LoadingController, ToastController, Platform,IonicModule } from '@ionic/angular';
-import { Wechat } from "@ionic-native/wechat/ngx";
+import * as Parse from 'parse';
+import { HttpClient } from '@angular/common/http';
+import { Router } from '@angular/router';
+import { catchError } from 'rxjs/operators';
+import {
+  LoadingController,
+  ToastController,
+  Platform,
+  IonicModule,
+} from '@ionic/angular';
+import { Wechat } from '@ionic-native/wechat/ngx';
 import { NavComponent } from '../../../app/components/nav/nav.component';
 declare var wx: any;
 
 @Component({
-	selector: 'app-recharge',
-	templateUrl: './recharge.component.html',
-	styleUrls: ['./recharge.component.scss'],
-	standalone: true,
-  imports: [IonicModule,NavComponent,FormsModule],
+  selector: 'app-recharge',
+  templateUrl: './recharge.component.html',
+  styleUrls: ['./recharge.component.scss'],
+  standalone: true,
+  imports: [IonicModule, NavComponent, FormsModule],
 })
 export class RechargeComponent implements OnInit {
-	constructor(private http: HttpClient, public toastController: ToastController,
-		public loadingController: LoadingController,
-		// private wxSDK: Wechat,
-		private router: Router,
-		private platform: Platform,
-	) { }
-	price: any = 0
-	loading: any
-	company = localStorage.getItem('company')
-	account?: Parse.Object
-	public modal: boolean = false
-	public method: any = { value: 'wx', name: '微信支付' }
-	public alertInputs = [
+  options: Array<number> = [30, 50, 100, 200, 500, 1000, 2000, 5000];
+  price: any = 0;
+  loading: any;
+  company = localStorage.getItem('company');
+  account?: Parse.Object;
+  public modal: boolean = false;
+  public method: any = { value: 'wx', name: '微信支付' };
+  public alertInputs = [
     {
       label: '微信支付',
       type: 'radio',
@@ -41,7 +41,7 @@ export class RechargeComponent implements OnInit {
       value: 'zfb',
     },
   ];
-	public alertButtons = [
+  public alertButtons = [
     {
       text: 'Cancel',
       role: 'cancel',
@@ -53,260 +53,286 @@ export class RechargeComponent implements OnInit {
       text: 'OK',
       role: 'confirm',
       handler: () => {
-        this.confirmRechare()
+        this.confirmRechare();
       },
     },
   ];
-	public data: Array<object> = [
-		{ value: 'wx', name: '微信支付', icon: 'https://file-cloud.fmode.cn/uiZD6NisQm/20220810/kvp1el034906.png' },
-		{ value: 'zfb', name: '其他支付', icon: 'https://file-cloud.fmode.cn/uiZD6NisQm/20220810/6pr338034905.png' }
-	];
-	wxpayEnabled = false;
-	wxAppId = "";
-	ngOnInit() {
-		let ua = navigator.userAgent.toLowerCase();
-		let isWeixin = ua.indexOf('micromessenger') != -1;
-		if (isWeixin) {
-			this.getWXSignPackageInWechat();
-		}
-		this.getAccount()
-	}
-
-
-	// 获取微信签名
-	getWXSignPackageInWechat() {
-		let that = this;
-		let params = {
-			company: localStorage.getItem("company"),
-			href: encodeURIComponent(location.href.split("#")[0]),
-		};
-		this.http
-			.post(`https://test.fmode.cn/api/wechat/getconfig`, params)
-			.subscribe((response) => {
-				// 返回的签名信息
-				let res: any = response;
-				const signPackage = res.data;
-				that.wxAppId = signPackage.appid;
-				this.wxpayEnabled = true;
-				wx.config({
-					debug: false, // 开启调试模式
-					appId: signPackage.appid, // 必填,公众号的唯一标识
-					timestamp: signPackage.timestamp, // 必填,生成签名的时间戳
-					nonceStr: signPackage.nonceStr, // 必填,生成签名的随机串
-					signature: signPackage.signature, // 必填,签名,见附录1
-					jsApiList: [
-						"chooseWXPay", // JSAPI微信支付
-					], // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
-				});
-				wx.ready(() => { });
-				wx.error(() => { });
-			});
-	}
-
-	back() {
-		history.back();
-	}
-	async getAccount() {
-		let Account = new Parse.Query("Account")
-		Account.include("user")
-		Account.equalTo("user", Parse.User.current()?.id)
-		this.account = await Account.first()
-		console.log(this.account);
-	}
-
-	onChange(event:any){
-		this.method = JSON.parse(JSON.stringify(event))
-		console.log(this.method);
-	}
-
-
-	async showPay() {
-		if (this.price <= 0 || isNaN(this.price)) {
-			return this.presentToast(`充值错误,请重新确认充值金额!`, 1500, "danger");
-		}
-		if (this.price > 100000) {
-			return this.presentToast('单笔充值最多不超过100000元!', 1500, 'danger')
-		}
-		this.modal = true
-		this.price = parseInt(this.price)
-	}
+  public data: Array<object> = [
+    {
+      value: 'wx',
+      name: '微信支付',
+      icon: 'https://file-cloud.fmode.cn/uiZD6NisQm/20220810/kvp1el034906.png',
+    },
+    {
+      value: 'zfb',
+      name: '其他支付',
+      icon: 'https://file-cloud.fmode.cn/uiZD6NisQm/20220810/6pr338034905.png',
+    },
+  ];
+  wxpayEnabled = false;
+  wxAppId = '';
+  constructor(
+    private http: HttpClient,
+    public toastController: ToastController,
+    public loadingController: LoadingController,
+    // private wxSDK: Wechat,
+    private router: Router,
+    private platform: Platform
+  ) {}
+  ngOnInit() {
+    let ua = navigator.userAgent.toLowerCase();
+    let isWeixin = ua.indexOf('micromessenger') != -1;
+    if (isWeixin) {
+      this.getWXSignPackageInWechat();
+    }
+    this.getAccount();
+  }
 
-	async confirmRechare() {
-		let now = new Date();
-		let tradeNo = "C" +
-			String(now.getFullYear()) +
-			(now.getMonth() + 1) +
-			now.getDate() +
-			now.getHours() +
-			now.getMinutes() +
-			now.getSeconds() +
-			Math.random().toString().slice(-6); //生成六位随机数
-		console.log('订单编号:', tradeNo);
-		console.log(this.method.value);
+  // 获取微信签名
+  getWXSignPackageInWechat() {
+    let that = this;
+    let params = {
+      company: localStorage.getItem('company'),
+      href: encodeURIComponent(location.href.split('#')[0]),
+    };
+    this.http
+      .post(`https://test.fmode.cn/api/wechat/getconfig`, params)
+      .subscribe((response) => {
+        // 返回的签名信息
+        let res: any = response;
+        const signPackage = res.data;
+        that.wxAppId = signPackage.appid;
+        this.wxpayEnabled = true;
+        wx.config({
+          debug: false, // 开启调试模式
+          appId: signPackage.appid, // 必填,公众号的唯一标识
+          timestamp: signPackage.timestamp, // 必填,生成签名的时间戳
+          nonceStr: signPackage.nonceStr, // 必填,生成签名的随机串
+          signature: signPackage.signature, // 必填,签名,见附录1
+          jsApiList: [
+            'chooseWXPay', // JSAPI微信支付
+          ], // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
+        });
+        wx.ready(() => {});
+        wx.error(() => {});
+      });
+  }
 
-		// if (this.method.value == 'outline') {
-		// 	await this.updataOrder(tradeNo, 'outline')
-		// 	this.presentToast(`请选择支付方式`, 1500, "success");
-		// 	return
-		// } else 
-		if (this.method.value == 'wx') {
-			let ua = navigator.userAgent.toLowerCase();
+  back() {
+    history.back();
+  }
+  async getAccount() {
+    let Account = new Parse.Query('Account');
+    Account.include('user');
+    Account.equalTo('user', Parse.User.current()?.id);
+    this.account = await Account.first();
+    console.log(this.account);
+  }
 
-			let isWeixin = ua.indexOf('micromessenger') != -1;
-			if (isWeixin) { // 微信支付
-				await this.wxPay(tradeNo)
-			} else if (this.platform.is("cordova")) { // APP 调起微信支付
-				this.presentToast(`APP内暂不支持微信支付请前往微信端网页进行支付`, 3000, "success");
-				return
-				await this.openWxPay(tradeNo)
-			} else {
-				this.presentToast(`微信支付请在微信进入应用`, 1500, "success");
-			}
-		} else {
-			this.presentToast(`待开通支付通道`, 1500, "success");
-		}
-	}
+  onChange(event: any) {
+    this.method = JSON.parse(JSON.stringify(event));
+    console.log(this.method);
+  }
 
-	// 调起微信支付
-	async openWxPay(tradeNo:string) {
-		let loading = await this.loadingController.create({
-			cssClass: "my-custom-class",
-			message: "支付跳转...",
-			duration: 1500,
-		});
-		loading.present();
-		let params = {
-			company: this.company,
-			out_trade_no: tradeNo,
-			total_fee: this.price,
-		};
-		try {
-			this.http
-				.post(`https://server.fmode.cn/api/wxpay/newsdkorder`, params)
-				.pipe(
-					catchError(async (e) => { // 显示报错
-						loading.present();
-						await this.presentToast(`服务器请求错误,请稍后重试`, 1500, "danger");
-					})
-				)
-				.subscribe(async (response) => {
-					let payParams: any = response;
-					console.log(payParams);
+  async showPay() {
+    if (this.price <= 0 || isNaN(this.price)) {
+      return this.presentToast(
+        `充值错误,请重新确认充值金额!`,
+        1500,
+        'danger'
+      );
+    }
+    if (this.price > 100000) {
+      return this.presentToast('单笔充值最多不超过100000元!', 1500, 'danger');
+    }
+    this.modal = true;
+    this.price = parseInt(this.price);
+  }
 
-					// this.wxSDK
-					// 	.sendPaymentRequest({
-					// 		appid: payParams.appid, // merchant id
-					// 		partnerid: payParams.partnerid, // merchant id
-					// 		prepayid: payParams.prepayid, // prepay id
-					// 		package: payParams.package, // nonce
-					// 		noncestr: payParams.noncestr, // nonce
-					// 		timestamp: payParams.timestamp, // timestamp
-					// 		sign: payParams.sign, // signed string
-					// 	})
-					// 	.then(async (data) => {
-					// 		if (data) {
-					// 			loading.present();
-					// 			console.log('支付成功返回结果:', data);
-					// 			await this.updataOrder(tradeNo, '微信')
-					// 		}
-					// 	})
-					// 	.catch(async (error) => {
-					// 		loading.present();
-					// 		await this.presentToast(`支付失败`, 1500, "danger");
-					// 		console.log('调起微信失败', error);
-					// 	});
-				});
-		} catch (error) {
-			loading.present();
-			await this.presentToast(`支付失败`, 1500, "danger");
-			console.log(error);
-		}
-	}
+  async confirmRechare() {
+    let now = new Date();
+    let tradeNo =
+      'C' +
+      String(now.getFullYear()) +
+      (now.getMonth() + 1) +
+      now.getDate() +
+      now.getHours() +
+      now.getMinutes() +
+      now.getSeconds() +
+      Math.random().toString().slice(-6); //生成六位随机数
+    console.log('订单编号:', tradeNo);
+    console.log(this.method.value);
 
+    // if (this.method.value == 'outline') {
+    // 	await this.updataOrder(tradeNo, 'outline')
+    // 	this.presentToast(`请选择支付方式`, 1500, "success");
+    // 	return
+    // } else
+    if (this.method.value == 'wx') {
+      let ua = navigator.userAgent.toLowerCase();
 
+      let isWeixin = ua.indexOf('micromessenger') != -1;
+      if (isWeixin) {
+        // 微信支付
+        await this.wxPay(tradeNo);
+      } else if (this.platform.is('cordova')) {
+        // APP 调起微信支付
+        this.presentToast(
+          `APP内暂不支持微信支付请前往微信端网页进行支付`,
+          3000,
+          'success'
+        );
+        return;
+        await this.openWxPay(tradeNo);
+      } else {
+        this.presentToast(`微信支付请在微信进入应用`, 1500, 'success');
+      }
+    } else {
+      this.presentToast(`待开通支付通道`, 1500, 'success');
+    }
+  }
 
-	// 微信浏览器内支付
-	async wxPay(tradeNo:string) {
-		let openid = localStorage.getItem('openid')
-		if (openid) {
-			let params = {
-				company: this.company,
-				out_trade_no: tradeNo,
-				total_fee: this.price,
-				openid: openid,
-				appid: "wxb4579e09e263afa9"
-			};
-			let that = this
-			this.http
-				.post(`https://test.fmode.cn/api/wxpay/neworder`, params)
-				.subscribe(async (response) => {
-					let accountLog: any = await this.updataOrder(tradeNo, '微信')
-					let payinfo: any = response;
-					wx.chooseWXPay({
-						timestamp: payinfo.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
-						nonceStr: payinfo.nonceStr, // 支付签名随机串,不长于 32 位
-						package: payinfo.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
-						signType: "MD5", // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
-						paySign: payinfo.paySign, // 支付签名
-						success: async (res:any) => {
-							// 支付成功后的回调函数
-							if (res) {
-								accountLog.set("isVerified", true)
-								await accountLog.save()
-								that.presentToast(`充值成功`, 1500, "success");
-								that.modal = false
-								that.price = 0
-							}
-						},
-					});
-				});
-		}
+  // 调起微信支付
+  async openWxPay(tradeNo: string) {
+    let loading = await this.loadingController.create({
+      cssClass: 'my-custom-class',
+      message: '支付跳转...',
+      duration: 1500,
+    });
+    loading.present();
+    let params = {
+      company: this.company,
+      out_trade_no: tradeNo,
+      total_fee: this.price,
+    };
+    try {
+      this.http
+        .post(`https://server.fmode.cn/api/wxpay/newsdkorder`, params)
+        .pipe(
+          catchError(async (e) => {
+            // 显示报错
+            loading.present();
+            await this.presentToast(
+              `服务器请求错误,请稍后重试`,
+              1500,
+              'danger'
+            );
+          })
+        )
+        .subscribe(async (response) => {
+          let payParams: any = response;
+          console.log(payParams);
 
+          // this.wxSDK
+          // 	.sendPaymentRequest({
+          // 		appid: payParams.appid, // merchant id
+          // 		partnerid: payParams.partnerid, // merchant id
+          // 		prepayid: payParams.prepayid, // prepay id
+          // 		package: payParams.package, // nonce
+          // 		noncestr: payParams.noncestr, // nonce
+          // 		timestamp: payParams.timestamp, // timestamp
+          // 		sign: payParams.sign, // signed string
+          // 	})
+          // 	.then(async (data) => {
+          // 		if (data) {
+          // 			loading.present();
+          // 			console.log('支付成功返回结果:', data);
+          // 			await this.updataOrder(tradeNo, '微信')
+          // 		}
+          // 	})
+          // 	.catch(async (error) => {
+          // 		loading.present();
+          // 		await this.presentToast(`支付失败`, 1500, "danger");
+          // 		console.log('调起微信失败', error);
+          // 	});
+        });
+    } catch (error) {
+      loading.present();
+      await this.presentToast(`支付失败`, 1500, 'danger');
+      console.log(error);
+    }
+  }
 
-	}
+  // 微信浏览器内支付
+  async wxPay(tradeNo: string) {
+    let openid = localStorage.getItem('openid');
+    if (openid) {
+      let params = {
+        company: this.company,
+        out_trade_no: tradeNo,
+        total_fee: this.price,
+        openid: openid,
+        appid: 'wxb4579e09e263afa9',
+      };
+      let that = this;
+      this.http
+        .post(`https://test.fmode.cn/api/wxpay/neworder`, params)
+        .subscribe(async (response) => {
+          let accountLog: any = await this.updataOrder(tradeNo, '微信');
+          let payinfo: any = response;
+          wx.chooseWXPay({
+            timestamp: payinfo.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
+            nonceStr: payinfo.nonceStr, // 支付签名随机串,不长于 32 位
+            package: payinfo.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
+            signType: 'MD5', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
+            paySign: payinfo.paySign, // 支付签名
+            success: async (res: any) => {
+              // 支付成功后的回调函数
+              if (res) {
+                accountLog.set('isVerified', true);
+                await accountLog.save();
+                that.presentToast(`充值成功`, 1500, 'success');
+                that.modal = false;
+                that.price = 0;
+              }
+            },
+          });
+        });
+    }
+  }
 
-	async presentToast(title:string, time:number, color:string) {
-		const toast = await this.toastController.create({
-			message: title,
-			duration: time,
-			color: color
-		});
-		toast.present();
-	}
-	//充值记录
-	async updataOrder(tradeNo:string, type:string) {
-		let AccountLog = Parse.Object.extend('AccountLog')
-		let account = new AccountLog()
-		account.set("isVerified", false)
-		account.set("company", {
-			__type: "Pointer",
-			className: "Company",
-			objectId: this.company
-		})
-		account.set("targetAccount", {
-			__type: "Pointer",
-			className: "Account",
-			objectId: this.account?.id
-		})
-		account.set("fromName", "system")
-		account.set("fromAccountName", "system")
-		account.set("orderNumber", tradeNo)
-		account.set("desc", `${type}充值${this.price}`)
-		account.set("assetType", 'balance')
-		account.set("orderType", `${type}recharge`)
-		account.set("assetCount", this.price)
-		account.save().then((res: any) => {
-			return res
-			// res.set("isVerified", true)
-			// res.save().then(res => {
-			// 	this.presentToast(`充值成功`, 1500, "success");
-			// 	this.modal = false
-			// 	this.price = 0
-			// })
-		})
-	}
+  async presentToast(title: string, time: number, color: string) {
+    const toast = await this.toastController.create({
+      message: title,
+      duration: time,
+      color: color,
+    });
+    toast.present();
+  }
+  //充值记录
+  async updataOrder(tradeNo: string, type: string) {
+    let AccountLog = Parse.Object.extend('AccountLog');
+    let account = new AccountLog();
+    account.set('isVerified', false);
+    account.set('company', {
+      __type: 'Pointer',
+      className: 'Company',
+      objectId: this.company,
+    });
+    account.set('targetAccount', {
+      __type: 'Pointer',
+      className: 'Account',
+      objectId: this.account?.id,
+    });
+    account.set('fromName', 'system');
+    account.set('fromAccountName', 'system');
+    account.set('orderNumber', tradeNo);
+    account.set('desc', `${type}充值${this.price}`);
+    account.set('assetType', 'balance');
+    account.set('orderType', `${type}recharge`);
+    account.set('assetCount', this.price);
+    account.save().then((res: any) => {
+      return res;
+      // res.set("isVerified", true)
+      // res.save().then(res => {
+      // 	this.presentToast(`充值成功`, 1500, "success");
+      // 	this.modal = false
+      // 	this.price = 0
+      // })
+    });
+  }
 
-	onClose() {
-		this.modal = false;
-	}
+  onClose() {
+    this.modal = false;
+  }
 }

+ 8 - 7
projects/live-app/src/modules/account/wattle/wattle.component.html

@@ -4,17 +4,17 @@
     <div class="box">
       <div class="account_info">
         <div class="balance">
-          <div class="count">{{ account?.balance?.toFixed(2) || 0}}</div>
+          <div class="count">{{ account?.balance?.toFixed(2) || 0 }}</div>
           <div class="title">我的余额</div>
         </div>
       </div>
       <div class="figure">
         <div class="recharge" (click)="recharge()">充值</div>
-        <div class="recharges" (click)="withdrawal()">提现</div>
+        <!-- <div class="recharges" (click)="withdrawal()">提现</div> -->
       </div>
     </div>
 
-    <div class="install" (click)="toBank()">
+    <!-- <div class="install" (click)="toBank()">
       <div class="install-to">
         <div class="name">我的银行卡</div>
       </div>
@@ -22,7 +22,7 @@
         class="img"
         src="https://file-cloud.fmode.cn/uiZD6NisQm/20220808/9sq3d1093746.png"
       />
-    </div>
+    </div> -->
     <div class="install" (click)="record()">
       <div class="install-to">
         <div class="name">充值记录</div>
@@ -32,7 +32,7 @@
         src="https://file-cloud.fmode.cn/uiZD6NisQm/20220808/9sq3d1093746.png"
       />
     </div>
-    <div class="install" (click)="records()">
+    <!-- <div class="install" (click)="records()">
       <div class="install-to">
         <div class="name">提现记录</div>
       </div>
@@ -40,5 +40,6 @@
         class="img"
         src="https://file-cloud.fmode.cn/uiZD6NisQm/20220808/9sq3d1093746.png"
       />
-    </div></div
-></ion-content>
+    </div> -->
+  </div>
+</ion-content>

+ 12 - 4
projects/live-app/src/modules/goods/vip/vip.component.html

@@ -77,7 +77,8 @@
     <div class="member-title">会员服务说明</div>
     <div class="detail-title">关于虚拟产品说明</div>
     <div class="detail-text">
-      购买即表示同意<span (click)="showAgreement()">《购买协议条款》</span>,会员服务为虚拟产品,因此购买之后无法进行退换货。
+      购买即表示同意<span (click)="showAgreement()">《购买协议条款》</span
+      >,会员服务为虚拟产品,因此购买之后无法进行退换货。
     </div>
     <div class="detail-title">会员购买期限</div>
     <div class="detail-text">
@@ -95,7 +96,7 @@
           <div class="price">¥{{ currentGoods?.get("price") }}</div>
           <div class="vip-tag">
             {{ currentGoods?.get("name") }} <img src="img/VIP.png" alt="" />
-            {{currentGoods?.get("services")[0]?.get("duration")}}天
+            {{ currentGoods?.get("services")[0]?.get("duration") }}天
           </div>
         </div>
         <!-- <div class="agreement">
@@ -113,5 +114,12 @@
   }
 </ion-content>
 @if (showPay) {
-  <app-pay-comp [tradeNo]="tradeNo" #paycomp [price]="price"></app-pay-comp>
-}
+<app-pay-comp
+  (payResult)="onComplete($event)"
+  [tradeNo]="tradeNo"
+  [gid]="this.currentGoods?.id"
+  [orderType]="'service'"
+  [price]="price"
+  #paycomp
+></app-pay-comp>
+}

+ 15 - 11
projects/live-app/src/modules/goods/vip/vip.component.ts

@@ -1,5 +1,5 @@
 import { Component, OnInit, ViewChild } from '@angular/core';
-import { IonicModule, ModalController } from '@ionic/angular';
+import { IonicModule, ModalController, ToastController } from '@ionic/angular';
 import { NavComponent } from '../../../app/components/nav/nav.component';
 import { FormsModule } from '@angular/forms';
 import * as Parse from 'parse';
@@ -34,14 +34,15 @@ export class VipComponent implements OnInit {
   isCheck: boolean = false;
   currentGoods?: Parse.Object; //当前选择的会员
   showPay: boolean = false;
-  price:number = 0;
+  price: number = 0;
   tradeNo: string = ''; //支付单号
-
+  orderId?: string;
   constructor(
     private modalController: ModalController,
+    public toastController: ToastController,
     private authSer: AuthService,
     private datePipe: DatePipe,
-    private accServ: AccountService,
+    private accServ: AccountService
   ) {}
 
   ngOnInit() {
@@ -75,14 +76,14 @@ export class VipComponent implements OnInit {
   async getGoods() {
     let goods = new Parse.Query('ShopGoods');
     goods.equalTo('company', this.authSer.company);
-    goods.equalTo('type', 'vip');
+    goods.equalTo('type', 'service');
     goods.equalTo('status', true);
     goods.ascending('top');
     goods.notEqualTo('isDeleted', true);
     goods.include('services');
     this.goodsList = await goods.find();
     this.currentGoods = this.goodsList[0];
-    this.price = this.currentGoods?.get('price')
+    this.price = this.currentGoods?.get('price');
   }
   getAgreement() {
     let Agreement = new Parse.Query('ContractAgreement');
@@ -105,12 +106,15 @@ export class VipComponent implements OnInit {
   }
   onchang(data: Parse.Object) {
     this.currentGoods = data;
-    this.price = this.currentGoods?.get('price')
+    this.price = this.currentGoods?.get('price');
+  }
+  onComplete(evet: any) {
+    console.log(evet);
+    // this.showPay = false;
+    this.tradeNo = evet.tradeNo;
   }
-  openpay() {
-    this.showPay = true
-    this.tradeNo = this.accServ.setTradeNo();
-    
+  async openpay() {
+    this.showPay = true;
     this.paycomp.isOpen = true;
   }
 }

+ 3 - 1
projects/live-app/src/modules/tabs/my/my.component.ts

@@ -11,6 +11,7 @@ import { AlertController, ModalController } from '@ionic/angular';
 import { ActivatedRoute, Router } from '@angular/router';
 import { AuthService } from '../../../services/auth.service';
 import { AiChatService } from '../../../services/aichart.service';
+import { AccountService } from '../../../services/account.service';
 @Component({
   selector: 'app-my',
   templateUrl: './my.component.html',
@@ -29,7 +30,8 @@ export class MyComponent implements OnInit {
     public toastController: ToastController,
     private activateRoute: ActivatedRoute,
     private router: Router,
-    private aiServ: AiChatService
+    private aiServ: AiChatService,
+    private accServ: AccountService,
   ) {}
   tools: Array<{ icon: string; title: string; path: string }> = [
     {

+ 1 - 1
projects/live-app/src/modules/user/profile/profile.component.ts

@@ -328,7 +328,7 @@ export class ProfileComponent implements OnInit {
   async sendVideoCallInvite() {
     this.iscall = true;
     // this.router.navigate(['live/link-room/' + this.room?.id]);
-    await this.msgSer.subscribeMessage(this.uid, { message: true }); //进入对方主播频道发送聊天邀请
+    await this.msgSer.subscribeMessage(this.uid, { message: true,presence:true }); //进入对方主播频道发送聊天邀请
     this.msgSer.publishMessage('USERCALLINVITATION', this.uid);
   }
   async onCloseCall() {

+ 134 - 37
projects/live-app/src/services/account.service.ts

@@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
 import Parse from 'parse';
 import { HttpClient } from '@angular/common/http';
 import { AuthService } from './auth.service';
+import { ToastController } from '@ionic/angular';
 declare var wx: any;
 
 @Injectable({
@@ -11,9 +12,13 @@ export class AccountService {
   company: string = '';
   wxAppId = '';
   wxpayEnabled: boolean = false;
-  appid: string = localStorage.getItem('WECHAT_APP_ID') || 'wxb4193c93ae9aa696';
+  appid: string = localStorage.getItem('WECHAT_APP_ID') || 'wx86a6c35812a41d41';
   shareInfo: any;
-  constructor(private authServ: AuthService, private http: HttpClient) {
+  constructor(
+    public toast: ToastController,
+    private authServ: AuthService,
+    private http: HttpClient
+  ) {
     this.company = this.authServ.company;
     this.getUserOpenid();
   }
@@ -165,60 +170,40 @@ export class AccountService {
         wx.error(() => {});
       });
   }
-
-  async saveAccountLog(
-    info: object,
-    orderid: string,
-    company: string,
-    message: any
-  ) {
-    let url = 'https://test.fmode.cn/api/apig/saveAccountLog';
-    return new Promise((res, rej) => {
-      this.http
-        .post(url, {
-          company: company,
-          uid: Parse.User.current()?.id,
-          orderid: orderid,
-          info: info,
-        })
-        .subscribe(
-          (data: any) => {
-            console.log(data);
-            res(true);
-          },
-          (err) => {
-            console.warn(err);
-            message && message.error('请求超时,请稍后再试');
-            rej();
-          }
-        );
-    });
-  }
   setTradeNo() {
     let now = new Date();
     let tradeNo =
       'C' +
-      this.company +
       String(now.getFullYear()) +
       (now.getMonth() + 1) +
       now.getDate() +
       now.getHours() +
       now.getMinutes() +
       now.getSeconds() +
-      now.getMilliseconds();
+      now.getMilliseconds()+Math.floor(Math.random() * 10000)
     return tradeNo;
   }
 
   // 存支付记录
-  async setOrder(type: string, params: any, message?: any): Promise<any> {
+  async setOrder(params: {
+    type: string;
+    gid: string;
+    price: number;
+    total_fee: number;
+    tradeNo: string;
+    out_trade_no:string;
+    payType: string;
+    code?: string;
+  }): Promise<any> {
     let url = 'https://server.fmode.cn/api/apig/created-order';
     return new Promise((res, rej) => {
       this.http
         .post(url, {
           fcompany: this.company,
-          type: type,
-          gid: params.id,
           uid: Parse.User.current()?.id,
+          type: params.type,
+          gid: params.gid,
+          invite:Parse.User.current()?.get('invite')?.id,
           params: params,
         })
         .subscribe(
@@ -227,10 +212,122 @@ export class AccountService {
             res(data.data);
           },
           (err) => {
-            message?.error('网络错误,订单创建失败');
             rej(err);
           }
         );
     });
   }
+  // 生成一条 AccountLog 记录
+  async saveAccountLog(param: {
+    price: number;
+    tradeNo: string;
+    orderType: string;
+    payType: string;
+    orderId?: string;
+  }) {
+    // 查询当前订单是否已有支付记录
+    const user = Parse.User.current()!;
+    //查询账户
+    let Account = new Parse.Query('Account');
+    Account.equalTo('company', this.company);
+    Account.equalTo('user', user?.id);
+    Account.select('objectId');
+    let account = await Account.first();
+    if (!account?.id) {
+      account = await this.createdAccount(user.id);
+    }
+    let Query = new Parse.Query('AccountLog');
+    Query.equalTo('company', this.company);
+    Query.equalTo('user', user.id);
+    Query.equalTo('orderNumber', param.tradeNo);
+    Query.equalTo('fromAccount', account.id);
+    Query.equalTo('payType', param.payType);
+    let result = await Query.first();
+    if (result && result.id) {
+      return result;
+    }
+    let AccountLog = Parse.Object.extend('AccountLog');
+    let tool = new AccountLog();
+    tool.set('fromAccount', {
+      __type: 'Pointer',
+      className: 'Account',
+      objectId: account.id,
+    });
+    tool.set('user', {
+      __type: 'Pointer',
+      className: '_User',
+      objectId: user.id,
+    });
+    param.orderId && tool.set('orderId', param.orderId);
+    tool.set('company', {
+      __type: 'Pointer',
+      className: 'Company',
+      objectId: this.company,
+    });
+    tool.set('orderType', param.orderType);
+    tool.set('isVerified', false);
+    tool.set(
+      'fromName',
+      user?.get('nickname') ? user.get('nickname') : user?.get('mobile')
+    );
+    tool.set('orderNumber', param.tradeNo);
+    tool.set('targetName', 'system');
+    tool.set('payType', param.payType);
+    tool.set('assetCount', param.price);
+    return await tool.save();
+  }
+  /* 激活Account */
+  async createdAccount(uid: string): Promise<Parse.Object> {
+    let Account = new Parse.Query('Account');
+    Account.equalTo('company', this.company);
+    Account.equalTo('user', uid);
+    let account: any = await Account.first();
+    if (!account?.id) {
+      let obj = Parse.Object.extend('Account');
+      account = new obj();
+      account?.set('user', {
+        __type: 'Pointer',
+        className: '_User',
+        objectId: uid,
+      });
+      account?.set('company', {
+        __type: 'Pointer',
+        className: 'Company',
+        objectId: this.company,
+      });
+      account?.set('balance', 0);
+      account = await account?.save();
+    }
+    return account;
+  }
+
+  async updateAccountLog(info: object, orderid:string) {
+    let url = "https://server.fmode.cn/api/apig/saveAccountLog";
+    return new Promise((res,rej)=>{
+      this.http
+      .post(url, {
+        company: this.company,
+        uid: Parse.User.current()?.id,
+        orderid: orderid,
+        info: info,
+      })
+      .subscribe(
+        (data: any) => {
+          console.log(data);
+          res (true)
+        },
+        async (err) => {
+          console.warn(err);
+          const toast = await this.toast.create({
+            message: '支付成功,订单记录异常',
+            color: 'warning',
+            duration: 1500,
+          });
+          toast.present();
+          rej()
+        }
+      );
+    })
+    
+  }
 }

+ 8 - 4
projects/live-app/src/services/message.service.ts

@@ -61,8 +61,8 @@ export class MessageService {
     // let states = ['CONNECTED', 'CONNECTING'];
     if (this.options.connectState) return;
     await this.getToken();
-    const rtmConfig = { logLevel: 'debug',logUpload:true };
-    this.rtmClient = new AgoraRTM.RTM(this.appid, this.userId,rtmConfig);
+    const rtmConfig = { logLevel: 'INFO', logUpload: false };
+    this.rtmClient = new AgoraRTM.RTM(this.appid, this.userId, rtmConfig);
     this.joinReady();
     await this.loginRTM();
     // this.subscribeMessage(channelName);
@@ -118,8 +118,12 @@ export class MessageService {
       Mode: mode,
     };
     try {
-      let res = await this.rtmClient?.presence.setState(channelName, channelType, states);
-      console.log('频道状态发生更改:',res);
+      let res = await this.rtmClient?.presence.setState(
+        channelName,
+        channelType,
+        states
+      );
+      console.log('频道状态发生更改:', res);
     } catch (err: any) {
       console.log(err);
     }