ios开发微信支付的介绍与实现(代码片段)

ch520 ch520     2022-12-06     585

关键词:

1、前期准备

  • 1) 到微信开放平台注册账号
    技术图片
    • 需要登录邮箱验证
      技术图片
    • 填写您的商户信息
      技术图片
  • 2) 进入管理中心 --- 移动应用 --- 创建移动应用 --- 根据页面完善应用资料
  • 3) 审核过后,通过应用详情页面,查看应用详情,查看AppID和AppSecret相关信息
  • 4) 创建这些是没有支付能力的,需要额外申请,还是根据提示一步步填写,填写完之后会发一封邮件到您的预留的邮箱,然后到商户平台点击打开链接填写资料,最主要的是验证下开户收款账号,会收到一波几分钱的巨额财产,那么这个时候如果你填写的是你的开户账号,直接跑路吧,这些钱够你在深圳买房了。。。。。。如果你是个好人,那么找你们财务验证下是否有收到,就代表通过了,愉快的代码时间来了.

2、实现过程

  • 步骤1:
    • 用户在商户APP中选择商品,提交订单,选择微信支付。
  • 步骤2:
    • 商户后台收到用户支付单,调用微信支付统一下单接口
  • 步骤3:
    • 统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。参与签名的字段名为appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式为Sign=WXPay
  • 步骤4:
  • 步骤5:
  • 步骤6:

