2015-09-20 15:50:59 CHENYUFENG1991 阅读数 1410
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27820 人正在学习 去看看 秦子恒

      当你一个App在后台运行时,有可能服务器会向你推送重要的信息,常见的如微信,QQ等,就算你的App在后台,也会以通知的形式给你推送。推送服务分为本地推送和在线推送。本次我们先来实现本地推送通知。

(1)代码实现如下:

#import "AppDelegate.h"
#import "ViewController.h"


@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  
  return YES;
}

//程序从前台到后台时执行该方法;
- (void)applicationDidEnterBackground:(UIApplication *)application
{
  
  //如果已经获得发送通知的授权则创建本地通知,否则请求授权(注意:如果不请求授权在设置中是没有对应的通知设置项的,也就是说如果从来没有发送过请求,即使通过设置也打不开消息允许设置)
  if ([[UIApplication sharedApplication]currentUserNotificationSettings].types != UIUserNotificationTypeNone) {
    
    [self addLocalNotification];
  }else{
    [[UIApplication sharedApplication]registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound  categories:nil]];
  }
  
}

//程序在后台运行,再次打开时回调该方法;此时取消badge数字;
- (void)applicationWillEnterForeground:(UIApplication *)application
{
  
  [[UIApplication sharedApplication]setApplicationIconBadgeNumber:0];//进入前台取消应用消息图标
}

#pragma mark Notification

-(void)addLocalNotification{
  
  //定义本地通知对象
  UILocalNotification *notification=[[UILocalNotification alloc] init];
  //设置调用时间
  notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:3.0];//通知触发的时间,10s以后
  notification.repeatInterval = 2;//通知重复次数
  //notification.repeatCalendar=[NSCalendar currentCalendar];//当前日历,使用前最好设置时区等信息以便能够自动同步时间
  
  //设置通知属性
  notification.alertBody=@"这是App推送的消息通知,哈哈"; //通知主体
  notification.applicationIconBadgeNumber = 1;//应用程序图标右上角显示的消息数
  notification.alertAction = @"打开应用"; //待机界面的滑动动作提示
  notification.alertLaunchImage = @"Default";//通过点击通知打开应用时的启动图片,这里使用程序启动图片
  //notification.soundName=UILocalNotificationDefaultSoundName;//收到通知时播放的声音,默认消息声音
  notification.soundName = @"msg.caf";//通知声音(需要真机才能听到声音)
  
  //设置用户信息
  notification.userInfo=@{@"id":@1,@"user":@"Kenshin Cui"};//绑定到通知上的其他附加信息
  
  //调用通知
  [[UIApplication sharedApplication] scheduleLocalNotification:notification];
}


@end

(2)程序运行如下:





(3)我设置的是应用程序退出后3s推送通知。可以发现App图标有一个红色的badge,就如同微信的一样。点击进去后,badge会消失。根据你自己的逻辑,是不是就可以方便的使用了呢?当然安装时需要用户授权。



github主页:https://github.com/chenyufeng1991  。欢迎大家访问!


2017-09-20 21:43:58 coco2d_x2014 阅读数 3128
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27820 人正在学习 去看看 秦子恒
2016-05-21 17:08:26 qq_24513469 阅读数 375
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27820 人正在学习 去看看 秦子恒


iOS-本地推送和远程推送,常用的三方推送和常用的测试方法,推送实现和原理详解

什么是消息推送

举一个常见的例子,我们的手机上经常会有弹出一些信息,例如QQ信息、微信信息等等,这就是常见的消息推送。

例如:

消息推送的类型:

  • 在屏幕顶部显示一块横幅(显示具体内容)
  • 在屏幕中间弹出一个UIAlertView(显示具体内容)
  • 在锁屏界面显示一块横幅(锁屏状态下,显示具体内容)
  • 更新app图标的数字(说明新内容的数量)
  • 播放音效(提醒作用)

这是我们常见的推送消息的样式,我们可以在手机上自定义接收的消息如何展示。

在一些软件中,如果用户不小心关闭了我们的推送服务,我们也可以这样提示用户怎么打开允许接收推送服务(iOS8以后)。

注意:

  • 发出推送通知时,如果当前程序正运行在前台,那么推送通知就不会被呈现出来

  • 点击推送通知后,默认会自动打开发出推送通知的app

  • 不管app打开还是关闭,推送通知都能如期发出

