younger_times
2023-07-14 b932f704f6c04adc7d7b4104a06cbc09c8d49cb5
报名课程流程完成
33个文件已修改
4个文件已添加
958 ■■■■ 已修改文件
Podfile 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai-Bridging-Header.h 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai.xcodeproj/project.pbxproj 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/AppDelegate.swift 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Common/View/PaymentView.swift 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Common/View/PaymentView.xib 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Config/Def.swift 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Config/Enums.swift 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Info.plist 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Model/CommonModels.swift 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Network/NetworkRequest.swift 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Network/OBSUploader.swift 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Network/Services.swift 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Activity/VC/ActivityDetailApplyVC.swift 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Activity/View/StoresInfoView.swift 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Activity/View/StoresInfoView.xib 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/VC/CourseDetailApplyVC.swift 97 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/VC/CourseDetailApplyVC.xib 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/VC/CourseDetailVC.swift 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Home/VC/HomeVC.swift 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Home/VC/JoinMemberIntroduceVC.swift 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Other/TCell/CouponTCell.swift 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Other/TCell/CouponTCell.xib 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Other/TCell/StudentInfoTCell.swift 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Other/TCell/StudentInfoTCell.xib 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Other/View/CouponChooseView.swift 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Other/View/CouponChooseView.xib 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Other/View/StudentChooseView.swift 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Welfare/VC/RechargeCenterVC.swift 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Welfare/VC/WelfareFreeVC.swift 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Welfare/VC/WelfareFreeVC.xib 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Welfare/VC/WelfareRedeemGoodsDetailVC.swift 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Welfare/VC/WelfareVC.swift 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Yard/VC/YardDetailVC.swift 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/YYPaymentManager/YYPayRequest.swift 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/YYPaymentManager/YYPaymentManager.swift 242 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/YYPaymentManager/YYPaymentResultModel.swift 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Podfile
@@ -15,6 +15,9 @@
  pod 'Lantern'
  pod 'SVProgressHUD'
  pod 'AliyunOSSiOS'
  pod 'WechatOpenSDK-XCFramework'
  pod 'AlipaySDK-iOS'
  post_install do |installer|
    installer.pods_project.targets.each do |target|
WanPai-Bridging-Header.h
New file
@@ -0,0 +1,13 @@
//
//  WanPai-Bridging-Header.h
//  WanPai
//
//  Created by 无故事王国 on 2023/7/13.
//
#ifndef WanPai_Bridging_Header_h
#define WanPai_Bridging_Header_h
#import "WXApi.h"
#import <AlipaySDK/AlipaySDK.h>
#endif /* WanPai_Bridging_Header_h */
WanPai.xcodeproj/project.pbxproj
@@ -49,6 +49,9 @@
        13489E0B2A4C41A400155744 /* ProfileVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13489E092A4C41A400155744 /* ProfileVC.xib */; };
        134A750A2A5D0D64006D14AE /* RefreshModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 134A75092A5D0D64006D14AE /* RefreshModel.swift */; };
        134BD50A2A5FF72900786819 /* OBSUploader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 134BD5092A5FF72800786819 /* OBSUploader.swift */; };
        134BD52C2A6008BA00786819 /* YYPaymentManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 134BD5202A6008BA00786819 /* YYPaymentManager.swift */; };
        134BD52D2A6008BA00786819 /* YYPaymentResultModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 134BD5212A6008BA00786819 /* YYPaymentResultModel.swift */; };
        134BD52E2A6008BA00786819 /* YYPayRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 134BD5222A6008BA00786819 /* YYPayRequest.swift */; };
        1353D5752A56CA0A00539FCA /* Services.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1353D5732A56CA0A00539FCA /* Services.swift */; };
        1353D5762A56CA0A00539FCA /* NetworkRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1353D5742A56CA0A00539FCA /* NetworkRequest.swift */; };
        1355ABFA2A4BE9FF002B25E4 /* WelfareCouponsSubListVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1355ABF92A4BE9FF002B25E4 /* WelfareCouponsSubListVC.swift */; };
@@ -296,6 +299,10 @@
        13489E092A4C41A400155744 /* ProfileVC.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ProfileVC.xib; sourceTree = "<group>"; };
        134A75092A5D0D64006D14AE /* RefreshModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshModel.swift; sourceTree = "<group>"; };
        134BD5092A5FF72800786819 /* OBSUploader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OBSUploader.swift; sourceTree = "<group>"; };
        134BD5202A6008BA00786819 /* YYPaymentManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YYPaymentManager.swift; sourceTree = "<group>"; };
        134BD5212A6008BA00786819 /* YYPaymentResultModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YYPaymentResultModel.swift; sourceTree = "<group>"; };
        134BD5222A6008BA00786819 /* YYPayRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YYPayRequest.swift; sourceTree = "<group>"; };
        134BD5332A60099B00786819 /* WanPai-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WanPai-Bridging-Header.h"; sourceTree = SOURCE_ROOT; };
        1353D5732A56CA0A00539FCA /* Services.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Services.swift; sourceTree = "<group>"; };
        1353D5742A56CA0A00539FCA /* NetworkRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkRequest.swift; sourceTree = "<group>"; };
        1355ABF92A4BE9FF002B25E4 /* WelfareCouponsSubListVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelfareCouponsSubListVC.swift; sourceTree = "<group>"; };
@@ -577,6 +584,16 @@
            path = TCell;
            sourceTree = "<group>";
        };
        134BD51F2A6008BA00786819 /* YYPaymentManager */ = {
            isa = PBXGroup;
            children = (
                134BD5202A6008BA00786819 /* YYPaymentManager.swift */,
                134BD5212A6008BA00786819 /* YYPaymentResultModel.swift */,
                134BD5222A6008BA00786819 /* YYPayRequest.swift */,
            );
            path = YYPaymentManager;
            sourceTree = "<group>";
        };
        1353D5722A56CA0A00539FCA /* Network */ = {
            isa = PBXGroup;
            children = (
@@ -840,6 +857,7 @@
        8D8400D02A2F1430003AF6A2 /* WanPai */ = {
            isa = PBXGroup;
            children = (
                134BD51F2A6008BA00786819 /* YYPaymentManager */,
                13FB93B72A5C0270009F558A /* Category */,
                137546412A57F564001FA77A /* Model */,
                1375463E2A57F538001FA77A /* ViewModel */,
@@ -855,6 +873,7 @@
                8D8400DA2A2F1432003AF6A2 /* Assets.xcassets */,
                8D8400DC2A2F1432003AF6A2 /* LaunchScreen.storyboard */,
                8D8400DF2A2F1432003AF6A2 /* Info.plist */,
                134BD5332A60099B00786819 /* WanPai-Bridging-Header.h */,
            );
            path = WanPai;
            sourceTree = "<group>";
@@ -1195,6 +1214,7 @@
                8D8400CB2A2F1430003AF6A2 /* Frameworks */,
                8D8400CC2A2F1430003AF6A2 /* Resources */,
                FE57E4383C5D7AA7AAE198DF /* [CP] Embed Pods Frameworks */,
                FBBF5E081625CBBDD26D1B09 /* [CP] Copy Pods Resources */,
            );
            buildRules = (
            );
@@ -1372,6 +1392,23 @@
            shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
            showEnvVarsInLog = 0;
        };
        FBBF5E081625CBBDD26D1B09 /* [CP] Copy Pods Resources */ = {
            isa = PBXShellScriptBuildPhase;
            buildActionMask = 2147483647;
            files = (
            );
            inputFileListPaths = (
                "${PODS_ROOT}/Target Support Files/Pods-WanPai/Pods-WanPai-resources-${CONFIGURATION}-input-files.xcfilelist",
            );
            name = "[CP] Copy Pods Resources";
            outputFileListPaths = (
                "${PODS_ROOT}/Target Support Files/Pods-WanPai/Pods-WanPai-resources-${CONFIGURATION}-output-files.xcfilelist",
            );
            runOnlyForDeploymentPostprocessing = 0;
            shellPath = /bin/sh;
            shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-WanPai/Pods-WanPai-resources.sh\"\n";
            showEnvVarsInLog = 0;
        };
        FE57E4383C5D7AA7AAE198DF /* [CP] Embed Pods Frameworks */ = {
            isa = PBXShellScriptBuildPhase;
            buildActionMask = 2147483647;
@@ -1468,7 +1505,9 @@
                1375464B2A581716001FA77A /* HomeModel.swift in Sources */,
                8D70178D2A330E5700473C40 /* CourseDetailVC.swift in Sources */,
                1355ABFD2A4C15C7002B25E4 /* RechargeRecordVC.swift in Sources */,
                134BD52C2A6008BA00786819 /* YYPaymentManager.swift in Sources */,
                1353D5762A56CA0A00539FCA /* NetworkRequest.swift in Sources */,
                134BD52D2A6008BA00786819 /* YYPaymentResultModel.swift in Sources */,
                13B640C02A54108B00EA33ED /* UploadImgCCell.swift in Sources */,
                130E40262A4EC029003A3D75 /* SearchStoreDetailVC.swift in Sources */,
                139A39F02A41374100737AFB /* YardBookingSubListVC.swift in Sources */,
@@ -1476,6 +1515,7 @@
                8D5732BD2A3724A900B2F8E3 /* AddStudentVC.swift in Sources */,
                8D5C150F2A31885B00A8BCC9 /* AgreentView.swift in Sources */,
                1387B6692A4AC0B300BF2F2E /* CourseBookingSubListVC.swift in Sources */,
                134BD52E2A6008BA00786819 /* YYPayRequest.swift in Sources */,
                13D084592A4071F2005B05D5 /* YardBookingListVC.swift in Sources */,
                1330DE3B2A4D390700106D69 /* CoinStoreCenterVC.swift in Sources */,
                1387B6752A4ACA1000BF2F2E /* CourseBooking_1_TCell.swift in Sources */,
@@ -1687,6 +1727,10 @@
                CURRENT_PROJECT_VERSION = 1;
                DEVELOPMENT_TEAM = "";
                "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 2MWV8K39DV;
                FRAMEWORK_SEARCH_PATHS = (
                    "$(inherited)",
                    "$(PROJECT_DIR)/WanPai/YYPaymentManager/Alipay",
                );
                GENERATE_INFOPLIST_FILE = YES;
                INFOPLIST_FILE = WanPai/Info.plist;
                INFOPLIST_KEY_CFBundleDisplayName = "玩湃生活";
@@ -1704,6 +1748,10 @@
                    "$(inherited)",
                    "@executable_path/Frameworks",
                );
                LIBRARY_SEARCH_PATHS = (
                    "$(inherited)",
                    "$(PROJECT_DIR)/WanPai/YYPaymentManager/WeChatPay",
                );
                MARKETING_VERSION = 1.0;
                PRODUCT_BUNDLE_IDENTIFIER = com.sinata.WeParkLife;
                PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1713,6 +1761,7 @@
                SUPPORTS_MACCATALYST = NO;
                SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
                SWIFT_EMIT_LOC_STRINGS = YES;
                SWIFT_OBJC_BRIDGING_HEADER = "WanPai-Bridging-Header.h";
                SWIFT_VERSION = 5.0;
                TARGETED_DEVICE_FAMILY = 1;
            };
