iOS接入微信支付(小白都能看懂的微信支付)

因?yàn)榻陧?xiàng)目中需要接入微信支付功能毕箍,自己也爬了很多的坑,所以做了一下這邊文章供大家學(xué)習(xí)參考道盏,遠(yuǎn)離爬坑而柑,文章主要講到以下五部分:

一、 填寫商戶平臺(tái)所需資料

二荷逞、 具體Demo代碼@Github下載地址


本文為本人學(xué)習(xí)記錄筆記媒咳,如需轉(zhuǎn)載,請(qǐng)注明出處@iOS_lyon


填寫商戶平臺(tái)所需資料

一种远、填寫經(jīng)營(yíng)信息


@查看截圖指引

下圖選擇不同的類目涩澡,所需要上傳的資料也是有所不同的,下圖拿其它為例子

填寫經(jīng)營(yíng)信息

二院促、填寫商戶信息(確認(rèn)信息操作筏养,此處省略)

三斧抱、填寫對(duì)公帳號(hào)信息(此處省略)


以下是微信官方給出的交互步驟

商戶系統(tǒng)和微信支付系統(tǒng)主要交互說明:
步驟1:用戶在商戶APP中選擇商品,提交訂單渐溶,選擇微信支付辉浦。
步驟2:商戶后臺(tái)收到用戶支付單,調(diào)用微信支付統(tǒng)一下單接口茎辐。參見【統(tǒng)一下單API】宪郊。
步驟3:統(tǒng)一下單接口返回正常的prepay_id,再按簽名規(guī)范重新生成簽名后拖陆,將數(shù)據(jù)傳輸給APP弛槐。參與簽名的字段名為appId,partnerId依啰,prepayId乎串,nonceStr,timeStamp速警,package叹誉。注意:package的值格式為Sign=WXPay
步驟4:商戶APP調(diào)起微信支付。api參見本章節(jié)【app端開發(fā)步驟說明
步驟5:商戶后臺(tái)接收支付通知闷旧。api參見【支付結(jié)果通知API
步驟6:商戶后臺(tái)查詢支付結(jié)果长豁。,api參見【查詢訂單API

具體項(xiàng)目

一忙灼、創(chuàng)建一個(gè)項(xiàng)目
二匠襟、下載微信終端SDK文件

SDK文件包括 libWeChatSDK.a,WXApi.h该园,WXApiObject.h 三個(gè)酸舍。
請(qǐng)前往“資源下載頁”下載最新SDK包

1.將下載好的SDK導(dǎo)入項(xiàng)目,如下圖

Paste_Image.png

2.添加依賴庫(kù)


Paste_Image.png

3.準(zhǔn)備所需配置的數(shù)據(jù)

// 開放平臺(tái)登錄https://open.weixin.qq.com的開發(fā)者中心獲取APPID
#define WX_APPID @"wxd21d890***2db4ca"
// 開放平臺(tái)登錄https://open.weixin.qq.com的開發(fā)者中心獲取AppSecret。
#define WX_APPSecret @"fc32dfae9****eb5f77dddd4ea5"
// 微信支付商戶號(hào)
#define MCH_ID  @"13536**702"

// 安全校驗(yàn)碼(MD5)密鑰爬范,商戶平臺(tái)登錄賬戶和密碼登錄http://pay.weixin.qq.com 平臺(tái)設(shè)置的“API密鑰”父腕,為了安全,請(qǐng)?jiān)O(shè)置為以數(shù)字和字母組成的32字符串青瀑。
#define WX_PartnerKey @"b5f9c901480*****0f4c6e659be0"

4.在Xcode中璧亮,選擇你的工程設(shè)置項(xiàng),選中“TARGETS”一欄斥难,在“info”標(biāo)簽欄的“URL type“添加“URL scheme”為你所注冊(cè)AppId(如下圖所示)

Paste_Image.png

配置好上述參數(shù)后就可以寫代碼了枝嘶,具體可查看@Github下載地址

  • PCH頭文件: 在該文件配置好以下備注中要配置參數(shù)即可運(yùn)行demo
