支付宝微信支付全本地写法和与服务器沟通方法

首先集成支付宝,微信,申请各自该申请的东西。这里不重复

主要包含以下东西:
主要包含的内容有这些

XZLPayBusiness要导入的头文件包含以下内容
要导入的头文件

1.支付宝全本地支付

+ (void)doAPPay:(NSString *)money {

    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"2048"ofType:@"txt"]; //这个文件里面就是支付宝的私钥
    NSString *rsa2PrivateKey = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];

    APOrderInfo* order = [APOrderInfo new];//这个类是直接用的支付宝Demo里的APOrderInfo,没有改,下面也有附上它的代码
    order.app_id = @"2018XXXXXXXXXXXXX"; // 写的是支付宝申请的appID,
    order.method = @"alipay.trade.app.pay";
    order.charset = @"utf-8";
    NSDateFormatter* formatter = [NSDateFormatter new];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    order.timestamp = [formatter stringFromDate:[NSDate date]];
    order.version = @"1.0";
    order.sign_type = @"RSA2";//我用的是RSA2加密方式,所以写RSA2
    order.notify_url = @"https://www.alipay.com";//这个我没有,有也可以写自己的(支付宝的结果会告诉这个接口)
    order.biz_content = [APBizContent new]; //这个也是直接从支付宝Demo拿过来的
    order.biz_content.body = @"三季度净亏损";
    order.biz_content.subject = @"健康管家";//这个名字支付的时候会显示出来的
    order.biz_content.out_trade_no = [self generateTradeNO]; //订单ID(由商家自行制定)
    order.biz_content.timeout_express = @"30m"; //超时时间设置
    order.biz_content.total_amount = [NSString stringWithFormat:@"%.2f", 0.01]; //商品价格 1分钱,支付宝和微信的单位不一样,下面有微信的

    NSString *orderInfo = [order orderInfoEncoded:NO];
    NSString *orderInfoEncoded = [order orderInfoEncoded:YES];
    NSString *signedString = nil;
    APRSASigner* signer = [[APRSASigner alloc] initWithPrivateKey:rsa2PrivateKey];
    signedString = [signer signString:orderInfo withRSA2:YES];

    if (signedString != nil) {
        NSString *appScheme = @"xxxxxxx";//写在info.plist加上的appScheme(是别的app跳到我们这个app的appScheme)
        NSString *orderString = [NSString stringWithFormat:@"%@&sign=%@",
                                 orderInfoEncoded, signedString];
        [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
            NSLog(@"reslut = %@",resultDic);//这个地方网页支付的时候会返回结果,
        }];
    }
}

辅助方法:
生成随机订单方法:

+ (NSString *)generateTradeNO
{
    static int kNumber = 15;
    NSString *sourceStr = @"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    NSMutableString *resultStr = [[NSMutableString alloc] init];
    srand((unsigned)time(0));
    for (int i = 0; i < kNumber; i++)
    {
        unsigned index = rand() % [sourceStr length];
        NSString *oneStr = [sourceStr substringWithRange:NSMakeRange(index, 1)];
        [resultStr appendString:oneStr];
    }
    return resultStr;
}

此外还需要在appDelegate写上如下代码,以知道支付完成返回的结果
appDelegate中倒入头文件:

#import <AlipaySDK/AlipaySDK.h>
#import "WXApiManager.h"
#pragma mark - -->(0)application:openURL:
- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {

    if ([url.host isEqualToString:@"safepay"]) {
        // 支付跳转支付宝钱包进行支付,处理支付结果
        [self handleResultAlipayURL:url];
    }
    [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]]; // 这个是微信的,一并在这里写了

    return YES;
}

- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {

    if ([url.host isEqualToString:@"safepay"]) {
        [self handleResultAlipayURL:url];
    }

    [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
    return YES;
}

- (void)handleResultAlipayURL:(NSURL *)url {

     __block BOOL isSuccess = NO;
    // 支付跳转支付宝钱包进行支付,处理支付结果
    [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
        NSLog(@"result = %@",resultDic);
        NSString *strMeg = @"支付失败";
        if ([resultDic[@"resultStatus"] isEqualToString:@"9000"]) {
            strMeg = @"支付成功";
        }
    }];
}

2.微信全本地支付