@@ -1729,6 +1778,10 @@
                CURRENT_PROJECT_VERSION = 1;
                DEVELOPMENT_TEAM = "";
                "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 2MWV8K39DV;
                FRAMEWORK_SEARCH_PATHS = (
                    "$(inherited)",
                    "$(PROJECT_DIR)/WanPai/YYPaymentManager/Alipay",
                );
                GENERATE_INFOPLIST_FILE = YES;
                INFOPLIST_FILE = WanPai/Info.plist;
                INFOPLIST_KEY_CFBundleDisplayName = "玩湃生活";
@@ -1746,6 +1799,10 @@
                    "$(inherited)",
                    "@executable_path/Frameworks",
                );
                LIBRARY_SEARCH_PATHS = (
                    "$(inherited)",
                    "$(PROJECT_DIR)/WanPai/YYPaymentManager/WeChatPay",
                );
                MARKETING_VERSION = 1.0;
                PRODUCT_BUNDLE_IDENTIFIER = com.sinata.WeParkLife;
                PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1755,6 +1812,7 @@
                SUPPORTS_MACCATALYST = NO;
                SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
                SWIFT_EMIT_LOC_STRINGS = YES;
                SWIFT_OBJC_BRIDGING_HEADER = "WanPai-Bridging-Header.h";
                SWIFT_VERSION = 5.0;
                TARGETED_DEVICE_FAMILY = 1;
            };
WanPai/AppDelegate.swift
@@ -18,6 +18,8 @@
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        Services.startNetworkMonitor()
        YYPaymentManager.shared.configuredWeChat(appID: WeChatAPPID, universalLink: WechatUniversalLinks)
        YYPaymentManager.shared.configuredAlipay(appScheme: APPScheme)
        return true
    }
@@ -42,6 +44,17 @@
            return orientation
        }
    }
    func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
        return YYPaymentManager.shared.handleApplication(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
    }
    func application(_ application: UIApplication, handleOpen url: URL) -> Bool {
        return YYPaymentManager.shared.handleApplication(application, handleOpen: url)
    }
    // NOTE: 9.0以后使用新API接口
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        return YYPaymentManager.shared.handleApplication(app, open: url, options: options)
    }
}
extension AppDelegate{
WanPai/Common/View/PaymentView.swift
@@ -9,27 +9,54 @@
import JQTools
class PaymentView: UIView,JQNibView{
    @IBOutlet weak var view_container: UIView!
    @IBOutlet weak var cons_bottom: NSLayoutConstraint!
    @IBOutlet weak var btn_wechat: UIButton!
    @IBOutlet weak var btn_alipay: UIButton!
    @IBOutlet weak var btn_coin: UIButton!
    private var clouse:((Bool)->Void)?
    @IBOutlet weak var btn_course: UIButton!
    @IBOutlet weak var view_wechat: UIView!
    @IBOutlet weak var view_alipay: UIView!
    @IBOutlet weak var view_coin: UIView!
    @IBOutlet weak var view_course: UIView!
    @IBOutlet weak var label_wechatMoney: UILabel!
    @IBOutlet weak var label_aliPayMoney: UILabel!
    @IBOutlet weak var label_coinMoney: UILabel!
    @IBOutlet weak var label_courseMoney: UILabel!
    private var clouse:((PayType)->Void)?
    private var payType:PayType?
    
    override func awakeFromNib() {
        super.awakeFromNib()
        
        cons_bottom.constant = -(225 + UIDevice.jq_safeEdges.bottom)
       view_wechat.isHidden = true
       view_coin.isHidden = true
       view_course.isHidden = true
       view_alipay.isHidden = true
        alpha = 0
        layoutIfNeeded()
    }
    