#ifndef PrefixHeader_pch
#define PrefixHeader_pch

#pragma mark -  
#pragma mark - 微信支付配置參數(shù)

// 開放平臺(tái)登錄https://open.weixin.qq.com的開發(fā)者中心獲取APPID
#define WX_APPID @"wxd21d89033***b4ca"
// 開放平臺(tái)登錄https://open.weixin.qq.com的開發(fā)者中心獲取AppSecret。
#define WX_APPSecret @"fc32dfae99bc67e****5f77dddd4ea5"
// 微信支付商戶號(hào)
#define MCH_ID  @"1353***702"
// 安全校驗(yàn)碼(MD5)密鑰哑诊,商戶平臺(tái)登錄賬戶和密碼登錄http://pay.weixin.qq.com
// 平臺(tái)設(shè)置的“API密鑰”群扶,為了安全,請(qǐng)?jiān)O(shè)置為以數(shù)字和字母組成的32字符串。
#define WX_PartnerKey @"B6246A6D8***C730EEA0F78D3B461"


#pragma mark -  
#pragma mark - 統(tǒng)一下單請(qǐng)求參數(shù)鍵值

//  應(yīng)用id
#define WXAPPID @"appid"
//  商戶號(hào)
#define WXMCHID @"mch_id"
//  隨機(jī)字符串
#define WXNONCESTR @"nonce_str"
//  簽名
#define WXSIGN @"sign"
//  商品描述
#define WXBODY @"body"
//  商戶訂單號(hào)
#define WXOUTTRADENO @"out_trade_no"
//  總金額
#define WXTOTALFEE @"total_fee"
//  終端IP
#define WXEQUIPMENTIP @"spbill_create_ip"
//  通知地址
#define WXNOTIFYURL @"notify_url"
//  交易類型
#define WXTRADETYPE @"trade_type"
//  預(yù)支付交易會(huì)話
#define WXPREPAYID @"prepay_id"



#pragma mark - 
#pragma mark - 微信下單接口

//  微信統(tǒng)一下單接口連接
#define WXUNIFIEDORDERURL @"https://api.mch.weixin.qq.com/pay/unifiedorder"

#endif /* PrefixHeader_pch */
 
#import "AppDelegate.h"
#import "WXApiManager.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // 注冊(cè)微信
    [WXApi registerApp:WX_APPID withDescription:@"demo 2.0"];
    
    return YES;
}

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

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

@end

** 微信支付回調(diào)管理類**


#import "WXApiManager.h"

@implementation WXApiManager

#pragma mark - 單粒

+(instancetype)sharedManager {
    static dispatch_once_t onceToken;
    static WXApiManager *instance;
    dispatch_once(&onceToken, ^{
        instance = [[WXApiManager alloc] init];
    });
    return instance;
}

#pragma mark - WXApiDelegate

- (void)onResp:(BaseResp *)resp
{
    if([resp isKindOfClass:[PayResp class]]){
        
        //支付返回結(jié)果竞阐,實(shí)際支付結(jié)果需要去微信服務(wù)器端查詢
        NSString *strMsg;
    
        switch (resp.errCode) {
            case WXSuccess:
                strMsg = @"支付結(jié)果:成功缴饭!";
                NSLog(@"支付成功-PaySuccess,retcode = %d", resp.errCode);
                break;
                
            default:
                strMsg = [NSString stringWithFormat:@"支付結(jié)果:失斅嬗ā颗搂!retcode = %d, retstr = %@", resp.errCode,resp.errStr];
                NSLog(@"錯(cuò)誤,retcode = %d, retstr = %@", resp.errCode,resp.errStr);
                break;
        }
    }
}

@end

步驟1:用戶在商戶APP中選擇商品幕垦,提交訂單丢氢,選擇微信支付。

#import "ViewController.h"
#import "WXApiRequestHandler.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //  發(fā)起支付
    [WXApiRequestHandler jumpToBizPay];
}

@end

