import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ActivatedRoute } from '@angular/router'; import { AccountService } from '../../../services/account.service'; import { HttpClient } from '@angular/common/http'; import * as Parse from 'parse'; import { ionicStandaloneModules, AlertController, ToastController, } from '../../../modules/ionic-standalone.modules'; declare var wx: any; @Component({ selector: 'app-pay-comp', templateUrl: './pay-comp.component.html', styleUrls: ['./pay-comp.component.scss'], standalone: true, imports: [...ionicStandaloneModules, CommonModule], }) export class PayCompComponent implements OnInit { @Input('price') price!: number; @Input('credit') credit!: number | undefined; //钻石 @Input('gid') gid: string | undefined; @Input('orderType') orderType!: string; //订单类型 @Input('tradeNo') tradeNo: string | undefined; //支付单号 @Input('title') title: string = '会员购买'; @Output() payResult: EventEmitter = new EventEmitter(); @Input('orderId') orderId?: string; isOpen: boolean = true; //打开弹窗 checkpay: string = 'wxpay'; userAgent?: string; //获取当前浏览器环境 codeLink?: string; user: Parse.Object = Parse.User.current()!; timer: any; //定时查询 accountLog?: Parse.Object; // 充值记录 constructor( private accServ: AccountService, private toastController: ToastController, private alertCtrl: AlertController, private http: HttpClient, private activRoute: ActivatedRoute ) {} ngOnInit() { this.activRoute.paramMap.subscribe((params) => { let ua = navigator.userAgent.toLowerCase(); if (ua.indexOf('micromessenger') != -1) { this.userAgent = 'weixin'; this.accServ.getWXSignPackageInWechat(); } else if (ua.indexOf('windows') != -1 || ua.indexOf('Macintosh') != -1) { this.userAgent = 'pc'; } }); } onchangPay(val: string) { this.checkpay = val; console.log(val); } /* 用户确认支付 */ async userPayment() { if (!this.tradeNo) { this.tradeNo = this.accServ.setTradeNo(); } else { this.orderId = await this.getOrder(); if (this.orderType == 'vip' && !this.orderId) { this.tradeNo = this.accServ.setTradeNo(); } else if ( this.orderType == 'recharge' && (!this.accountLog?.id || this.accountLog?.get('isVerified')) ) { this.tradeNo = this.accServ.setTradeNo(); } } console.log(this.tradeNo); switch (this.checkpay) { case 'wxpay': this.openWxPay(); break; case 'alipay': this.openAlipay(); break; } } /* 校验支付方式 */ async openWxPay() { let ua = navigator.userAgent.toLowerCase(); let isWeixin = ua.indexOf('micromessenger') != -1; if (isWeixin) { //JSAPI 支付 this.wxPayH5(); } else { this.wxPay(); } } isDisabled: boolean = false; //防抖 /* 微信浏览器H5环境 */ async wxPayH5() { if (this.isDisabled) return; try { this.isDisabled = true; let wechat = Parse.User.current()?.get('wechat'); let openid = localStorage.getItem('openid') || wechat['wx86a6c35812a41d41']?.openid; if (openid) { await this.getOrderId(); let params = { company: this.accServ.company, body: this.title, out_trade_no: this.tradeNo, total_fee: +this.price, openid: openid, appid: 'wx86a6c35812a41d41', }; let _this = this; this.http .post(`https://server.fmode.cn/api/wxpay/neworder`, params) .subscribe((response) => { 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) { let info = { out_trade_no: _this.tradeNo, nonce_str: payinfo.nonceStr, company: this.accServ.company, }; if (this.orderId) { this.accServ.updateAccountLog(info, this.orderId); } else if (this.orderType == 'recharge') { this.accountLog = await this.accServ.updateRecharge( this.accountLog! ); } _this.toast('支付成功', 'success'); _this.isOpen = false; _this.payResult.emit({ code: 200, tradeNo: this.tradeNo, type: this.checkpay, }); } }, }); this.isDisabled = false; }); } else { // alert('缺少openid,请重新登录') this.isDisabled = false; let alert = await this.alertCtrl.create({ header: '提示', subHeader: '', message: '缺少openid,请刷新页面或重新登录', buttons: [ { role: 'ok', text: '确认', handler: () => { location.reload(); }, }, ], }); alert.present(); } } catch (err: any) { this.isDisabled = false; let alert = await this.alertCtrl.create({ header: '异常错误', subHeader: '', message: err.message, buttons: [ { role: 'ok', text: '确认', handler: () => {}, }, ], }); alert.present(); } } /* 浏览器二维码支付 */ async wxPay() { let params = { company: this.accServ.company, out_trade_no: this.tradeNo, total_fee: this.price, body: this.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'); }); } /* 支付宝支付 */ async openAlipay(){ if (this.isDisabled) return; try { this.isDisabled = true; await this.getOrderId(); let data:any = await this.getAliPayUrl(); console.log(data.pay_url); window.open(data.pay_url, "newW"); this.timer = setInterval(async () => { console.log("支付结果轮询"); let AccountLog = new Parse.Query("AccountLog"); AccountLog.equalTo("company", this.accServ.company); AccountLog.equalTo("orderNumber", this.tradeNo); AccountLog.equalTo("payType", "aliPay"); AccountLog.equalTo("isVerified", true); let result = await AccountLog.first(); if (result && result.id) { clearInterval(this.timer); this.timer = null; } if (!this.timer) { //支付成功返回状态 this.toast('支付成功', 'success'); this.isOpen = false; this.payResult.emit({ code: 200, tradeNo: this.tradeNo, type: this.checkpay, }); } }, 1000); }catch (err: any) { this.isDisabled = false; let alert = await this.alertCtrl.create({ header: '异常错误', subHeader: '', message: err.message, buttons: [ { role: 'ok', text: '确认', handler: () => {}, }, ], }); alert.present(); } } // 获取支付宝支付 async getAliPayUrl() { return new Promise((resolve, reject) => { let beforURL = window.location.href; let params = { company: this.accServ.company, tradeNo: this.tradeNo, price: this.price, tradetype:'wap', // price: 0.01, orderTitle: this.title, returnUrl: beforURL, }; try { this.http .post("https://server.fmode.cn/api/alipay/neworder", params) .subscribe((res: any) => { if (res.code !== 200) { this.toast('网络错误,请稍后重试', 'warning'); return } if (res.data && res.data.pay_url) { resolve(res.data); } }); } catch (err) { if (err) { this.toast('网络错误,请稍后重试', 'warning'); reject(err); } } }); } /* 关闭支付弹窗 */ onClose() { this.isOpen = false; const result = { code: 0, tradeNo: this.tradeNo, type: this.checkpay, }; this.payResult.emit(result); } async getOrderId() { if (this.orderType == 'vip' && !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: this.checkpay, }); console.log(resulte); if (resulte?.objectId) { this.orderId = resulte.objectId; } } else if (this.orderType == 'recharge') { this.accountLog = await this.accServ.creatdRechargeLog({ tradeNo: this.tradeNo!, payType: this.checkpay, price: this.price, credit: this.credit!, }); } } 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); } else if (this.orderType == 'recharge') { this.accountLog = await this.accServ.updateRecharge( this.accountLog! ); } that.toast('支付成功', 'success'); that.isOpen = false; that.payResult.emit({ code: 200, tradeNo: this.tradeNo, type: this.checkpay, }); } }) .catch((err) => {}); }, 3000); } async getOrder(): Promise { 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({ message: text, color: type ?? 'warning', duration: 1500, }); toast.present(); } }