iOS之“微信支付”开发流程

  • 实现微信支付的开发,iOS端里面只需要四个步骤:
    • 向服务端请求预支付,获得prepayid以及noncestr;
    • 把参数拼起来签名;
    • 发起支付请求;
    • 处理支付结果。
  • iOS的微信SDK的接入:即为“向微信注册你的应用程序id”、“下载微信终端SDK文件”、“搭建开发环境”、“在代码中使用开发工具包”。详情请参看:iOS微信接入指南
  • 导入微信支付库:开发者需要在工程中链接上:SystemConfiguration.framework,libz.dylib,libsqlite3.0.dylib,最重要的库是libc++.dylib;
  • iOS微信支付的具体流程:
    • 向服务端请求预支付,获得prepayid以及noncestr
//提交预支付
- (NSString *)sendPrepay:(NSMutableDictionary *)prePayParams {
    NSString *prepayid = nil;
    //获取提交支付
    NSString *send = [self genPackage:prePayParams];
    //输出Debug Info
    [debugInfo appendFormat:@"API链接:%@\n", payUrl];
    [debugInfo appendFormat:@"发送的xml:%@\n", send];
    //发送请求post xml数据
    NSData *res = [WXUtil httpSend:payUrl method:@"POST" data:send];
    //输出Debug Info
    [debugInfo appendFormat:@"服务器返回:\n%@\n\n",[[NSString alloc] initWithData:res encoding:NSUTF8StringEncoding]];
    
    XMLHelper *xml  = [XMLHelper alloc];
    
    //开始解析
    [xml startParse:res];
    NSMutableDictionary *resParams = [xml getDict];
    
    //判断返回
    NSString *return_code   = [resParams objectForKey:@"return_code"];
    NSString *result_code   = [resParams objectForKey:@"result_code"];
    if ([return_code isEqualToString:@"SUCCESS"]) {
        //生成返回数据的签名
        NSString *sign      = [self createMd5Sign:resParams ];
        NSString *send_sign =[resParams objectForKey:@"sign"] ;
        
        //验证签名正确性
        if( [sign isEqualToString:send_sign]) {
            if( [result_code isEqualToString:@"SUCCESS"]) {
                //验证业务处理状态
                prepayid    = [resParams objectForKey:@"prepay_id"];
                return_code = 0;
                [debugInfo appendFormat:@"获取预支付交易标示成功!\n"];
            }
        }else{
            last_errcode = 1;
            [debugInfo appendFormat:@"gen_sign=%@\n   _sign=%@\n",sign,send_sign];
            [debugInfo appendFormat:@"服务器返回签名验证错误!!!\n"];
        }
    }else{
        last_errcode = 2;
        [debugInfo appendFormat:@"接口返回错误!!!\n"];
    }
    return prepayid;
}

- (NSMutableDictionary *)sendPay_WithPrice:(NSString *)order_price orderNo:(NSString *)orderNo {
    
    //订单标题,展示给用户
    NSString *order_name = @"展示给用户的订单标题";
    //预付单参数订单设置
    srand( (unsigned)time(0) );
    NSString *noncestr  = [NSString stringWithFormat:@"%d", rand()];
    NSString *orderno   = orderNo;
    NSMutableDictionary *packageParams = [NSMutableDictionary dictionary];
    
    [packageParams setObject: appid          forKey:@"appid"];           //开放平台appid
    [packageParams setObject: mchid          forKey:@"mch_id"];          //商户号
    [packageParams setObject: @"APP-001"     forKey:@"device_info"];     //支付设备号或门店号
    [packageParams setObject: noncestr       forKey:@"nonce_str"];       //随机串
    [packageParams setObject: @"APP"         forKey:@"trade_type"];      //支付类型,固定为APP
    [packageParams setObject: order_name     forKey:@"body"];            //订单描述,展示给用户
    [packageParams setObject: NOTIFY_URL     forKey:@"notify_url"];      //支付结果异步通知
    [packageParams setObject: orderno        forKey:@"out_trade_no"];    //商户订单号
    [packageParams setObject: @"196.168.1.1" forKey:@"spbill_create_ip"];//发器支付的机器ip
    [packageParams setObject: order_price    forKey:@"total_fee"];       //订单金额,单位为分
    
    //获取prepayId(预支付交易会话标识)
    NSString *prePayid;
    prePayid = [self sendPrepay:packageParams];
    
    if ( prePayid != nil) {
        //获取到prepayid后进行第二次签名
        NSString *package, *time_stamp, *nonce_str;
        
        //设置支付参数
        time_t now;
        time(&now);
        time_stamp  = [NSString stringWithFormat:@"%ld", now];
        nonce_str	= [WXUtil md5:time_stamp];
        //重新按提交格式组包,微信客户端暂只支持package=Sign=WXPay格式,须考虑升级后支持携带package具体参数的情况
        package = @"Sign=WXPay";
        
        //第二次签名参数列表
        NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
        [signParams setObject: appid        forKey:@"appid"];
        [signParams setObject: nonce_str    forKey:@"noncestr"];
        [signParams setObject: package      forKey:@"package"];
        [signParams setObject: mchid        forKey:@"partnerid"];
        [signParams setObject: time_stamp   forKey:@"timestamp"];
        [signParams setObject: prePayid     forKey:@"prepayid"];
        
        //生成签名
        NSString *sign = [self createMd5Sign:signParams];
        
        //添加签名
        [signParams setObject: sign forKey:@"sign"];
        [debugInfo appendFormat:@"第二步签名成功,sign=%@\n",sign];
        
        //返回参数列表
        return signParams;
        
    }else{
        [debugInfo appendFormat:@"获取prepayid失败!\n"];
    }
    return nil;
}

    • 把参数拼起来签名