步驟2:商戶后臺(tái)收到用戶支付單先改,調(diào)用微信支付統(tǒng)一下單接口疚察。參見【統(tǒng)一下單API】。

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

@interface WXApiRequestHandler : NSObject

+ (NSString *)jumpToBizPay;

@end

#import "WXApi.h"
#import "WXApiRequestHandler.h"
#import "WXApiManager.h"
#import "DataMD5.h"
#import "XMLDictionary.h"
#import <AFNetworking.h>

#pragma mark - 用于獲取設(shè)備ip地址

#include <ifaddrs.h>
#include <arpa/inet.h>

@implementation WXApiRequestHandler

#pragma mark - 產(chǎn)生隨機(jī)字符串

//生成隨機(jī)數(shù)算法 ,隨機(jī)字符串仇奶,不長(zhǎng)于32位
//微信支付API接口協(xié)議中包含字段nonce_str貌嫡,主要保證簽名不可預(yù)測(cè)。
//我們推薦生成隨機(jī)數(shù)算法如下:調(diào)用隨機(jī)數(shù)函數(shù)生成该溯,將得到的值轉(zhuǎn)換為字符串衅枫。

+ (NSString *)generateTradeNO {
    
    static int kNumber = 15;
    
    NSString *sourceStr = @"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
    NSMutableString *resultStr = [[NSMutableString alloc] init];
    
    //  srand函數(shù)是初始化隨機(jī)數(shù)的種子,為接下來的rand函數(shù)調(diào)用做準(zhǔn)備朗伶。
    //  time(0)函數(shù)返回某一特定時(shí)間的小數(shù)值。
    //  這條語句的意思就是初始化隨機(jī)數(shù)種子步咪,time函數(shù)是為了提高隨機(jī)的質(zhì)量(也就是減少重復(fù))而使用的论皆。
    
    // srand(time(0)) 就是給這個(gè)算法一個(gè)啟動(dòng)種子,也就是算法的隨機(jī)種子數(shù)猾漫,有這個(gè)數(shù)以后才可以產(chǎn)生隨機(jī)數(shù),用1970.1.1至今的秒數(shù)点晴,初始化隨機(jī)數(shù)種子。
    // Srand是種下隨機(jī)種子數(shù)悯周,你每回種下的種子不一樣粒督,用Rand得到的隨機(jī)數(shù)就不一樣。為了每回種下一個(gè)不一樣的種子禽翼,所以就選用Time(0)屠橄,Time(0)是得到當(dāng)前時(shí)時(shí)間值(因?yàn)槊繒r(shí)每刻時(shí)間是不一樣的了)。
    
    srand(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;
}

#pragma mark - 獲取設(shè)備ip地址

+ (NSString *)fetchIPAddress {
    NSString *address = @"error";
    struct ifaddrs *interfaces = NULL;
    struct ifaddrs *temp_addr = NULL;
    int success = 0;
    // retrieve the current interfaces - returns 0 on success
    success = getifaddrs(&interfaces);
    if (success == 0) {
        // Loop through linked list of interfaces
        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;
        }
    }
    // Free memory
    freeifaddrs(interfaces);
    return address;
}