消息推送和平常的从服务器获取数据有什么不同?

  • 当我们从服务器获取数据的时候,我们会主动向服务器发送消息,然后服务器才会给我们发送我们需要的信息;而消息推送是当我们不在聊天状态下,甚至是连QQ软件都没有打开的情况下,服务器主动向我们发送消息,告诉我们一些信息。

当然了,消息推送和通知(NSNotification)可不一样,虽然它们的使用类名看起来有点相似。

  • NSNotification是抽象的,不可见的
  • 消息推送是可见(肉眼可见的)

本地推送

在iOS中,推送分为本地推送和远程推送,本地推送不需要网络(不需要服务器的支持),常见的应用场景例如:

  • 事件提醒类的软件,到了我们自定义的时间,就会弹出一些信息告诉我们该干什么了。

  • 记账类软件,会提醒我们的一些花销等等。


我们先来学习一下本地推送

相关使用的类(重要)

  • 创建本地推送通知对象
UILocalNotification *ln = [[UILocalNotification alloc] init];
  • 设置本地推送通知属性
//推送通知的触发时间(何时发出推送通知)
@property(nonatomic,copy) NSDate *fireDate;

//推送通知的具体内容
@property(nonatomic,copy) NSString *alertBody;

//在锁屏时显示的动作标题(完整标题:“滑动来” + alertAction)
@property(nonatomic,copy) NSString *alertAction;

//音效文件名
@property(nonatomic,copy) NSString *soundName;

//app图标数字
@property(nonatomic) NSInteger applicationIconBadgeNumber;

//每隔多久重复发一次推送通知
@property(nonatomic) NSCalendarUnit repeatInterval;

//点击推送通知打开app时显示的启动图片
@property(nonatomic,copy) NSString *alertLaunchImage;

//附加的额外信息
@property(nonatomic,copy) NSDictionary *userInfo;

//时区
@property(nonatomic,copy) NSTimeZone *timeZone;
(一般设置为[NSTimeZone defaultTimeZone] ,跟随手机的时区)

//调度本地推送通知(调度完毕后,推送通知会在特地时间fireDate发出)
[[UIApplication sharedApplication] scheduleLocalNotification:ln];

//获得被调度(定制)的所有本地推送通知
@property(nonatomic,copy) NSArray *scheduledLocalNotifications;
(已经发出且过期的推送通知就算调度结束,会自动从这个数组中移除)

//取消调度本地推送通知
- (void)cancelLocalNotification:(UILocalNotification *)notification;
- (void)cancelAllLocalNotifications;

//立即发出本地推送通知
- (void)presentLocalNotificationNow:(UILocalNotification *)notification;
  • 用户点击推送消息进入app时的调用方法

//当用户点击本地推送通知,会自动打开app,这里有2种情况
//app并没有关闭,一直隐藏在后台
//让app进入前台,并会调用AppDelegate的下面方法(并非重新启动app)
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;

//app已经被关闭(进程已死)
//启动app,启动完毕会调用AppDelegate的下面方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
//launchOptions参数通过UIApplicationLaunchOptionsLocalNotificationKey取出本地推送通知对象
//当点击通知进入app时,launchOptions参数才会有值,当正常启动app时,launchOptions为null

注意:

在iOS 8.0中,如果要使用本地通知,需要得到用户的许可
在didFinishLaunchingWithOptions方法中添加如下代码:

UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil];

[application registerUserNotificationSettings:settings];

实例:


//在需要的地方注册本地消息推送

    // 1.创建本地通知
    UILocalNotification *localNote = [[UILocalNotification alloc] init];

    // 2.设置本地通知的信息
    // 2.1.设置提示信息
    localNote.alertBody = @"吃饭了吗?";
    // 2.2.设置通知弹出的时间
    localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:5.0];
    // 2.3.设置滑块显示的文字
    localNote.alertAction = @"快点";
    // 2.4.是否让上面的文字生效
    localNote.hasAction = NO;
    // 2.5.设置通知中心的标题
    localNote.alertTitle = @"你大哥";
    // 2.6.设置通知的声音
    localNote.soundName = @"buyao.wav";
    // 2.7.设置应用程序图标右上角的数字
    localNote.applicationIconBadgeNumber = 10;

    // 3.调度通知
    //调度前要先把原来的通知取消
    UIApplication *app = [UIApplication sharedApplication];
    [app cancelAllLocalNotifications];
    [app scheduleLocalNotification:localNote];