//创建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=%@", spkey];
    //得到MD5 sign签名
    NSString *md5Sign =[WXUtil md5:contentString];
    //输出Debug Info
    [debugInfo appendFormat:@"MD5签名字符串:\n%@\n\n",contentString];
    
    return md5Sign;
}

//获取package带参数的签名包
- (NSString *)genPackage:(NSMutableDictionary*)packageParams {
    NSString *sign;
    NSMutableString *reqPars=[NSMutableString string];
    //生成签名
    sign = [self createMd5Sign:packageParams];
    //生成xml的package
    NSArray *keys = [packageParams allKeys];
    [reqPars appendString:@"<xml>\n"];
    for (NSString *categoryId in keys) {
        [reqPars appendFormat:@"<%@>%@</%@>\n", categoryId, [packageParams objectForKey:categoryId],categoryId];
    }
    [reqPars appendFormat:@"<sign>%@</sign>\n</xml>", sign];
    return [NSString stringWithString:reqPars];
}

    • 发起支付请求
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    //支付结果通知注册
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getOrderPayResult:) name:@"ORDER_PAY_NOTIFICATION" object:nil];
}

//调用微信支付
- (void)viewDidLoad {
    [super viewDidLoad];
    [self WXPay];
}

#pragma mark -- 发起”微信支付“请求
- (void)WXPay {
    if (![WXApi isWXAppInstalled]) {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"您还没有安装微信" message:nil preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            //跳转到微信的下载安装地址
        }];
        [alert addAction:sureAction];
        [self.navigationController presentViewController:alert animated:YES completion:nil];
        return ;
    }
    YDWWeChatPayResquest *req = [YDWWeChatPayResquest new];
    //初始化支付签名对象
    [req init:APP_ID mch_id:MCH_ID];
    //设置密钥
    [req setKey:PARTNER_ID];
    
    //获取到实际调起微信支付的参数后,在app端调起支付
    NSInteger payTheAmount;//支付金额
    NSString *orderMeony = [NSString stringWithFormat:@"%ld",payTheAmount];

    NSDictionary *orderDic;//支付订单
    NSString *orderNo = [orderDic objectForKey:@"orderNumber"];
    NSMutableDictionary *dict = [req sendPay_WithPrice:orderMeony orderNo: orderNo];
    
    if(dict == nil){
        //错误提示
        NSString *debug = [req getDebugifo];
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:debug message:nil preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
        [alert addAction:sureAction];
        [self.navigationController presentViewController:alert animated:YES completion:nil];
    }else{
        
        NSMutableString *stamp  = [dict objectForKey:@"timestamp"];
        
        //调起微信支付
        PayReq* req             = [[PayReq alloc] init];
        req.openID              = [dict objectForKey:@"appid"];
        req.partnerId           = [dict objectForKey:@"partnerid"];
        req.prepayId            = [dict objectForKey:@"prepayid"];
        req.nonceStr            = [dict objectForKey:@"noncestr"];
        req.timeStamp           = stamp.intValue;
        req.package             = [dict objectForKey:@"package"];
        req.sign                = [dict objectForKey:@"sign"];
        
        [WXApi sendReq:req];
    }
}