#pragma mark - Public Methods
//  發(fā)起微信支付
+ (void)jumpToWxPay
 {
    
#pragma mark 客戶端操作時(shí)候的代碼 \ 但是這些步驟應(yīng)該放在服務(wù)端操作

//============================================================
    // V3&V4支付流程實(shí)現(xiàn)
    // 注意:參數(shù)配置請(qǐng)查看服務(wù)器端Demo
    // 更新時(shí)間:2015年11月20日
    //============================================================
    
// 交易類型
#define TRADE_TYPE @"APP"
    
// 交易結(jié)果通知網(wǎng)站此處用于測(cè)試闰挡,隨意填寫锐墙,正式使用時(shí)填寫正確網(wǎng)站
#define NOTIFY_URL @"http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php"
    
// 交易價(jià)格1表示0.01元,10表示0.1元
#define PRICE @"1"
    
    
    //  隨機(jī)字符串變量 這里最好使用和安卓端一致的生成邏輯
    NSString *nonce_str = [self generateTradeNO];
    
    //  設(shè)備IP地址,請(qǐng)?jiān)賥ifi環(huán)境下測(cè)試,否則獲取的ip地址為error,正確格式應(yīng)該是8.8.8.8
    NSString *addressIP = [self fetchIPAddress];
    
    //  隨機(jī)產(chǎn)生訂單號(hào)用于測(cè)試长酗,正式使用請(qǐng)換成你從自己服務(wù)器獲取的訂單號(hào)
    NSString *orderno = [NSString stringWithFormat:@"%ld",time(0)];
  
    //  獲取SIGN簽名
    DataMD5 *data = [[DataMD5 alloc] initWithAppid:WX_APPID
                                            mch_id:MCH_ID
                                         nonce_str:nonce_str
                                        partner_id:WX_PartnerKey
                                              body:@"充值"
                                      out_trade_no:orderno
                                         total_fee:PRICE
                                  spbill_create_ip:addressIP
                                        notify_url:NOTIFY_URL
                                        trade_type:TRADE_TYPE];
    
    // 轉(zhuǎn)換成xml字符串
    NSString *string = [[data dic] XMLString];
  
    
    AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
    //這里傳入的xml字符串只是形似xml溪北,但不是正確是xml格式,需要使用AF方法進(jìn)行轉(zhuǎn)義
    session.responseSerializer = [[AFHTTPResponseSerializer alloc] init];
    [session.requestSerializer setValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    [session.requestSerializer setValue:WXUNIFIEDORDERURL forHTTPHeaderField:@"SOAPAction"];
    [session.requestSerializer setQueryStringSerializationWithBlock:^NSString *(NSURLRequest *request, NSDictionary *parameters, NSError *__autoreleasing *error) {
        return string;
    }];
    [session POST:WXUNIFIEDORDERURL parameters:string progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        //  輸出XML數(shù)據(jù)
        NSString *responseString = [[NSString alloc] initWithData:responseObject
                                                         encoding:NSUTF8StringEncoding] ;
        //  將微信返回的xml數(shù)據(jù)解析轉(zhuǎn)義成字典
        NSDictionary *dic = [NSDictionary dictionaryWithXMLString:responseString];
        
        // 判斷返回的許可
        if ([[dic objectForKey:@"result_code"] isEqualToString:@"SUCCESS"]
            &&[[dic objectForKey:@"return_code"] isEqualToString:@"SUCCESS"] ) {
            // 發(fā)起微信支付,設(shè)置參數(shù)
            PayReq *request = [[PayReq alloc] init];
            request.openID = [dic objectForKey:WXAPPID];
            request.partnerId = [dic objectForKey:WXMCHID];
            request.prepayId= [dic objectForKey:WXPREPAYID];
            request.package = @"Sign=WXPay";
            request.nonceStr= [dic objectForKey:WXNONCESTR];
            // 將當(dāng)前時(shí)間轉(zhuǎn)化成時(shí)間戳
            NSDate *datenow = [NSDate date];
            NSString *timeSp = [NSString stringWithFormat:@"%ld", (long)[datenow timeIntervalSince1970]];
            UInt32 timeStamp =[timeSp intValue];
            request.timeStamp= timeStamp;
            // 簽名加密
            DataMD5 *md5 = [[DataMD5 alloc] init];
            request.sign = [dic objectForKey:@"sign"];
            request.sign=[md5 createMD5SingForPay:request.openID
                                        partnerid:request.partnerId
                                         prepayid:request.prepayId
                                          package:request.package
                                         noncestr:request.nonceStr
                                        timestamp:request.timeStamp];
            // 調(diào)用微信
            [WXApi sendReq:request];
        }
 
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        NSLog(@"%@",error);
    }];

#pragma mark  服務(wù)端操作微信支付 / 上述客戶端操作可以忽略(僅供參考)沒辦法之拨,靠后臺(tái)還不如靠自己茉继,先自己了解客戶端實(shí)現(xiàn)支付的操作
    
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    params[WXTOTALFEE] = @"1";
    params[WXEQUIPMENTIP] = [self fetchIPAddress];
    
    AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
    [session POST:URLSTRING parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
 
        NSLog(@"responseObject = %@",responseObject);
        
        // 判斷返回的許可
        if ([[responseObject objectForKey:@"result_code"] isEqualToString:@"SUCCESS"]
            &&[[responseObject objectForKey:@"return_code"] isEqualToString:@"SUCCESS"] ) {
            
            // 發(fā)起微信支付,設(shè)置參數(shù)
            PayReq *request     = [[PayReq alloc] init];
            request.openID      = [responseObject objectForKey:WXAPPID];
            request.partnerId   = [responseObject objectForKey:WXMCHID];
            request.prepayId    = [responseObject objectForKey:WXPREPAYID];
            request.package     = @"Sign=WXPay";
            request.nonceStr    = [responseObject objectForKey:WXNONCESTR];
            request.timeStamp   = [[responseObject objectForKey:@"timestamp"] intValue];
            request.sign        = [responseObject objectForKey:@"sign"];
            // 調(diào)用微信支付
            [WXApi sendReq:request];
        }else{
            // 顯示錯(cuò)誤信息
            [LyonKeyWindow.rootViewController showHint:responseObject[@"err_code_des"]];
        }
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        NSLog(@"%@",error);
    }];

}

