第一步: 導入微信SDK

第三步: 設置URL Types
注: 這步操作後運轉, 假如是新建的項目能夠會報這個錯誤

第八步: 創立一個PCH文件 Common.pch
定義三個宏
#define WeChatAppID @"xxxxxxxxxxxxx"//
APPID
#define PartnerID @"xxxxx"//商戶ID
#define APISignKey @"xxxxxxxx商戶平台 -> 賬戶中心 -> API平安 -> API密鑰, 設置密鑰"//
API私鑰
//
// ViewController.m
// ZHWeChatPay
//
// Created by 周昊 on 2016/12/28.
// Copyright © 2016年 Cloud. All rights reserved.
//
#import "ViewController.h"
#import "WXApi.h"
#import <CommonCrypto/CommonDigest.h> // MD5加密需求導此包
// ------------獲取終端IP地址需求以下引入及定義
#include <ifaddrs.h>
#include <arpa/.net.h>
#include <.net/if.h>
#define IOS_CELLULAR @"pdp_ip0"
#define IOS_WIFI @"en0"
#define IOS_VPN @"utun0"
#define IP_ADDR_IPv4 @"ipv4"
#define IP_ADDR_IPv6 @"ipv6"
// -------------
#import "XmlRss/ target=_blank class=infotextkey>XmlReader.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *payServerBtn = [UIButton buttonWithType:UIButtonTypeSystem];
[payServerBtn setTitle:@"包括服務器端操作的領取" forState:UIControlStateNormal];
[payServerBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[payServerBtn addTarget:self action:@selector(zh_weChatPayIncludeServer) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:payServerBtn];
[payServerBtn sizeToFit];
payServerBtn.frame = CGRectMake((self.view.frame.size.width - payServerBtn.frame.size.width) / 2.0, 200, payServerBtn.frame.size.width, payServerBtn.frame.size.height);
UIButton *payBtn = [UIButton buttonWithType:UIButtonTypeSystem];
[payBtn setTitle:@"微信領取" forState:UIControlStateNormal];
[payBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[payBtn addTarget:self action:@selector(zh_weChatPay) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:payBtn];
[payBtn sizeToFit];
payBtn.frame = CGRectMake((self.view.frame.size.width - payBtn.frame.size.width) / 2.0, CGRectGetMaxY(payServerBtn.frame) + 100, payBtn.frame.size.width, payBtn.frame.size.height);
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(zh_handleWeChatPayResult:) name:@"doWeChatPayResult" object:nil];
}
- (void)zh_handleWeChatPayResult:(NSNotification *)notification
{
BaseResp *resp = notification.object;
switch (resp.errCode)
{
case WXSuccess:
NSLog(@"領取成功");
break;
default:
NSLog(@"領取失敗");
break;
}
}
#pragma mark - 微信領取(包括服務器端的操作)
- (void)zh_weChatPayIncludeServer
{
if (![WXApi isWXAppInstalled])
{
NSLog(@"未裝置微信客戶端");
return;
}
if (![WXApi isWXAppSupportApi])
{
NSLog(@"不支持微信領取");
return;
}
NSString *url = @"https://api.mch.weixin.qq.com/pay/unifiedorder"; // 懇求騰訊服務器
// 拼接詳細的訂雙數據
NSDictionary *postDict = [self zh_getProductArgs]; // 服務器端拼接數據及簽名
// 拼接調用領取接口所需求的參數(拼接成XmlRss/ target=_blank class=infotextkey>Xml格式)
NSString *string = [NSString stringWithFormat:@"<Xml><sign>%@</sign><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>%d</total_fee><trade_type>APP</trade_type></xml>",[postDict objectForKey:@"sign"], WeChatAppID, [postDict objectForKey:@"body"], PartnerID, [postDict objectForKey:@"nonce_str"], [postDict objectForKey:@"notify_url"], [postDict objectForKey:@"out_trade_no"], [postDict objectForKey:@"spbill_create_ip"],[[postDict objectForKey:@"total_fee"] intValue]];
// 創立網絡懇求
NSURL *requestURL = [NSURL URLWithString:url];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:requestURL];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:[string dataUsingEncoding:NSUTF8StringEncoding]];
NSHTTPURLResponse* urlResponse = nil;
NSError *error = [[NSError alloc] init];
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&error];
NSString *result = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
if ([urlResponse statusCode] >= 200 && [urlResponse statusCode] < 300)
{
NSError *error2 = [NSError alloc];
// 從騰訊服務器懇求回來的數據將XML格式解析成字典
NSDictionary *xmlDict = [[XMLReader dictionaryForXMLString:result error:&error2] objectForKey:@"xml"];
// 調用領取接口
PayReq *payRequest = [[PayReq alloc]init];
payRequest.partnerId = [[xmlDict objectForKey:@"mch_id"] objectForKey:@"text"];
payRequest.prepayId = [[xmlDict objectForKey:@"prepay_id"] objectForKey:@"text"];
payRequest.package = @"Sign=WXPay";
payRequest.nonceStr = [[xmlDict objectForKey:@"nonce_str"] objectForKey:@"text"];
payRequest.timeStamp = [[NSString stringWithFormat:@"%ld", (long)[[NSDate date] timeIntervalSince1970]] intValue];
// 結構參數列表,再次簽名
NSMutableDictionary *payDict = [NSMutableDictionary dictionary];
[payDict setObject:WeChatAppID forKey:@"appid"];
[payDict setObject:payRequest.nonceStr forKey:@"noncestr"];
[payDict setObject:payRequest.package forKey:@"package"];
[payDict setObject:payRequest.partnerId forKey:@"partnerid"];
[payDict setObject:payRequest.prepayId forKey:@"prepayid"];
[payDict setObject:[NSString stringWithFormat:@"%u", (unsigned int)payRequest.timeStamp]forKey:@"timestamp"];
payRequest.sign = [self zh_genSign:payDict];
[WXApi sendReq:payRequest];
}
}
// 結構預付訂單參數列表
- (NSDictionary *)zh_getProductArgs
{
NSMutableDictionary *params = [NSMutableDictionary dictionary];
NSString *timeStamp = [NSString stringWithFormat:@"%ld", (long)[[NSDate date] timeIntervalSince1970]]; // 獲取時間戳
NSString *nonceStr = [[self zh_md5:[NSString stringWithFormat:@"%d", arc4random() % 10000]] uppercaseString]; // 獲取32位內的隨機串, 防重發
// 獲取商家對用戶的獨一標識
NSString *outTradNo = [NSString stringWithFormat:@"%d", arc4random() % 10000];
NSString *out_trade_no= [NSString stringWithFormat:@"%@%@",timeStamp,outTradNo];//獲取商戶訂單號
[params setObject:WeChatAppID forKey:@"appid"];//必填
[params setObject:nonceStr forKey:@"nonce_str"];//隨機字符串,必填
[params setObject:@"APP" forKey:@"trade_type"]; //買賣類型 必填
[params setObject:@"有逼格的順序員" forKey:@"body"];//商品描繪,必填
[params setObject:@"這裡是你本地接納回調告訴的地址" forKey:@"notify_url"]; // 此處填可以讓後台寫個接口,假如領取成功,則微信後台調用此接口,前往yes,失敗則前往no;
[params setObject:out_trade_no forKey:@"out_trade_no"];//商戶訂單號,必填
[params setObject:PartnerID forKey:@"mch_id"]; // 商戶ID
[params setObject:[self zh_getIPAddress:YES] forKey:@"spbill_create_ip"];//終端ip,必填
[params setObject:@"1" forKey:@"total_fee"];
//簽名
[params setObject:[self zh_genSign:params] forKey:@"sign"];
return params;
}
// 將字符串MD5加密
- (NSString *)zh_md5:(NSString *)str
{
// #import <CommonCrypto/CommonDigest.h> // MD5加密需求導此包
const char *cStr = str.UTF8String;
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5(cStr, strlen(cStr), digest);
NSMutableString *md5Str = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
{
[md5Str appendFormat:@"%02x", digest[i]];
}
return md5Str;
}
// 簽名
- (NSString *)zh_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:@"&"];
}
[sign appendString:@"key="];
[sign appendString:APISignKey];// 留意:不能hardcode在客戶端,建議genPackage這個進程都由服務器端完成
NSString *result = [[self zh_md5:sign] uppercaseString];
return result;
}
// 獲取終端IP地址
- (NSString *)zh_getIPAddress:(BOOL)preferIPv4
{
/*
需求引入一下頭文件及定義宏
#include <ifaddrs.h>
#include <arpa/.net.h>
#include <net/if.h>
#define IOS_CELLULAR @"pdp_ip0"
#define IOS_WIFI @"en0"
#define IOS_VPN @"utun0"
#define IP_ADDR_IPv4 @"ipv4"
#define IP_ADDR_IPv6 @"ipv6"
*/
NSArray *searchArray = preferIPv4 ?
@[ IOS_WIFI @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6 ] :
@[ IOS_WIFI @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4 ] ;
NSDictionary *addresses = [self zh_getIPAddresses];
__block NSString *address;
[searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
{
address = addresses[key];
if(address) *stop = YES;
} ];
return address ? address : @"0.0.0.0";
}
- (NSDictionary *)zh_getIPAddresses
{
NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
// retrieve the current interfaces - returns 0 on success
// 導入ifaddrs.h
struct ifaddrs *interfaces;
if(!getifaddrs(&interfaces))
{
// Loop through linked list of interfaces
struct ifaddrs *interface;
for(interface=interfaces; interface; interface=interface->ifa_next)
{
if(!(interface->ifa_flags & IFF_UP) || (interface->ifa_flags & IFF_LOOPBACK))
{
continue; // deeply nested code harder to read IFF_UP需求導入頭文件
}
const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6))
{
NSString *name = [NSString stringWithUTF8String:interface->ifa_name];
char addrBuf[INET6_ADDRSTRLEN];
if(inet_ntop(addr->sin_family, &addr->sin_addr, addrBuf, sizeof(addrBuf)))
{
NSString *key = [NSString stringWithFormat:@"%@/%@", name, addr->sin_family == AF_INET ? IP_ADDR_IPv4 : IP_ADDR_IPv6];
addresses[key] = [NSString stringWithUTF8String:addrBuf];
}
}
}
// Free memory
freeifaddrs(interfaces);
}
// The dictionary keys have the form "interface" "/" "ipv4 or ipv6"
return [addresses count] ? addresses : nil;
}
#pragma mark - 微信領取(不包括服務器, 正常的操作流程就需求這一個辦法即可)
- (void)zh_weChatPay
{
if (![WXApi isWXAppInstalled])
{
NSLog(@"未裝置微信客戶端");
return;
}
if (![WXApi isWXAppSupportApi])
{
NSLog(@"不支持微信領取");
return;
}
// 此處的懇求可以交換為AFNetworking的懇求
NSString *urlString = @"http://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // 向自己的服務器懇求訂單生成預領取訂單信息
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
// body: 商品描繪
// out_trade_no: 商品訂單流水號
// spbill_create_ip: 終端IP地址
// total_fee: 商品價錢 單位: 分
NSString *outTradNo = [NSString stringWithFormat:@"%d", arc4random() % 10000];
NSString *out_trade_no= [NSString stringWithFormat:@"%@%@",[NSString stringWithFormat:@"%ld", (long)[[NSDate date] timeIntervalSince1970]],outTradNo]; // 隨機生成商戶訂單號
NSString *bodyString = [NSString stringWithFormat:@"body=商品的描繪&out_trade_no=%@&spbill_create_ip=%@&total_fee=1", out_trade_no, [self zh_getIPAddress:YES]];
NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:bodyData];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
if ([[NSString stringWithFormat:@"%@", result[@"opflag"]] isEqualToString:@"1"])
{
NSError *error = nil;
NSDictionary *xmlDict = [[XMLReader dictionaryForXMLString:result[@"weixinPost"] error:&error] objectForKey:@"xml"];
//調用領取接口
PayReq *payRequest = [[PayReq alloc]init];
payRequest.partnerId = [[xmlDict objectForKey:@"mch_id"] objectForKey:@"text"];
payRequest.prepayId = [[xmlDict objectForKey:@"prepay_id"] objectForKey:@"text"];
payRequest.package = @"Sign=WXPay";
payRequest.nonceStr = [[xmlDict objectForKey:@"nonce_str"] objectForKey:@"text"];
payRequest.timeStamp = [[NSString stringWithFormat:@"%ld", (long)[[NSDate date] timeIntervalSince1970]] intValue];
//結構參數列表,再次簽名
NSMutableDictionary *payDict = [NSMutableDictionary dictionary];
[payDict setObject:WeChatAppID forKey:@"appid"];
[payDict setObject:payRequest.nonceStr forKey:@"noncestr"];
[payDict setObject:payRequest.package forKey:@"package"];
[payDict setObject:payRequest.partnerId forKey:@"partnerid"];
[payDict setObject:payRequest.prepayId forKey:@"prepayid"];
[payDict setObject:[NSString stringWithFormat:@"%u", (unsigned int)payRequest.timeStamp] forKey:@"timestamp"];
payRequest.sign = [self zh_genSign:payDict];
if ([WXApi sendReq:payRequest]) // 調起微信客戶端領取
{
NSLog(@"調起微信領取成功!");
}
else
{
NSLog(@"調起微信領取失敗!");
}
}
else
{
NSLog(@"調起微信領取失敗!");
}
}
#pragma mark -
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
// NOTE: 8.0運用API接口
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
if ([url.host isEqualToString:@"pay"]) // 微信後果回調
{
return [WXApi handleOpenURL:url delegate:self];
}
return YES;
}
// NOTE: 9.0當前運用新API接口
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options
{
if ([url.host isEqualToString:@"pay"]) // 微信後果回調
{
return [WXApi handleOpenURL:url delegate:self];
}
return YES;
}
// 微信領取
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
return [WXApi handleOpenURL:url delegate:self];
}
- (void)onResp:(BaseResp *)resp
{
if([resp isKindOfClass:[PayResp class]])
{
[[NSNotificationCenter defaultCenter] postNotificationName:@"doWeChatPayResult" object:resp];
}
}第十一步: 回調的時分需求觸發一個代理, 簽代理<WXApiDelegate>
第十二步: 在ViewController.m的viewDidLoad辦法中注冊告訴
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(zh_handleWeChatPayResult:) name:@"doWeChatPayResult" object:nil];
- (void)zh_handleWeChatPayResult:(NSNotification *)notification
{
BaseResp *resp = notification.object;
switch (resp.errCode)
{
case WXSuccess:
NSLog(@"領取成功");
break;
default:
NSLog(@"領取失敗");
break;
}
}【iOS 微信領取 SDK版本1.7.5(2016年12月27日)】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!