在appdelegate类中实现相应的跳转方法

#import "AppDelegate.h"

#define IS_iOS8 ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0)

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    /*
     UIUserNotificationTypeNone    = 0,      不发出通知
     UIUserNotificationTypeBadge   = 1 << 0, 改变应用程序图标右上角的数字
     UIUserNotificationTypeSound   = 1 << 1, 播放音效
     UIUserNotificationTypeAlert   = 1 << 2, 是否运行显示横幅
     */

    [application setApplicationIconBadgeNumber:0];

    if (IS_iOS8) {
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound categories:nil];
        [application registerUserNotificationSettings:settings];
    }

    // 如果是正常启动应用程序,那么launchOptions参数是null
    // 如果是通过其他方式启动应用程序,那么launchOptions就有值,里面存储的是通知的内容
    if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) {
        // 当被杀死状态收到本地通知时执行的跳转代码
         [self jumpToSession];
    }

    return YES;
}

//程序没有关闭时,点击通知进入app才会调用,如果将程序完全退出,点击通知进入app时只会调用上面的方法,不会调用这个方法
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
    // 在这里写跳转代码
    // 如果是应用程序在前台,依然会收到通知,但是收到通知之后不应该跳转
    if (application.applicationState == UIApplicationStateActive) return;

    if (application.applicationState == UIApplicationStateInactive) {
        // 当应用在后台收到本地通知时执行的跳转代码
        [self jumpToSession];
    }
}

- (void)jumpToSession
{
    UILabel *redView = [[UILabel alloc] init];
    redView.backgroundColor = [UIColor redColor];
    redView.frame = CGRectMake(0, 100, 300, 400);
    redView.numberOfLines = 0;
    // redView.text = [NSString stringWithFormat:@"%@", launchOptions];
    [self.window.rootViewController.view addSubview:redView];
}

@end

远程推送

先介绍一下iOS中远程推送的原理:

我们先要明确一点,所有的iOS设备收到的远程推送消息都是通过苹果的服务器发出来的。我们自己公司的服务器或者第三方的推送服务器都是将要发送给我们的推送消息先推给苹果的服务器,然后再由苹果的服务器发送给我们。

如下图:

所以,我们的苹果设备在联网的情况下,都会默认和苹果的服务器保持一个长连接(这里不解释长连接的概念,你可以理解成是有一条线一直在两者之间联系着,为了保持服务器不断开和我们设备的联系,我们的设备默认每隔一段时间会向服务器发送心跳包(一个很小的文件),来告诉苹果服务器不要和我们的设备断开连接)。

原理图讲解

下面详细解释一下iOS中的远程推送原理

上图中1-8的步骤就可以很好的解释远程推送的过程了,而客户端需要做的只有几个步骤:

  • 1:发送设备的UDID和
    应用的Bundle Identifier
    给APNs服务器

  • 2:经苹果加密生成一个
    deviceToken

  • 3:发送当前用户的deviceToken
    和用户的标志(比如id或者qq)到自己公司的服务器或者第三方推送服务器

  • 4:监听通知的点击事件

其余的步骤由服务器端实现:

  • 4:自己的服务器或者第三方推送服务器将客户端发送过来的用户信息保存在自己的服务器中

  • 5:有人发送消息的时候,从服务器中(根据deviceToken)查询要发给谁

  • 6:查询到要发送给某人以后,将信息发送给苹果服务器

  • 7:苹果服务器根据得到的deviceToken和信息,查到要接受信息的设备和app,将信息发送给用户。

调试iOS的远程推送功能, 必备条件:

1.真机

2.调试推送需要的证书文件
1> aps_development.cer : 某台电脑就能调试某个app的推送服务
2> iphone5_qq.mobileprovision : 某台电脑就能利用某台设备调试某个程序

三.发布具有推送服务的app,需要的证书文件
1> aps_production.cer : 如果发布的程序中包含了推送服务,就必须安装这个证书
2> qq.mobileprovision : 某台电脑就能发布某个程序

实际操作

