实用技术——支付_微信

  • 与微信官方签署在线协议

实用技术——支付_微信_第1张图片
  • 导入微信支付需要的SDK相关文件

  • 配置App跳转的白名单

  • 添加URL Schemes

实用技术——支付_微信_第2张图片
  • 配置代码

    1. 在AppDelegate.m中向微信注册第三方应用
      //向微信终端程序注册第三方应用
      [WXApi registerApp:wexinAppId];
    2. 确保支付结果回调方法能够接受到,在AppDelegate.m中添加一下代码
      - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
      if([url.host isEqualToString:@"pay"]){
      return [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
      }else{
      return YES;
      }
      }
      - (BOOL)application:(UIApplication *)application handleOpenURL:(nonnull NSURL *)url
      {
      if([url.host isEqualToString:@"pay"]){
      return [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
      }else{
      return YES;
      }
      }
      - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options{
      if([url.host isEqualToString:@"pay"]){
      return [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
      }else{
      return YES;
      }
      }
    • 设置支付信息,调用微信支付
      NSMutableDictionary dict = [result[@"data"] objectAtIndex:0];
      //调起微信支付
      PayReq
      req = [[PayReq alloc] init];
      //由用户微信号和AppID组成的唯一标识
      req.openID = [dict objectForKey:@"appid"];
      //商家向财付通申请的商家id
      req.partnerId = [dict objectForKey:@"mch_id"];
      //预支付订单
      req.prepayId = [dict objectForKey:@"prepay_id"];
      //随机串,防重发
      req.nonceStr = [dict objectForKey:@"nonce_str"];
      //时间戳,防重发
      req.timeStamp = [[dict objectForKey:@"timeStamp"] intValue];
      //商家根据财付通文档填写的数据和签名
      req.package = @"Sign=WXPay";
      //商家根据微信开放平台文档对数据做的签名
      req.sign = [self getWeiXinPaySign:req];
      [WXApi sendReq:req];

    • 处理支付结果
      为了对支付结果可以进行不同的操作处理,可以创建一个单例对象来管理。
      #import
      #import "WXApi.h"
      @protocol WXApiManagerDelegate
      @optional
      - (void)managerDidRecvPayForSuccessResponse:(PayResp *)response;

      - (void)managerDidRecvPayForFailResponse:(PayResp *)response;
      @end
      
      @interface WXApiManager : NSObject
      @property (nonatomic, assign) id delegate;
      + (instancetype)sharedManager;
      @end
      
      #import "WXApiManager.h"
      @implementation WXApiManager
      
      #pragma mark - LifeCycle
      +(instancetype)sharedManager {
        static dispatch_once_t onceToken;
        static WXApiManager *instance;
        dispatch_once(&onceToken, ^{
        instance = [[WXApiManager alloc] init];
        });
      return instance;
      }
      
      - (void)dealloc {
        self.delegate = nil;
        [super dealloc];
      }
      
      #pragma mark - WXApiDelegate
      - (void)onResp:(BaseResp *)resp {
          if([resp isKindOfClass:[PayResp class]]){
              switch (resp.errCode) {
                  case WXSuccess:
                  {
                      if (_delegate && [_delegate respondsToSelector:@selector(managerDidRecvPayForSuccessResponse:)]) {
                      PayResp *payResp = (PayResp *)resp;
                      [_delegate managerDidRecvPayForSuccessResponse:payResp];
              }
          }
              break;
              
          default:
              if (_delegate && [_delegate respondsToSelector:@selector(managerDidRecvPayForFailResponse:)]) {
                  PayResp *payResp = (PayResp *)resp;
                  [_delegate managerDidRecvPayForFailResponse:payResp];
              }
              break;
          }
        }
      }
      @end
      
    • 签名sign生成方法
      //获取微信签名
      -(NSString)getWeiXinPaySign:(PayReq)req
      {
      NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
      [signParams setObject: req.openID forKey:@"appid"];
      [signParams setObject: req.nonceStr forKey:@"noncestr"];
      [signParams setObject: req.package forKey:@"package"];
      [signParams setObject: req.partnerId forKey:@"partnerid"];
      [signParams setObject: [NSString stringWithFormat:@"%u",(unsigned int)req.timeStamp] forKey:@"timestamp"];
      [signParams setObject: req.prepayId forKey:@"prepayid"];
      //生成签名
      NSString *sign = [self createMd5Sign:signParams];
      return sign;
      }

      //创建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=%@", @"xxxxxxxxxxx"];
          //得到MD5 sign签名
          NSString *md5Sign =[WXUtil md5:contentString];
          return md5Sign;
        }
      //md5 encode
      +(NSString *) md5:(NSString *)str
      {
          const char *cStr = [str UTF8String];
          unsigned char digest[CC_MD5_DIGEST_LENGTH];
          CC_MD5( cStr, (unsigned int)strlen(cStr), digest );
      
          NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
          //这里的x是小写则产生的md5也是小写,是大写则产生的md5是大写
          for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
              [output appendFormat:@"%02X", digest[i]];
      
          return output;
      }
      
  • 注意事项:

    1. 签名Sign一定得进行MD5加密,格式严格按照微信官方方式加密。
      prepayId(预支付订单)失效、过期。
      如果出现上述问题(一般是参数错误),就会造成调起微信支付,只出现一个确定按钮
    • 支付结果无法获取回调?
      确保第四步的b步骤是否实现
    • 如果APP里面使用了友盟或者ShareSDK做分享,那就不用再导入SDK了,否则会出现一些诡异的问题,
      例如无法调起手机微信客户端、无法调起微信客户端web页面,调起了但是一闪而过。这都基本上都是因为分享的SDK里面已经包括了微信的SDK。所以如果出现诡异的错误了看看是不是两个冲突了。
    • 如果你用了友盟社会化分享来做微信登录的话,那么你要先用友盟注册微信,后调用微信SDK注册
      [UMSocialWechatHandlersetWXAppId:SHappSecret:SH url:SHAREURL];
      [WXApiregisterApp:SHARE_WX withDescription:@"demo"];
    • 微信无法调起
      未安装微信、未将微信加入白名单

你可能感兴趣的:(实用技术——支付_微信)