1. 程式人生 > >iOS開發之第三方支付微信支付教程,史上最新最全第三方微信支付方式實現、微信整合教程,微信實現流程

iOS開發之第三方支付微信支付教程,史上最新最全第三方微信支付方式實現、微信整合教程,微信實現流程

 1. 微信支付微信支付前奏大致流程為 :

1. 公司需要到微信進行申請app支付功能 , 獲得appid和微信支付商戶號(mch_id)和API祕鑰(key) 、 Appsecret(secret,開發中用到的,很重要

  1. appidappid是微信公眾賬號或開放平臺APP的唯一標識,在公眾平臺申請公眾賬號或者在開放平臺申請APP賬號後,微信會自動分配對應的appid,用於標識該應用。可在微信公眾平臺-->開發者中心檢視,商戶的微信支付稽核通過郵件中也會包含該欄位值。
  2. 微信支付商戶號:商戶申請微信支付後,由微信支付分配的商戶收款賬號。
  3. API金鑰: 交易過程生成簽名的金鑰,僅保留在商戶系統和微信支付後臺,不會在網路中傳播。商戶妥善保管該Key,切勿在網路中傳輸,不能在其他客戶端中儲存,保證key不會被洩漏。商戶可根據郵件提示登入微信商戶平臺進行設定。也可按一下路徑設定:微信商戶平臺(pay.weixin.qq.com)-->賬戶設定-->API安全-->金鑰設定

  4. App secret : AppSecret是APPID對應的介面密碼,用於獲取介面呼叫憑證access_token時使用。

      還有Demo地址.


3.   根據上面的整合教程地址 ,搭建好專案

4.   設定好URL Types ,(具體怎麼設定也在環境搭建的文章中說到了,請大家注意看)。

5.    記得把網路從https 改變成為 http。 

6. 設定微信白名單 。 


7. 現在基本就是環境搭配完畢了。 

2. 微信支付具體流程如下:

1. 流程圖一覽


2. 具體流程

步驟1:使用者在商戶APP中選擇商品,提交訂單,選擇微信支付。
步驟2:商戶後臺收到使用者支付單,呼叫微信支付統一下單介面。參見【統一下單API】。
步驟3:統一下單介面返回正常的prepay_id,再按簽名規範重新生成簽名後,將資料傳輸給APP。參與簽名的欄位名為appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式為Sign=WXPay
步驟4:商戶APP調起微信支付。api參見本章節【app端開發步驟說明】
步驟5:商戶後臺接收支付通知。api參見【支付結果通知API】
步驟6:商戶後臺查詢支付結果。,api參見【查詢訂單API】

3.開發前需要注意的幾個方面。

特別注意以下重要規則:
◆ 引數名ASCII碼從小到大排序(字典序);
◆ 如果引數的值為空不參與簽名;
◆ 引數名區分大小寫;
◆ 驗證呼叫返回或微信主動通知簽名時,傳送的sign引數不參與簽名,將生成的簽名與該sign值作校驗。
◆ 微信介面可能增加欄位,驗證簽名時必須支援增加的擴充套件欄位

4. 具體的客戶端開發過程:

步驟1:使用者進入商戶APP,選擇商品下單、確認購買,進入支付環節。商戶服務後臺生成支付訂單,簽名後將資料傳輸到APP端,可參照官方支付demo。  https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=11_1
步驟2:使用者點選後發起支付操作,進入到微信介面,調起微信支付,出現確認支付介面,。
步驟3:使用者確認收款方和金額,點選立即支付後出現輸入密碼介面,可選擇零錢或銀行卡支付.
第四步:輸入正確密碼後,支付完成,使用者端微信出現支付詳情頁面。
第五步:回跳到商戶APP中,商戶APP根據支付結果個性化展示訂單處理結果.


5. 正式程式設計 。

1. 再次確認url schemes中設定 APPID , 商戶在微信開放平臺申請開發APP應用後,微信開放平臺會生成APP的唯一標識APPID。在Xcode中開啟專案,設定專案屬性中的URL Schemes為您的APPID。

2.  商戶APP工程中引入微信lib庫和標頭檔案,呼叫API前,需要先向微信註冊您的APPID,程式碼如下:[WXApi registerApp:@"wxd930ea5d5a258f4f" withDescription:@"123"];


3. 調起微信支付 (引數拼接, 簽名)

4 支付結果回撥 

核心程式碼展示 : 

回撥方法展示:

appdelegate.m

/*! 微信回撥,不管是登入還是分享成功與否,都是走這個方法 @brief 傳送一個sendReq後,收到微信的迴應
 *
 * 收到一個來自微信的處理結果。呼叫一次sendReq後會收到onResp。
 * 可能收到的處理結果有SendMessageToWXResp、SendAuthResp等。
 * @param resp具體的迴應內容,是自動釋放的
 */
-(void) onResp:(BaseResp*)resp{
    NSLog(@"resp %d",resp.errCode);
    
    /*
    enum  WXErrCode {
        WXSuccess           = 0,    成功
        WXErrCodeCommon     = -1,  普通錯誤型別
        WXErrCodeUserCancel = -2,    使用者點選取消並返回
        WXErrCodeSentFail   = -3,   傳送失敗
        WXErrCodeAuthDeny   = -4,    授權失敗
        WXErrCodeUnsupport  = -5,   微信不支援
    };
    */
    if ([resp isKindOfClass:[SendAuthResp class]]) {   //授權登入的類。
        if (resp.errCode == 0) {  //成功。
            //這裡處理回撥的方法 。 通過代理吧對應的登入訊息傳送過去。
            if ([_wxDelegate respondsToSelector:@selector(loginSuccessByCode:)]) {
                SendAuthResp *resp2 = (SendAuthResp *)resp;
                [_wxDelegate loginSuccessByCode:resp2.code];
            }
        }else{ //失敗
            NSLog(@"error %@",resp.errStr);
            UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"登入失敗" message:[NSString stringWithFormat:@"reason : %@",resp.errStr] delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil];
            [alert show];
        }
    }
    
    if ([resp isKindOfClass:[SendMessageToWXResp class]]) { //微信分享 微信迴應給第三方應用程式的類
        SendMessageToWXResp *response = (SendMessageToWXResp *)resp;
        NSLog(@"error code %d  error msg %@  lang %@   country %@",response.errCode,response.errStr,response.lang,response.country);
        
        if (resp.errCode == 0) {  //成功。
            //這裡處理回撥的方法 。 通過代理吧對應的登入訊息傳送過去。
            if (_wxDelegate) {
                if([_wxDelegate respondsToSelector:@selector(shareSuccessByCode:)]){
                    [_wxDelegate shareSuccessByCode:response.errCode];
                }
            }
        }else{ //失敗
            NSLog(@"error %@",resp.errStr);
            UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"分享失敗" message:[NSString stringWithFormat:@"reason : %@",resp.errStr] delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil];
            [alert show];
        }
    }
    
    /*
    0  展示成功頁面
    -1  可能的原因:簽名錯誤、未註冊APPID、專案設定APPID不正確、註冊的APPID與設定的不匹配、其他異常等。
    -2  使用者取消	無需處理。發生場景:使用者不支付了,點選取消,返回APP。
     */
    if ([resp isKindOfClass:[PayResp class]]) { // 微信支付
        
        PayResp*response=(PayResp*)resp;
        switch(response.errCode){
            case 0:
                //伺服器端查詢支付通知或查詢API返回的結果再提示成功
                NSLog(@"支付成功");
                break;
                
            default:
                NSLog(@"支付失敗,retcode=%d  errormsg %@",resp.errCode ,resp.errStr);
                break;
        }
    }
}