- (void)weixinPay {
    YDWWeixinPayParams *signParams = [[YDWWeixinPayParams alloc] initWithPrepayid:self.prepay_id noncestr:self.nonce_str];
    //调起微信支付
    PayReq *req = [[PayReq alloc] init];
    req.openID = signParams.appid;
    req.partnerId = signParams.partnerid;
    req.prepayId = signParams.prepayid;
    req.nonceStr = signParams.noncestr;
    req.timeStamp = signParams.timestamp.intValue;
    req.package = signParams.package;
    req.sign = [signParams sign];
    
    [WXApi sendReq:req];
}

#pragma mark - 支付结果通知信息
- (void)getOrderPayResult:(NSNotification *)notification{
    if ([notification.object isEqualToString:@"success"]) {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"恭喜" message:@"您已成功支付啦!" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
        [alert addAction:sureAction];
        [self.navigationController presentViewController:alert animated:YES completion:nil];
    }
    else
    {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"支付失败,可在待付款订单中查看" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
        [alert addAction:sureAction];
        [self.navigationController presentViewController:alert animated:YES completion:nil];
    }
}

//移除通知
- (void)viewWillDisappear:(BOOL)animated{
    [[NSNotificationCenter defaultCenter]removeObserver:self];
}
    • 处理支付结果,在AppDelegate中做的工作:
      • 1、导入#import “WXApi.h”和#import “WXApiObject.h”,并遵守WXApiDelegate协议,要使你的程序启动后微信终端能响应你的程序,必须在代码中向微信终端注册你的id:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    [WXApi registerApp:@"WXAppId" withDescription:@"YDWWXPayDes"];
    
    return YES;
}
      • 2、重写AppDelegate的handleOpenURL和openURL方法:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
     if ([url.absoluteString hasPrefix:Weixin_Appid]) {
        return [WXApi handleOpenURL:url delegate:self];
    } 
    return YES;
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
    
    return [WXApi handleOpenURL:url delegate:self];
}
      • 3、处理结果:
- (void)onResp:(BaseResp *)resp {
    NSString *strMsg = [NSString stringWithFormat:@"errcode:%d", resp.errCode];
    NSString *strTitle;
    
    if([resp isKindOfClass:[SendMessageToWXResp class]]) {
        strTitle = [NSString stringWithFormat:@"发送媒体消息结果"];
    }
    
    if([resp isKindOfClass:[PayResp class]])
    {
        //支付返回结果,实际支付结果需要去微信服务器端查询
        strTitle = [NSString stringWithFormat:@"支付结果"];
        
        switch (resp.errCode) {
            case WXSuccess:{
                strMsg = @"支付结果:成功!";
                NSLog(@"支付成功-PaySuccess,retcode = %d", resp.errCode);
                NSNotification *notification = [NSNotification notificationWithName:@"ORDER_PAY_NOTIFICATION" object:@"success"];
                [[NSNotificationCenter defaultCenter] postNotification:notification];
                break;
            }
            default:{
                strMsg = [NSString stringWithFormat:@"支付结果:失败!retcode = %d, retstr = %@", resp.errCode,resp.errStr];
                NSLog(@"错误,retcode = %d, retstr = %@", resp.errCode,resp.errStr);
                NSNotification *notification = [NSNotification notificationWithName:@"ORDER_PAY_NOTIFICATION" object:@"fail"];
                [[NSNotificationCenter defaultCenter] postNotification:notification];
                break;
            }
        }
    }
    
//        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:strTitle message:strMsg delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
//        [alert show];

}
  • 常见的问题:
    • 如果跳转到微信里之只弹出了一个确定按钮,那么这时候需要检查几个方面:
      • 1、appid,mch_id,partner_id是否设置正确。mch_id对应的key其实是partnerid,partner_id对应的key其实是key;
      • 2、timestamp 应为10位;
      • 3、签名需要排序,并用md5加密。
  • 最后附上重要的类的全部代码:
    • AppDelegate:
//  AppDelegate.h
//  微信支付
//
//  Created by YDW on 16/3/28.
//  Copyright © 2016年 IZHUO.NET. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "WXApi.h"
#import "WXApiObject.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate,WXApiDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

//  AppDelegate.m
//  微信支付
//
//  Created by YDW on 16/3/28.
//  Copyright © 2016年 IZHUO.NET. All rights reserved.
//