+ (void)WXAppPay:(NSString *)body money:(NSString *)money {

    APWXOrderInfo* order = [APWXOrderInfo new];

    order.appid = WXAPPID;
    order.body = @"App pay test";
    order.mch_id = WXMCHID; //商户ID,自行申请
    order.nonce_str = [self generateTradeNO]; //生成随机订单方法,上面已写
    order.notify_url = @"http://www.weixin.qq.com";
    order.out_trade_no = [self getRandomString];
    order.spbill_create_ip = [self deviceIPAdress];
    order.total_fee = @"1";
    order.total_fee = [NSString stringWithFormat:@"%d",(int)([money floatValue] * 100)];
    order.trade_type = @"APP";

    NSString *orderInfo = [order orderInfoEncoded:NO];
    NSString *stringSignTemp = [NSString stringWithFormat:@"%@&key=%@",
                             orderInfo, WXKey];
    NSString *sign = [self md5:stringSignTemp];

    order.sign = sign;

    NSString *xmlStr = [order XMLStr];

    [self POST:@"https://api.mch.weixin.qq.com/pay/unifiedorder" params:xmlStr success:^(id responseObject) {

        NSDictionary *dict = [NSDictionary dictionaryWithXMLData:responseObject];

        if ([dict[@"return_code"] isEqualToString:@"SUCCESS"]) {

            if ([dict[@"result_code"] isEqualToString:@"SUCCESS"]) {

                //调起微信支付
                PayReq* req             = [[PayReq alloc] init];

                req.partnerId           = WXMCHID;
                req.prepayId            = [dict objectForKey:@"prepay_id"];
                req.package             = @"Sign=WXPay";
                req.nonceStr            = [dict objectForKey:@"nonce_str"];
                req.timeStamp           = [[NSString stringWithFormat:@"%.0f",[[NSDate date] timeIntervalSince1970]] intValue];

                NSString *orderInfo = [self partnerSignOrder:req];
                NSString *stringSignTemp = [NSString stringWithFormat:@"%@&key=%@",
                                            orderInfo, WXKey];
                NSString *sign = [self md5:stringSignTemp];

                req.sign                = sign;
                BOOL success = [WXApi sendReq:req];
                if (!success) {
                    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"启动微信失败" message:@"请检查微信是否安装" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
                    [alert show];
                }
            } else {

                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"下单失败" message:dict[@"err_code_des"] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
                [alert show];
            }

        } else {

            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"下单失败" message:dict[@"return_msg"] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
            [alert show];
        }

    } failure:^(NSHTTPURLResponse *httpResponse, NSError *error) {

    }];
}

辅助方法:

+ (NSString *)getRandomString
{
    NSString *str = [NSString stringWithFormat:@"%s",genRandomString(32)];
    return str;
}

char* genRandomString(int length)
{
    int flag, i;
    char* string;
    srand((unsigned) time(NULL ));
    if ((string = (char*) malloc(length)) == NULL )
    {
        //NSLog(@"Malloc failed!flag:14\n");
        return NULL ;
    }

    for (i = 0; i < length - 1; i++)
    {
        flag = rand() % 3;
        switch (flag)
        {
            case 0:
                string[i] = 'A' + rand() % 26;
                break;
            case 1:
                string[i] = 'a' + rand() % 26;
                break;
            case 2:
                string[i] = '0' + rand() % 10;
                break;
            default:
                string[i] = 'x';
                break;
        }
    }
    string[length - 1] = '\0';
    return string;
}

+ (NSString *)deviceIPAdress {

    NSString *address = @"an error occurred when obtaining ip address";
    struct ifaddrs *interfaces = NULL;
    struct ifaddrs *temp_addr = NULL;
    int success = 0;

    success = getifaddrs(&interfaces);

    if (success == 0) { // 0 表示获取成功

        temp_addr = interfaces;
        while (temp_addr != NULL) {
            if( temp_addr->ifa_addr->sa_family == AF_INET) {
                // Check if interface is en0 which is the wifi connection on the iPhone
                if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
                    // Get NSString from C String
                    address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
                }
            }

            temp_addr = temp_addr->ifa_next;
        }
    }

    freeifaddrs(interfaces);
    return address;
}
+ (NSString *)md5:(NSString *)string{
    const char *cStr = [string UTF8String];
    unsigned char digest[CC_MD5_DIGEST_LENGTH];

    CC_MD5(cStr, (CC_LONG)strlen(cStr), digest);

    NSMutableString *result = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        [result appendFormat:@"%02X", digest[i]];
    }

    return result;
}