方法呼叫。

viewController.m方法

#pragma mark 微信支付
- (IBAction)weixinPayAction:(id)sender {
    
    
    /**
     *  外界呼叫的微信支付方法
     *
     *  @param ordeNumber  系統下發訂單號%100000000 得出的數字,確保唯一。
     *  @param myNumber    訂單號  確保唯一
     *  @param price       價格
     付款流程:
     
     1. 獲取 AccessToken
     2. 獲取 genPackage
     3. 調起微信付款
     4. 在appdelegate 中的 onResp 監聽 回撥方法。 看是付款成功。
     
     回撥程式碼引數說明:
     0  展示成功頁面
     -1  可能的原因:簽名錯誤、未註冊APPID、專案設定APPID不正確、註冊的APPID與設定的不匹配、其他異常等。
     -2  使用者取消	無需處理。發生場景:使用者不支付了,點選取消,返回APP。
     */

    helper = [[WeixinPayHelper alloc] init];
    [helper payProductWith:@"Test Product" andName:@"product number 1" andPrice:[NSString stringWithFormat:@"%d",1500]];
    
}
封裝的核心支付工具類方法

WeixinPayHelper.h

//
//  WeixinPayHelper.h
//  weixinLoginDemo
//
//  Created by 張國榮 on 16/7/1.
//  Copyright © 2016年 BateOrganization. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "WXApi.h"
#import "AFNetworking.h"
/**
 *  微信支付工具類
 */