#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    [WXApi registerApp:@"WXAppId" withDescription:@"YDWWXPayDes"];
    
    return YES;
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
    
    return [WXApi handleOpenURL:url delegate:self];
}

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
    
    return  [WXApi handleOpenURL:url delegate:self];
}


- (void)onResp:(BaseResp *)resp {
    NSString *strMsg = [NSString stringWithFormat:@"errcode:%d", resp.errCode];
    NSString *strTitle;
    
    if([resp isKindOfClass:[SendMessageToWXResp class]]) {
        strTitle = [NSString stringWithFormat:@"发送媒体消息结果"];
    }
    
    if([resp isKindOfClass:[PayResp class]])
    {
        //支付返回结果,实际支付结果需要去微信服务器端查询
        strTitle = [NSString stringWithFormat:@"支付结果"];
        
        switch (resp.errCode) {
            case WXSuccess:{
                strMsg = @"支付结果:成功!";
                NSLog(@"支付成功-PaySuccess,retcode = %d", resp.errCode);
                NSNotification *notification = [NSNotification notificationWithName:@"ORDER_PAY_NOTIFICATION" object:@"success"];
                [[NSNotificationCenter defaultCenter] postNotification:notification];
                break;
            }
            default:{
                strMsg = [NSString stringWithFormat:@"支付结果:失败!retcode = %d, retstr = %@", resp.errCode,resp.errStr];
                NSLog(@"错误,retcode = %d, retstr = %@", resp.errCode,resp.errStr);
                NSNotification *notification = [NSNotification notificationWithName:@"ORDER_PAY_NOTIFICATION" object:@"fail"];
                [[NSNotificationCenter defaultCenter] postNotification:notification];
                break;
            }
        }
    }
    
//        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:strTitle message:strMsg delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
//        [alert show];

}

YDWWeChatPayResquest:

//  YDWWeChatPayResquest.h
//  微信支付
//
//  Created by YDW on 16/3/28.
//  Copyright © 2016年 IZHUO.NET. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "WXUtil.h"
#import "ApiXml.h"

/*
 * 账号的账户资料:更改商户后的相关参数后可以使用
 */

#define APP_ID        @"你的APP的ID"       //APPID
#define APP_SECRET    @"你的APP的secret"   //appsecret
#define MCH_ID        @"商户号"            //商户号,填写商户对应参数
#define PARTNER_ID    @"商户API密钥"       //商户API密钥,填写相应参数
#define NOTIFY_URL    @"回调页面地址"       //支付结果回调页面
#define SP_URL        @"服务器端支付数据地址"//获取服务器端支付数据地址(商户自定义)

@interface YDWWeChatPayResquest : NSObject {
    //预支付的url地址
    NSString *payUrl;
    
    //lash_errcode;
    long     last_errcode;
    
    //debug信息
    NSMutableString *debugInfo;
    NSString        *appid,*mchid,*spkey;

}

- (BOOL)init:(NSString *)app_id mch_id:(NSString *)mch_id;
- (NSString *)getDebugifo;
- (long)getLasterrCode;
//设置商户密钥
- (void)setKey:(NSString *)key;
//创建package签名
- (NSString*)createMd5Sign:(NSMutableDictionary*)dict;
//获取package带参数的签名包
- (NSString *)genPackage:(NSMutableDictionary*)packageParams;
//提交预支付
- (NSString *)sendPrepay:(NSMutableDictionary *)prePayParams;

- (NSMutableDictionary *)sendPay_WithPrice:(NSString *)order_price orderNo:(NSString *)orderNo;
//签名实例测试
//- (NSMutableDictionary *)sendPay_demo;
@end


//  YDWWeChatPayResquest.m
//  微信支付
//
//  Created by YDW on 16/3/28.
//  Copyright © 2016年 IZHUO.NET. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "YDWWeChatPayResquest.h"

@implementation YDWWeChatPayResquest

- (BOOL)init:(NSString *)app_id mch_id:(NSString *)mch_id {
    payUrl     = @"https://api.mch.weixin.qq.com/pay/unifiedorder";
    if (debugInfo == nil){
        debugInfo = [NSMutableString string];
    }
    [debugInfo setString:@""];
    appid = app_id;
    mchid = mch_id;
    return YES;
}

//设置商户密钥
- (void)setKey:(NSString *)key {
    spkey = [NSString stringWithString:key];
}

//获取debug信息
- (NSString*)getDebugifo {
    NSString *res = [NSString stringWithString:debugInfo];
    [debugInfo setString:@""];
    return res;
}