@end

以下皆是客戶端的簽名方法類

#import "DataMD5.h"
#import <CommonCrypto/CommonDigest.h>
@interface DataMD5()

@property (nonatomic,strong) NSString *appid;
@property (nonatomic,strong) NSString *mch_id;
@property (nonatomic,strong) NSString *nonce_str;
@property (nonatomic,strong) NSString *partnerkey;
@property (nonatomic,strong) NSString *body;
@property (nonatomic,strong) NSString *out_trade_no;
@property (nonatomic,strong) NSString *total_fee;
@property (nonatomic,strong) NSString *spbill_create_ip;
@property (nonatomic,strong) NSString *notify_url;
@property (nonatomic,strong) NSString *trade_type;

@end

@implementation DataMD5

#pragma makr - 懶加載

- (NSMutableDictionary *)dic
{
    if (!_dic) {
        _dic = [NSMutableDictionary dictionary];
    }
    return _dic;
}

#pragma mark - Config

-(instancetype)initWithAppid:(NSString *)appid_key
                      mch_id:(NSString *)mch_id_key
                   nonce_str:(NSString *)noce_str_key
                  partner_id:(NSString *)partner_id
                        body:(NSString *)body_key
               out_trade_no :(NSString *)out_trade_no_key
                   total_fee:(NSString *)total_fee_key
            spbill_create_ip:(NSString *)spbill_create_ip_key
                  notify_url:(NSString *)notify_url_key
                  trade_type:(NSString *)trade_type_key
{
    if (self = [super init]) {
        
        _appid          = appid_key;
        _mch_id         = mch_id_key;
        _nonce_str      = noce_str_key;
        _partnerkey     = partner_id;
        _body           = body_key;
        _out_trade_no   = out_trade_no_key;
        _total_fee      = total_fee_key;
        _spbill_create_ip = spbill_create_ip_key;
        _notify_url     = notify_url_key;
        _trade_type     = trade_type_key;
        
        [self.dic setValue:_appid forKey:WXAPPID];
        [self.dic setValue:_mch_id forKey:WXMCHID];
        [self.dic setValue:_nonce_str forKey:WXNONCESTR];
        [self.dic setValue:_body forKey:WXBODY];
        [self.dic setValue:_out_trade_no forKey:WXOUTTRADENO];
        [self.dic setValue:_total_fee forKey:WXTOTALFEE];
        [self.dic setValue:_spbill_create_ip forKey:WXEQUIPMENTIP];
        [self.dic setValue:_notify_url forKey:WXNOTIFYURL];
        [self.dic setValue:_trade_type forKey:WXTRADETYPE];
        
        [self createMd5Sign:self.dic];
    }
    return self;
}