@interface WeixinPayHelper : NSObject
@property (nonatomic, strong) AFHTTPSessionManager *request;
@property (nonatomic, copy) NSString *timeStamp;
@property (nonatomic, copy) NSString *nonceStr;
@property (nonatomic, copy) NSString *traceId;
@property (nonatomic, copy) NSString *orderId;
@property (nonatomic, copy) NSString *orderPrice;
@property (nonatomic, copy) NSString *orderAllId;
+ (instancetype)shareInstance;


/**
 *  外界呼叫的微信支付方法
 *
 *  @param ordeNumber  系統下發訂單號%100000000 得出的數字,確保唯一。
 *  @param myNumber    訂單號  確保唯一
 *  @param price       價格
 付款流程:
 
  1. 獲取 AccessToken
  2. 獲取 PrepayId 、 包含引數拼接,簽名、genPackage等
  3. 調起微信付款
  4. 在appdelegate 中的 onResp 監聽 回撥方法。 看是付款成功。
 
 回撥程式碼引數說明:
 0  展示成功頁面
 -1  可能的原因:簽名錯誤、未註冊APPID、專案設定APPID不正確、註冊的APPID與設定的不匹配、其他異常等。
 -2  使用者取消	無需處理。發生場景:使用者不支付了,點選取消,返回APP。
 */
- (void)payProductWith:(NSString*)ordeNumber andName:(NSString*)myNumber andPrice:(NSString*)price;

@end


WeixinPayHelper.m

//
//  WeixinPayHelper.m
//  weixinLoginDemo
//
//  Created by 張國榮 on 16/7/1.
//  Copyright © 2016年 BateOrganization. All rights reserved.
//

#import "WeixinPayHelper.h"
#import "CommonUtil.h"
#import "Constant.h"

#define ISOFTEN_WECHARPAY_URL            @"https://www.sizzee.com/tenpay/payment/mobilesuccess"

@interface WeixinPayHelper()

@end

@implementation WeixinPayHelper

NSString *AccessTokenKey = @"access_token";
NSString *PrePayIdKey = @"prepayid";
NSString *errcodeKey = @"errcode";
NSString *errmsgKey = @"errmsg";
NSString *expiresInKey = @"expires_in";

/**
 *  微信開放平臺申請得到的 appid, 需要同時新增在 URL schema
 */
NSString * const WXAppId = @"app id";
/**
 * 微信開放平臺和商戶約定的支付金鑰
 *
 * 注意:不能hardcode在客戶端,建議genSign這個過程由伺服器端完成
 */
NSString * const WXAppKey = @"appkey";

/**
 * 微信開放平臺和商戶約定的金鑰
 *
 * 注意:不能hardcode在客戶端,建議genSign這個過程由伺服器端完成
 */