//获取最后服务返回错误代码
- (long)getLasterrCode {
    return last_errcode;
}

//创建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=%@", spkey];
    //得到MD5 sign签名
    NSString *md5Sign =[WXUtil md5:contentString];
    //输出Debug Info
    [debugInfo appendFormat:@"MD5签名字符串:\n%@\n\n",contentString];
    
    return md5Sign;
}

//获取package带参数的签名包
- (NSString *)genPackage:(NSMutableDictionary*)packageParams {
    NSString *sign;
    NSMutableString *reqPars=[NSMutableString string];
    //生成签名
    sign = [self createMd5Sign:packageParams];
    //生成xml的package
    NSArray *keys = [packageParams allKeys];
    [reqPars appendString:@"<xml>\n"];
    for (NSString *categoryId in keys) {
        [reqPars appendFormat:@"<%@>%@</%@>\n", categoryId, [packageParams objectForKey:categoryId],categoryId];
    }
    [reqPars appendFormat:@"<sign>%@</sign>\n</xml>", sign];
    return [NSString stringWithString:reqPars];
}

//提交预支付
- (NSString *)sendPrepay:(NSMutableDictionary *)prePayParams {
    NSString *prepayid = nil;
    //获取提交支付
    NSString *send = [self genPackage:prePayParams];
    //输出Debug Info
    [debugInfo appendFormat:@"API链接:%@\n", payUrl];
    [debugInfo appendFormat:@"发送的xml:%@\n", send];
    //发送请求post xml数据
    NSData *res = [WXUtil httpSend:payUrl method:@"POST" data:send];
    //输出Debug Info
    [debugInfo appendFormat:@"服务器返回:\n%@\n\n",[[NSString alloc] initWithData:res encoding:NSUTF8StringEncoding]];
    
    XMLHelper *xml  = [XMLHelper alloc];
    
    //开始解析
    [xml startParse:res];
    NSMutableDictionary *resParams = [xml getDict];
    
    //判断返回
    NSString *return_code   = [resParams objectForKey:@"return_code"];
    NSString *result_code   = [resParams objectForKey:@"result_code"];
    if ([return_code isEqualToString:@"SUCCESS"]) {
        //生成返回数据的签名
        NSString *sign      = [self createMd5Sign:resParams ];
        NSString *send_sign =[resParams objectForKey:@"sign"] ;
        
        //验证签名正确性
        if( [sign isEqualToString:send_sign]) {
            if( [result_code isEqualToString:@"SUCCESS"]) {
                //验证业务处理状态
                prepayid    = [resParams objectForKey:@"prepay_id"];
                return_code = 0;
                [debugInfo appendFormat:@"获取预支付交易标示成功!\n"];
            }
        }else{
            last_errcode = 1;
            [debugInfo appendFormat:@"gen_sign=%@\n   _sign=%@\n",sign,send_sign];
            [debugInfo appendFormat:@"服务器返回签名验证错误!!!\n"];
        }
    }else{
        last_errcode = 2;
        [debugInfo appendFormat:@"接口返回错误!!!\n"];
    }
    return prepayid;
}