    static func show(_ clouse:@escaping (Bool)->Void){
    static func show(money:(ali:Double?,wx:Double?,coin:Int?,course:Int?),_ clouse:@escaping (PayType)->Void){
        let paymentView = PaymentView.jq_loadNibView()
        paymentView.frame = screnDelegate?.window?.frame ?? .zero
        paymentView.clouse = clouse
        paymentView.view_wechat.isHidden = money.wx == nil
        paymentView.view_coin.isHidden = money.coin == nil
        paymentView.view_course.isHidden = money.course == nil
        paymentView.view_alipay.isHidden = money.ali == nil
        paymentView.label_aliPayMoney.text = money.ali?.currency() ?? "0"
        paymentView.label_wechatMoney.text = money.wx?.currency() ?? "0"
        paymentView.label_coinMoney.text = "\(money.coin ?? 0)币"
        paymentView.label_courseMoney.text = "\(money.course ?? 0)课时"
        screnDelegate?.window?.addSubview(paymentView)
        paymentView.cons_bottom.constant = 0
        
@@ -58,27 +85,30 @@
    
    @IBAction func tapAction(_ sender: UIButton) {
        switch sender.tag{
        case 10:
            payType = .wechat
        case 11:
            payType = .aliPay
        case 12:
            payType = .coin
        default:break
            case 10:
                payType = .wechat
            case 11:
                payType = .aliPay
            case 12:
                payType = .coin
            case 14:
                payType = .courseNum
            default:break
        }
        
        btn_alipay.isSelected = payType == .aliPay
        btn_coin.isSelected = payType == .coin
        btn_wechat.isSelected = payType == .wechat
        btn_course.isSelected = payType == .courseNum
    }
    
    @IBAction func paymentAction(_ sender: UIButton) {
        clouse?(true)
        guard payType != nil else {alertError(msg: "请选择支付方式");return}
        clouse?(payType!)
        hidden()
    }
    
    @IBAction func cancelAction(_ sender: UIButton) {
        clouse?(false)
        hidden()
    }
    
WanPai/Common/View/PaymentView.xib
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
    <device id="retina6_12" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
        <capability name="Named colors" minToolsVersion="9.0"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
@@ -216,7 +216,7 @@
                                            <color key="textColor" red="0.93333333330000001" green="0.043137254899999998" blue="0.043137254899999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                            <nil key="highlightedColor"/>
                                        </label>
                                        <button opaque="NO" tag="12" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SXc-6d-61u">
                                        <button opaque="NO" tag="14" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SXc-6d-61u">
                                            <rect key="frame" x="354" y="23" width="25" height="25"/>
                                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
                                            <state key="normal" image="btn_choose"/>
@@ -314,9 +314,18 @@
            <connections>
                <outlet property="btn_alipay" destination="WE2-FK-qOV" id="Keo-5R-2iV"/>
                <outlet property="btn_coin" destination="fBI-qy-chO" id="W1f-WZ-xIJ"/>
                <outlet property="btn_course" destination="SXc-6d-61u" id="zd6-Ee-k8H"/>
                <outlet property="btn_wechat" destination="iQH-s2-Sm4" id="pDO-q6-Iek"/>
                <outlet property="cons_bottom" destination="9AD-6H-0r8" id="9hQ-qM-ZMJ"/>
                <outlet property="label_aliPayMoney" destination="uCD-UF-eto" id="1BE-9I-1Dh"/>
                <outlet property="label_coinMoney" destination="MfR-5x-oVT" id="Rwg-Rc-14o"/>
                <outlet property="label_courseMoney" destination="1dn-gY-wfT" id="H3V-IY-yYU"/>
                <outlet property="label_wechatMoney" destination="nW3-BN-jAP" id="HUP-W9-gDY"/>
                <outlet property="view_alipay" destination="4Ft-AC-zgU" id="W5X-ct-zGp"/>
                <outlet property="view_coin" destination="S7h-OF-RAr" id="0wr-zD-dLr"/>
                <outlet property="view_container" destination="I0g-vn-aAw" id="i7z-aB-Zfq"/>
                <outlet property="view_course" destination="zmh-9K-6Xt" id="JZe-co-2IU"/>
                <outlet property="view_wechat" destination="ME6-yW-eFT" id="rKw-i7-02q"/>
            </connections>
            <point key="canvasLocation" x="139.69465648854961" y="20.422535211267608"/>
        </view>
@@ -329,7 +338,7 @@
        <image name="icon_notice" width="26" height="32"/>
        <image name="icon_wechat" width="28" height="29"/>
        <namedColor name="FE6E0D">
            <color red="0.99599999189376831" green="0.4309999942779541" blue="0.050999999046325684" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
            <color red="0.99199998378753662" green="0.53299999237060547" blue="0.0080000003799796104" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
        </namedColor>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
WanPai/Config/Def.swift
@@ -14,6 +14,9 @@
let SHAKEY = "BT7NPhA0f775uzcUuftWjCE1TYZlWmHZ"
let WechatUniversalLinks = ""
let WeChatAPPID = ""
let APPScheme = "weparklife"
let app = UIApplication.shared.delegate as! AppDelegate
WanPai/Config/Enums.swift
@@ -15,10 +15,10 @@
    /// 支付方式
enum PayType:Int{
    case aliPay = 0
    case aliPay = 2
    case wechat = 1
    case coin = 2
    case courseNum = 3
    case coin = 3
    case courseNum = 4
}
enum ItemType{
@@ -167,4 +167,13 @@
    case voucher = 2
        /// 体验券
    case experience = 3
    var rawTitle:String{
        switch self {
            case .none:return ""
            case .discount:return "满减券"
            case .voucher:return "代金券"
            case .experience:return "体验券"
        }
    }
}
WanPai/Info.plist
@@ -13,6 +13,12 @@
            </array>
        </dict>
    </array>
    <key>LSApplicationQueriesSchemes</key>
    <array>
        <string>weixin</string>
        <string>weixinULAPI</string>
        <string>weixinURLParamsAPI</string>
    </array>
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
WanPai/Model/CommonModels.swift
@@ -54,7 +54,7 @@
    var age: Int = 0
    var id: Int = 0
    var name = ""
    var phone: String = ""
    var phone:String?
}
struct StudentProfileModel:HandyJSON{
@@ -79,3 +79,12 @@
        /// 使用条件
    var useCondition: String = ""
}
struct PaymentModel:HandyJSON{
    var orderString = ""
}
struct StoreWalfareModel:HandyJSON{
    var phone = ""
    var img = ""
}
WanPai/Network/NetworkRequest.swift
@@ -59,12 +59,12 @@
        return self
    }
    @discardableResult
    func append(key: String,value: String) -> ParamsAppender {
        if value.isEmpty{return self}
        params += ["\(key)":"\(value)"]
        return self
    }
//    @discardableResult
//    func append(key: String,value: String) -> ParamsAppender {
//        if value.isEmpty{return self}
//        params += ["\(key)":"\(value)"]
//        return self
//    }
    @discardableResult
    func append(key: String,value: Bool) -> ParamsAppender {
@@ -74,7 +74,7 @@
    @discardableResult
    func append(key: String,value: String?) -> ParamsAppender {
        if value != nil {
        if value != nil && value?.isEmpty == false {
            params += ["\(key)":"\(value!)"]
        }
        return self
WanPai/Network/OBSUploader.swift
@@ -53,7 +53,7 @@
class OBSUploader: NSObject {
    struct Config {
        static var oss_domain = "https://we-park-life.oss-cn-beijing.aliyuncs.com/img"
        static var oss_domain = "https://we-park-life.oss-cn-beijing.aliyuncs.com"
        static var accessKeyId = "LTAI47eyqWWhBPXM"
        static var accessKeySecret = "orsYX78NvgXS9KbN7wCwRja1wkUwPc"
        static var bucketName = "we-park-life"
@@ -139,7 +139,7 @@
            return Observable<String>.create{ ob in
                let put = OSSPutObjectRequest()
                put.bucketName = Config.bucketName
                put.objectKey = "\(key).png"
                put.objectKey = "img/\(key).png"
                if scaleSize != nil{
                    put.uploadingData = image.jq_scaled(to: scaleSize!).pngData()!
@@ -149,7 +149,7 @@
                let task = client.putObject(put)
                task.continue({ r in
                    if r.error == nil {
                        ob.onNext("\(Config.oss_domain)/\(key).png")
                        ob.onNext("\(Config.oss_domain)/img/\(key).png")
                    } else {
                        ob.onError(ImageUploadError.Failed)
                    }
@@ -198,7 +198,8 @@
        return Observable<String>.create{ ob in
            let put = OSSPutObjectRequest()
            put.bucketName = Config.bucketName
            put.objectKey = "\(key).png"
            put.objectKey = "img/\(key).png"
            var img:UIImage?
@@ -215,7 +216,7 @@
            let task = client.putObject(put)
            task.continue({ r in
                if r.error == nil {
                    ob.onNext("\(Config.oss_domain)/\(key).png")
                    ob.onNext("\(Config.oss_domain)/img/\(key).png")
                } else {
                    ob.onError(ImageUploadError.Failed)
                }
WanPai/Network/Services.swift
@@ -157,7 +157,28 @@
            .append(key: "sex", value: model.sex.rawValue)
            .append(key: "weight", value: model.weight.string)
        return NetworkRequest.request(params: params, method: .post, progress: false)
    }
        /// 购买课程
    class func courcePayment(conponId:Int? = nil,courseConfigId:Int,id:Int,price:Double,payType:PayType,stuId:[Int])->Observable<BaseResponse<PaymentModel>>{
        let params = ParamsAppender.build(url: All_Url)
            .interface(url: "/course/api/course/paymentCourse")
            .append(key: "conponId", value: conponId)
            .append(key: "coursePackagePaymentConfigId", value: courseConfigId)
            .append(key: "id", value: id)
            .append(key: "payType", value: payType.rawValue)
            .append(key: "price", value: price.string)
            .append(key: "studentIds", value: stuId.map({"\($0)"}).joined(separator: ";"))
        return NetworkRequest.request(params: params, method: .post, progress: true)
    }
        /// 查询店的免费福利
    class func queryStoreFreeBenefit(id:Int)->Observable<BaseResponse<StoreWalfareModel>>{
        let params = ParamsAppender.build(url: All_Url)
            .interface(url: "other/base/store/queryStoreFreeBenefit")
            .append(key: "id", value: id)
        return NetworkRequest.request(params: params, method: .post, progress: true)
    }
}
@@ -176,6 +197,13 @@
            .append(key: "position", value: type.rawValue)
        return NetworkRequest.request(params: params, method: .post, progress: false)
    }
    class func enrollMember(paytype:PayType)->Observable<BaseResponse<PaymentModel>>{
        let params = ParamsAppender.build(url: All_Url)
            .interface(url: "/account/api/appUser/addVipPayment")
            .append(key: "payType", value: paytype.rawValue)
        return NetworkRequest.request(params: params, method: .post, progress: true)
    }
}
extension Services{
WanPai/Root/Activity/VC/ActivityDetailApplyVC.swift
@@ -28,7 +28,7 @@
    }
    
    @IBAction func addStudentAction(_ sender: QMUIButton) {
        StudentChooseView.show(itemType:.activity) {
        StudentChooseView.show(itemType: .activity) { studs in
            
        } needAddClouse: {[weak self] () in
            let vc = ActivityStudentListVC()
@@ -37,17 +37,21 @@
    }
    
    @IBAction func applyAction(_ sender: UIButton) {
        StoresInfoView.show({ status in
            if status{
                PaymentView.show { stat in
                    let result:PaymentResultVC.PaymentResult = status ? .success:.fail
                    let vc = PaymentResultVC(result: result, objType: .activityApply)
                    vc.modalPresentationStyle = .fullScreen
                    self.present(vc, animated: true)
                }
            }
        })
        StoresInfoView.show(CourseDetailModel()) { status in
        }
//        StoresInfoView.show(CourseDetailModel() { status in
//            if status{
//                PaymentView.show(money: (ali:1,wx:2,coin:2,course:2)) { stat in
//                    let result:PaymentResultVC.PaymentResult = status ? .success:.fail
//                    let vc = PaymentResultVC(result: result, objType: .activityApply)
//                    vc.modalPresentationStyle = .fullScreen
//                    self.present(vc, animated: true)
//                }
//            }
//        }
    }
}
WanPai/Root/Activity/View/StoresInfoView.swift
@@ -10,7 +10,11 @@
class StoresInfoView: UIView,JQNibView{
    @IBOutlet weak var view_container: UIView!
    @IBOutlet weak var img_logo: UIImageView!
    @IBOutlet weak var label_title: UILabel!
    @IBOutlet weak var label_address: UILabel!
    @IBOutlet weak var label_distance: UILabel!
    private var clouse:((Bool)->Void)!
    
    override func awakeFromNib() {
@@ -20,9 +24,14 @@
        layoutIfNeeded()
    }
    
    static func show(_ clouse:@escaping (Bool)->Void){
    static func show(_ detailModel:CourseDetailModel,clouse:@escaping (Bool)->Void){
        let storesView = StoresInfoView.jq_loadNibView()
        storesView.frame = screnDelegate?.window?.frame ?? .zero
        storesView.img_logo.sd_setImage(with: URL(string: detailModel.coverDrawing)!)
        storesView.label_title.text = detailModel.name
        storesView.label_address.text = detailModel.storeAddress
        storesView.label_distance.text = String(format: "距你%.2lfkm", detailModel.distance)
        storesView.clouse = clouse
        screnDelegate?.window?.addSubview(storesView)
        
@@ -34,6 +43,11 @@
    
    @IBAction func cancelAction(_ sender: UIButton) {
        close()
    }
    @IBAction func exchangeAction(_ sender: UIButton) {
        close()
        clouse(false)
    }
    
WanPai/Root/Activity/View/StoresInfoView.xib
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
    <device id="retina6_12" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
        <capability name="Named colors" minToolsVersion="9.0"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
@@ -65,6 +65,9 @@
                            <state key="normal" title="更换门店" image="btn_edit_gray">
                                <color key="titleColor" red="0.0" green="0.0" blue="0.0" alpha="0.69999999999999996" colorSpace="custom" customColorSpace="sRGB"/>
                            </state>
                            <connections>
                                <action selector="exchangeAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="Cxg-Z6-tcN"/>
                            </connections>
                        </button>
                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Jpw-FW-83z">
                            <rect key="frame" x="27" y="331.66666666666674" width="150.66666666666666" height="40"/>
@@ -159,6 +162,10 @@
                <constraint firstItem="YPc-hT-wLG" firstAttribute="centerX" secondItem="vUN-kp-3ea" secondAttribute="centerX" id="chg-wY-k2g"/>
            </constraints>
            <connections>
                <outlet property="img_logo" destination="OiY-s7-UjK" id="8ec-gh-7ta"/>
                <outlet property="label_address" destination="0wv-DE-XuG" id="s3a-3G-Ijd"/>
                <outlet property="label_distance" destination="ZUc-jP-D3A" id="EKG-km-ayN"/>
                <outlet property="label_title" destination="Uxo-kQ-Zqa" id="wZQ-eZ-uoP"/>
                <outlet property="view_container" destination="YPc-hT-wLG" id="9n8-u0-HGJ"/>
            </connections>
            <point key="canvasLocation" x="38.931297709923662" y="20.422535211267608"/>
@@ -167,7 +174,7 @@
    <resources>
        <image name="btn_edit_gray" width="26" height="22"/>
        <namedColor name="FE6E0D">
            <color red="0.99599999189376831" green="0.4309999942779541" blue="0.050999999046325684" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
            <color red="0.99199998378753662" green="0.53299999237060547" blue="0.0080000003799796104" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
        </namedColor>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
WanPai/Root/Course/VC/CourseDetailApplyVC.swift
@@ -31,6 +31,7 @@
    @IBOutlet weak var label_vipPrice: UILabel!
    @IBOutlet weak var label_coin: UILabel!
    @IBOutlet weak var btn_hasCoupon: TapBtn!
    @IBOutlet weak var btn_couponInfo: UIButton!
    @IBOutlet weak var studentTableView: UITableView!
@@ -40,6 +41,7 @@
    private var CellH:Double!
    private var studentModels = [CourseDetailStudentModel]()
    private var couponModels = [CouponInfoModel]()
    private var selectCouponModel:CouponInfoModel?
    
    override func viewDidLoad() {
        super.viewDidLoad()
@@ -53,7 +55,6 @@
            label_store.text = m.storeName
            label_address.text = m.storeAddress
            changePrice(selectClassIndex)
            if let stu = m.student{studentModels.append(stu)}
            cons_collHei.constant = ceil(Double(m.list.count) / 3.0) * CellH + floor(Double(m.list.count) / 3.0) * 21.0
@@ -61,6 +62,7 @@
            cons_tableHei.constant = CGFloat(studentModels.count * 87)
            tableView.reloadData()
            changePrice(selectClassIndex)
        }
    }
    
@@ -94,16 +96,22 @@
    @IBAction func couponAction(_ sender: TapBtn) {
        guard couponModels.count != 0 else {
            alertError(msg: "暂无优惠券");return
        CouponChooseView.show(couponModels,defaultModel: selectCouponModel) { m in
            self.selectCouponModel = m
            guard m != nil else {
                self.btn_couponInfo.setTitle("去选择", for: .normal);return
            }
            self.btn_couponInfo.setTitle("-\(m!.favorable)", for: .normal)
        }
        CouponChooseView.show()
    }
    
    @IBAction func studentAction(_ sender: QMUIButton) {
        StudentChooseView.show(itemType:.course,defaultStu: detailModel?.student) {
        StudentChooseView.show(itemType: .course, defaultStu: studentModels) { [weak self] studs in
            guard let weakSelf = self else { return }
            weakSelf.studentModels = studs
            weakSelf.tableView.reloadData()
            weakSelf.cons_tableHei.constant = CGFloat((weakSelf.studentModels.count) * 87)
            weakSelf.changePrice(weakSelf.selectClassIndex)
        } needAddClouse: { [weak self] () in
            let vc = AddStudentVC()
            self?.push(vc: vc)
@@ -111,34 +119,67 @@
    }
    
    @IBAction func paymentAction(_ sender: UIButton) {
        PaymentView.show { status in
            let paymentState:PaymentResultVC.PaymentResult = status ? .success:.fail
            let vc = PaymentResultVC(result: paymentState, objType: .courseApply)
            vc.modalPresentationStyle = .fullScreen
            self.present(vc, animated: true)
        guard detailModel != nil else {return}
        guard studentModels.count != 0 else {alertError(msg: "请选择学员");return}
        StoresInfoView.show(detailModel!) { [weak self] status in
            guard let weakSelf = self else { return }
            if status{
                if let model = weakSelf.detailModel?.list[weakSelf.selectClassIndex]{
                    let price = model.vipPrice == nil ? model.originalPrice : model.vipPrice
                    let coin = model.playPaiCoin
                    PaymentView.show(money: (ali:price,wx:price,coin:coin,course:nil)) { [weak self] payType in
                        guard let weakSelf = self else { return }
                        Services.courcePayment(conponId: weakSelf.selectCouponModel?.id, courseConfigId: model.id, id: weakSelf.detailModel!.id, price: model.paymentPrice, payType: payType, stuId: weakSelf.studentModels.map({$0.id})).subscribe(onNext: { data in
                            if let m = data.data{
                                switch payType {
                                    case .aliPay:
                                        YYPaymentManager.shared.sendPaymentRequest(YYAlipayRequest(orderString: m.orderString)) { [weak self] result in
                                            switch result {
                                                case .success:
                                                    let vc = PaymentResultVC(result: .success, objType: .courseApply)
                                                    self?.present(vc, animated: true)
                                                case .cancel:
                                                    let vc = PaymentResultVC(result: .fail, objType: .courseApply)
                                                    self?.present(vc, animated: true)
                                                case .failure(let error):
                                                    let vc = PaymentResultVC(result: .fail, objType: .courseApply)
                                                    self?.present(vc, animated: true)
                                            }
                                        }
                                    case .wechat:break
                                    case .coin:break
                                    case .courseNum:break
                                }
                            }else{
                                alertError(msg: data.msg)
                            }
                        }).disposed(by: weakSelf.disposeBag)
                    }
                }
            }else{
                self?.navigationController?.popToRootViewController(animated: true)
            }
        }
    }
    private func changePrice(_ index:Int){
        if let subM = detailModel?.list[index]{
            label_price.text = subM.paymentPrice.currency()
            label_originPrice.isHidden = subM.originalPrice == nil
            label_coin.isHidden = subM.playPaiCoin == nil
            label_vipPrice.isHidden = subM.vipPrice == nil
            label_price.text = (subM.paymentPrice * Double(studentModels.count)).currency()
            label_originPrice.isHidden = subM.originalPrice == nil || subM.originalPrice == 0
            label_coin.isHidden = subM.playPaiCoin == nil || subM.playPaiCoin == 0
            label_vipPrice.isHidden = subM.vipPrice == nil || subM.vipPrice == 0
                //原价
            if let originPrice =  subM.originalPrice{
                let attribute = AttributedStringbuilder.build().add(string: originPrice.currency(), withFont: UIFont.systemFont(ofSize: 16, weight: .semibold), withColor: UIColor(hexStr: "#3F3F3F").withAlphaComponent(0.58)).underLine(color: UIColor(hexStr: "#3F3F3F").withAlphaComponent(0.58))
                let attribute = AttributedStringbuilder.build().add(string: (originPrice * Double(studentModels.count)).currency(), withFont: UIFont.systemFont(ofSize: 16, weight: .semibold), withColor: UIColor(hexStr: "#3F3F3F").withAlphaComponent(0.58)).underLine(color: UIColor(hexStr: "#3F3F3F").withAlphaComponent(0.58))
                label_originPrice.attributedText = attribute.mutableAttributedString
            }
                //玩湃币
            if let paiCoin = subM.playPaiCoin{
                let coinAttribute = AttributedStringbuilder.build()
                    .add(string: "玩湃币:", withFont: UIFont.systemFont(ofSize: 14, weight: .semibold), withColor: UIColor(hexStr: "#3F3F3F"))
                    .add(string: "\(paiCoin)币", withFont: UIFont.systemFont(ofSize: 14, weight: .semibold), withColor: UIColor(hexStr: "#F21313"))
                    .add(string: "\(paiCoin * studentModels.count)币", withFont: UIFont.systemFont(ofSize: 14, weight: .semibold), withColor: UIColor(hexStr: "#F21313"))
                label_coin.attributedText = coinAttribute.mutableAttributedString
            }
@@ -146,7 +187,7 @@
            if let vipPrice = subM.vipPrice{
                let vipAttribute = AttributedStringbuilder.build()
                    .add(string: "会员价:", withFont: UIFont.systemFont(ofSize: 14, weight: .semibold), withColor: UIColor(hexStr: "#3F3F3F"))
                    .add(string: vipPrice.currency(), withFont: UIFont.systemFont(ofSize: 14, weight: .semibold), withColor: UIColor(hexStr: "#F21313"))
                    .add(string: (vipPrice * Double(studentModels.count)).currency(), withFont: UIFont.systemFont(ofSize: 14, weight: .semibold), withColor: UIColor(hexStr: "#F21313"))
                label_vipPrice.attributedText = vipAttribute.mutableAttributedString
            }
        }
@@ -169,7 +210,7 @@
                LogError("会员优惠价格出现问题:nil");return
            }
            Services.queryAvaiableCopons(id: subM.id, price: price!).subscribe(onNext: { [weak self] data in
            Services.queryAvaiableCopons(id: detailModel!.id, price: price!).subscribe(onNext: { [weak self] data in
                self?.btn_hasCoupon.isHidden = (data.data?.count ?? 0) == 0
                self?.couponModels = data.data ?? []
            }).disposed(by: disposeBag)
@@ -222,8 +263,18 @@
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "_StudentInfoTCell") as! StudentInfoTCell
        cell.indexPath = indexPath
        cell.studentModel = studentModels[indexPath.row]
        cell.deleClouse = { [weak self] index in
            guard let weakSelf = self else { return }
            tableView.beginUpdates()
            weakSelf.studentModels.remove(at: index)
            tableView.deleteRows(at: [IndexPath(row: index, section: 0)], with: .right)
            tableView.endUpdates()
            weakSelf.cons_tableHei.constant = CGFloat((weakSelf.studentModels.count) * 87)
            tableView.reloadData()
            weakSelf.changePrice(weakSelf.selectClassIndex)
        }
        return cell
    }
}
WanPai/Root/Course/VC/CourseDetailApplyVC.xib
@@ -14,6 +14,7 @@
            <connections>
                <outlet property="btn_addStudent" destination="kv0-E8-XGD" id="H56-eE-BCc"/>
                <outlet property="btn_coupon" destination="XNI-Vj-heV" id="es4-Cw-MCW"/>
                <outlet property="btn_couponInfo" destination="uvW-sZ-v3z" id="0Up-RU-njq"/>
                <outlet property="btn_hasCoupon" destination="XNI-Vj-heV" id="680-zV-BEX"/>
                <outlet property="collectionView" destination="ZtR-nH-Ly1" id="Snf-0R-x4b"/>
                <outlet property="cons_collHei" destination="wOm-8j-9fG" id="gZo-vk-a95"/>
WanPai/Root/Course/VC/CourseDetailVC.swift
@@ -50,9 +50,9 @@
            label_price.text = detailModel.list.first!.paymentPrice.currency()
            if let subM = detailModel.list.first {
                label_originPrice.isHidden = subM.originalPrice == nil
                label_coin.isHidden = subM.playPaiCoin == nil
                label_vipPrice.isHidden = subM.vipPrice == nil
                label_originPrice.isHidden = subM.originalPrice == nil || subM.originalPrice == 0
                label_coin.isHidden = subM.playPaiCoin == nil || subM.playPaiCoin == 0
                label_vipPrice.isHidden = subM.vipPrice == nil || subM.vipPrice == 0
                    //原价
                if let originPrice =  subM.originalPrice{
@@ -108,8 +108,10 @@
    }
    @IBAction func applyAction(_ sender: UIButton) {
         let vc = CourseDetailApplyVC(detailModel: detailModel)
        push(vc: vc)
        if let m = detailModel{
            let vc = CourseDetailApplyVC(detailModel: detailModel)
           push(vc: vc)
        }
    }
    
    
WanPai/Root/Home/VC/HomeVC.swift
@@ -30,7 +30,7 @@
    private var layout:WaterFallFlowLayout!
    @IBOutlet weak var label_store: UILabel!
    private var items = Array<HomeStoreConfigModel>()
    private var storeModel:HomeStoreModel?
//    private var storeModel:HomeStoreModel?
    var viewModel = HomeViewModel()
    override func viewDidLoad() {
@@ -149,10 +149,11 @@
extension HomeVC:UICollectionViewDelegate{
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//        let vc = JQ_CommonWebViewController(url: "https://whctw-qa.whitecoat.global/#/packageA/shares/index?booking_id=1b16387e-7dc4-4a0f-beb0-c919caf46fd2&token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoibWVtYmVyIiwibmFtZWlkIjoicnlwL2ZIK3Urck81TnBrQ3VtUnl1OW10dUUxb1JibXExUnVEbytjaXVaQWcxbTNLZzZ0S2daM1R1VDRqK3BIcyIsInJmci10a24iOiIwMDA2MDEwNjEwMjA4Ny1EOTU4ODk2My00QTZBLTRCMDgtQTQ0Ri1GODg1RkZCQTkzQ0MiLCJyZXF1ZXN0X3VwZGF0ZV9jb250YWN0X2luZm8iOiJGYWxzZSIsInJlcXVlc3RfYWN0aXZhdGVfYWNjb3VudCI6IkZhbHNlIiwiZm9yX2NoaWxkX3RoYXRfdHVybmVkXzIxIjoiRmFsc2UiLCJkZXZpY2VfaWQiOiIiLCJkZXZpY2VfdHlwZSI6IjEiLCJpc3MiOiJodHRwczovL3doY2FwaS1xYS53aGl0ZWNvYXQuZ2xvYmFsLyIsImF1ZCI6IjQxNGUxOTI3YTM4ODRmNjhhYmM3OWY3MjgzODM3ZmQxIiwiZXhwIjoxNzIwNjA1ODE3LCJuYmYiOjE2ODkwNjk4MTd9.T5hMybqAV7W_FuqX9WlPkZjgFBzkjw_XP5RGxlN2aUQ&device_id=raBw19aP3NkWnm8g93LOPmZ7iSffnu%3Ftoken%3DeyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoibWVtYmVyIiwibmFtZWlkIjoicnlwL2ZIK3Urck81TnBrQ3VtUnl1OW10dUUxb1JibXExUnVEbytjaXVaQWcxbTNLZzZ0S2daM1R1VDRqK3BIcyIsInJmci10a24iOiIwMDA2MDEwNjEwMjA4Ny1EOTU4ODk2My00QTZBLTRCMDgtQTQ0Ri1GODg1RkZCQTkzQ0MiLCJyZXF1ZXN0X3VwZGF0ZV9jb250YWN0X2luZm8iOiJGYWxzZSIsInJlcXVlc3RfYWN0aXZhdGVfYWNjb3VudCI6IkZhbHNlIiwiZm9yX2NoaWxkX3RoYXRfdHVybmVkXzIxIjoiRmFsc2UiLCJkZXZpY2VfaWQiOiIiLCJkZXZpY2VfdHlwZSI6IjEiLCJpc3MiOiJodHRwczovL3doY2FwaS1xYS53aGl0ZWNvYXQuZ2xvYmFsLyIsImF1ZCI6IjQxNGUxOTI3YTM4ODRmNjhhYmM3OWY3MjgzODM3ZmQxIiwiZXhwIjoxNzIwNjA1ODE3LCJuYmYiOjE2ODkwNjk4MTd9.T5hMybqAV7W_FuqX9WlPkZjgFBzkjw_XP5RGxlN2aUQ&device_id=raBw19aP3NkWnm8g93LOPmZ7iSffnu")
//        let vc = JQ_CommonWebViewController(url: "http://192.168.110.103:8080/#/packageA/shares/index")
//        vc.modalPresentationStyle = .fullScreen
//        present(vc, animated: true)
//        push(vc: vc)
//        return
        let item = items[indexPath.row]
@@ -179,8 +180,16 @@
                let vc = WelfareWeeklyListVC()
                push(vc: vc)
            case .welfare:
                let vc = WelfareFreeVC()
                push(vc: vc)
                if viewModel.storeId.value != 0{
                    Services.queryStoreFreeBenefit(id: viewModel.storeId.value).subscribe(onNext: {[weak self] data in
                        if let m = data.data{
                            let vc = WelfareFreeVC(m)
                            self?.push(vc: vc)
                        }
                    }).disposed(by: disposeBag)
                }else{
                    alertError(msg: "当前门店获取失败")
                }
            case .none:break
        }
    }
WanPai/Root/Home/VC/JoinMemberIntroduceVC.swift
@@ -35,12 +35,35 @@
    
    
    @IBAction func joinAction(_ sender: QMUIButton) {
        PaymentView.show { status in
            let paymentState:PaymentResultVC.PaymentResult = status ? .success:.fail
            let vc = PaymentResultVC(result: paymentState, objType: .member)
            vc.modalPresentationStyle = .fullScreen
            self.present(vc, animated: true)
        PaymentView.show(money: (ali:199,wx:199,coin:nil,course:nil)) { type in
            Services.enrollMember(paytype: type).subscribe(onNext: {data in
                switch type {
                    case .aliPay:
                        if let orderString = data.data?.orderString{
                            YYPaymentManager.shared.sendPaymentRequest(YYAlipayRequest(orderString: orderString)) { result in
                                switch result {
                                    case .success:
                                        alertSuccess(msg: "支付成功")
                                    case .cancel:
                                        alert(msg: "已取消支付")
                                    case .failure(let error):
                                        alertError(msg: error.localizedDescription)
                                }
                            }
                        }
                    case .wechat:break
                    default:break
                }
            }).disposed(by: self.disposeBag)
        }
//        PaymentView.show { status in
//            let paymentState:PaymentResultVC.PaymentResult = status ? .success:.fail
//            let vc = PaymentResultVC(result: paymentState, objType: .member)
//            vc.modalPresentationStyle = .fullScreen
//            self.present(vc, animated: true)
//
//        }
    }
}
WanPai/Root/Other/TCell/CouponTCell.swift
@@ -9,6 +9,26 @@
class CouponTCell: UITableViewCell {
    var couponInfoModel:CouponInfoModel?{
        didSet{
            if let m = couponInfoModel{
                label_info.text = m.useCondition
                label_price.text = m.favorable
                label_duetime.text = "有效期至" + m.effectiveTime
                label_title.text = m.type.rawTitle
            }
        }
    }
    @IBOutlet weak var label_price: UILabel!
    @IBOutlet weak var label_title: UILabel!
    @IBOutlet weak var label_info: UILabel!
    @IBOutlet weak var label_duetime: UILabel!
    @IBOutlet weak var img_select: UIImageView!
    @IBOutlet weak var btn_more: UIButton!
    override func awakeFromNib() {
        super.awakeFromNib()
        selectionStyle = .none
WanPai/Root/Other/TCell/CouponTCell.xib
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
    <device id="retina6_12" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@@ -23,6 +23,9 @@
                        <subviews>
                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="1000" verticalHuggingPriority="251" image="icon_coupon_header" translatesAutoresizingMaskIntoConstraints="NO" id="zmS-eg-Mj0">
                                <rect key="frame" x="0.0" y="0.0" width="100" height="122"/>
                                <constraints>
                                    <constraint firstAttribute="width" constant="100" id="Q7m-lv-Y2D"/>
                                </constraints>
                            </imageView>
                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon_coupon_footer" translatesAutoresizingMaskIntoConstraints="NO" id="gIO-rm-Idg">
                                <rect key="frame" x="100" y="0.0" width="331" height="122"/>
@@ -122,13 +125,21 @@
                </constraints>
            </tableViewCellContentView>
            <viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
            <connections>
                <outlet property="btn_more" destination="uap-oQ-COV" id="6rH-JW-JWe"/>
                <outlet property="img_select" destination="MyU-nB-kSQ" id="2cI-8f-HcM"/>
                <outlet property="label_duetime" destination="7mn-yy-wtX" id="eG2-2c-YAE"/>
                <outlet property="label_info" destination="QGi-7X-2rC" id="cSC-hJ-WSP"/>
                <outlet property="label_price" destination="3QE-LO-GFM" id="txg-Rm-w2r"/>
                <outlet property="label_title" destination="pqd-2P-O0e" id="Iyu-aC-JX7"/>
            </connections>
            <point key="canvasLocation" x="96.946564885496173" y="54.929577464788736"/>
        </tableViewCell>
    </objects>
    <resources>
        <image name="btn_choose_1" width="24" height="24"/>
        <image name="icon_coupon_footer" width="262" height="100"/>
        <image name="icon_coupon_header" width="100" height="100"/>
        <image name="icon_coupon_footer" width="19.333333969116211" height="46.666667938232422"/>
        <image name="icon_coupon_header" width="20.333333969116211" height="38.666667938232422"/>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
WanPai/Root/Other/TCell/StudentInfoTCell.swift
@@ -12,7 +12,7 @@
    var studentModel:CourseDetailStudentModel?{
        didSet{
            label_name.text = studentModel?.name ?? "--"
            label_phone.text = studentModel?.phone ?? "--"
            label_phone.text = studentModel?.phone ?? "未填写"
            label_age.text = "\(studentModel?.age ?? 0)岁"
        }
    }
@@ -21,8 +21,16 @@
    @IBOutlet weak var label_age: UILabel!
    @IBOutlet weak var btn_handle: UIButton!
    var indexPath: IndexPath!
    var deleClouse:((Int)->Void)?
    override func awakeFromNib() {
        super.awakeFromNib()
        selectionStyle = .none
    }
    @IBAction func handleAction(_ sender: UIButton) {
        deleClouse?(indexPath.row)
    }
}
WanPai/Root/Other/TCell/StudentInfoTCell.xib
@@ -68,6 +68,9 @@
                                <rect key="frame" x="314" y="12" width="16" height="22"/>
                                <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
                                <state key="normal" image="btn_delete"/>
                                <connections>
                                    <action selector="handleAction:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="TEy-5W-Wfp"/>
                                </connections>
                            </button>
                        </subviews>
                        <color key="backgroundColor" red="1" green="0.90588235294117647" blue="0.80000000000000004" alpha="0.080000000000000002" colorSpace="custom" customColorSpace="sRGB"/>
WanPai/Root/Other/View/CouponChooseView.swift
@@ -13,6 +13,10 @@
    @IBOutlet weak var view_container: UIView!
    @IBOutlet weak var cons_bottom: NSLayoutConstraint!
    @IBOutlet weak var tableView: UITableView!
    private var models = [CouponInfoModel]()
    private var clouse:((CouponInfoModel?)->Void)!
    private var defaultModel:CouponInfoModel?
    
    override func awakeFromNib() {
        super.awakeFromNib()
@@ -25,16 +29,21 @@
        layoutIfNeeded()
    }
    
    static func show(){
    static func show(_ models:[CouponInfoModel],defaultModel:CouponInfoModel? = nil,clouse:@escaping (CouponInfoModel?)->Void){
        let couponView = CouponChooseView.jq_loadNibView()
        couponView.models = models
        couponView.defaultModel = defaultModel
        couponView.frame = screnDelegate?.window?.frame ?? .zero
        screnDelegate?.window?.addSubview(couponView)
        couponView.cons_bottom.constant = 0
        couponView.clouse = clouse
        
        UIView.animate(withDuration: 0.4) {
            couponView.alpha = 1
            couponView.layoutIfNeeded()
        }completion: { status in
            couponView.tableView.reloadData()
        }
    }
    
@@ -47,15 +56,18 @@
        self.cons_bottom.constant = -(JQ_ScreenW * 1.1)
        UIView.animate(withDuration: 0.4) {
            self.alpha = 0
            self.layoutIfNeeded()
        } completion: { _ in
            self.removeFromSuperview()
        }
    }
    
    @IBAction func completeAction(_ sender: UIButton) {
        clouse(defaultModel)
        self.cons_bottom.constant = -(JQ_ScreenW * 1.1)
        UIView.animate(withDuration: 0.4) {
            self.alpha = 0
            self.layoutIfNeeded()
        } completion: { _ in
            self.removeFromSuperview()
        }
@@ -63,16 +75,33 @@
}
extension CouponChooseView:UITableViewDelegate{
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let model = models[indexPath.row]
        if defaultModel?.id == model.id{
            defaultModel = nil
        }else{
            defaultModel = model
        }
        tableView.reloadData()
    }
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 115
    }
}
extension CouponChooseView:UITableViewDataSource{
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 5
        return models.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let model = models[indexPath.row]
        let cell = tableView.dequeueReusableCell(withIdentifier: "_CouponTCell") as! CouponTCell
        cell.couponInfoModel = model
        cell.btn_more.isHidden = true
        cell.img_select.image = defaultModel?.id == model.id ? UIImage(named: "btn_choose_s") : UIImage(named: "btn_choose_1")
        return cell
    }
}
WanPai/Root/Other/View/CouponChooseView.xib
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
    <device id="retina6_12" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
        <capability name="Named colors" minToolsVersion="9.0"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
@@ -86,12 +86,23 @@
                        <constraint firstItem="Ksj-7h-JHG" firstAttribute="top" secondItem="aWM-tn-Qlc" secondAttribute="top" constant="8" id="qUr-w6-up5"/>
                    </constraints>
                </view>
                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7sR-sG-JMu">
                    <rect key="frame" x="0.0" y="59" width="393" height="360.66666666666669"/>
                    <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
                    <connections>
                        <action selector="cancelAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="gsi-lU-c3b"/>
                    </connections>
                </button>
            </subviews>
            <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
            <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
            <constraints>
                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="aWM-tn-Qlc" secondAttribute="trailing" id="Aog-ls-NWS"/>
                <constraint firstItem="7sR-sG-JMu" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="OOw-br-rXZ"/>
                <constraint firstItem="7sR-sG-JMu" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" id="sTO-4x-htZ"/>
                <constraint firstAttribute="bottom" secondItem="aWM-tn-Qlc" secondAttribute="bottom" id="wu0-fc-WSc"/>
                <constraint firstItem="aWM-tn-Qlc" firstAttribute="top" secondItem="7sR-sG-JMu" secondAttribute="bottom" id="xja-IK-Jno"/>
                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="7sR-sG-JMu" secondAttribute="trailing" id="yHG-Tu-JcS"/>
                <constraint firstItem="aWM-tn-Qlc" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="z6M-8v-Tq6"/>
            </constraints>
            <connections>
@@ -104,7 +115,7 @@
    </objects>
    <resources>
        <namedColor name="FE6E0D">
            <color red="0.99599999189376831" green="0.4309999942779541" blue="0.050999999046325684" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
            <color red="0.99199998378753662" green="0.53299999237060547" blue="0.0080000003799796104" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
        </namedColor>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
WanPai/Root/Other/View/StudentChooseView.swift
@@ -24,7 +24,7 @@
    @IBOutlet weak var cons_bottom: NSLayoutConstraint!
    @IBOutlet weak var btn_add: QMUIButton!
    
    private var clickClouse:(()->Void)!
    private var clickClouse:(([CourseDetailStudentModel])->Void)!
    private var needAddClouse:(()->Void)!
    private var itemType:ItemType!
    private var selectStudents = [CourseDetailStudentModel]()
@@ -46,10 +46,10 @@
    }
    
    static func show(itemType:ItemType,defaultStu:CourseDetailStudentModel? = nil,clickClouse:@escaping ()->Void,needAddClouse:@escaping ()->Void){
    static func show(itemType:ItemType,defaultStu:[CourseDetailStudentModel]? = nil,clickClouse:@escaping ([CourseDetailStudentModel])->Void,needAddClouse:@escaping ()->Void){
        let studentChooseView = StudentChooseView.jq_loadNibView()
        if defaultStu != nil{
            studentChooseView.selectStudents.append(defaultStu!)
            studentChooseView.selectStudents = defaultStu!
        }
        if itemType == .course{
            studentChooseView.tableView.register(UINib(nibName: "StudentInfoTCell", bundle: nil), forCellReuseIdentifier: "_StudentInfoTCell")
@@ -100,7 +100,7 @@
    }
    
    @IBAction func completeAction(_ sender: UIButton) {
        clickClouse!()
        clickClouse!(selectStudents)
        closeAction()
    }
}
WanPai/Root/Welfare/VC/RechargeCenterVC.swift
@@ -61,11 +61,11 @@
    }
    @IBAction func rechargeAction(_ sender: UIButton) {
        PaymentView.show { status in
            let result:PaymentResultVC.PaymentResult = status ? .success:.fail
            let vc = PaymentResultVC(result: result, objType: .activityApply)
            vc.modalPresentationStyle = .fullScreen
            self.present(vc, animated: true)
        PaymentView.show(money: (ali:1,wx:2,coin:2,course:2)) { status in
//            let result:PaymentResultVC.PaymentResult = status ? .success:.fail
//            let vc = PaymentResultVC(result: result, objType: .activityApply)
//            vc.modalPresentationStyle = .fullScreen
//            self.present(vc, animated: true)
        }
    }
}
WanPai/Root/Welfare/VC/WelfareFreeVC.swift
@@ -6,11 +6,39 @@
//
import UIKit
import WebKit
import JQTools
class WelfareFreeVC: BaseVC {
    var storeWalfareModel:StoreWalfareModel?
    @IBOutlet weak var webView: WKWebView!
    @IBOutlet weak var btn_call: UIButton!
    init(_ model:StoreWalfareModel) {
        super.init(nibName: nil, bundle: nil)
        self.storeWalfareModel = model
    }
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "免费福利"
        if let m = storeWalfareModel{
            let html = "<img src='\(m.img)' width='\(JQ_ScreenW)' loading=eager/>"
            self.webView.loadHTMLString(html.jq_wrapHtml(), baseURL: nil)
            self.btn_call.isHidden = m.phone.isEmpty
        }
    }
    @IBAction func callPhoneAction(_ sender: UIButton) {
        if let phone = storeWalfareModel?.phone{
            UIApplication.shared.open(URL(string: "tel://\(phone)")!, options: [:], completionHandler: nil)
        }
    }
}
WanPai/Root/Welfare/VC/WelfareFreeVC.xib
@@ -12,7 +12,9 @@
    <objects>
        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="WelfareFreeVC" customModule="WanPai" customModuleProvider="target">
            <connections>
                <outlet property="btn_call" destination="myM-xc-SEC" id="8zp-al-FgC"/>
                <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
                <outlet property="webView" destination="BSv-nd-B1r" id="Avo-HD-pJX"/>
            </connections>
        </placeholder>
        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
@@ -31,6 +33,9 @@
                    <state key="normal" title="联系商家">
                        <color key="titleColor" red="0.94901960784313721" green="0.97647058823529409" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                    </state>
                    <connections>
                        <action selector="callPhoneAction:" destination="-1" eventType="touchUpInside" id="9tH-r7-cLT"/>
                    </connections>
                </button>
                <wkWebView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="BSv-nd-B1r">
                    <rect key="frame" x="0.0" y="59" width="393" height="711"/>
WanPai/Root/Welfare/VC/WelfareRedeemGoodsDetailVC.swift
@@ -36,7 +36,7 @@
    }
    @IBAction func chooseAction(_ sender: QMUIButton) {
        StudentChooseView.show(itemType: .course) {
        StudentChooseView.show(itemType: .course) { studs in
        } needAddClouse: {
            let vc = ActivityStudentListVC()
@@ -52,11 +52,11 @@
                    .add(string: "0积分和¥0\n", withFont: UIFont.systemFont(ofSize: 16, weight: .medium), withColor: UIColor(hexStr: "#E41818").withAlphaComponent(0.8))
                    .add(string: "兑换此商品吗?", withFont: UIFont.systemFont(ofSize: 16, weight: .medium), withColor: .black.withAlphaComponent(0.9))
                CommonAlertView.show(title: "兑换商品", attribute: attribute.mutableAttributedString) { state in
                    PaymentView.show { status in
                        let result:PaymentResultVC.PaymentResult = status ? .success:.fail
                        let vc = PaymentResultVC(result: result, objType: .activityApply)
                        vc.modalPresentationStyle = .fullScreen
                        self.present(vc, animated: true)
                    PaymentView.show(money: (ali:1,wx:2,coin:2,course:2)) { status in
//                        let result:PaymentResultVC.PaymentResult = status ? .success:.fail
//                        let vc = PaymentResultVC(result: result, objType: .activityApply)
//                        vc.modalPresentationStyle = .fullScreen
//                        self.present(vc, animated: true)
                    }
                }
            }
WanPai/Root/Welfare/VC/WelfareVC.swift
@@ -78,7 +78,7 @@
    }
    
    @IBAction func freeTodayAction(_ sender: UIButton) {
        let vc = WelfareFreeVC()
        let vc = WelfareFreeVC(StoreWalfareModel())
        push(vc: vc)
    }
WanPai/Root/Yard/VC/YardDetailVC.swift
@@ -54,7 +54,9 @@
    }
    @IBAction func couponAction(_ sender: UIButton) {
        CouponChooseView.show()
        CouponChooseView.show([]){ m in
        }
    }
    @IBAction func calendarAction(_ sender: QMUIButton) {
@@ -64,16 +66,16 @@
    @IBAction func bookingAction(_ sender: UIButton) {
        StoresInfoView.show({ status in
        StoresInfoView.show(CourseDetailModel()) { status in
            if status{
                PaymentView.show { stat in
                    let result:PaymentResultVC.PaymentResult = status ? .success:.fail
                    let vc = PaymentResultVC(result: result, objType: .activityApply)
                    vc.modalPresentationStyle = .fullScreen
                    self.present(vc, animated: true)
                PaymentView.show(money: (ali:1,wx:2,coin:2,course:2)) { sta in
//                    let result:PaymentResultVC.PaymentResult = status ? .success:.fail
//                    let vc = PaymentResultVC(result: result, objType: .activityApply)
//                    vc.modalPresentationStyle = .fullScreen
//                    self.present(vc, animated: true)
                }
            }
        })
        }
    }
WanPai/YYPaymentManager/YYPayRequest.swift
New file
@@ -0,0 +1,41 @@
//
//  YYPayRequest.swift
//  YYBase
//
//  Created by alvin_y on 2020/7/2.
//  Copyright © 2020 yangwang. All rights reserved.
//
import Foundation
import HandyJSON
struct YYAlipayRequest {
    let orderString: String
}
struct YYWeChatPayRequest {
    let partnerId: String
    let prepayId: String
    let package: String
    let nonceStr: String
    let timeStamp: TimeInterval
    let sign: String
}
struct YYWeChatMiniProgramPayRequest: HandyJSON {
    var orderId: Int? = nil
    var orderType: Int? = nil
    var type: Int = 0
    var uid: Int = 0
    var userType: Int = 0
    var content: String? = nil
}
WanPai/YYPaymentManager/YYPaymentManager.swift
New file
@@ -0,0 +1,242 @@
//
//  YYPaymentManager.swift
//  YYBase
//
//  Created by alvin_y on 2020/7/2.
//  Copyright © 2020 yangwang. All rights reserved.
//
import Foundation
enum YYPaymentResult {
    case success
    case cancel
    case failure(Error)
}
private protocol YYPaymentManagerDelegate: AnyObject {
     func paymentManager(_ paymentManager: YYPaymentManager, didReceivePayment result: YYPaymentResult)
}
class YYPaymentManager: NSObject {
    /// 支付单例
    static let shared = YYPaymentManager()
    private override init() {}
    private weak var delegate: YYPaymentManagerDelegate?
    private var alipay_appScheme: String?
    /// 微信AppID
    private var weChat_appID: String?
    private var didReceivePaymentInfos: ((_ result: YYPaymentResult) -> Void)?
}
extension YYPaymentManager {
    /// 配置支付宝AppScheme
    ///
    /// - Parameter appScheme: 支付宝AppScheme
    func configuredAlipay(appScheme: String) {
        alipay_appScheme = appScheme
    }
    /// 配置微信AppID
    ///
    /// - Parameter appID: 微信AppID
    func configuredWeChat(appID: String,universalLink:String) {
        weChat_appID = appID
        WXApi.registerApp(appID, universalLink: universalLink)
    }
}
extension YYPaymentManager {
    /// 发送支付宝支付请求
    ///
    /// - Parameters:
    ///   - request: 支付宝支付请求类 MMAlipayRequest
    ///   - result: 返回支付结果 success: 支付成功,cancel:支付被取消,failure:支付失败
    func sendPaymentRequest(_ request: YYAlipayRequest, didReceive result: @escaping (YYPaymentResult) -> Void) {
        guard let appScheme = alipay_appScheme, !appScheme.isEmpty else {
            fatalError("未设置appScheme")
        }
        AlipaySDK.defaultService()?.payOrder(request.orderString,
                                             fromScheme: appScheme,
                                             callback: { (result) in
                                                self.handleAlipayResult(result)
        })
        didReceivePaymentInfos = { (infos) in
            result(infos)
        }
    }
//    /// 拉起小程序支付
//    func sendWXPaymentRequest(_ request: YYWeChatMiniProgramPayRequest,didReceive result: @escaping (YYPaymentResult) -> Void)  {
//
//        guard WXApi.isWXAppInstalled() else {
//            self.delegate?.paymentManager(self, didReceivePayment: .failure(NSError(domain: "com.paymentManager.error", code: -9999, userInfo: [NSLocalizedDescriptionKey: "未安装微信"])))
//            result(.failure(NSError(domain: "com.paymentManager.error", code: -9999, userInfo: [NSLocalizedDescriptionKey: "未安装微信"])))
//            return
//        }
//        let launchMiniProgramReq = WXLaunchMiniProgramReq.object()
//        // /拉起的小程序的username-原始ID
//        launchMiniProgramReq.userName = "gh_33e52f44fac0"
//        // 拉起小程序页面的可带参路径,不填默认拉起小程序首页
//        launchMiniProgramReq.path = "/pages/appPay/appPay?orderId=\(request.orderId ?? 0)&orderType=\(request.orderType ?? 0)&type=\(request.type)&uid=\(request.uid)&userType=\(request.userType)&content=\(request.content ?? "")"
//        launchMiniProgramReq.miniProgramType = .release
////        launchMiniProgramReq.extMsg = request.toJSONString()
//        WXApi.send(launchMiniProgramReq) { (success) in
//
//        }
//    }
    /// 发送微信支付请求
    ///
    /// - Parameters:
    ///   - request: 微信支付请求类 MMWeChatPayRequest
    ///   - result: 返回支付结果 success: 支付成功,cancel:支付被取消,failure:支付失败
    func sendPaymentRequest(_ request: YYWeChatPayRequest, didReceive result: @escaping (YYPaymentResult) -> Void) {
        guard let weChat_appID = weChat_appID, !weChat_appID.isEmpty else {
            fatalError("未设置微信AppID")
        }
        guard WXApi.isWXAppInstalled() else {
            self.delegate?.paymentManager(self, didReceivePayment: .failure(NSError(domain: "com.paymentManager.error", code: -9999, userInfo: [NSLocalizedDescriptionKey: "未安装微信"])))
            result(.failure(NSError(domain: "com.paymentManager.error", code: -9999, userInfo: [NSLocalizedDescriptionKey: "未安装微信"])))
            return
        }
        let req = PayReq()
        req.partnerId = request.partnerId
        req.prepayId = request.prepayId
        req.package = request.package
        req.nonceStr = request.nonceStr
        req.timeStamp = UInt32(request.timeStamp)
        req.sign = request.sign
        WXApi.send(req) { (success) in
        }
        didReceivePaymentInfos = { (infos) in
            result(infos)
        }
    }
}
extension YYPaymentManager {
    /// 处理通过URL启动App时传递的数据
    ///
    /// 在AppDelegate中对应方法中调用并将结果返回给系统的方法
    func handleApplication(_ application: UIApplication, handleOpen url: URL) -> Bool {
        return handle(open: url)
    }
    /// 处理通过URL启动App时传递的数据
    ///
    /// 在AppDelegate中对应方法中调用并将结果返回给系统的方法
    func handleApplication(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
        return handle(open: url)
    }
    /// 处理通过URL启动App时传递的数据
    ///
    /// 在AppDelegate中对应方法中调用并将结果返回给系统的方法
    func handleApplication(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        return handle(open: url)
    }
    private func handle(open url: URL) -> Bool {
        if url.host == "safepay" {
            // 支付宝
            AlipaySDK.defaultService()?.processOrder(withPaymentResult: url, standbyCallback: { (result) in
                self.handleAlipayResult(result)
            })
            return true
        }
        if url.host == "pay" {
            // 微信
            return WXApi.handleOpen(url, delegate: self)
        }
        else if url.host == "resendContextReqByScheme" {
            // 微信
            return WXApi.handleOpen(url, delegate: self)
        }
        return false
    }
    private func handleResult(_ result: YYPaymentResult) {
        delegate?.paymentManager(self, didReceivePayment: result)
        didReceivePaymentInfos?(result)
    }
}
extension YYPaymentManager {
    private func handleAlipayResult(_ result: [AnyHashable: Any]?) {
        if let code = result?["resultStatus"] as? String, let message = result?["memo"] as? String {
            switch code {
            case "9000":
                handleResult(.success)
            case "6001":
                handleResult(.cancel)
            default:
                handleResult(.failure(NSError(domain: "com.abitofcomedy.paymentManager.error",
                                              code: Int(code) ?? -9999,
                                              userInfo: [NSLocalizedDescriptionKey: message])))
            }
        } else {
            handleResult(.failure(NSError(domain: "com.abitofcomedy.paymentManager.error",
                                          code: -9999,
                                          userInfo: [NSLocalizedDescriptionKey: "支付失败"])))
        }
    }
}
extension YYPaymentManager: WXApiDelegate {
    /// 微信支付回调代理方法,不要直接调用
    final func onResp(_ resp: BaseResp) {
//        WXSuccess           = 0,    /**< 成功    */
//        WXErrCodeCommon     = -1,   /**< 普通错误类型    */
//        WXErrCodeUserCancel = -2,   /**< 用户点击取消并返回    */
//        WXErrCodeSentFail   = -3,   /**< 发送失败    */
//        WXErrCodeAuthDeny   = -4,   /**< 授权失败    */
//        WXErrCodeUnsupport  = -5,   /**< 微信不支持    */
        if let response = resp as? PayResp {
            switch response.errCode {
            case 0: // 成功
                handleResult(.success)
            case -2: // 取消
                handleResult(.cancel)
            default:
                handleResult(.failure(NSError(domain: "com.paymentManager.error",
                                              code: Int(response.errCode),
                                              userInfo: [NSLocalizedDescriptionKey: "支付失败"])))
            }
        }
    }
}
WanPai/YYPaymentManager/YYPaymentResultModel.swift
New file
@@ -0,0 +1,17 @@
//
//  YYPaymentResultModel.swift
//  YYBase
//
//  Created by alvin_y on 2020/7/2.
//  Copyright © 2020 yangwang. All rights reserved.
//
import Foundation
struct YYAliPayResultModel: Codable {
    /// 描述信息
    let memo: String
    /// 结果码
    let resultStatus: String
}