NSString * const WXAppSecret = @"app Secret";

/**
 * 微信開放平臺和商戶約定的支付金鑰
 *
 * 注意:不能hardcode在客戶端,建議genSign這個過程由伺服器端完成
 */
NSString * const WXPartnerKey = @"祕鑰、 放伺服器的,這兒方便演示";
/**
 *  微信公眾平臺商戶模組生成的ID
 */
NSString * const WXPartnerId = @"商戶id";


+ (instancetype)shareInstance
{
    static WeixinPayHelper *sharedClient = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedClient = [[WeixinPayHelper  alloc] init];
    });
    return sharedClient;
}
/**
 *  外界調起微信下單的方法
 *
 *  @param ordeNumber 訂單號 ,由伺服器下發、經過處理的  生成genPackage 需要用到
 *  @param myNumber   訂單號 ,由伺服器下發  生成genPackage 需要用到
 *  @param price      商品價格   生成genPackage 需要用到
 
 
 
 */
- (void)payProductWith:(NSString *)ordeNumber andName:(NSString *)myNumber andPrice:(NSString *)price{
    self.orderId = ordeNumber;
    self.orderPrice = price;
    self.orderAllId = myNumber;
    [self getAccessToken];
}

#pragma mark - 生成各種引數

#pragma mark 時間戳 生成
- (NSString *)genTimeStamp
{
    return [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970]];
}

/**
 * 注意:商戶系統內部的訂單號,32個字元內、可包含字母,確保在商戶系統唯一
 */
- (NSString *)genNonceStr
{
    return [CommonUtil md5:[NSString stringWithFormat:@"%d", arc4random() % 10000]];
}

/**
 * 建議 traceid 欄位包含使用者資訊及訂單資訊,方便後續對訂單狀態的查詢和跟蹤
 */
- (NSString *)genTraceId
{
    return [NSString stringWithFormat:@"crestxu_%@", [self genTimeStamp]];
}

- (NSString *)genOutTradNo
{
    return [CommonUtil md5:[NSString stringWithFormat:@"%d", arc4random() % 10000]];
}

#pragma mark genPackage 這個應該是伺服器完成。 在這兒方便演示。
- (NSString *)genPackage
{
    // 構造引數列表
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    [params setObject:@"WX" forKey:@"bank_type"];
    [params setObject:[NSString stringWithFormat:@"拾裳%@訂單", self.orderAllId] forKey:@"body"];
    [params setObject:@"1" forKey:@"fee_type"];
    [params setObject:@"UTF-8" forKey:@"input_charset"];
    [params setObject:ISOFTEN_WECHARPAY_URL forKey:@"notify_url"];
    [params setObject:[self genOutTradNo] forKey:@"out_trade_no"];
    [params setObject:WXPartnerId forKey:@"partner"];
    [params setObject:[CommonUtil getIPAddress:YES] forKey:@"spbill_create_ip"];
    [params setObject:self.orderPrice forKey:@"total_fee"];    // 1 == ¥0.01
    NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[[NSURL URLWithString:@"https://www.sizzee.com"] absoluteURL]];
    NSHTTPCookie *cookie;
    NSMutableArray* arr=[NSMutableArray array];
    for (cookie in cookies) {
        if (![cookie.name isEqualToString:@"app_code"]) {
            NSString* str=[NSString stringWithFormat:@"%@||%@",cookie.name,cookie.value];
            [arr addObject:str];
        }
    }
    
    
    NSString* aa=[arr componentsJoinedByString:@"||"];
    [params setObject:[NSString stringWithFormat:@"%@||%@||%@",self.orderId,[CommonUtil md5:[NSString stringWithFormat:@"1219929601fef54y3d5wsxf5yu55t5g5d5e35yujki%@",self.orderId]],aa] forKey:@"attach"];
    
    NSArray *keys = [params allKeys];
    NSArray *sortedKeys = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        return [obj1 compare:obj2 options:NSNumericSearch];
    }];
    
    // 生成 packageSign
    NSMutableString *package = [NSMutableString string];
    for (NSString *key in sortedKeys) {
        [package appendString:key];
        [package appendString:@"="];
        [package appendString:[params objectForKey:key]];
        [package appendString:@"&"];
    }
    
    [package appendString:@"key="];
    [package appendString:WXPartnerKey]; // 注意:不能hardcode在客戶端,建議genPackage這個過程都由伺服器端完成
    
    // 進行md5摘要前,params內容為原始內容,未經過url encode處理
    NSString *packageSign = [[CommonUtil md5:[package copy]] uppercaseString];
    package = nil;
    
    // 生成 packageParamsString
    NSString *value = nil;
    package = [NSMutableString string];
    for (NSString *key in sortedKeys) {
        [package appendString:key];
        [package appendString:@"="];
        value = [params objectForKey:key];
        
        // 對所有鍵值對中的 value 進行 urlencode 轉碼
        value = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)value, nil, (CFStringRef)@"!*'&=();:@+$,/?%#[]", kCFStringEncodingUTF8));
        
        [package appendString:value];
        [package appendString:@"&"];
    }
    NSString *packageParamsString = [package substringWithRange:NSMakeRange(0, package.length - 1)];
    
    NSString *result = [NSString stringWithFormat:@"%@&sign=%@", packageParamsString, packageSign];
    
    
    
    return result;
}