下面就开始真正的使用一下远程推送功能吧。

证书配置01 – 创建App ID

配置明确的App ID

大概步骤如下:

先选择明确的App ID

配置远程推送的调试证书


配置远程推送的发布证书(使用第二种方法配置)

新建项目,将Bundle ID改成和上面配置的成相同名字。

如果还是不行,检查这里

将配置好的证书下载后安装。

接下来就可以开始处理远程推送的消息了:

  • 1、向苹果注册我们的设备,并获取到deviceToken

注意:
在iOS7和iOS8中的注册方法不一样

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // 请求获取DeviceToken
    if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) {
        // 1.获取发送通知的权限
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
        [application registerUserNotificationSettings:settings];

        // 2.注册远程通知
        [application registerForRemoteNotifications];
    } else {
        [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound];
    }

    return YES;
}

//获取到deviceToken
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    NSLog(@"%@", deviceToken);
}
  • 2、处理远程通知的消息

这里有两个方法,注意两者的区别,更具需要调用

//这个方法可以处理当用户点击消息进入前台做一些操作
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    NSLog(@"%@", userInfo);
}

//这个方法可以实现在用户手机收到消息就可以在后台进行一些操作,例如更新UI

//不过,这个方法要先设置后台模式,方法如下:
/*
 1.开启后台模式
 2.调用completionHandler,告诉系统你现在是否有新的数据更新
 3.userInfo添加一个字段:"content-available" : "1" : 只要添加了该字段,接受到通知都会在后台运行
 */
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
    UIView *redView = [[UIView alloc] init];
    redView.frame = CGRectMake(100, 100, 100, 100);
    redView.backgroundColor = [UIColor redColor];
    [self.window.rootViewController.view addSubview:redView];

    completionHandler(UIBackgroundFetchResultFailed);
}

添加后台模式方法:

测试工具介绍

下面介绍一种测试远程通知的工具PushMeBaby

  • PushMeBaby是一款用来测试ANPs的开源Mac项目
  • 它充当了服务器的作用,用法非常简单
  • 它负责将内容提交给苹果的APNs服务器,苹果的APNs服务器再将内容推送给用户的设备

使用步骤:

  • 注释掉不要的错误

  • 填写必要信息

    • deviceToken:用于找到设备的令牌

    • payload:推送的内容

  • 将推送的调试证书改为名apns.cer,添加到PushMeBaby项目中

  • command + R启动程序,然后点击Push
    接下来就可以在设备上接收到远程推送通知

常用的第三方推送(极光推送)

什么是JPush

一套远程推送解决方案,支持android和iOS两个平台
它能够快捷地为iOS App增加推送功能,减少集成APNs需要的工作量、开发复杂度

更多的信息,可以参考JPush官方网站:https://www.jpush.cn

集成iOS SDK的步骤可以参考
http://docs.jpush.cn/pages/viewpage.action?pageId=2621727



2018-08-07 00:21:48 qq_38844040 阅读数 2597
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27820 人正在学习 去看看 秦子恒

1可以利用测试公众号进行开发(个人的是没有网页授权的)
这里写图片描述

配置好相关信息
这里我们可以手工方式原生的按照微信文档进行操作 但现在我们使用第三方sdk来接入,
这个sdk的稳定性 安全性 可用性是值得信赖的 在github上有近1W的star。(包含了微信相关开发的所有了 下面的 mp是公众号模块)
给出github地址:https://github.com/chanjarster/weixin-java-tools/
我们在项目里引入依赖(maven gradle 都支持)

        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-mp</artifactId>
            <version>2.7.0</version>
        </dependency>

下面来看看代码
为了灵活性和解耦合,我们把一些东西单独放在配置文件里(让它从apllication.yml中读取)

package com.lq.sell.config;


import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@Data
@ConfigurationProperties(prefix = "wechat")
public class WechatAccountConfig {

    private  String appid;
    private  String secret;
    private  String returnUrl;
    private  String token;
}

上图中的接口配置信息地址在下面的类中验证

 @RequestMapping("/check")
    public void check(ServletResponse response, String timestamp, String nonce, String signature, String echostr) {
        if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
            log.error("不合法");
            throw new SellException(ResultEnum.WECHAT_ERROR);
        }
        PrintWriter o = null;
        try {
            o = new PrintWriter(response.getWriter());
            o.print(echostr);
        } catch (IOException e) {
            log.error("写回微信端错误{}", e.getMessage());
        } finally {
            o.close();
        }
    }