- (NSMutableDictionary *)sendPay_WithPrice:(NSString *)order_price orderNo:(NSString *)orderNo {
    
    //订单标题,展示给用户
    NSString *order_name = @"展示给用户的订单标题";
    //预付单参数订单设置
    srand( (unsigned)time(0) );
    NSString *noncestr  = [NSString stringWithFormat:@"%d", rand()];
    NSString *orderno   = orderNo;
    NSMutableDictionary *packageParams = [NSMutableDictionary dictionary];
    
    [packageParams setObject: appid          forKey:@"appid"];           //开放平台appid
    [packageParams setObject: mchid          forKey:@"mch_id"];          //商户号
    [packageParams setObject: @"APP-001"     forKey:@"device_info"];     //支付设备号或门店号
    [packageParams setObject: noncestr       forKey:@"nonce_str"];       //随机串
    [packageParams setObject: @"APP"         forKey:@"trade_type"];      //支付类型,固定为APP
    [packageParams setObject: order_name     forKey:@"body"];            //订单描述,展示给用户
    [packageParams setObject: NOTIFY_URL     forKey:@"notify_url"];      //支付结果异步通知
    [packageParams setObject: orderno        forKey:@"out_trade_no"];    //商户订单号
    [packageParams setObject: @"196.168.1.1" forKey:@"spbill_create_ip"];//发器支付的机器ip
    [packageParams setObject: order_price    forKey:@"total_fee"];       //订单金额,单位为分
    
    //获取prepayId(预支付交易会话标识)
    NSString *prePayid;
    prePayid            = [self sendPrepay:packageParams];
    
    if ( prePayid != nil) {
        //获取到prepayid后进行第二次签名
        NSString    *package, *time_stamp, *nonce_str;
        
        //设置支付参数
        time_t now;
        time(&now);
        time_stamp  = [NSString stringWithFormat:@"%ld", now];
        nonce_str	= [WXUtil md5:time_stamp];
        //重新按提交格式组包,微信客户端暂只支持package=Sign=WXPay格式,须考虑升级后支持携带package具体参数的情况
        package         = @"Sign=WXPay";
        
        //第二次签名参数列表
        NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
        [signParams setObject: appid        forKey:@"appid"];
        [signParams setObject: nonce_str    forKey:@"noncestr"];
        [signParams setObject: package      forKey:@"package"];
        [signParams setObject: mchid        forKey:@"partnerid"];
        [signParams setObject: time_stamp   forKey:@"timestamp"];
        [signParams setObject: prePayid     forKey:@"prepayid"];
        
        //生成签名
        NSString *sign = [self createMd5Sign:signParams];
        
        //添加签名
        [signParams setObject: sign forKey:@"sign"];
        [debugInfo appendFormat:@"第二步签名成功,sign=%@\n",sign];
        
        //返回参数列表
        return signParams;
        
    }else{
        [debugInfo appendFormat:@"获取prepayid失败!\n"];
    }
    return nil;
}

@end

    • 调用微信支付的页面:
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self WXPay];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    //支付结果通知注册
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getOrderPayResult:) name:@"ORDER_PAY_NOTIFICATION" object:nil];
}

#pragma mark -- 发起”微信支付“请求
- (void)WXPay {
    if (![WXApi isWXAppInstalled]) {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"您还没有安装微信" message:nil preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            //跳转到微信的下载安装地址
        }];
        [alert addAction:sureAction];
        [self.navigationController presentViewController:alert animated:YES completion:nil];
        return ;
    }
    YDWWeChatPayResquest *req = [YDWWeChatPayResquest new];
    //初始化支付签名对象
    [req init:APP_ID mch_id:MCH_ID];
    //设置密钥
    [req setKey:PARTNER_ID];
    
    //获取到实际调起微信支付的参数后,在app端调起支付
    NSInteger payTheAmount;//支付金额
    NSString *orderMeony = [NSString stringWithFormat:@"%ld",payTheAmount];

    NSDictionary *orderDic;//支付订单
    NSString *orderNo = [orderDic objectForKey:@"orderNumber"];
    NSMutableDictionary *dict = [req sendPay_WithPrice:orderMeony orderNo: orderNo];
    
    if(dict == nil){
        //错误提示
        NSString *debug = [req getDebugifo];
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:debug message:nil preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
        [alert addAction:sureAction];
        [self.navigationController presentViewController:alert animated:YES completion:nil];
    }else{
        
        NSMutableString *stamp  = [dict objectForKey:@"timestamp"];
        
        //调起微信支付
        PayReq* req             = [[PayReq alloc] init];
        req.openID              = [dict objectForKey:@"appid"];
        req.partnerId           = [dict objectForKey:@"partnerid"];
        req.prepayId            = [dict objectForKey:@"prepayid"];
        req.nonceStr            = [dict objectForKey:@"noncestr"];
        req.timeStamp           = stamp.intValue;
        req.package             = [dict objectForKey:@"package"];
        req.sign                = [dict objectForKey:@"sign"];
        
        [WXApi sendReq:req];
    }
}

#pragma mark - 支付结果通知信息
- (void)getOrderPayResult:(NSNotification *)notification{
    if ([notification.object isEqualToString:@"success"]) {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"恭喜" message:@"您已成功支付啦!" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
        [alert addAction:sureAction];
        [self.navigationController presentViewController:alert animated:YES completion:nil];
    }
    else
    {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"支付失败,可在待付款订单中查看" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
        [alert addAction:sureAction];
        [self.navigationController presentViewController:alert animated:YES completion:nil];
    }
}

//移除通知
- (void)viewWillDisappear:(BOOL)animated{
    [[NSNotificationCenter defaultCenter]removeObserver:self];
}

@end

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

╰つ栺尖篴夢ゞ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值