- (NSString *)genSign:(NSDictionary *)signParams
{
    // 排序
    NSArray *keys = [signParams allKeys];
    NSArray *sortedKeys = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        return [obj1 compare:obj2 options:NSNumericSearch];
    }];
    
    // 生成
    NSMutableString *sign = [NSMutableString string];
    for (NSString *key in sortedKeys) {
        [sign appendString:key];
        [sign appendString:@"="];
        [sign appendString:[signParams objectForKey:key]];
        [sign appendString:@"&"];
    }
    NSString *signString = [[sign copy] substringWithRange:NSMakeRange(0, sign.length - 1)];
    
    NSString *result = [CommonUtil sha1:signString];
    
    return result;
}

- (NSMutableDictionary *)getProductArgs
{
    self.timeStamp = [self genTimeStamp];
    self.nonceStr = [self genNonceStr]; // traceId 由開發者自定義,可用於訂單的查詢與跟蹤,建議根據支付使用者資訊生成此id
    self.traceId = [self genTraceId];
    
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    [params setObject:WXAppId forKey:@"appid"];
    [params setObject:WXAppKey forKey:@"appkey"];
    [params setObject:self.timeStamp forKey:@"noncestr"];
    [params setObject:self.timeStamp forKey:@"timestamp"];
    [params setObject:self.traceId forKey:@"traceid"];
    [params setObject:[self genPackage] forKey:@"package"];
    [params setObject:[self genSign:params] forKey:@"app_signature"];
    [params setObject:@"sha1" forKey:@"sign_method"];
    
    NSError *error = nil;
//    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params options:NSJSONWritingPrettyPrinted error: &error];
    
    return params;
}

#pragma mark - 主體流程 - 獲取 accessToken , 然後呼叫再拿著accessToken呼叫微信的支付介面。
- (void)getAccessToken
{
    //欄位
    NSString *getAccessTokenUrl = [NSString stringWithFormat:@"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%@&secret=%@", WXAppId, WXAppSecret];

    self.request = [AFHTTPSessionManager manager];
    
    
    __weak WeixinPayHelper *weakSelf = self;
    self.request.requestSerializer = [AFJSONRequestSerializer serializer];//請求
    self.request.responseSerializer = [AFHTTPResponseSerializer serializer];//響應
    self.request.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html",@"application/json", @"text/json",@"text/plain", nil];

    [self.request POST:getAccessTokenUrl parameters:nil progress:^(NSProgress * _Nonnull uploadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
         NSError *error = nil;
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseObject options:kNilOptions                           error:&error];
        if (error) {
            [weakSelf showAlertWithTitle:@"錯誤" msg:@"獲取 AccessToken 失敗"];
            return;
        }
        NSString *accessToken = dict[AccessTokenKey];
        if (accessToken) {
            __strong WeixinPayHelper *strongSelf = weakSelf;
            [strongSelf getPrepayId:accessToken];
        } else {
            NSString *strMsg = [NSString stringWithFormat:@"errcode: %@, errmsg:%@", dict[errcodeKey], dict[errmsgKey]];
            [weakSelf showAlertWithTitle:@"錯誤" msg:strMsg];
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        [weakSelf showAlertWithTitle:@"錯誤" msg:@"獲取 AccessToken 失敗"];

    }];
    
}