+ (void)POST:(NSString *)urlString
      params:(NSString *)params
     success:(successBlock)success
     failure:(failureBlock)failure
{

    // 调用微信"统一下单"API
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://api.mch.weixin.qq.com/pay/unifiedorder"]];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
    [request setValue:@"text/plain" forHTTPHeaderField:@"content-type"];

    NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];

    if (success) {
        success(returnData);
    }
}
+ (NSString *)partnerSignOrder:(PayReq *)req {

    // NOTE: 增加不变部分数据
    NSMutableDictionary *tmpDict = [NSMutableDictionary new];
    [tmpDict addEntriesFromDictionary:@{@"appid":WXAPPID,
                                        @"noncestr":req.nonceStr,
                                        @"package":req.package,
                                        @"partnerid":req.partnerId,
                                        @"prepayid":req.prepayId,
                                        @"timestamp":[NSString stringWithFormat:@"%u",(unsigned int)req.timeStamp],
                                        }];

    // NOTE: 排序,得出最终请求字串
    NSArray* sortedKeyArray = [[tmpDict allKeys] sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        return [obj1 compare:obj2];
    }];

    NSMutableArray *tmpArray = [NSMutableArray new];
    for (NSString* key in sortedKeyArray) {
        NSString* orderItem = [self orderItemWithKey:key andValue:[tmpDict objectForKey:key] encoded:NO];
        if (orderItem.length > 0) {
            [tmpArray addObject:orderItem];
        }
    }
    return [tmpArray componentsJoinedByString:@"&"];
}

APWXOrderInfo.h

@interface APWXOrderInfo : NSObject

// NOTE: 支付宝分配给开发者的应用ID(如2014072300007148)
@property (nonatomic, copy) NSString *appid;

// NOTE: 商品描述
@property (nonatomic, copy) NSString *body;

// NOTE: 商户号
@property (nonatomic, copy) NSString *mch_id;

// NOTE: 随机字符串
@property (nonatomic, copy) NSString *nonce_str;

// NOTE: 支付宝服务器主动通知商户服务器里指定的页面http路径(本Demo仅做展示所用,商户需要配置这个参数)
@property (nonatomic, copy) NSString *notify_url;

// NOTE: 商户订单号
@property (nonatomic, copy) NSString *out_trade_no;

// NOTE: 终端IP
@property (nonatomic, copy) NSString *spbill_create_ip;

// NOTE: 总金额
@property (nonatomic, copy) NSString *total_fee;

// NOTE: 交易类型
@property (nonatomic, copy) NSString *trade_type;


// NOTE: 签名
@property (nonatomic, copy) NSString *sign;

// NOTE: (非必填项)签名类型
@property (nonatomic, copy) NSString *sign_type;

 // NOTE: (非必填项)设备号
 @property (nonatomic, copy) NSString *device_info;

// NOTE: (非必填项)商品详情
@property (nonatomic, copy) NSString *detail;

// NOTE: (非必填项)附加数据
@property (nonatomic, copy) NSString *attach;

// NOTE: (非必填项)货币类型
@property (nonatomic, copy) NSString *fee_type

// NOTE: (非必填项)交易起始时间
@property (nonatomic, copy) NSString *time_start;

// NOTE: (非必填项)交易结束时间
@property (nonatomic, copy) NSString *time_expire;

// NOTE: (非必填项)订单优惠标记
@property (nonatomic, copy) NSString *goods_tag;

// NOTE: (非必填项)指定支付方式
@property (nonatomic, copy) NSString *limit_pay;

// NOTE: (非必填项)场景信息
@property (nonatomic, copy) NSString *scene_info;

/**
 *  获取订单信息串
 *
 *  @param bEncoded       订单信息串中的各个value是否encode
 *                        非encode订单信息串,用于生成签名
 *                        encode订单信息串 + 签名,用于最终的支付请求订单信息串
 */
- (NSString *)orderInfoEncoded:(BOOL)bEncoded;

- (NSString *)XMLStr;

@end

APWXOrderInfo.m

@implementation APWXOrderInfo