微信将请求这个地址来验证接口信息(就是上图中的地址)
这个方法的五个参数作用分别是:
response 将echostr原样写回微信告诉它通过验证;
微信端验证时传过来的参数—时间戳;
微信端验证时传过来的参数—随机数;
微信端验证时传过来的参数—签名;
这里checkSignature()方法会具体去检验是否合法。
通过后返回echostr;验证通过。(我们的token呢???? 别急 后面会出现的)

这个sdk的使用在mp模块主要有两个类(不清楚的可以上github看文档)
WxMpService;WxMpConfigStorage;
下面是在springboot里的配置

package com.lq.sell.config;

import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class WechatMpConfig {
    @Autowired
    private WechatAccountConfig wechatAccountConfig;



    @Bean
    public WxMpService wxMpService() {
        WxMpService wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
        return wxMpService;
    }

    @Bean
    public WxMpConfigStorage wxMpConfigStorage() {
        WxMpInMemoryConfigStorage wxMpInMemoryConfigStorage = new WxMpInMemoryConfigStorage();
        wxMpInMemoryConfigStorage.setAppId(wechatAccountConfig.getAppid());
        wxMpInMemoryConfigStorage.setSecret(wechatAccountConfig.getSecret());
        wxMpInMemoryConfigStorage.setToken(wechatAccountConfig.getToken());
//        wxMpInMemoryConfigStorage.setAesKey("m8lg6owoQN2xK79ku5JW0JJXxz7QepX2BWlj5NHFsi8");
        return wxMpInMemoryConfigStorage;
    }
}

上面的代码setToken实际上是去做了我们第一步的checkSignature();

当我们通过验证后
就编写对应的controller就好了
看看我们的代码

package com.lq.sell.controller;

import com.lq.sell.config.WechatAccountConfig;
import com.lq.sell.config.WechatMpConfig;
import com.lq.sell.enums.ResultEnum;
import com.lq.sell.sellException.SellException;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.ServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;

@Controller
@RequestMapping("/wechat")
@Slf4j
public class WechatController {

    @Autowired
    private WxMpService wxMpService;

    @Autowired
    private WechatAccountConfig wechatAccountConfig;

    @RequestMapping("/authorize")
    public String authorize(@RequestParam("returnUrl") String returnUrl) {

        String redirectUrl = wxMpService.oauth2buildAuthorizationUrl(wechatAccountConfig.getReturnUrl(), WxConsts.OAUTH2_SCOPE_USER_INFO, URLEncoder.encode(returnUrl));
        log.info("获得code redirectUrl{}", redirectUrl);

        return "redirect:" + redirectUrl;
    }

    @RequestMapping("/userInfo")
    public String userInfo(@RequestParam("code") String code, @RequestParam("state") String returnUrl) {
        log.info("redirect code{}  state{}", code, returnUrl);
        WxMpOAuth2AccessToken wxMpOAuth2AccessToken = null;
        try {
            wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
        } catch (WxErrorException e) {
            log.error("wechat  error{}", e.getError().getErrorMsg());
            throw new SellException(e.getError().getErrorMsg());
        }
        String openId = wxMpOAuth2AccessToken.getOpenId();
        log.info("openid{}", openId);
        log.info("enter");
        log.info("return url{}", returnUrl);
        return "redirect:" + "https://www.imooc.com/" + "?openid=" + openId;
    }


    @RequestMapping("/check")
    public void check(ServletResponse response, String timestamp, String nonce, String signature, String echostr) {
        if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
            log.error("不合法");
            throw new SellException(ResultEnum.WECHAT_ERROR);
        }
        PrintWriter o = null;
        try {
            o = new PrintWriter(response.getWriter());
            o.print(echostr);
        } catch (IOException e) {
            log.error("写回微信端错误{}", e.getMessage());
        } finally {
            o.close();
        }
    }
}

注意 这里的bean名 路径 controller名 方法名(authorize())要一致,这个sdk文档有说明的。
authorize()我们去请求微信
userInfo()这个方法我们就可以去做我们想做的事了 比如得到openid ,获取用户信息 ,重定向到某个网页(上面就是)等。
下图是一些步骤 和注意的地方(坑)
务必小心!
有问题可以给我留言。
这里写图片描述