#pragma mark 根據accessToken 獲取 PrePayID . 然後進行下單。

- (void)getPrepayId:(NSString *)accessToken
{
    
    NSString *getPrepayIdUrl = [NSString stringWithFormat:@"https://api.weixin.qq.com/pay/genprepay?access_token=%@", accessToken];

    NSMutableDictionary *postData = [self getProductArgs];
    __weak WeixinPayHelper *weakSelf = self;
    
    self.request = [AFHTTPSessionManager manager];
    self.request.requestSerializer = [AFJSONRequestSerializer serializer];//請求
    self.request.responseSerializer = [AFHTTPResponseSerializer serializer];//響應
    self.request.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html",@"application/json", @"text/json",@"text/plain", nil];

    [self.request POST:getPrepayIdUrl parameters:postData progress:^(NSProgress * _Nonnull uploadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSError *error = nil;
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseObject options:kNilOptions  error:&error];
        if (error) {
            [weakSelf showAlertWithTitle:@"錯誤" msg:@"獲取 PrePayId 失敗"];
            return;
        }
        
        NSString *prePayId = dict[PrePayIdKey];
        if (prePayId) {
            // 調起微信支付
            PayReq *request   = [[PayReq alloc] init];
            request.partnerId = WXPartnerId;
            request.prepayId  = prePayId;
            request.package   = @"Sign=WXPay";      // 文件為 `Request.package = _package;` , 但如果填寫上面生成的 `package` 將不能支付成功
            request.nonceStr  = weakSelf.nonceStr;
            request.timeStamp = [weakSelf.timeStamp longLongValue];
            
            // 構造引數列表
            NSMutableDictionary *params = [NSMutableDictionary dictionary];
            [params setObject:WXAppId forKey:@"appid"];
            [params setObject:WXAppKey forKey:@"appkey"];
            [params setObject:request.nonceStr forKey:@"noncestr"];
            [params setObject:request.package forKey:@"package"];
            [params setObject:request.partnerId forKey:@"partnerid"];
            [params setObject:request.prepayId forKey:@"prepayid"];
            [params setObject:weakSelf.timeStamp forKey:@"timestamp"];
            request.sign = [weakSelf genSign:params];
            
            // 在支付之前,如果應用沒有註冊到微信,應該先呼叫 [WXApi registerApp:appId] 將應用註冊到微信
            [WXApi sendReq:request];
            
        } else {
            NSString *strMsg = [NSString stringWithFormat:@"errcode: %@, errmsg:%@", dict[errcodeKey], dict[errmsgKey]];
            [weakSelf showAlertWithTitle:@"錯誤" msg:strMsg];
        }
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
         [weakSelf showAlertWithTitle:@"錯誤" msg:@"獲取 PrePayId 失敗"];
    }];
   
}

#pragma mark - Alert

- (void)showAlertWithTitle:(NSString *)title msg:(NSString *)msg
{
    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:title message: msg delegate: self cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];
    [alert show];

}
@end


總結:

 我這裡付款做的比官方的demo做的複雜了很多, 做了很多伺服器要做的事情,比如說 簽名演算法 、 以及引數按照key=value的格式 、 拼接祕鑰 等。 

我介意沒有特殊要求的朋友,就稍微看看,不必自己再操作一遍。  大家多去看看官方的api,上面講的很詳細。