- (NSString *)orderInfoEncoded:(BOOL)bEncoded {

    if (_appid.length <= 0) {
        return nil;
    }

    // NOTE: 增加不变部分数据
    NSMutableDictionary *tmpDict = [NSMutableDictionary new];
    [tmpDict addEntriesFromDictionary:@{@"appid":_appid,
                                        @"body":_body,
                                        @"mch_id":_mch_id,
                                        @"nonce_str":_nonce_str,
                                        @"notify_url":_notify_url,
                                        @"out_trade_no":_out_trade_no,
                                        @"spbill_create_ip":_spbill_create_ip,
                                        @"total_fee":_total_fee,
                                        @"trade_type":_trade_type,
                                        }];

    if (_device_info.length > 0) {
        [tmpDict setObject:_device_info forKey:@"device_info"];
    }

    if (_sign_type.length > 0) {
        [tmpDict setObject:_sign_type forKey:@"sign_type"];
    }

    if (_detail.length > 0) {
        [tmpDict setObject:_detail forKey:@"detail"];
    }

    if (_attach.length > 0) {
        [tmpDict setObject:_attach forKey:@"attach"];
    }

    if (_fee_type.length > 0) {
        [tmpDict setObject:_fee_type forKey:@"fee_type"];
    }

    if (_time_start.length > 0) {
        [tmpDict setObject:_time_start forKey:@"time_start"];
    }

    if (_time_expire.length > 0) {
        [tmpDict setObject:_time_expire forKey:@"time_expire"];
    }

    if (_goods_tag.length > 0) {
        [tmpDict setObject:_goods_tag forKey:@"goods_tag"];
    }

    if (_limit_pay.length > 0) {
        [tmpDict setObject:_limit_pay forKey:@"limit_pay"];
    }

    if (_scene_info.length > 0) {
        [tmpDict setObject:_scene_info forKey:@"scene_info"];
    }

    // NOTE: 排序,得出最终请求字串
    NSArray* sortedKeyArray = [[tmpDict allKeys] sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        return [obj1 compare:obj2];
    }];

    NSMutableArray *tmpArray = [NSMutableArray new];
    for (NSString* key in sortedKeyArray) {
        NSString* orderItem = [self orderItemWithKey:key andValue:[tmpDict objectForKey:key] encoded:bEncoded];
        if (orderItem.length > 0) {
            [tmpArray addObject:orderItem];
        }
    }
    return [tmpArray componentsJoinedByString:@"&"];
}

- (NSString *)XMLStr {

    if (_appid.length <= 0) {
        return nil;
    }

    NSMutableString *str = [[NSMutableString alloc] init];
    [str appendString:@"<xml>"];

    [str appendString:[NSString stringWithFormat:@"<appid>%@</appid>",_appid]];

    [str appendString:[NSString stringWithFormat:@"<body>%@</body>",_body]];

    if (_attach.length > 0) {
        [str appendString:[NSString stringWithFormat:@"<attach>%@</attach>",_attach]];
    }
    if (_detail.length > 0) {
        [str appendString:[NSString stringWithFormat:@"<detail>%@</detail>",_detail]];
    }
    if (_device_info.length > 0) {
        [str appendString:[NSString stringWithFormat:@"<device_info>%@</device_info>",_device_info]];
    }

    if (_fee_type.length > 0) {
        [str appendString:[NSString stringWithFormat:@"<fee_type>%@</fee_type>",_fee_type]];
    }

    if (_goods_tag.length > 0) {
        [str appendString:[NSString stringWithFormat:@"<goods_tag>%@</goods_tag>",_goods_tag]];
    }

    if (_limit_pay.length > 0) {
        [str appendString:[NSString stringWithFormat:@"<limit_pay>%@</limit_pay>",_limit_pay]];
    }

    [str appendString:[NSString stringWithFormat:@"<mch_id>%@</mch_id>",_mch_id]];

    [str appendString:[NSString stringWithFormat:@"<nonce_str>%@</nonce_str>",_nonce_str]];

    [str appendString:[NSString stringWithFormat:@"<notify_url>%@</notify_url>",_notify_url]];

    [str appendString:[NSString stringWithFormat:@"<out_trade_no>%@</out_trade_no>",_out_trade_no]];


    if (_scene_info.length > 0) {
        [str appendString:[NSString stringWithFormat:@"<scene_info>%@</scene_info>",_scene_info]];
    }

    if (_sign_type.length > 0) {
        [str appendString:[NSString stringWithFormat:@"<sign_type>%@</sign_type>",_sign_type]];
    }

    [str appendString:[NSString stringWithFormat:@"<spbill_create_ip>%@</spbill_create_ip>",_spbill_create_ip]];

    if (_time_expire.length > 0) {
        [str appendString:[NSString stringWithFormat:@"<time_expire>%@</time_expire>",_time_expire]];
    }
    if (_time_start.length > 0) {
        [str appendString:[NSString stringWithFormat:@"<time_start>%@</time_start>",_time_start]];
    }

    [str appendString:[NSString stringWithFormat:@"<total_fee>%@</total_fee>",_total_fee]];

    [str appendString:[NSString stringWithFormat:@"<trade_type>%@</trade_type>",_trade_type]];

    [str appendString:[NSString stringWithFormat:@"<sign>%@</sign>",_sign]];

    [str appendString:@"</xml>"];

    return str;
}