//創(chuàng)建簽名
//簽名算法
//簽名生成的通用步驟如下:
//第一步蚀乔,設(shè)所有發(fā)送或者接收到的數(shù)據(jù)為集合M烁竭,將集合M內(nèi)非空參數(shù)值的參數(shù)按照參數(shù)名ASCII碼從小到大排序(字典序),使用URL鍵值對(duì)的格式(即key1=value1&key2=value2…)拼接成字符串stringA乙墙。
//特別注意以下重要規(guī)則:
//◆ 參數(shù)名ASCII碼從小到大排序(字典序)颖变;
//◆ 如果參數(shù)的值為空不參與簽名;
//◆ 參數(shù)名區(qū)分大小寫听想;
//◆ 驗(yàn)證調(diào)用返回或微信主動(dòng)通知簽名時(shí)腥刹,傳送的sign參數(shù)不參與簽名,將生成的簽名與該sign值作校驗(yàn)汉买。
//◆ 微信接口可能增加字段衔峰,驗(yàn)證簽名時(shí)必須支持增加的擴(kuò)展字段
//第二步,在stringA最后拼接上key得到stringSignTemp字符串蛙粘,并對(duì)stringSignTemp進(jìn)行MD5運(yùn)算垫卤,再將得到的字符串所有字符轉(zhuǎn)換為大寫,得到sign值signValue出牧。
//key設(shè)置路徑:微信商戶平臺(tái)(pay.weixin.qq.com)-->賬戶設(shè)置-->API安全-->密鑰設(shè)置

-(void)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:@""]
            && ![[dict objectForKey:categoryId] isEqualToString:@"sign"]
            && ![[dict objectForKey:categoryId] isEqualToString:@"key"]
            )
        {
            [contentString appendFormat:@"%@=%@&", categoryId, [dict objectForKey:categoryId]];
        }
    }
    //添加商戶密鑰key字段
    [contentString appendFormat:@"key=%@",_partnerkey];
    
    NSLog(@"contentString = %@",contentString);
    
    //MD5 獲取Sign簽名
    NSString *md5Sign =[self md5:contentString];
    
    //  
    [self.dic setValue:md5Sign forKey:@"sign"];
    
}

//創(chuàng)建發(fā)起支付時(shí)的sige簽名

-(NSString *)createMD5SingForPay:(NSString *)appid_key partnerid:(NSString *)partnerid_key prepayid:(NSString *)prepayid_key package:(NSString *)package_key noncestr:(NSString *)noncestr_key timestamp:(UInt32)timestamp_key{
    NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
    [signParams setObject:appid_key forKey:@"appid"];
    [signParams setObject:noncestr_key forKey:@"noncestr"];
    [signParams setObject:package_key forKey:@"package"];
    [signParams setObject:partnerid_key forKey:@"partnerid"];
    [signParams setObject:prepayid_key forKey:@"prepayid"];
    [signParams setObject:[NSString stringWithFormat:@"%u",(unsigned int)timestamp_key] forKey:@"timestamp"];
    
    NSMutableString *contentString  =[NSMutableString string];
    NSArray *keys = [signParams allKeys];
    //按字母順序排序
    NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        return [obj1 compare:obj2 options:NSNumericSearch];
    }];
    //拼接字符串
    for (NSString *categoryId in sortedArray) {
        if (   ![[signParams objectForKey:categoryId] isEqualToString:@""]
            && ![[signParams objectForKey:categoryId] isEqualToString:@"sign"]
            && ![[signParams objectForKey:categoryId] isEqualToString:@"key"]
            )
        {
            [contentString appendFormat:@"%@=%@&", categoryId, [signParams objectForKey:categoryId]];
        }
    }
    //添加商戶密鑰key字段
#warning 注意此處一定要添加上商戶密鑰
    [contentString appendFormat:@"key=%@", WX_PartnerKey];
    NSString *result = [self md5:contentString];
    
    NSLog(@"result = %@",result);
    return result;
}