3、代码部分

  • 3.1 工程配置

    • 1) 通过手动配置
      • SDK接入
        技术图片
      • 依赖库导入(貌似还差个libc++.dylib,也一并加入)
        技术图片
      • iOS 9 配置白名单
        技术图片
      • 配置下Scheme(这填写的是申请回来的ID)
        技术图片
    • 2) 实用pod方式配置
      • 在工程的Podfile里面添加以下代码:
      pod 'WechatOpenSDK'
      • 保存并执行pod install,然后用后缀为.xcworkspace的文件打开工程。
        • 注意:
          • 命令行下执行pod search WechatOpenSDK,如显示的WechatOpenSDK版本不是最新的,则先执行pod repo update操作更新本地repo的内容
      • 在Xcode中,选择你的工程设置项,选中“TARGETS”一栏,在“info”标签栏的“URL type“添加“URL scheme”为你所注册的应用程序id(如下图所示)。
        技术图片
  • 3.2 代码实现

    • 1) 向微信注册你的AppID
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
        // Override point for customization after application launch.
    
        // 注册APP,这里的字符串就是Wechat URL Scheme里面对应的ID 也是申请回来的ID,必须一致
        [WXApi registerApp:@"这里填写申请回来的ID"];
        return YES;
    
    • 2) 请求服务器的参数,拉起微信支付App(超级关键,注意听)
    #pragma mark - 微信支付
    - (void)wechatPay 
        // 把生成的订单信息组装起来传给服务器,如何组装就和服务器约定好
        [[TWTShoppingCartLogic sharedData] goToWechatEasyPay:self.orderStr way:@"2" complete:^(NSError *error, id data) 
    
            NSMutableString *stamp  = [data objectForKey:@"timestamp"];
    
            // 调起微信支付
            PayReq *req = [[PayReq alloc] init];
            req.partnerId = [data objectForKey:@"partnerid"];
            req.prepayId = [data objectForKey:@"prepayid"];
            req.nonceStr = [data objectForKey:@"noncestr"];
            req.timeStamp = stamp.intValue;
            req.package = [data objectForKey:@"package"];
            req.sign = [data objectForKey:@"sign"];
            [WXApi sendReq:req];
    
        ];
    
    • 这里请求的方法和步骤就不写了,无非就是post信息给服务器,咱们看看需要的数据格式(假数据)
    
      "appid" : "wxb4b",微信开放平台审核通过的AppID
      "noncestr" : "171127dd056d05e423c8b9e",随机字符串
      "package" : "Sign=WXPay", 固定值
      "partnerid" : "130", 微信支付分配的商户ID
      "prepayid" : "wx201609291601", 预支付交易会话ID
      "sign" : "684371081C049B6017641", 签名,除了sign,剩下6个组合的再次签名字符串
      "timestamp" : 147513 当前时间
    
    • 第一种:老司机后台类型
      • 其实当你把订单传给后台的时候,后台事先会把订单通过微信的生成预支付订单生成prepayID,点击打开链接,那么对于老司机来说,怎么可能把这种返回的数据返回给你?
      • 他们会把接受的prepayID根据上面的结构组装起来,那么预支付订单生成的时候也会返回sign字段,老司机不会直接用,后台会把这个字段,也就是剩下6个字段再次md5签名生成签名算法新的sign字段组装完毕返回给你,这种情况下直接在App上配置模型,拉起微信支付,非常舒畅,一气呵成!!!
    • 第二种:无法理解类型后台(让你自己签名)
      • 当你把订单传给他的时候,同样他会生成个预订单prepayID,那么这种司机开车特别猛,直接把返回的参数根据格式组装后弹回给你,sign字段也是预订单生成后的,没有经过二次md5签名,他也没有告诉你,那么你也特别猛,没问他,直接用他的字段,组装完毕,拉起微信,我擦,你会直接懵逼了,那么你将会只会看到这个。自己写个本地的md5玩玩(假的千万别用,网上找来的分享下)
      // 创建package签名
      - (NSString *) createMd5Sign:(NSMutableDictionary *)dict 
      
          NSMutableString *contentString  =[NSMutableString string];
          NSArray *keys = [dict allKeys];
          // 按字母顺序排序
          NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) 
              return [obj1 compare:obj2 options:NSNumericSearch];
          ];
          // 拼接字符串
          for (NSString *categoryId in sortedArray) 
              if (   ![[dict objectForKey:categoryId] isEqualToString:@""]
                  && ![categoryId isEqualToString:@"sign"]
                  && ![categoryId isEqualToString:@"key"]
                  ) 
                  [contentString appendFormat:@"%@=%@&", categoryId, [dict objectForKey:categoryId]];
              
      
          
          // 添加key字段
          [contentString appendFormat:@"key=%@", self.spKey];
          // 得到MD5 sign签名
          NSString *md5Sign =[contentString MD5];
      
          return md5Sign;
      
      
      - (NSMutableDictionary *)payWithprePayid:(NSString *)prePayid 
      
          if(prePayid == nil) 
              NSLog(@"prePayid 为空");
              return nil;
          
      
          // 获取到prepayid后进行第二次签名
          NSString *package, *time_stamp, *nonce_str;
          // 设置支付参数
          time_t now;
          time(&now);
          time_stamp  = [NSString stringWithFormat:@"%ld", now];
          nonce_str = [time_stamp MD5];
          // 重新按提交格式组包,微信客户端暂只支持package = Sign = WXPay格式,须考虑升级后支持携带package具体参数的情况
          // package = [NSString stringWithFormat:@"Sign = %@",package];
          package = @"Sign = WXPay";
          // 第二次签名参数列表
          NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
          NSLog(@"%@", signParams);
          [signParams setObject: self.appId forKey:@"appid"];
          [signParams setObject: self.mchId forKey:@"partnerid"];
          [signParams setObject: nonce_str forKey:@"noncestr"];
          [signParams setObject: package forKey:@"package"];
          [signParams setObject: time_stamp forKey:@"timestamp"];
          [signParams setObject: prePayid forKey:@"prepayid"];
      
          // 生成签名
          NSString *sign = [self createMd5Sign:signParams];
      
          // 添加签名
          [signParams setObject: sign forKey:@"sign"];
      
          //返回参数列表
          return signParams;
      
    • 如果真的要在App端二次签名的话,那加密的时候还要加入申请的密钥,但是真的不好
    • 这样做
      • 其一:服务器已经做过一次签名了,第二次做了返回给你就好了,没必要再给App。
      • 其二:不安全,全放在App上,这种东西一定要放到服务器
    • 小技巧:其实出现上面那种情况有几种可能
      • 1.sign没有二次签名
      • 2.noncerStr是服务器返回的,不要自己生成
      • 3.package是写死的,不要写错了
      • 4.timeStamp是10位数
      • 5.自己签名的sign一定要全部大写
      • 6.为了避免上面的情况,交给服务器管理,我们负责组装拉起微信支付就好了
    • 3) 处理回调信息
    Appdelegate
    - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url 
    
        // 跳转到URL scheme中配置的地址
        // NSLog(@"跳转到URL scheme中配置的地址-->%@",url);
        return [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
    
    
    // 支付成功时调用,回到第三方应用中
    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation 
        // 微信调用结束
        if ([url.scheme isEqualToString:WECHAT_APPKEY]) 
            return [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
        
    
    
    • 这里的处理是根据微信官网提供的方法,代理到专门处理的单利当中去统一处理WXApiManager
    • 注意点:有些人用NSNotificationCenter来通知到发出请求的界面去,然后在发起的界面处理回调的逻辑,但是这里, 你要考虑一种非人类的交互,TMD有人在拉起微信支付的时候把自己的App给推出了或者App自己挂了,那么当回调生效的时候,原先拉起微信支付App的界面已经消失了,你发的通知他收不到了,这种情况我是存到本地的
    [[NSUserDefaultsstandardUserDefaults] setValue:self.orderStrforKey:@"WECHAT_PAY_ORDER_TRADEID"];
    
    [[NSUserDefaultsstandardUserDefaults] synchronize];
    • 处理回调的时候直接从本地读取
    • 最终处理逻辑的地方(这里不能直接用他的返回接过,要二次确认)
    // 微信回调,有支付结果的时候会回调这个方法
    - (void)onResp:(BaseResp *)resp 
        if([resp isKindOfClass:[PayResp class]]) 
            // 支付返回结果,实际支付结果需要去微信服务器端查询
            NSString *strMsg,*strTitle = [NSString stringWithFormat:@"支付结果"];
    
            switch (resp.errCode) 
                case WXSuccess:
                    strMsg = @"支付结果:成功!";
                    NSLog(@"支付成功-PaySuccess,retcode = %d", resp.errCode);
                    // 这里别用返回的状态来确定是否正真支付成功了,这样是不对的,我们必须拿着存到本地的traderID去服务器再次check,这样和服务器收到的异步回调结果匹配之后才能确认是否真的已经支付成功了
                    [[TWTShoppingCartLogic sharedData] gotoCheckWeChatOrder:tradeID compelete:^(NSError *error, id data) 
                        // 二次确认
                    ];
                    break;
    
                default:
                    strMsg = [NSString stringWithFormat:@"支付结果:失败!retcode = %d, retstr = %@", resp.errCode,resp.errStr];
                    NSLog(@"错误,retcode = %d, retstr = %@", resp.errCode,resp.errStr);
                    break;
            
        
    

4、需要注意的问题

  • 1.App Scheme一定要配置正确
  • 2.千万不能用生成预订单返回的Sign,要重新生成(和后台沟通)
  • 3.要考虑拉起App支付的时候自己程序被退出或者自杀了
  • 4.一定不能用异步返回给App的参数进行判断成功与否,需要和后台进行二次确认,异步返回给后台的数据才是最终的

5、常见问题及解决办法

c#开发微信门户及应用--微信消息的处理和应答(代码片段)

...解一下相关的开发历程。本篇随笔主要基于上一篇《C#开发微信门户及应用(1)--开始使用微信接口》的基础上进行深入的介绍,介绍微信消息的处理和应答的过程。 查看详情

c#开发微信支付之企业向用户付款

1、企业付款的介绍所谓企业付款指的是,在功能开放后诸如保险行业的客户理赔、退保、商品退款、发放征集活动奖金、抽奖互动等操作都可以通过企业付款完成。而此前,微信支付只能提供客户向企业单向付款。商户如果需... 查看详情

uni-app.11.开发微信小程序实现消息订阅(代码片段)

开发微信小程序实现消息订阅使用场景订阅消息一次性订阅消息长期订阅消息实现步骤1.获取模板ID2.uni.requestSubscribeMessage3.subscribeMessage.send4.测试使用场景在我们开发的小程序中司机首次登录需要先认证从业资质和车辆。司机在... 查看详情

使用easywechat快速开发微信支付

前期准备:申请微信支付后,会收到2个参数,商户id,和商户key.注意,这2个参数,不要和微信的参数混淆.微信参数:appid,appkey,token支付参数:merchant_id(商户号),key(支付密钥)支付密钥怎么得到?到https://pay.weixin.qq.com-->账户中心-->API安... 查看详情

如何使用easywechat开发微信支付功能

这类专业的技术问题,建议您可以下载一下开发者文档该文档在您申请了微信商家之后就可以下载的然后根据文档里面的技术规范进行调整和开发参考技术A信支付功能 查看详情

开发微信小程序在html5中怎么实现的

小程序代码里可以嵌入h5制作页面的,也方便与公众号的页面相通。我是上次用了个叮铛应用的小程序制作平台,就是链接个页面而已,还是零代码,现在体验版测试没问题了,在审核中。参考技术A不解藏踪迹, 查看详情

ios开发applepay的介绍与实现(代码片段)

...ApplePay官方1.1ApplePay概念ApplePay,简单来说,就是一种移动支付方式。通过TouchID/Passcode,用户可使用存储在iPhone6,6p等之后的新设备上的信用卡和借记卡支付证书来授权支付;它是苹果公司在2014苹果秋季新品发布会上发布的一种基... 查看详情

uni-app开发微信小程序使用微信小程序的插件(代码片段)

假如使用uni-app开发微信小程序需要用到官方插件----OCR插件,插件地址如下:OCR插件申请方式见插件地址介绍。本文主要记录调用方式1.在manifest.json的“mp-weixin”里添加"plugins":"ocr-plugin":"version":"3.0.1",... 查看详情

delphixe7用indy开发微信公众平台所有功能,可刷阅读,可刷赞,可加推广(除微支付)

http://www.cnblogs.com/devinlee/p/4565933.htmlDelphiXE7用indy开发微信公众平台所有功能,可刷阅读,可刷赞,可加推广(除微支付)关注作者的微信公众平台,测试效果包含微信公众平台的所有功能(除微支付)示例代码:(如需要全部代码,... 查看详情

开发微信“自动抢红包”软件,被罚400多万(代码片段)

????????关注后回复 “进群” ,拉你进程序员交流群????????中国基金报记者王建蔷微信群里发的红包总有人会抢到,他可能使用了自动抢红包外挂软件。然而很多人不知道的是,此类软件暗含知识产权侵权风险。近期... 查看详情

uniapp开发微信小程序,从构建到上线(代码片段)

...过程中的一个详细流程,比较适合第一次使用uniapp开发微信小程序的伙伴,或者没有过实战经验的小伙伴参考;使用Hbuildx配合Uniapp框架结合Uview的UI框架为大家演示今天的Demo!  目录一、uniapp项目起步1.工具下载2... 查看详情

uni-app开发微信小程使用腾讯位置服务获取用户的位置信息(代码片段)

uni-app开发微信小程使用腾讯位置服务获取用户的位置信息一、开通腾讯位置服务二、编码实现(一)获取定位坐标(二)、在项目中使用一、开通腾讯位置服务在这里我们先要登录腾讯我i之服务的官网开通位置服务腾讯位置服... 查看详情

uni-app开发微信小程使用腾讯位置服务获取用户的位置信息(代码片段)

uni-app开发微信小程使用腾讯位置服务获取用户的位置信息一、开通腾讯位置服务二、编码实现(一)获取定位坐标(二)、在项目中使用一、开通腾讯位置服务在这里我们先要登录腾讯我i之服务的官网开通位置服务腾讯位置服... 查看详情

unity开发微信小游戏3-获取微信权限(代码片段)

...X.Authorize();4.WX.Authorize();5.WX.GetUserInfo();总结前言用unity3d开发微信小游戏,遇到了一些问题,记录一下,同时创建了一个交流群QQ641029627,有需要的可以加入一起讨论,广告哥远离提示:以下是本篇文章正文... 查看详情

如何使用easywechat开发微信支付功能

直接接入微信支付,这是微信最为官方的,也是较为权威的支付模式,微信平台运营者可以通过微信官方开通微信支付,开通微信支付,首先你的账号需要是一个服务号,其次,你要申请并通过微信公众平台的认证,通过认证之... 查看详情

(十四)springboot开发微信授权支付

前提:配置好域名,在公众号配置一.引用jar包,在pom.xml文件加入依赖<dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-mp</artifactId><version>2.7.0</version></ 查看详情

java开发微信扫码支付,怎么做测试,公众账号id,商户号这些怎么来?

...中加入微网页,四、通过第三方APP收款,参考技术Ajava开发微信扫码支付测试,公众账号ID,商户号 查看详情

android_app开发微信支付集成

最近项目里面需要支付功能,boss一致决定用微信支付,所以在网上查了很多资料,说的不全,完了就找以前的同事指教。算是成功集成上去了。在这里做个总结记录。1、在APP上集成微信支付,首先当然是当官... 查看详情