这里写图片描述
这里写图片描述

2016-08-06 15:35:46 qcx321 阅读数 919
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27820 人正在学习 去看看 秦子恒

什么是消息推送

举一个常见的例子,我们的手机上经常会有弹出一些信息,例如QQ信息、微信信息等等,这就是常见的消息推送。

例如:

消息推送的类型:

  • 在屏幕顶部显示一块横幅(显示具体内容)
  • 在屏幕中间弹出一个UIAlertView(显示具体内容)
  • 在锁屏界面显示一块横幅(锁屏状态下,显示具体内容)
  • 更新app图标的数字(说明新内容的数量)
  • 播放音效(提醒作用)

这是我们常见的推送消息的样式,我们可以在手机上自定义接收的消息如何展示。

在一些软件中,如果用户不小心关闭了我们的推送服务,我们也可以这样提示用户怎么打开允许接收推送服务(iOS8以后)。

注意:

  • 发出推送通知时,如果当前程序正运行在前台,那么推送通知就不会被呈现出来

  • 点击推送通知后,默认会自动打开发出推送通知的app

  • 不管app打开还是关闭,推送通知都能如期发出

消息推送和平常的从服务器获取数据有什么不同?

  • 当我们从服务器获取数据的时候,我们会主动向服务器发送消息,然后服务器才会给我们发送我们需要的信息;而消息推送是当我们不在聊天状态下,甚至是连QQ软件都没有打开的情况下,服务器主动向我们发送消息,告诉我们一些信息。

当然了,消息推送和通知(NSNotification)可不一样,虽然它们的使用类名看起来有点相似。

  • NSNotification是抽象的,不可见的
  • 消息推送是可见(肉眼可见的)

本地推送

在iOS中,推送分为本地推送和远程推送,本地推送不需要网络(不需要服务器的支持),常见的应用场景例如:

  • 事件提醒类的软件,到了我们自定义的时间,就会弹出一些信息告诉我们该干什么了。

  • 记账类软件,会提醒我们的一些花销等等。


我们先来学习一下本地推送

相关使用的类(重要)

  • 创建本地推送通知对象
UILocalNotification *ln = [[UILocalNotification alloc] init];
  • 设置本地推送通知属性
//推送通知的触发时间(何时发出推送通知)
@property(nonatomic,copy) NSDate *fireDate;

//推送通知的具体内容
@property(nonatomic,copy) NSString *alertBody;

//在锁屏时显示的动作标题(完整标题:“滑动来” + alertAction)
@property(nonatomic,copy) NSString *alertAction;

//音效文件名
@property(nonatomic,copy) NSString *soundName;

//app图标数字
@property(nonatomic) NSInteger applicationIconBadgeNumber;

//每隔多久重复发一次推送通知
@property(nonatomic) NSCalendarUnit repeatInterval;

//点击推送通知打开app时显示的启动图片
@property(nonatomic,copy) NSString *alertLaunchImage;

//附加的额外信息
@property(nonatomic,copy) NSDictionary *userInfo;

//时区
@property(nonatomic,copy) NSTimeZone *timeZone;
(一般设置为[NSTimeZone defaultTimeZone] ,跟随手机的时区)

//调度本地推送通知(调度完毕后,推送通知会在特地时间fireDate发出)
[[UIApplication sharedApplication] scheduleLocalNotification:ln];

//获得被调度(定制)的所有本地推送通知
@property(nonatomic,copy) NSArray *scheduledLocalNotifications;
(已经发出且过期的推送通知就算调度结束,会自动从这个数组中移除)

//取消调度本地推送通知
- (void)cancelLocalNotification:(UILocalNotification *)notification;
- (void)cancelAllLocalNotifications;

//立即发出本地推送通知
- (void)presentLocalNotificationNow:(UILocalNotification *)notification;
  • 用户点击推送消息进入app时的调用方法

//当用户点击本地推送通知,会自动打开app,这里有2种情况
//app并没有关闭,一直隐藏在后台
//让app进入前台,并会调用AppDelegate的下面方法(并非重新启动app)
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;