// MD5加密算法
-(NSString *) md5:(NSString *)str
{
    const char *cStr = [str UTF8String];
    //加密規(guī)則穴肘,因?yàn)槎罕任⑿艣]有出微信支付demo,這里加密規(guī)則是參照安卓demo來得
    unsigned char result[16]= "0123456789abcdef";
    CC_MD5(cStr, (CC_LONG)strlen(cStr), result);
    //這里的x是小寫則產(chǎn)生的md5也是小寫舔痕,x是大寫則md5是大寫评抚,這里只能用大寫,逗比微信的大小寫驗(yàn)證很逗
    return [NSString stringWithFormat:
            @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
            result[0], result[1], result[2], result[3],
            result[4], result[5], result[6], result[7],
            result[8], result[9], result[10], result[11],
            result[12], result[13], result[14], result[15]
            ];
}

@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末伯复,一起剝皮案震驚了整個(gè)濱河市慨代,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌啸如,老刑警劉巖侍匙,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異叮雳,居然都是意外死亡想暗,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門帘不,熙熙樓的掌柜王于貴愁眉苦臉地迎上來江滨,“玉大人,你說我怎么就攤上這事厌均』;” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)晶密。 經(jīng)常有香客問我擒悬,道長(zhǎng),這世上最難降的妖魔是什么稻艰? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任懂牧,我火速辦了婚禮,結(jié)果婚禮上尊勿,老公的妹妹穿的比我還像新娘僧凤。我一直安慰自己,他們只是感情好元扔,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布躯保。 她就那樣靜靜地躺著,像睡著了一般澎语。 火紅的嫁衣襯著肌膚如雪途事。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天擅羞,我揣著相機(jī)與錄音尸变,去河邊找鬼。 笑死减俏,一個(gè)胖子當(dāng)著我的面吹牛召烂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播娃承,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼骑晶,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了草慧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤匙头,失蹤者是張志新(化名)和其女友劉穎漫谷,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蹂析,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舔示,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了电抚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惕稻。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蝙叛,靈堂內(nèi)的尸體忽然破棺而出俺祠,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布蜘渣,位于F島的核電站淌铐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蔫缸。R本人自食惡果不足惜腿准,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拾碌。 院中可真熱鬧吐葱,春花似錦、人聲如沸校翔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽展融。三九已至窖认,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間告希,已是汗流浹背扑浸。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留燕偶,地道東北人喝噪。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像指么,于是被迫代替她去往敵國(guó)和親酝惧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 今日推薦 經(jīng)常閱讀博客是個(gè)好習(xí)慣推薦鴻洋CSDN的博客 微信支付相關(guān)文章 詳細(xì)介紹Android開發(fā)集成微信支付(...
    MrQ_Android閱讀 6,167評(píng)論 9 52
  • 前言:本篇文章目的在于梳理知識(shí)伯诬,鞏固思想晚唇,學(xué)習(xí)總結(jié)。有什么好的建議盗似,都可以留言哩陕。互相促進(jìn)赫舒!總觀悍及,微信支付,也沒心思...
    麥穗0615閱讀 10,027評(píng)論 8 70
  • 自己總結(jié)的微信支付寶支付流程和注意點(diǎn): 準(zhǔn)備工作: 需要公司的營(yíng)業(yè)執(zhí)照接癌,稅務(wù)信息心赶,等老板的身份證信息等,我記得缺猛,用...
    Www劉閱讀 18,558評(píng)論 2 50
  • 準(zhǔn)備工作: 需要公司的營(yíng)業(yè)執(zhí)照缨叫,稅務(wù)信息椭符,等老板的身份證信息等,我記得弯汰,用這些材料艰山,去支付寶注冊(cè)一個(gè)商家賬戶(審核...
    Hevin_Chen閱讀 6,800評(píng)論 0 9
  • 突然想起前一段時(shí)間還嚷嚷著“才不要談戀愛,要安分守己的當(dāng)一條宇宙無敵單身哈士奇就好啦”的自己覺得甚是好笑咏闪。比起酸澀...
    我才不愛你呢_閱讀 340評(píng)論 0 0