- (NSString*)orderItemWithKey:(NSString*)key andValue:(NSString*)value encoded:(BOOL)bEncoded
{
    if (key.length > 0 && value.length > 0) {
        if (bEncoded) {
            value = [self encodeValue:value];
        }
        return [NSString stringWithFormat:@"%@=%@", key, value];
    }
    return nil;
}

- (NSString*)encodeValue:(NSString*)value {

    return getUrlEncodeStr(value);

    NSString* encodedValue = value;
    if (value.length > 0) {                                                            //!*'();:@&=+$,   #[]
        NSCharacterSet *charset = [[NSCharacterSet characterSetWithCharactersInString:@"!*'();:@&=+$,/?%#[]"]invertedSet];
        encodedValue = [value stringByAddingPercentEncodingWithAllowedCharacters:charset];
    }
    return encodedValue;
}
@end

在APPDelegate里的内容见1.支付宝全本地支付的AppDelagate里面的内容:结果解析见WXApiManager文件里面的- (void)onResp:(BaseResp *)resp方法,在那个方法里分析结果

3.支付宝与服务器沟通方法

+ (void)WXAppPay:(XZLPayOrderReq *)req {

    [self getPayOrderWithReq:req success:^(DQNetWorkResult *networkResult) { // 这个是个网络请求方法,写你们的请求就可以,req写你们的要求字段

        if ([networkResult.status isEqualToString:@"success"]) {

            XZLPayOrderRes *payOrderRes = networkResult.result.lastObject;

            //调起微信支付
            PayReq* req             = [[PayReq alloc] init];
            req.partnerId           = payOrderRes.partnerId;
            req.prepayId            = payOrderRes.prepayId;
            req.package             = payOrderRes.packageStr;
            req.nonceStr            = payOrderRes.noncestr;
            req.timeStamp           = [payOrderRes.timestamp intValue];
            req.sign                = payOrderRes.sign;
            NSTimeInterval timeInter = [[NSDate date] timeIntervalSince1970];
            NSString *timeStr = [NSString stringWithFormat:@"%.0f",timeInter];

            BOOL success = [WXApi sendReq:req];
            if (!success) {
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"启动微信失败" message:@"请检查微信是否安装" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
                [alert show];
            }
        } else {

            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"下单失败" message:networkResult.message delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
            [alert show];
        }
    } failure:^(NSString *error) {

        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"下单失败" message:error.description delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [alert show];
    }];

}

4.支付宝与服务器沟通

“`
[self getPayOrderWithReq:req success:^(DQNetWorkResult *networkResult) {

    if ([networkResult.status isEqualToString:@"success"]) {

        XZLPayOrderRes *payOrderRes = networkResult.result.lastObject;
        NSString *appScheme = @"xxxxxxxx";
        [[AlipaySDK defaultService] payOrder:payOrderRes.orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
            NSLog(@"reslut = %@",resultDic);
        }];

    } else {

        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"下单失败" message:networkResult.message delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [alert show];
    }
} failure:^(NSString *error) {

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"下单失败" message:error.description delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
    [alert show];
}];```

如果有任何我写的不明白或错的地方,欢迎评论

猜你喜欢

转载自blog.csdn.net/ai_pple/article/details/81167509
今日推荐