iOS集成微信支付

2015-12-31  本文已影响342人  超C

微信支付流程

官方说明

Paste_Image.png
https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=8_5

环境设置

  1. 拖入我附件中的SDK(可以将我附件中的SDK替换为官方的, 只为你放心)

  2. 设置URL Schemes : 微信应用注册后的 : AppID


    Snip20151231_10.png
Snip20151231_11.png

3 . 需要导入的框架
libc++.tbd libz.tbd libsqlite3.0.tbd SystemConfiguration.framework CoreTelephony.framework

4 . 为了以防万一 : 备用

// 设置URLSchemes白名单
<key>LSApplicationQueriesSchemes</key>
<array>
<string>weixin</string>
</array>

//设置退回Http
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>

AppDelegate中

#import "WXApi.h"

@interface AppDelegate ()<WXApiDelegate>

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

//微信支付返回程序
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
    return [WXApi handleOpenURL:url delegate:self];
}

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

// 并且将下面方法添加到上面设置的delegate中, 支付完成微信会回调代理的这个方法
- (void)onResp:(BaseResp*)resp{
    if ([resp isKindOfClass:[PayResp class]]){
        PayResp *response = (PayResp*)resp;
        switch(response.errCode){
            case WXSuccess:
                //服务器端查询支付通知或查询API返回的结果再提示成功
                NSLog(@"支付成功");
                break;
            default:
                NSLog(@"支付失败,retcode=%d",resp.errCode);
                break;
        }
    }
}

// 使用CCPay, 修改自己需要的即可

CCPay中封装的代码 主要流程

一. 预支付 : 发送商品信息到预支付地址获取prepay_id
  1. 收集预付单参数
参数 noncestr 与 orderno 都是随机生成的
    [orderParas setObject: CCAppID           forKey:@"appid"];       //开放平台appid
    [orderParas setObject: CCMchID           forKey:@"mch_id"];      //商户号
    [orderParas setObject: @"iPhone10X"        forKey:@"device_info"]; //支付设备号或门店号
    [orderParas setObject: noncestr          forKey:@"nonce_str"];   //随机串
    [orderParas setObject: @"APP"            forKey:@"trade_type"];  //支付类型,固定为APP
    [orderParas setObject: @"大宝SOD咪咪"        forKey:@"body"];        //订单描述,展示给用户
    [orderParas setObject: @"You_Custom"    forKey:@"notify_url"];  //支付结果异步通知
    [orderParas setObject: orderno           forKey:@"out_trade_no"];//商户订单号
    [orderParas setObject: [CCDevice deviceIPAdress]    forKey:@"spbill_create_ip"];//发起支付的机器ip
    [orderParas setObject: @"1"       forKey:@"total_fee"];       //订单金额,单位为分
  1. 通过上面的参数按照官方的要求生成XML格式的参数
    NSMutableString *reqPars = [NSMutableString string];

    //生成xml的package
    NSArray *keys = [paras allKeys];
    [reqPars appendString:@"<xml>\n"];
    for (NSString *categoryId in keys) {
        [reqPars appendFormat:@"<%@>%@</%@>\n", categoryId, [paras objectForKey:categoryId],categoryId];
    }
    
    //生成签名,并将签名添加到签名包中
    sign = [self createMd5Sign:paras];
    [reqPars appendFormat:@"<sign>%@</sign>\n</xml>", sign];

    return [NSString stringWithString:reqPars];
  1. 将该参数转换为Data数据,通过POST发出请求
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:5];
    //设置提交方式
    [request setHTTPMethod:method];
    //设置数据类型
    [request addValue:@"text/xml" forHTTPHeaderField:@"Content-Type"];
    //设置编码
    [request setValue:@"UTF-8" forHTTPHeaderField:@"charset"];
    //如果是POST
    [request setHTTPBody:[data dataUsingEncoding:NSUTF8StringEncoding]];
    
    NSError *error;
    //将请求的url数据放到NSData对象中
    NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
    return response;
  1. 解析响应的NSData数据, 获得prepayid
    dictionary =[NSMutableDictionary dictionary];
    contentString=[NSMutableString string];
    
    // XML解析实例
    xmlElements = [[NSMutableArray alloc] init];
    
    xmlParser = [[NSXMLParser alloc] initWithData:data];
    
    [xmlParser setDelegate:self];
    [xmlParser parse];

代理中得到数据, 获取 prepayid

二. 真正的支付 : 发送PayReq(官方类)请求
  1. 生成确认支付的参数
    //获取到prepayid后进行第二次签名
    
    //设置支付参数
    time_t now;
    time(&now);
    NSString *time_stamp  = [NSString stringWithFormat:@"%ld", now];
    NSString *nonce_str = [CCUtil stringMd5WithString:time_stamp];
    NSString *package     = @"Sign=WXPay";    // 官方要求
    
    // 第二次签名参数列表
    NSMutableDictionary *signParas = [NSMutableDictionary dictionary];
    [signParas setObject: CCAppID        forKey:@"appid"];
    [signParas setObject: nonce_str    forKey:@"noncestr"];
    [signParas setObject: package      forKey:@"package"];
    [signParas setObject: CCMchID        forKey:@"partnerid"];
    [signParas setObject: time_stamp   forKey:@"timestamp"];
    [signParas setObject: prepayID     forKey:@"prepayid"];
    //[signParams setObject: @"MD5"       forKey:@"signType"];
    
    // 生成签名
    NSString *sign  = [self createMd5Sign:signParas];
    
    // 添加签名
    [signParas setObject: sign         forKey:@"sign"];
    
    return signParas;
  1. 调用微信进行支付
    PayReq* req             = [[PayReq alloc] init];
    req.openID              = [paras objectForKey:@"appid"];
    req.partnerId           = [paras objectForKey:@"partnerid"];
    req.prepayId            = [paras objectForKey:@"prepayid"];
    req.nonceStr            = [paras objectForKey:@"noncestr"];
    req.timeStamp           = [[paras objectForKey:@"timestamp"] intValue];
    req.package             = [paras objectForKey:@"package"];
    req.sign                = [paras objectForKey:@"sign"];
    
    // 发起微信支付
    [WXApi sendReq:req];

代码

http://pan.baidu.com/s/1qXt463y

封装为传入参数 : 订单名与价格即可开始支付, 有自己的需求, 到.m中自行修改
/**
 *  通过微信支付
 *
 *  @param orderName 订单名
 *  @param price     价格
 */
+ (void)payWXWithOrderName:(NSString *)orderName price:(NSString *)price;

最后

上面流程为自己从头开始完成支付, 并不是说必须按照上面步骤. 这里不同公司可能如何处理方式会有差异.
例如: 第一步预支付验证可以后台实现, 前台只需要请求公司内部服务器, 内部服务器发送对应的预支付请求, 并且将返回的数据简析完成后返回给前台, 前台直接执行支付操作.

上一篇下一篇

猜你喜欢

热点阅读