//app已经被关闭(进程已死)
//启动app,启动完毕会调用AppDelegate的下面方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
//launchOptions参数通过UIApplicationLaunchOptionsLocalNotificationKey取出本地推送通知对象
//当点击通知进入app时,launchOptions参数才会有值,当正常启动app时,launchOptions为null

注意:

在iOS 8.0中,如果要使用本地通知,需要得到用户的许可
在didFinishLaunchingWithOptions方法中添加如下代码:

UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil];

[application registerUserNotificationSettings:settings];

实例:


//在需要的地方注册本地消息推送

    // 1.创建本地通知
    UILocalNotification *localNote = [[UILocalNotification alloc] init];

    // 2.设置本地通知的信息
    // 2.1.设置提示信息
    localNote.alertBody = @"吃饭了吗?";
    // 2.2.设置通知弹出的时间
    localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:5.0];
    // 2.3.设置滑块显示的文字
    localNote.alertAction = @"快点";
    // 2.4.是否让上面的文字生效
    localNote.hasAction = NO;
    // 2.5.设置通知中心的标题
    localNote.alertTitle = @"你大哥";
    // 2.6.设置通知的声音
    localNote.soundName = @"buyao.wav";
    // 2.7.设置应用程序图标右上角的数字
    localNote.applicationIconBadgeNumber = 10;

    // 3.调度通知
    //调度前要先把原来的通知取消
    UIApplication *app = [UIApplication sharedApplication];
    [app cancelAllLocalNotifications];
    [app scheduleLocalNotification:localNote];

在appdelegate类中实现相应的跳转方法

#import "AppDelegate.h"

#define IS_iOS8 ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0)

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    /*
     UIUserNotificationTypeNone    = 0,      不发出通知
     UIUserNotificationTypeBadge   = 1 << 0, 改变应用程序图标右上角的数字
     UIUserNotificationTypeSound   = 1 << 1, 播放音效
     UIUserNotificationTypeAlert   = 1 << 2, 是否运行显示横幅
     */

    [application setApplicationIconBadgeNumber:0];

    if (IS_iOS8) {
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound categories:nil];
        [application registerUserNotificationSettings:settings];
    }

    // 如果是正常启动应用程序,那么launchOptions参数是null
    // 如果是通过其他方式启动应用程序,那么launchOptions就有值,里面存储的是通知的内容
    if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) {
        // 当被杀死状态收到本地通知时执行的跳转代码
         [self jumpToSession];
    }

    return YES;
}

//程序没有关闭时,点击通知进入app才会调用,如果将程序完全退出,点击通知进入app时只会调用上面的方法,不会调用这个方法
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
    // 在这里写跳转代码
    // 如果是应用程序在前台,依然会收到通知,但是收到通知之后不应该跳转
    if (application.applicationState == UIApplicationStateActive) return;

    if (application.applicationState == UIApplicationStateInactive) {
        // 当应用在后台收到本地通知时执行的跳转代码
        [self jumpToSession];
    }
}

- (void)jumpToSession
{
    UILabel *redView = [[UILabel alloc] init];
    redView.backgroundColor = [UIColor redColor];
    redView.frame = CGRectMake(0, 100, 300, 400);
    redView.numberOfLines = 0;
    // redView.text = [NSString stringWithFormat:@"%@", launchOptions];
    [self.window.rootViewController.view addSubview:redView];
}

@end

远程推送

先介绍一下iOS中远程推送的原理:

我们先要明确一点,所有的iOS设备收到的远程推送消息都是通过苹果的服务器发出来的。我们自己公司的服务器或者第三方的推送服务器都是将要发送给我们的推送消息先推给苹果的服务器,然后再由苹果的服务器发送给我们。

如下图:

所以,我们的苹果设备在联网的情况下,都会默认和苹果的服务器保持一个长连接(这里不解释长连接的概念,你可以理解成是有一条线一直在两者之间联系着,为了保持服务器不断开和我们设备的联系,我们的设备默认每隔一段时间会向服务器发送心跳包(一个很小的文件),来告诉苹果服务器不要和我们的设备断开连接)。

原理图讲解

下面详细解释一下iOS中的远程推送原理

上图中1-8的步骤就可以很好的解释远程推送的过程了,而客户端需要做的只有几个步骤:

  • 1:发送设备的UDID和
    应用的Bundle Identifier
    给APNs服务器

  • 2:经苹果加密生成一个
    deviceToken

  • 3:发送当前用户的deviceToken
    和用户的标志(比如id或者qq)到自己公司的服务器或者第三方推送服务器

  • 4:监听通知的点击事件

其余的步骤由服务器端实现:

  • 4:自己的服务器或者第三方推送服务器将客户端发送过来的用户信息保存在自己的服务器中

  • 5:有人发送消息的时候,从服务器中(根据deviceToken)查询要发给谁

  • 6:查询到要发送给某人以后,将信息发送给苹果服务器

  • 7:苹果服务器根据得到的deviceToken和信息,查到要接受信息的设备和app,将信息发送给用户。

调试iOS的远程推送功能, 必备条件:

1.真机

2.调试推送需要的证书文件
1> aps_development.cer : 某台电脑就能调试某个app的推送服务
2> iphone5_qq.mobileprovision : 某台电脑就能利用某台设备调试某个程序

三.发布具有推送服务的app,需要的证书文件
1> aps_production.cer : 如果发布的程序中包含了推送服务,就必须安装这个证书
2> qq.mobileprovision : 某台电脑就能发布某个程序

实际操作

下面就开始真正的使用一下远程推送功能吧。

证书配置01 – 创建App ID

配置明确的App ID

大概步骤如下:

先选择明确的App ID

配置远程推送的调试证书


配置远程推送的发布证书(使用第二种方法配置)

新建项目,将Bundle ID改成和上面配置的成相同名字。

如果还是不行,检查这里

将配置好的证书下载后安装。

接下来就可以开始处理远程推送的消息了:

  • 1、向苹果注册我们的设备,并获取到deviceToken

注意:
在iOS7和iOS8中的注册方法不一样

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // 请求获取DeviceToken
    if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) {
        // 1.获取发送通知的权限
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
        [application registerUserNotificationSettings:settings];

        // 2.注册远程通知
        [application registerForRemoteNotifications];
    } else {
        [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound];
    }

    return YES;
}

//获取到deviceToken
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    NSLog(@"%@", deviceToken);
}
  • 2、处理远程通知的消息

这里有两个方法,注意两者的区别,更���需要调用

//这个方法可以处理当用户点击消息进入前台做一些操作
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    NSLog(@"%@", userInfo);
}

//这个方法可以实现在用户手机收到消息就可以在后台进行一些操作,例如更新UI

//不过,这个方法要先设置后台模式,方法如下:
/*
 1.开启后台模式
 2.调用completionHandler,告诉系统你现在是否有新的数据更新
 3.userInfo添加一个字段:"content-available" : "1" : 只要添加了该字段,接受到通知都会在后台运行
 */
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
    UIView *redView = [[UIView alloc] init];
    redView.frame = CGRectMake(100, 100, 100, 100);
    redView.backgroundColor = [UIColor redColor];
    [self.window.rootViewController.view addSubview:redView];

    completionHandler(UIBackgroundFetchResultFailed);
}

添加后台模式方法:

测试工具介绍

下面介绍一种测试远程通知的工具PushMeBaby

  • PushMeBaby是一款用来测试ANPs的开源Mac项目
  • 它充当了服务器的作用,用法非常简单
  • 它负责将内容提交给苹果的APNs服务器,苹果的APNs服务器再将内容推送给用户的设备

使用步骤:

  • 注释掉不要的错误

  • 填写必要信息

    • deviceToken:用于找到设备的令牌

    • payload:推送的内容

  • 将推送的调试证书改为名apns.cer,添加到PushMeBaby项目中

  • command + R启动程序,然后点击Push
    接下来就可以在设备上接收到远程推送通知

常用的第三方推送(极光推送)

什么是JPush

一套远程推送解决方案,支持android和iOS两个平台
它能够快捷地为iOS App增加推送功能,减少集成APNs需要的工作量、开发复杂度

更多的信息,可以参考JPush官方网站:https://www.jpush.cn

集成iOS SDK的步骤可以参考
http://docs.jpush.cn/pages/viewpage.action?pageId=2621727


支持原创  http://www.cnblogs.com/66it/p/4784224.html

iOS 自定义通知声音

阅读数 1771

没有更多推荐了,返回首页